<commit_before>package endpoints

import "github.com/rackspace/gophercloud"

// Endpoint describes the entry point for another service's API.
type Endpoint struct {
	ID        string    `json:"id"`
	Interface Interface `json:"interface"`
	Name      string    `json:"name"`
	Region    string    `json:"region"`
	ServiceID string    `json:"service_id"`
	URL       string    `json:"url"`
}

// EndpointList contains a page of Endpoint results.
type EndpointList struct {
	gophercloud.Pagination
	Endpoints []Endpoint
}
<commit_msg>Take out a stale reference before I start on Endpoints.<commit_after>package endpoints

import "github.com/rackspace/gophercloud"

// Endpoint describes the entry point for another service's API.
type Endpoint struct {
	ID        string    `json:"id"`
	Interface Interface `json:"interface"`
	Name      string    `json:"name"`
	Region    string    `json:"region"`
	ServiceID string    `json:"service_id"`
	URL       string    `json:"url"`
}

// EndpointList contains a page of Endpoint results.
type EndpointList struct {
	service   *gophercloud.ServiceClient
	Endpoints []Endpoint
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"log"
	"math/big"
	"strings"
	"sync"
	"time"

	"github.com/go-mangos/mangos"
	"github.com/go-mangos/mangos/protocol/bus"
	"github.com/go-mangos/mangos/transport/tlstcp"
	"github.com/nictuku/dht"
)

type BusMessage struct {
	From    string
	To      string
	Seq     int64
	Cmd     string
	Payload string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) String() string {
	return fmt.Sprintf("[%s: %v (ID: %d)]", b.Cmd, b.Payload, b.Seq)
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
	pm       *PeerManager
}

func NewFriend(name string, pm *PeerManager) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now(), pm: pm}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg == nil {
		return fmt.Sprintf(`%s: no message, last seen: %s`, f.name, f.lastSeen)
	}

	return fmt.Sprintf("%s: last message: %s, last seen: %s ago", f.name, f.msg, time.Now().Sub(f.lastSeen))
}

func (f *Friend) HandleMessage(m *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= m.Seq {
		/* We've already seen this message */
		return
	}

	f.msg = m
	f.lastSeen = time.Now()

	switch m.Cmd {
	case "event":
		ev := Event{}
		if err := json.Unmarshal([]byte(m.Payload), &ev); err != nil {
			log.Printf(`can't unmarshal event payload: %s`, err)
		}
		log.Printf(`got an event: %v`, ev)

		if err := f.pm.db.MergeEvent(ev); err != nil {
			log.Printf(`can't merge event: %s`, err)
		}
	case "hello":
		f.pm.mtx.Lock()
		defer f.pm.mtx.Unlock()

		f.pm.need_full_sync = true
	case "i'm alive":
		/* nothing */
	default:
		log.Printf(`unhandled message: tgt: %s, src: %s, cmd: %s, payload: %v`, m.To, m.From, m.Cmd, m.Payload)
	}
}

type PeerManager struct {
	d              *dht.DHT
	db             *DB
	bus            mangos.Socket
	nick           string
	friends        map[string]*Friend
	oldfriends     map[string]*Friend
	venue          string
	sequence       int64
	need_full_sync bool
	opts           map[string]interface{}
	mtx            *sync.RWMutex
}

func NewPeerManager(db *DB) *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000

	pm := PeerManager{db: db}

	pm.opts = map[string]interface{}{mangos.OptionTLSConfig: pm.setupTLS()}

	var err error
	pm.bus, err = bus.NewSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}
	pm.bus.AddTransport(tlstcp.NewTransport())

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) setupTLS() *tls.Config {
	cert := pm.setupCertificate()

	return &tls.Config{
		InsecureSkipVerify: true,
		Certificates:       []tls.Certificate{cert},
	}
}

func (pm *PeerManager) setupCertificate() tls.Certificate {
	template := x509.Certificate{
		SerialNumber: big.NewInt(4711),
		Subject: pkix.Name{
			Organization: []string{"unobtanium"},
			CommonName:   "*",
		},
		DNSNames:              []string{`*`},
		NotAfter:              time.Now().AddDate(0, 0, 10),
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		SignatureAlgorithm:    x509.SHA512WithRSA,
		PublicKeyAlgorithm:    x509.ECDSA,
		SubjectKeyId:          []byte{1, 2, 3, 4, 5},
		BasicConstraintsValid: true,
		IsCA: true,
	}

	log.Printf(`generating 2048 bit RSA private key`)
	priv, _ := rsa.GenerateKey(rand.Reader, 2048)
	pub := &priv.PublicKey
	log.Printf(`building self-signed certificate`)
	cert_raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, priv)
	if err != nil {
		log.Fatalf(`can't generate TLS certificate: %s`, err)
	}
	log.Printf(`created a cert of length %d bytes`, len(cert_raw))

	privbuf := &bytes.Buffer{}
	pem.Encode(privbuf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})

	certbuf := &bytes.Buffer{}
	pem.Encode(certbuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert_raw})

	cert, err := tls.X509KeyPair(certbuf.Bytes(), privbuf.Bytes())
	if err != nil {
		log.Fatalf(`can't build key pair: %s`, err)
	}

	return cert
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s, my sequence ID is %d", pm.nick, pm.sequence),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst, cmd, payload string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Cmd: cmd, Payload: payload}
	pm.mtx.Unlock()

	return pm.bus.Send(m.Bytes())
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	if err := pm.bus.ListenOptions(fmt.Sprintf("tls+tcp://*:%d", pm.d.Port()), pm.opts); err != nil {
		log.Fatalf(`can't listen on BUS socket: %s`, err)
	}

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv())
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From, pm)
				pm.friends[m.From] = f
				pm.need_full_sync = true
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, "hello", "")
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", "i'm alive", fmt.Sprintf("%d", i))
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	go func() {
		for {
			buf, err := json.Marshal(<-pm.db.Events)
			if err != nil {
				log.Fatalf(`can't marshal event: %s`, err)
			}
			pm.Publish("*", "event", string(buf))
		}
	}()

	go func() {
		for {
			time.Sleep(5 * time.Second)
			pm.mtx.Lock()
			if !pm.need_full_sync {
				pm.mtx.Unlock()
				continue
			}
			pm.need_full_sync = false
			pm.mtx.Unlock()

			log.Println(`doing a full sync`)

			for _, env := range pm.db.AllEnvelopes() {
				_, events, err := pm.db.EnvelopeWithHistory(env.Id)
				if err != nil {
					log.Fatalf(`can't get events for envelope %s: %s`, env.Id, err)
				}
				for _, e := range events {
					pm.db.Events <- e
				}
			}
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]time.Time)

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if t, ok := seen[addr]; !ok ||  t.Add(30 * time.Second).Before(time.Now()) {
					pm.connectToPeer(addr)
					seen[addr] = time.Now()
				}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	log.Printf(`dialing %s`, addr)
	if err := pm.bus.DialOptions(fmt.Sprintf("tls+tcp://%s", addr), pm.opts); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<commit_msg>Use a deadline of 5 seconds for reading and writing<commit_after>package main

import (
	"bytes"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"log"
	"math/big"
	"strings"
	"sync"
	"time"

	"github.com/go-mangos/mangos"
	"github.com/go-mangos/mangos/protocol/bus"
	"github.com/go-mangos/mangos/transport/tlstcp"
	"github.com/nictuku/dht"
)

type BusMessage struct {
	From    string
	To      string
	Seq     int64
	Cmd     string
	Payload string
}

func NewBusMessage(data []byte, err error) (*BusMessage, error) {
	if err != nil {
		return nil, err
	}

	rv := &BusMessage{}
	if err = json.Unmarshal(data, rv); err != nil {
		return nil, err
	}
	return rv, nil
}

func (b *BusMessage) String() string {
	return fmt.Sprintf("[%s: %v (ID: %d)]", b.Cmd, b.Payload, b.Seq)
}

func (b *BusMessage) Bytes() []byte {
	m, err := json.Marshal(b)
	if err != nil {
		log.Fatalf(`can't marshall bus message to json: %s`, err)
	}
	return m
}

type Friend struct {
	name     string
	msg      *BusMessage
	lastSeen time.Time
	mtx      *sync.Mutex
	pm       *PeerManager
}

func NewFriend(name string, pm *PeerManager) *Friend {
	return &Friend{name: name, mtx: &sync.Mutex{}, lastSeen: time.Now(), pm: pm}
}

func (f *Friend) String() string {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg == nil {
		return fmt.Sprintf(`%s: no message, last seen: %s`, f.name, f.lastSeen)
	}

	return fmt.Sprintf("%s: last message: %s, last seen: %s ago", f.name, f.msg, time.Now().Sub(f.lastSeen))
}

func (f *Friend) HandleMessage(m *BusMessage) {
	f.mtx.Lock()
	defer f.mtx.Unlock()

	if f.msg != nil && f.msg.Seq >= m.Seq {
		/* We've already seen this message */
		return
	}

	f.msg = m
	f.lastSeen = time.Now()

	switch m.Cmd {
	case "event":
		ev := Event{}
		if err := json.Unmarshal([]byte(m.Payload), &ev); err != nil {
			log.Printf(`can't unmarshal event payload: %s`, err)
		}
		log.Printf(`got an event: %v`, ev)

		if err := f.pm.db.MergeEvent(ev); err != nil {
			log.Printf(`can't merge event: %s`, err)
		}
	case "hello":
		f.pm.mtx.Lock()
		defer f.pm.mtx.Unlock()

		f.pm.need_full_sync = true
	case "i'm alive":
		/* nothing */
	default:
		log.Printf(`unhandled message: tgt: %s, src: %s, cmd: %s, payload: %v`, m.To, m.From, m.Cmd, m.Payload)
	}
}

type PeerManager struct {
	d              *dht.DHT
	db             *DB
	bus            mangos.Socket
	nick           string
	friends        map[string]*Friend
	oldfriends     map[string]*Friend
	venue          string
	sequence       int64
	need_full_sync bool
	opts           map[string]interface{}
	mtx            *sync.RWMutex
}

func NewPeerManager(db *DB) *PeerManager {
	conf := dht.NewConfig()
	conf.Port = 55000

	pm := PeerManager{db: db}

	pm.opts = map[string]interface{}{mangos.OptionTLSConfig: pm.setupTLS()}

	var err error
	pm.bus, err = bus.NewSocket()
	if err != nil {
		log.Fatalf(`can't create BUS socket: %s`, err)
	}
	pm.bus.AddTransport(tlstcp.NewTransport())
	pm.bus.SetOption(mangos.OptionRecvDeadline, 5 * time.Second)
	pm.bus.SetOption(mangos.OptionSendDeadline, 5 * time.Second)

	if pm.d, err = dht.New(conf); err != nil {
		log.Fatalf(`can't create DHT: %s`, err)
	}

	sum := sha1.Sum([]byte("LetsMeetHere"))
	pm.venue = hex.EncodeToString(sum[:])

	buf := make([]byte, 4)
	rand.Read(buf)
	pm.nick = hex.EncodeToString(buf)

	log.Printf(`My nickname is %s`, pm.nick)
	log.Printf(`I will meet my friends at %s`, pm.venue)

	pm.friends = make(map[string]*Friend)
	pm.oldfriends = make(map[string]*Friend)

	pm.mtx = &sync.RWMutex{}

	return &pm
}

func (pm *PeerManager) setupTLS() *tls.Config {
	cert := pm.setupCertificate()

	return &tls.Config{
		InsecureSkipVerify: true,
		Certificates:       []tls.Certificate{cert},
	}
}

func (pm *PeerManager) setupCertificate() tls.Certificate {
	template := x509.Certificate{
		SerialNumber: big.NewInt(4711),
		Subject: pkix.Name{
			Organization: []string{"unobtanium"},
			CommonName:   "*",
		},
		DNSNames:              []string{`*`},
		NotAfter:              time.Now().AddDate(0, 0, 10),
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		SignatureAlgorithm:    x509.SHA512WithRSA,
		PublicKeyAlgorithm:    x509.ECDSA,
		SubjectKeyId:          []byte{1, 2, 3, 4, 5},
		BasicConstraintsValid: true,
		IsCA: true,
	}

	log.Printf(`generating 2048 bit RSA private key`)
	priv, _ := rsa.GenerateKey(rand.Reader, 2048)
	pub := &priv.PublicKey
	log.Printf(`building self-signed certificate`)
	cert_raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, priv)
	if err != nil {
		log.Fatalf(`can't generate TLS certificate: %s`, err)
	}
	log.Printf(`created a cert of length %d bytes`, len(cert_raw))

	privbuf := &bytes.Buffer{}
	pem.Encode(privbuf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})

	certbuf := &bytes.Buffer{}
	pem.Encode(certbuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert_raw})

	cert, err := tls.X509KeyPair(certbuf.Bytes(), privbuf.Bytes())
	if err != nil {
		log.Fatalf(`can't build key pair: %s`, err)
	}

	return cert
}

func (pm *PeerManager) String() string {
	pm.mtx.RLock()
	defer pm.mtx.RUnlock()

	s := []string{
		fmt.Sprintf("DHT: Port: %d", pm.d.Port()),
		fmt.Sprintf("\r\nI am %s, my sequence ID is %d", pm.nick, pm.sequence),
		fmt.Sprintf("I have %d friend(s)", len(pm.friends)),
		fmt.Sprintf("We're meeting at '%s'", pm.venue),
		"\r\nThese are my friends:\r\n",
	}

	for _, f := range pm.friends {
		s = append(s, f.String())
	}

	s = append(s, "\r\nI haven't heard from these guys in a while:\r\n")
	for _, f := range pm.oldfriends {
		s = append(s, f.String())
	}

	return strings.Join(s, "\r\n")
}

func (pm *PeerManager) Publish(dst, cmd, payload string) error {
	pm.mtx.Lock()
	pm.sequence++
	m := &BusMessage{From: pm.nick, To: dst, Seq: pm.sequence, Cmd: cmd, Payload: payload}
	pm.mtx.Unlock()

	return pm.bus.Send(m.Bytes())
}

func (pm *PeerManager) Loop() {
	ih, err := dht.DecodeInfoHash(pm.venue)
	if err != nil {
		log.Printf(`can't decode infohash: %s`, err)
		return
	}

	if err := pm.d.Start(); err != nil {
		log.Printf(`can't start DHT: %s`, err)
		return
	}

	log.Printf(`DHT bound to port %d`, pm.d.Port())

	if err := pm.bus.ListenOptions(fmt.Sprintf("tls+tcp://*:%d", pm.d.Port()), pm.opts); err != nil {
		log.Fatalf(`can't listen on BUS socket: %s`, err)
	}

	go pm.drainPeers()

	go func() {
		for {
			time.Sleep(2 * time.Second)
			pm.mtx.Lock()
			for name, f := range pm.friends {
				f.mtx.Lock()
				if f.lastSeen.Add(10 * time.Second).Before(time.Now()) {
					log.Printf(`haven't heard from %s in a while`, name)
					pm.oldfriends[name] = f
					delete(pm.friends, name)
				}
				f.mtx.Unlock()
			}
			pm.mtx.Unlock()
		}
	}()

	go func() {
		for {
			/* Receive message */
			m, err := NewBusMessage(pm.bus.Recv())
			if err != nil {
				log.Printf(`can't receive message from bus: %s`, err)
				continue
			}

			/* Ignore messages from ourselves */
			if m.From == pm.nick {
				continue
			}

			/* Ignore messages not to 'everyone' or us */
			if m.To != pm.nick && m.To != "*" {
				continue
			}

			pm.mtx.Lock()
			f, ok := pm.friends[m.From]
			if !ok {
				f = NewFriend(m.From, pm)
				pm.friends[m.From] = f
				pm.need_full_sync = true
			}
			pm.mtx.Unlock()

			f.HandleMessage(m)

			if !ok {
				log.Printf(`%s is a new friend!`, m.From)
				pm.Publish(m.From, "hello", "")
			}
		}
	}()

	go func() {
		i := 0
		for {
			pm.Publish("*", "i'm alive", fmt.Sprintf("%d", i))
			i++
			time.Sleep(5 * time.Second)
		}
	}()

	go func() {
		for {
			buf, err := json.Marshal(<-pm.db.Events)
			if err != nil {
				log.Fatalf(`can't marshal event: %s`, err)
			}
			pm.Publish("*", "event", string(buf))
		}
	}()

	go func() {
		for {
			time.Sleep(5 * time.Second)
			pm.mtx.Lock()
			if !pm.need_full_sync {
				pm.mtx.Unlock()
				continue
			}
			pm.need_full_sync = false
			pm.mtx.Unlock()

			log.Println(`doing a full sync`)

			for _, env := range pm.db.AllEnvelopes() {
				_, events, err := pm.db.EnvelopeWithHistory(env.Id)
				if err != nil {
					log.Fatalf(`can't get events for envelope %s: %s`, env.Id, err)
				}
				for _, e := range events {
					pm.db.Events <- e
				}
			}
		}
	}()

	for {
		pm.d.PeersRequest(string(ih), true)
		time.Sleep(5 * time.Second)
	}
}

func (pm *PeerManager) drainPeers() {
	log.Printf(`draining DHT`)
	seen := make(map[string]struct{})

	for r := range pm.d.PeersRequestResults {
		for _, peers := range r {
			for _, x := range peers {
				addr := dht.DecodePeerAddress(x)
				if _, ok := seen[addr]; !ok {
					pm.connectToPeer(addr)
				}
				seen[addr] = struct{}{}
			}
		}
	}
}

func (pm *PeerManager) connectToPeer(addr string) {
	log.Printf(`dialing %s`, addr)
	if err := pm.bus.DialOptions(fmt.Sprintf("tls+tcp://%s", addr), pm.opts); err != nil {
		log.Printf(`can't connect SUB to %s: %s`, addr, err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"fmt"
	"time"
	"flag"
	"sort"
	"bufio"
	"strconv"
	"strings"
	"text/template"
)

var (
	scoresPath = "/home/krowbar/Code/irc/tildescores.txt"
	addictionData = "/home/karlen/bin/tilderoyale"
)

const (
	scoreDeltasPath = "/home/bear/scoredeltas.txt"
	deltaDelimiter = "+++"
)

func main() {
	fmt.Println("Starting...")

	// Get any arguments
	outPtr := flag.String("o", "tildescores", "Output file name")
	isTestPtr := flag.Bool("t", false, "Specifies we're developing")
	flag.Parse()

	if *isTestPtr {
		scoresPath = "/home/bear/tildescores.txt"
		addictionData = "/home/bear/addicted.sh"
	}

	headers := []string{ "User", "Tildes", "Last Collected", "# Asks", "Avg.", "Last Amt." }

	scoresData := readData(scoresPath, "&^%")
	updatesData := readData(scoreDeltasPath, deltaDelimiter)

	scoresData = checkScoreDelta(scoresData, updatesData)
	scoresTable := buildScoresTable(scoresData, headers)

	generate("tilde collectors", sortScore(scoresTable), *outPtr)
}

type Table struct {
	Headers []string
	Rows []Row
}

type Row struct {
	Data []string
}

type By func(r1, r2 *Row) bool
func (by By) Sort(rows []Row) {
	rs := &rowSorter {
		rows: rows,
		by: by,
	}
	sort.Sort(rs)
}
type rowSorter struct {
	rows []Row
	by func(r1, r2 *Row) bool
}
func (r *rowSorter) Len() int {
	return len(r.rows)
}
func (r *rowSorter) Swap(i, j int) {
	r.rows[i], r.rows[j] = r.rows[j], r.rows[i]
}
func (r *rowSorter) Less(i, j int) bool {
	return r.by(&r.rows[i], &r.rows[j])
}

func sortScore(table *Table) *Table {
	score := func(r1, r2 *Row) bool {
		s1, _ := strconv.Atoi(r1.Data[1])
		s2, _ := strconv.Atoi(r2.Data[1])
		return s1 < s2
	}
	decScore := func(r1, r2 *Row) bool {
		return !score(r1, r2)
	}
	By(decScore).Sort(table.Rows)

	return table
}

func parseTimestamp(ts string) time.Time {
	t, err := strconv.ParseInt(ts, 10, 64)
	if err != nil {
		panic(err)
	}
	return time.Unix(t, 0)
}

type LastScore struct {
	LastUpdate int
	LastScore int
	LastIncrement int
	Times int
	ScoreOffset int
}

func checkScoreDelta(scoreRows *[]Row, deltaRows *[]Row) *[]Row {
	users := make(map[string]LastScore)

	// Read score delta data
	for i := range *deltaRows {
		r := (*deltaRows)[i]

		if len(r.Data) < 4 {
			break
		}

		score, _ := strconv.Atoi(r.Data[1])
		update, _ := strconv.Atoi(r.Data[2])
		inc, _ := strconv.Atoi(r.Data[3])
		times, _ := strconv.Atoi(r.Data[4])
		so, _ := strconv.Atoi(r.Data[5])

		users[r.Data[0]] = LastScore{ LastScore: score, LastUpdate: update, LastIncrement: inc, Times: times, ScoreOffset: so }
	}

	// Fetch IRC log data
	fmt.Println("Fetching IRC log data")
	cmd := exec.Command(addictionData, "/home/karlen/bin/addictedtotilde -c")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Println(err)
	}
	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	r := bufio.NewReader(stdout)
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		logRow := strings.Split(scanner.Text(), "\t")
		uname := strings.TrimSpace(logRow[0])
		u, exists := users[uname]
		asks, _ := strconv.Atoi(strings.TrimSpace(logRow[3]))
		if !exists {
			u = LastScore{ ScoreOffset: 0 }
		}
		u.ScoreOffset = 0
		u.Times = asks
		users[uname] = u
	}

	for i := range *scoreRows {
		r := (*scoreRows)[i]
		u, exists := users[r.Data[0]]

		score, _ := strconv.Atoi(r.Data[1])
		update, _ := strconv.Atoi(r.Data[2])

		// Fill in any missing users
		if !exists {
			u = LastScore{ LastScore: score, LastIncrement: -1, LastUpdate: update, Times: 0, ScoreOffset: score }
			users[r.Data[0]] = u
		}

		// Match up "last collection" with rest of table data
		if update > u.LastUpdate {
			u.LastIncrement = score - u.LastScore
			u.LastUpdate = update
			u.LastScore = score
			u.Times++
		}

		var asksStr string
		if u.Times > 0 {
			asksStr = strconv.Itoa(u.Times)
		} else {
			asksStr = "-"
		}
		r.Data = append(r.Data, asksStr)

		var avgStr string
		if u.Times > 0 {
			var avg float64 = float64(u.LastScore - u.ScoreOffset) / float64(u.Times)
			avgStr = strconv.FormatFloat(avg, 'f', -1, 32)
		} else {
			avgStr = "-"
		}
		r.Data = append(r.Data, avgStr)

		var lastIncStr string
		if u.LastIncrement > -1 {
			lastIncStr = strconv.Itoa(u.LastIncrement)
		} else {
			lastIncStr = "-"
		}
		r.Data = append(r.Data, lastIncStr)

		users[r.Data[0]] = u
		(*scoreRows)[i] = r
	}

	// Write deltas
	f, err := os.OpenFile(scoreDeltasPath, os.O_CREATE | os.O_RDWR, 0644)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	for k, v := range users {
		userData := fmt.Sprintf("%d%s%d%s%d%s%d%s%d", v.LastScore, deltaDelimiter, v.LastUpdate, deltaDelimiter, v.LastIncrement, deltaDelimiter, v.Times, deltaDelimiter, v.ScoreOffset)
		_, err = f.WriteString(fmt.Sprintf("%s%s%s\n", k, deltaDelimiter, userData))
		if err != nil {
			fmt.Println(err)
		}
	}

	return scoreRows
}

func buildScoresTable(rows *[]Row, headers []string) *Table {
	table := &Table{Headers: headers, Rows: nil}

	const layout = "Jan 2, 2006 3:04pm MST"
	for i, r := range *rows {
		data := r.Data
		t := parseTimestamp(r.Data[2])
		r.Data[2] = t.UTC().Format(layout)
		row := &Row{Data: data}
		(*rows)[i] = *row
	}
	table.Rows = *rows

	return table
}

func readData(path string, delimiter string) *[]Row {
	f, _ := os.Open(path)

	defer f.Close()

	rows := []Row{}
	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)

	for s.Scan() {
		data := strings.Split(s.Text(), delimiter)
		row := &Row{Data: data}
		rows = append(rows, *row)
	}

	return &rows
}

type Page struct {
	Title string
	Table Table
	Updated string
	UpdatedForHumans string
}

func add(x, y int) int {
	return x + y
}

func generate(title string, table *Table, outputFile string) {
	fmt.Println("Generating page.")

	f, err := os.Create(os.Getenv("HOME") + "/public_html/" + outputFile + ".html")
	if err != nil {
		panic(err)
	}

	defer f.Close()

	funcMap := template.FuncMap {
		"add": add,
	}

	w := bufio.NewWriter(f)
	template, err := template.New("").Funcs(funcMap).ParseFiles("templates/table.html")
	if err != nil {
		panic(err)
	}

	// Extra page data
	curTime := time.Now().UTC()
	updatedReadable := curTime.Format(time.RFC1123)
	updated := curTime.Format(time.RFC3339)

	// Generate the page
	page := &Page{Title: title, Table: *table, UpdatedForHumans: updatedReadable, Updated: updated}
	template.ExecuteTemplate(w, "table", page)
	w.Flush()

	fmt.Println("DONE!")
}
<commit_msg>Trim averages to at most 2 decimal places<commit_after>package main

import (
	"os"
	"os/exec"
	"fmt"
	"time"
	"flag"
	"sort"
	"bufio"
	"strconv"
	"strings"
	"text/template"
)

var (
	scoresPath = "/home/krowbar/Code/irc/tildescores.txt"
	addictionData = "/home/karlen/bin/tilderoyale"
)

const (
	scoreDeltasPath = "/home/bear/scoredeltas.txt"
	deltaDelimiter = "+++"
)

func main() {
	fmt.Println("Starting...")

	// Get any arguments
	outPtr := flag.String("o", "tildescores", "Output file name")
	isTestPtr := flag.Bool("t", false, "Specifies we're developing")
	flag.Parse()

	if *isTestPtr {
		scoresPath = "/home/bear/tildescores.txt"
		addictionData = "/home/bear/addicted.sh"
	}

	headers := []string{ "User", "Tildes", "Last Collected", "# Asks", "Avg.", "Last Amt." }

	scoresData := readData(scoresPath, "&^%")
	updatesData := readData(scoreDeltasPath, deltaDelimiter)

	scoresData = checkScoreDelta(scoresData, updatesData)
	scoresTable := buildScoresTable(scoresData, headers)

	generate("tilde collectors", sortScore(scoresTable), *outPtr)
}

type Table struct {
	Headers []string
	Rows []Row
}

type Row struct {
	Data []string
}

type By func(r1, r2 *Row) bool
func (by By) Sort(rows []Row) {
	rs := &rowSorter {
		rows: rows,
		by: by,
	}
	sort.Sort(rs)
}
type rowSorter struct {
	rows []Row
	by func(r1, r2 *Row) bool
}
func (r *rowSorter) Len() int {
	return len(r.rows)
}
func (r *rowSorter) Swap(i, j int) {
	r.rows[i], r.rows[j] = r.rows[j], r.rows[i]
}
func (r *rowSorter) Less(i, j int) bool {
	return r.by(&r.rows[i], &r.rows[j])
}

func sortScore(table *Table) *Table {
	score := func(r1, r2 *Row) bool {
		s1, _ := strconv.Atoi(r1.Data[1])
		s2, _ := strconv.Atoi(r2.Data[1])
		return s1 < s2
	}
	decScore := func(r1, r2 *Row) bool {
		return !score(r1, r2)
	}
	By(decScore).Sort(table.Rows)

	return table
}

func parseTimestamp(ts string) time.Time {
	t, err := strconv.ParseInt(ts, 10, 64)
	if err != nil {
		panic(err)
	}
	return time.Unix(t, 0)
}

type LastScore struct {
	LastUpdate int
	LastScore int
	LastIncrement int
	Times int
	ScoreOffset int
}

func checkScoreDelta(scoreRows *[]Row, deltaRows *[]Row) *[]Row {
	users := make(map[string]LastScore)

	// Read score delta data
	for i := range *deltaRows {
		r := (*deltaRows)[i]

		if len(r.Data) < 4 {
			break
		}

		score, _ := strconv.Atoi(r.Data[1])
		update, _ := strconv.Atoi(r.Data[2])
		inc, _ := strconv.Atoi(r.Data[3])
		times, _ := strconv.Atoi(r.Data[4])
		so, _ := strconv.Atoi(r.Data[5])

		users[r.Data[0]] = LastScore{ LastScore: score, LastUpdate: update, LastIncrement: inc, Times: times, ScoreOffset: so }
	}

	// Fetch IRC log data
	fmt.Println("Fetching IRC log data")
	cmd := exec.Command(addictionData, "/home/karlen/bin/addictedtotilde -c")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Println(err)
	}
	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	r := bufio.NewReader(stdout)
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		logRow := strings.Split(scanner.Text(), "\t")
		uname := strings.TrimSpace(logRow[0])
		u, exists := users[uname]
		asks, _ := strconv.Atoi(strings.TrimSpace(logRow[3]))
		if !exists {
			u = LastScore{ ScoreOffset: 0 }
		}
		u.ScoreOffset = 0
		u.Times = asks
		users[uname] = u
	}

	for i := range *scoreRows {
		r := (*scoreRows)[i]
		u, exists := users[r.Data[0]]

		score, _ := strconv.Atoi(r.Data[1])
		update, _ := strconv.Atoi(r.Data[2])

		// Fill in any missing users
		if !exists {
			u = LastScore{ LastScore: score, LastIncrement: -1, LastUpdate: update, Times: 0, ScoreOffset: score }
			users[r.Data[0]] = u
		}

		// Match up "last collection" with rest of table data
		if update > u.LastUpdate {
			u.LastIncrement = score - u.LastScore
			u.LastUpdate = update
			u.LastScore = score
			u.Times++
		}

		var asksStr string
		if u.Times > 0 {
			asksStr = strconv.Itoa(u.Times)
		} else {
			asksStr = "-"
		}
		r.Data = append(r.Data, asksStr)

		var avgStr string
		if u.Times > 0 {
			avg := float64(score - u.ScoreOffset) / float64(u.Times)
			avgStr = fmt.Sprintf("%.2f", avg)
			avgStr = strings.TrimRight(avgStr, "0")
			avgStr = strings.TrimRight(avgStr, ".")
		} else {
			avgStr = "-"
		}
		r.Data = append(r.Data, avgStr)

		var lastIncStr string
		if u.LastIncrement > -1 {
			lastIncStr = strconv.Itoa(u.LastIncrement)
		} else {
			lastIncStr = "-"
		}
		r.Data = append(r.Data, lastIncStr)

		users[r.Data[0]] = u
		(*scoreRows)[i] = r
	}

	// Write deltas
	f, err := os.OpenFile(scoreDeltasPath, os.O_CREATE | os.O_RDWR, 0644)
	if err != nil {
		fmt.Println(err)
	}
	defer f.Close()

	for k, v := range users {
		userData := fmt.Sprintf("%d%s%d%s%d%s%d%s%d", v.LastScore, deltaDelimiter, v.LastUpdate, deltaDelimiter, v.LastIncrement, deltaDelimiter, v.Times, deltaDelimiter, v.ScoreOffset)
		_, err = f.WriteString(fmt.Sprintf("%s%s%s\n", k, deltaDelimiter, userData))
		if err != nil {
			fmt.Println(err)
		}
	}

	return scoreRows
}

func buildScoresTable(rows *[]Row, headers []string) *Table {
	table := &Table{Headers: headers, Rows: nil}

	const layout = "Jan 2, 2006 3:04pm MST"
	for i, r := range *rows {
		data := r.Data
		t := parseTimestamp(r.Data[2])
		r.Data[2] = t.UTC().Format(layout)
		row := &Row{Data: data}
		(*rows)[i] = *row
	}
	table.Rows = *rows

	return table
}

func readData(path string, delimiter string) *[]Row {
	f, _ := os.Open(path)

	defer f.Close()

	rows := []Row{}
	s := bufio.NewScanner(f)
	s.Split(bufio.ScanLines)

	for s.Scan() {
		data := strings.Split(s.Text(), delimiter)
		row := &Row{Data: data}
		rows = append(rows, *row)
	}

	return &rows
}

type Page struct {
	Title string
	Table Table
	Updated string
	UpdatedForHumans string
}

func add(x, y int) int {
	return x + y
}

func generate(title string, table *Table, outputFile string) {
	fmt.Println("Generating page.")

	f, err := os.Create(os.Getenv("HOME") + "/public_html/" + outputFile + ".html")
	if err != nil {
		panic(err)
	}

	defer f.Close()

	funcMap := template.FuncMap {
		"add": add,
	}

	w := bufio.NewWriter(f)
	template, err := template.New("").Funcs(funcMap).ParseFiles("templates/table.html")
	if err != nil {
		panic(err)
	}

	// Extra page data
	curTime := time.Now().UTC()
	updatedReadable := curTime.Format(time.RFC1123)
	updated := curTime.Format(time.RFC3339)

	// Generate the page
	page := &Page{Title: title, Table: *table, UpdatedForHumans: updatedReadable, Updated: updated}
	template.ExecuteTemplate(w, "table", page)
	w.Flush()

	fmt.Println("DONE!")
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "techstack"
	app.Version = Version
	app.Usage = ""
	app.Author = "timakin"
	app.Email = "timaki.st@gmail.com"
	app.Commands = Commands

	app.Run(os.Args)
}
<commit_msg>Rename app to ts<commit_after>package main

import (
	"os"

	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "ts"
	app.Version = Version
	app.Usage = ""
	app.Author = "timakin"
	app.Email = "timaki.st@gmail.com"
	app.Commands = Commands

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const (
	ImageRequiredOnlyResource = ImageResourceDependencies + `
resource "oci_core_image" "test_image" {
	#Required
	compartment_id = "${var.compartment_id}"
	instance_id = "${oci_core_instance.test_instance.id}"
	timeouts {
		create = "30m"
	}
}
`

	ImageResourceConfig = ImageResourceDependencies + `
data "oci_objectstorage_namespace" "t" {
}
resource "oci_core_image" "test_image" {
	#Required
	compartment_id = "${var.compartment_id}"

	#Optional
	defined_tags = "${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "${var.image_defined_tags_value}")}"
	display_name = "${var.image_display_name}"
	freeform_tags = "${var.image_freeform_tags}"
	image_source_details {
		#Required
		source_type = "${var.image_image_source_details_source_type}"

		#Optional
		source_image_type = "${var.image_image_source_details_source_image_type}"
		namespace_name = "${data.oci_objectstorage_namespace.t.namespace}"
		bucket_name = "test-artifacts"
		object_name = "test-image-export"
	}
	launch_mode = "${var.image_launch_mode}"
	timeouts {
		create = "30m"
	}
}
`
	ImagePropertyVariables = `
variable "image_defined_tags_value" { default = "value" }
variable "image_display_name" { default = "MyCustomImage" }
variable "image_freeform_tags" { default = {"Department"= "Finance"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

`
	ImageResourceDependencies = DefinedTagsDependencies + InstancePropertyVariables + InstanceResourceAsDependencyConfig
)

func TestCoreImageResource_basic(t *testing.T) {
	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getRequiredEnvSetting("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	resourceName := "oci_core_image.test_image"
	datasourceName := "data.oci_core_images.test_images"

	var resId, resId2 string

	resource.Test(t, resource.TestCase{
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify create
			{
				ImportState:       true,
				ImportStateVerify: true,
				Config:            config + ImagePropertyVariables + compartmentIdVariableStr + ImageRequiredOnlyResource,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "instance_id"),

					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, resourceName, "id")
						return err
					},
				),
			},

			// delete before next create
			{
				Config: config + compartmentIdVariableStr + ImageResourceDependencies,
			},
			// verify create with optionals
			{
				Config: config + ImagePropertyVariables + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "create_image_allowed"),
					resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "display_name", "MyCustomImage"),
					resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(resourceName, "id"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_image_type", "QCOW2"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_type", "objectStorageTuple"),
					resource.TestCheckResourceAttr(resourceName, "launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system_version"),
					resource.TestCheckResourceAttrSet(resourceName, "state"),
					resource.TestCheckResourceAttrSet(resourceName, "time_created"),

					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, resourceName, "id")
						return err
					},
				),
			},

			// verify updates to updatable parameters
			{
				Config: config + `
variable "image_defined_tags_value" { default = "updatedValue" }
variable "image_display_name" { default = "displayName2" }
variable "image_freeform_tags" { default = {"Department"= "Accounting"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

               ` + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "create_image_allowed"),
					resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "display_name", "displayName2"),
					resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(resourceName, "id"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_image_type", "QCOW2"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_type", "objectStorageTuple"),
					resource.TestCheckResourceAttr(resourceName, "launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system_version"),
					resource.TestCheckResourceAttrSet(resourceName, "state"),
					resource.TestCheckResourceAttrSet(resourceName, "time_created"),

					func(s *terraform.State) (err error) {
						resId2, err = fromInstanceState(s, resourceName, "id")
						if resId != resId2 {
							return fmt.Errorf("Resource recreated when it was supposed to be updated.")
						}
						return err
					},
				),
			},
			// verify datasource
			{
				Config: config + `
variable "image_defined_tags_value" { default = "updatedValue" }
variable "image_display_name" { default = "displayName2" }
variable "image_freeform_tags" { default = {"Department"= "Accounting"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

data "oci_core_images" "test_images" {
	#Required
	compartment_id = "${var.compartment_id}"

	#Optional
	display_name = "${var.image_display_name}"
	state = "${var.image_state}"

    filter {
    	name = "id"
    	values = ["${oci_core_image.test_image.id}"]
    }
}
                ` + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(datasourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttr(datasourceName, "display_name", "displayName2"),
					resource.TestCheckResourceAttr(datasourceName, "state", "AVAILABLE"),

					resource.TestCheckResourceAttr(datasourceName, "images.#", "1"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.create_image_allowed"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.defined_tags.%", "1"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.display_name", "displayName2"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.id"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.operating_system"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.operating_system_version"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.state"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.time_created"),
				),
			},
		},
	})
}
<commit_msg>Skip image tests since they are long running<commit_after>// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.

package provider

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

const (
	ImageRequiredOnlyResource = ImageResourceDependencies + `
resource "oci_core_image" "test_image" {
	#Required
	compartment_id = "${var.compartment_id}"
	instance_id = "${oci_core_instance.test_instance.id}"
	timeouts {
		create = "30m"
	}
}
`

	ImageResourceConfig = ImageResourceDependencies + `
data "oci_objectstorage_namespace" "t" {
}
resource "oci_core_image" "test_image" {
	#Required
	compartment_id = "${var.compartment_id}"

	#Optional
	defined_tags = "${map("${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}", "${var.image_defined_tags_value}")}"
	display_name = "${var.image_display_name}"
	freeform_tags = "${var.image_freeform_tags}"
	image_source_details {
		#Required
		source_type = "${var.image_image_source_details_source_type}"

		#Optional
		source_image_type = "${var.image_image_source_details_source_image_type}"
		namespace_name = "${data.oci_objectstorage_namespace.t.namespace}"
		bucket_name = "test-artifacts"
		object_name = "test-image-export"
	}
	launch_mode = "${var.image_launch_mode}"
	timeouts {
		create = "30m"
	}
}
`
	ImagePropertyVariables = `
variable "image_defined_tags_value" { default = "value" }
variable "image_display_name" { default = "MyCustomImage" }
variable "image_freeform_tags" { default = {"Department"= "Finance"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

`
	ImageResourceDependencies = DefinedTagsDependencies + InstancePropertyVariables + InstanceResourceAsDependencyConfig
)

func TestCoreImageResource_basic(t *testing.T) {
	t.Skip("Long running test")
	provider := testAccProvider
	config := testProviderConfig()

	compartmentId := getRequiredEnvSetting("compartment_ocid")
	compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)

	resourceName := "oci_core_image.test_image"
	datasourceName := "data.oci_core_images.test_images"

	var resId, resId2 string

	resource.Test(t, resource.TestCase{
		Providers: map[string]terraform.ResourceProvider{
			"oci": provider,
		},
		Steps: []resource.TestStep{
			// verify create
			{
				ImportState:       true,
				ImportStateVerify: true,
				Config:            config + ImagePropertyVariables + compartmentIdVariableStr + ImageRequiredOnlyResource,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "instance_id"),

					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, resourceName, "id")
						return err
					},
				),
			},

			// delete before next create
			{
				Config: config + compartmentIdVariableStr + ImageResourceDependencies,
			},
			// verify create with optionals
			{
				Config: config + ImagePropertyVariables + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "create_image_allowed"),
					resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "display_name", "MyCustomImage"),
					resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(resourceName, "id"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_image_type", "QCOW2"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_type", "objectStorageTuple"),
					resource.TestCheckResourceAttr(resourceName, "launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system_version"),
					resource.TestCheckResourceAttrSet(resourceName, "state"),
					resource.TestCheckResourceAttrSet(resourceName, "time_created"),

					func(s *terraform.State) (err error) {
						resId, err = fromInstanceState(s, resourceName, "id")
						return err
					},
				),
			},

			// verify updates to updatable parameters
			{
				Config: config + `
variable "image_defined_tags_value" { default = "updatedValue" }
variable "image_display_name" { default = "displayName2" }
variable "image_freeform_tags" { default = {"Department"= "Accounting"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

               ` + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(resourceName, "create_image_allowed"),
					resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "display_name", "displayName2"),
					resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(resourceName, "id"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.#", "1"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_image_type", "QCOW2"),
					resource.TestCheckResourceAttr(resourceName, "image_source_details.0.source_type", "objectStorageTuple"),
					resource.TestCheckResourceAttr(resourceName, "launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system"),
					resource.TestCheckResourceAttrSet(resourceName, "operating_system_version"),
					resource.TestCheckResourceAttrSet(resourceName, "state"),
					resource.TestCheckResourceAttrSet(resourceName, "time_created"),

					func(s *terraform.State) (err error) {
						resId2, err = fromInstanceState(s, resourceName, "id")
						if resId != resId2 {
							return fmt.Errorf("Resource recreated when it was supposed to be updated.")
						}
						return err
					},
				),
			},
			// verify datasource
			{
				Config: config + `
variable "image_defined_tags_value" { default = "updatedValue" }
variable "image_display_name" { default = "displayName2" }
variable "image_freeform_tags" { default = {"Department"= "Accounting"} }
variable "image_image_source_details_source_image_type" { default = "QCOW2" }
variable "image_image_source_details_source_type" { default = "objectStorageTuple" }
variable "image_launch_mode" { default = "NATIVE" }
variable "image_operating_system" { default = "operatingSystem" }
variable "image_operating_system_version" { default = "operatingSystemVersion" }
variable "image_state" { default = "AVAILABLE" }

data "oci_core_images" "test_images" {
	#Required
	compartment_id = "${var.compartment_id}"

	#Optional
	display_name = "${var.image_display_name}"
	state = "${var.image_state}"

    filter {
    	name = "id"
    	values = ["${oci_core_image.test_image.id}"]
    }
}
                ` + compartmentIdVariableStr + ImageResourceConfig,
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr(datasourceName, "compartment_id", compartmentId),
					resource.TestCheckResourceAttr(datasourceName, "display_name", "displayName2"),
					resource.TestCheckResourceAttr(datasourceName, "state", "AVAILABLE"),

					resource.TestCheckResourceAttr(datasourceName, "images.#", "1"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.compartment_id", compartmentId),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.create_image_allowed"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.defined_tags.%", "1"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.display_name", "displayName2"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.freeform_tags.%", "1"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.id"),
					resource.TestCheckResourceAttr(datasourceName, "images.0.launch_mode", "NATIVE"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.operating_system"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.operating_system_version"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.state"),
					resource.TestCheckResourceAttrSet(datasourceName, "images.0.time_created"),
				),
			},
		},
	})
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"strconv"
	"unicode/utf8"

	"github.com/nsf/termbox-go"
)

type UIState struct {
	Desktops []WMDesktop
	Selected int
	Height   int
	Width    int
}

func NewUIState(desks []WMDesktop) UIState {
	st := UIState{
		Desktops: desks,
	}

	for i, desk := range desks {
		if desk.IsCurrent {
			st.Selected = i
		}
		if nw := len(desk.Windows); nw > st.Height {
			st.Height = nw
		}
		for _, win := range desk.Windows {
			if nw := utf8.RuneCountInString(win.Name); nw > st.Width {
				st.Width = nw
			}
		}
	}

	return st
}

func (ui *UIState) Desk() *WMDesktop {
	return &ui.Desktops[ui.Selected]
}

func (ui *UIState) Prev() {
	for cur := ui.Selected - 1; cur > 0; cur-- {
		if ui.Desktops[cur].IsVisible() {
			ui.Selected = cur
			return
		}
	}
}

func (ui *UIState) Next() {
	for cur := ui.Selected + 1; cur < len(ui.Desktops); cur++ {
		if ui.Desktops[cur].IsVisible() {
			ui.Selected = cur
			return
		}
	}
}

var indexDigits = []rune{'⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹', '⁻', '⁼'}

func (ui *UIState) Draw() {
	cols, rows := termbox.Size()
	fgFrame := termbox.ColorWhite | termbox.AttrBold

	if rows < ui.Height+4 {
		panic("Too little rows!")
	}
	if cols < ui.Width+2 {
		panic("Too little cols!")
	}

	// Tab bar
	termbox.SetCell(0, 2, '╭', fgFrame, termbox.ColorDefault)
	col := 1
	for i, desk := range ui.Desktops {
		if !desk.IsVisible() {
			continue
		}

		fg := termbox.ColorDefault
		extra := termbox.Attribute(0)

		if i == ui.Selected {
			fg = termbox.ColorWhite
		}

		if desk.IsUrgent {
			fg = termbox.ColorRed
		}

		if desk.IsCurrent {
			extra = termbox.AttrUnderline
		}

		if i == ui.Selected {
			extra = extra | termbox.AttrBold
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '╭', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, '│', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '╯', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		// TODO: desktop # for keyboard shortcut here
		index := ' '
		if i < len(indexDigits) {
			index = indexDigits[i]
		}
		if i == ui.Selected {
			termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, index, termbox.ColorDefault, termbox.ColorDefault)
			termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, index, termbox.ColorDefault, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		for _, ch := range desk.Name {
			termbox.SetCell(col, 1, ch, fg|extra, termbox.ColorDefault)
			if i == ui.Selected {
				termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
			} else {
				termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
			}
			col++
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		for _, ch := range strconv.Itoa(len(desk.Windows)) {
			termbox.SetCell(col, 1, ch, termbox.ColorDefault, termbox.ColorDefault)
			if i == ui.Selected {
				termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
			} else {
				termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
			}
			col++
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '╮', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, '│', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '╰', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++
	}

	if col > ui.Width {
		ui.Width = col
	}

	for ; col < ui.Width+1; col++ {
		termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
	}
	termbox.SetCell(ui.Width+1, 2, '╮', fgFrame, termbox.ColorDefault)

	// Window List
	desk := ui.Desk()
	for i, win := range desk.Windows {
		fg := termbox.ColorDefault
		extra := termbox.Attribute(0)

		if win.IsUrgent {
			fg = termbox.ColorRed
		}

		if win.IsActive {
			extra = termbox.AttrUnderline
		}

		if i == desk.Selected {
			fg = fg | termbox.AttrReverse
		}

		termbox.SetCell(0, i+3, '│', fgFrame, termbox.ColorDefault)
		col = 1
		for _, ch := range win.Name {
			termbox.SetCell(col, i+3, ch, fg|extra, termbox.ColorDefault)
			col++
		}

		for ; col < ui.Width+1; col++ {
			termbox.SetCell(col, i+3, ' ', fg, termbox.ColorDefault)
		}
		termbox.SetCell(ui.Width+1, i+3, '│', fgFrame, termbox.ColorDefault)
	}

	for i := len(desk.Windows); i < ui.Height; i++ {
		termbox.SetCell(0, i+3, '│', fgFrame, termbox.ColorDefault)
		for j := 1; j < ui.Width+1; j++ {
			termbox.SetCell(j, i+3, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
		termbox.SetCell(ui.Width+1, i+3, '│', fgFrame, termbox.ColorDefault)
	}

	termbox.SetCell(0, ui.Height+3, '╰', fgFrame, termbox.ColorDefault)
	for j := 1; j < ui.Width+1; j++ {
		termbox.SetCell(j, ui.Height+3, '─', termbox.ColorDefault, termbox.ColorDefault)
	}
	termbox.SetCell(ui.Width+1, ui.Height+3, '╯', fgFrame, termbox.ColorDefault)

	termbox.Flush()
}

func (ui *UIState) Main() error {
	if err := termbox.Init(); err != nil {
		return err
	}
	defer termbox.Close()
	termbox.SetInputMode(termbox.InputEsc)

	ui.Draw()
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				return errors.New("Cancelled")
			case termbox.KeyArrowLeft:
				ui.Prev()
			case termbox.KeyArrowRight:
				ui.Next()
			case termbox.KeyArrowUp:
				ui.Desk().Prev()
			case termbox.KeyArrowDown:
				ui.Desk().Next()
			case termbox.KeyTab:
				ui.Desk().NextWrap()
			case termbox.KeyEnter:
				return nil
			}
		case termbox.EventError:
			return ev.Err
		}
		ui.Draw()
	}

	return errors.New("CAN'T HAPPEN")
}
<commit_msg>Start urxvt on a pty<commit_after>package main

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"
	"unicode/utf8"

	"github.com/kr/pty"
	"github.com/mpasternacki/termbox-go"
)

type UIState struct {
	Desktops []WMDesktop
	Selected int
	Height   int
	Width    int
}

func NewUIState(desks []WMDesktop) UIState {
	st := UIState{
		Desktops: desks,
	}

	for i, desk := range desks {
		if desk.IsCurrent {
			st.Selected = i
		}
		if nw := len(desk.Windows); nw > st.Height {
			st.Height = nw
		}
		for _, win := range desk.Windows {
			if nw := utf8.RuneCountInString(win.Name); nw > st.Width {
				st.Width = nw
			}
		}
	}

	return st
}

func (ui *UIState) Desk() *WMDesktop {
	return &ui.Desktops[ui.Selected]
}

func (ui *UIState) Prev() {
	for cur := ui.Selected - 1; cur > 0; cur-- {
		if ui.Desktops[cur].IsVisible() {
			ui.Selected = cur
			return
		}
	}
}

func (ui *UIState) Next() {
	for cur := ui.Selected + 1; cur < len(ui.Desktops); cur++ {
		if ui.Desktops[cur].IsVisible() {
			ui.Selected = cur
			return
		}
	}
}

var indexDigits = []rune{'⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹', '⁻', '⁼'}

func (ui *UIState) Draw() {
	cols, rows := termbox.Size()
	fgFrame := termbox.ColorWhite | termbox.AttrBold

	if rows < ui.Height+4 {
		panic("Too little rows!")
	}
	if cols < ui.Width+2 {
		panic("Too little cols!")
	}

	// Tab bar
	termbox.SetCell(0, 2, '╭', fgFrame, termbox.ColorDefault)
	col := 1
	for i, desk := range ui.Desktops {
		if !desk.IsVisible() {
			continue
		}

		fg := termbox.ColorDefault
		extra := termbox.Attribute(0)

		if i == ui.Selected {
			fg = termbox.ColorWhite
		}

		if desk.IsUrgent {
			fg = termbox.ColorRed
		}

		if desk.IsCurrent {
			extra = termbox.AttrUnderline
		}

		if i == ui.Selected {
			extra = extra | termbox.AttrBold
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '╭', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, '│', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '╯', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		// TODO: desktop # for keyboard shortcut here
		index := ' '
		if i < len(indexDigits) {
			index = indexDigits[i]
		}
		if i == ui.Selected {
			termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, index, termbox.ColorDefault, termbox.ColorDefault)
			termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, index, termbox.ColorDefault, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		for _, ch := range desk.Name {
			termbox.SetCell(col, 1, ch, fg|extra, termbox.ColorDefault)
			if i == ui.Selected {
				termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
			} else {
				termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
			}
			col++
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++

		for _, ch := range strconv.Itoa(len(desk.Windows)) {
			termbox.SetCell(col, 1, ch, termbox.ColorDefault, termbox.ColorDefault)
			if i == ui.Selected {
				termbox.SetCell(col, 0, '─', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, ' ', fgFrame, termbox.ColorDefault)
			} else {
				termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
				termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
			}
			col++
		}

		if i == ui.Selected {
			termbox.SetCell(col, 0, '╮', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, '│', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '╰', fgFrame, termbox.ColorDefault)
		} else {
			termbox.SetCell(col, 0, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 1, ' ', fgFrame, termbox.ColorDefault)
			termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
		}
		col++
	}

	if col > ui.Width {
		ui.Width = col
	}

	for ; col < ui.Width+1; col++ {
		termbox.SetCell(col, 2, '─', fgFrame, termbox.ColorDefault)
	}
	termbox.SetCell(ui.Width+1, 2, '╮', fgFrame, termbox.ColorDefault)

	// Window List
	desk := ui.Desk()
	for i, win := range desk.Windows {
		fg := termbox.ColorDefault
		extra := termbox.Attribute(0)

		if win.IsUrgent {
			fg = termbox.ColorRed
		}

		if win.IsActive {
			extra = termbox.AttrUnderline
		}

		if i == desk.Selected {
			fg = fg | termbox.AttrReverse
		}

		termbox.SetCell(0, i+3, '│', fgFrame, termbox.ColorDefault)
		col = 1
		for _, ch := range win.Name {
			termbox.SetCell(col, i+3, ch, fg|extra, termbox.ColorDefault)
			col++
		}

		for ; col < ui.Width+1; col++ {
			termbox.SetCell(col, i+3, ' ', fg, termbox.ColorDefault)
		}
		termbox.SetCell(ui.Width+1, i+3, '│', fgFrame, termbox.ColorDefault)
	}

	for i := len(desk.Windows); i < ui.Height; i++ {
		termbox.SetCell(0, i+3, '│', fgFrame, termbox.ColorDefault)
		for j := 1; j < ui.Width+1; j++ {
			termbox.SetCell(j, i+3, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
		termbox.SetCell(ui.Width+1, i+3, '│', fgFrame, termbox.ColorDefault)
	}

	termbox.SetCell(0, ui.Height+3, '╰', fgFrame, termbox.ColorDefault)
	for j := 1; j < ui.Width+1; j++ {
		termbox.SetCell(j, ui.Height+3, '─', termbox.ColorDefault, termbox.ColorDefault)
	}
	termbox.SetCell(ui.Width+1, ui.Height+3, '╯', fgFrame, termbox.ColorDefault)

	termbox.Flush()
}

func (ui *UIState) innerMain() error {
	if err := termbox.Init(); err != nil {
		return err
	}
	defer termbox.Close()
	termbox.SetInputMode(termbox.InputEsc)

	ui.Draw()
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				return errors.New("Cancelled")
			case termbox.KeyArrowLeft:
				ui.Prev()
			case termbox.KeyArrowRight:
				ui.Next()
			case termbox.KeyArrowUp:
				ui.Desk().Prev()
			case termbox.KeyArrowDown:
				ui.Desk().Next()
			case termbox.KeyTab:
				ui.Desk().NextWrap()
			case termbox.KeyEnter:
				return nil
			}
		case termbox.EventError:
			return ev.Err
		}
		ui.Draw()
	}

	return errors.New("CAN'T HAPPEN")
}

func (ui *UIState) Main() error {

	master, slave, err := pty.Open()
	if err != nil {
		return err
	}

	cmd := exec.Command("urxvt", "-pty-fd", "3", "-geometry", fmt.Sprintf("%dx%d", ui.Width+2, ui.Height+4))
	defer func() {
		slave.Close()
		if cmd.Process != nil {
			cmd.Wait()
		}
	}()

	cmd.ExtraFiles = []*os.File{master}
	cmd.Start()

	// poll until urxvt is done starting
	for {
		rows, _, err := pty.Getsize(slave)
		if err != nil {
			return err
		}
		if rows > 0 {
			break
		}
		time.Sleep(5 * time.Millisecond)
	}

	termbox.TerminalDevice = slave.Name()

	return ui.innerMain()
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Finds tsuru applications which deploys count % 20 == 0 |||| this is wrong! if count is 30 % 20 will be 10 and the app still needs a flatten!
// and flatten their filesystems in order to avoid aufs performance bottlenecks.
package docker

import (
	"bytes"
	"fmt"
	"github.com/dotcloud/docker"
	dcli "github.com/fsouza/go-dockerclient"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	"io/ioutil"
	"os"
)

func needsFlatten(a provision.App) bool {
	deploys := a.GetDeploys()
	if deploys != 0 && deploys%20 == 0 {
		return true
	}
	return false
}

func flatten(imageID string) error {
	config := docker.Config{
		Image:        imageID,
		Cmd:          []string{"/bin/bash"},
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
	}
	_, c, err := dockerCluster().CreateContainer(&config)
	if err != nil {
		return err
	}
	buf := &bytes.Buffer{}
	if err := dockerCluster().ExportContainer(c.ID, buf); err != nil {
		log.Errorf("Flatten: Caugh error while exporting container %s: %s", c.ID, err)
		return err
	}
	// code to debug import issue
	f, _ := os.Create(fmt.Sprintf("/tmp/container-%s", c.ID))
	f.Write(buf.Bytes())
	f.Close()
	out := &bytes.Buffer{}
	opts := dcli.ImportImageOptions{Repository: imageID, Source: "-"}
	if err := dockerCluster().ImportImage(opts, r, out); err != nil {
		log.Errorf("Flatten: Caugh error while importing image from container %s: %s", c.ID, err)
		return err
	}
	if err := dockerCluster().RemoveContainer(c.ID); err != nil {
		log.Errorf("Flatten: Caugh error while removing container %s: %s", c.ID, err)
	}
	removeFromRegistry(imageID)
	return nil
}

// Flatten finds the images that need to be flattened and export/import
// them in order to flatten them and logs errors when they happen.
func Flatten(a provision.App) {
	if needsFlatten(a) {
		image := getImage(a)
		log.Debugf("Flatten: attempting to flatten image %s.", image)
		if err := flatten(image); err != nil {
			log.Errorf("Flatten: Caugh error while flattening image %s: %s", image, err)
			return
		}
		log.Debugf("Flatten: successfully flattened image %s.", image)
	}
}
<commit_msg>docker: fixed tests.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Finds tsuru applications which deploys count % 20 == 0 |||| this is wrong! if count is 30 % 20 will be 10 and the app still needs a flatten!
// and flatten their filesystems in order to avoid aufs performance bottlenecks.
package docker

import (
	"bytes"
	"fmt"
	"github.com/dotcloud/docker"
	dcli "github.com/fsouza/go-dockerclient"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	"os"
)

func needsFlatten(a provision.App) bool {
	deploys := a.GetDeploys()
	if deploys != 0 && deploys%20 == 0 {
		return true
	}
	return false
}

func flatten(imageID string) error {
	config := docker.Config{
		Image:        imageID,
		Cmd:          []string{"/bin/bash"},
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
	}
	_, c, err := dockerCluster().CreateContainer(&config)
	if err != nil {
		return err
	}
	buf := &bytes.Buffer{}
	if err := dockerCluster().ExportContainer(c.ID, buf); err != nil {
		log.Errorf("Flatten: Caugh error while exporting container %s: %s", c.ID, err)
		return err
	}
	// code to debug import issue
	f, _ := os.Create(fmt.Sprintf("/tmp/container-%s", c.ID))
	f.Write(buf.Bytes())
	f.Close()
	out := &bytes.Buffer{}
	opts := dcli.ImportImageOptions{Repository: imageID, Source: "-"}
	if err := dockerCluster().ImportImage(opts, buf, out); err != nil {
		log.Errorf("Flatten: Caugh error while importing image from container %s: %s", c.ID, err)
		return err
	}
	if err := dockerCluster().RemoveContainer(c.ID); err != nil {
		log.Errorf("Flatten: Caugh error while removing container %s: %s", c.ID, err)
	}
	removeFromRegistry(imageID)
	return nil
}

// Flatten finds the images that need to be flattened and export/import
// them in order to flatten them and logs errors when they happen.
func Flatten(a provision.App) {
	if needsFlatten(a) {
		image := getImage(a)
		log.Debugf("Flatten: attempting to flatten image %s.", image)
		if err := flatten(image); err != nil {
			log.Errorf("Flatten: Caugh error while flattening image %s: %s", image, err)
			return
		}
		log.Debugf("Flatten: successfully flattened image %s.", image)
	}
}
<|endoftext|>


<commit_before>// R.I.P Shadowsocks
package shadowsocks

import (
	"sync"

	"errors"
	"v2ray.com/core/app"
	"v2ray.com/core/app/dispatcher"
	"v2ray.com/core/common"
	"v2ray.com/core/common/alloc"
	v2io "v2ray.com/core/common/io"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/proxy"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/udp"
)

type Server struct {
	packetDispatcher dispatcher.PacketDispatcher
	config           *ServerConfig
	user             *protocol.User
	account          *ShadowsocksAccount
	meta             *proxy.InboundHandlerMeta
	accepting        bool
	tcpHub           *internet.TCPHub
	udpHub           *udp.UDPHub
	udpServer        *udp.UDPServer
}

func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) (*Server, error) {
	if config.GetUser() == nil {
		return nil, protocol.ErrUserMissing
	}

	rawAccount, err := config.User.GetTypedAccount()
	if err != nil {
		return nil, errors.New("Shadowsocks|Server: Failed to get user account: " + err.Error())
	}
	account := rawAccount.(*ShadowsocksAccount)

	s := &Server{
		config:  config,
		meta:    meta,
		user:    config.GetUser(),
		account: account,
	}

	space.InitializeApplication(func() error {
		if !space.HasApp(dispatcher.APP_ID) {
			return app.ErrMissingApplication
		}
		s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
		return nil
	})

	return s, nil
}

func (this *Server) Port() v2net.Port {
	return this.meta.Port
}

func (this *Server) Close() {
	this.accepting = false
	// TODO: synchronization
	if this.tcpHub != nil {
		this.tcpHub.Close()
		this.tcpHub = nil
	}

	if this.udpHub != nil {
		this.udpHub.Close()
		this.udpHub = nil
	}
}

func (this *Server) Start() error {
	if this.accepting {
		return nil
	}

	tcpHub, err := internet.ListenTCP(this.meta.Address, this.meta.Port, this.handleConnection, this.meta.StreamSettings)
	if err != nil {
		log.Error("Shadowsocks: Failed to listen TCP on ", this.meta.Address, ":", this.meta.Port, ": ", err)
		return err
	}
	this.tcpHub = tcpHub

	if this.config.UdpEnabled {
		this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher)
		udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, udp.ListenOption{Callback: this.handlerUDPPayload})
		if err != nil {
			log.Error("Shadowsocks: Failed to listen UDP on ", this.meta.Address, ":", this.meta.Port, ": ", err)
			return err
		}
		this.udpHub = udpHub
	}

	this.accepting = true

	return nil
}

func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.SessionInfo) {
	source := session.Source
	request, data, err := DecodeUDPPacket(this.user, payload)
	if err != nil {
		log.Info("Shadowsocks|Server: Skipping invalid UDP packet from: ", source, ": ", err)
		log.Access(source, "", log.AccessRejected, err)
		payload.Release()
		return
	}

	if request.Option.Has(RequestOptionOneTimeAuth) && this.account.OneTimeAuth == Account_Disabled {
		log.Info("Shadowsocks|Server: Client payload enables OTA but server doesn't allow it.")
		payload.Release()
		return
	}

	if !request.Option.Has(RequestOptionOneTimeAuth) && this.account.OneTimeAuth == Account_Enabled {
		log.Info("Shadowsocks|Server: Client payload disables OTA but server forces it.")
		payload.Release()
		return
	}

	dest := request.Destination()
	log.Access(source, dest, log.AccessAccepted, "")
	log.Info("Shadowsocks|Server: Tunnelling request to ", dest)

	this.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: dest}, data, func(destination v2net.Destination, payload *alloc.Buffer) {
		defer payload.Release()

		data, err := EncodeUDPPacket(request, payload)
		if err != nil {
			log.Warning("Shadowsocks|Server: Failed to encode UDP packet: ", err)
			return
		}
		defer data.Release()

		this.udpHub.WriteTo(data.Value, source)
	})
}

func (this *Server) handleConnection(conn internet.Connection) {
	defer conn.Close()

	timedReader := v2net.NewTimeOutReader(16, conn)
	defer timedReader.Release()

	bufferedReader := v2io.NewBufferedReader(timedReader)
	defer bufferedReader.Release()

	request, bodyReader, err := ReadTCPSession(this.user, bufferedReader)
	if err != nil {
		log.Access(conn.RemoteAddr(), "", log.AccessRejected, err)
		log.Info("Shadowsocks|Server: Failed to create request from: ", conn.RemoteAddr(), ": ", err)
		return
	}
	defer bodyReader.Release()

	bufferedReader.SetCached(false)

	userSettings := this.user.GetSettings()
	timedReader.SetTimeOut(userSettings.PayloadReadTimeout)

	dest := request.Destination()
	log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "")
	log.Info("Shadowsocks|Server: Tunnelling request to ", dest)

	ray := this.packetDispatcher.DispatchToOutbound(this.meta, &proxy.SessionInfo{
		Source:      v2net.DestinationFromAddr(conn.RemoteAddr()),
		Destination: dest,
	})
	defer ray.InboundOutput().Release()

	var writeFinish sync.Mutex
	writeFinish.Lock()
	go func() {
		defer writeFinish.Unlock()

		bufferedWriter := v2io.NewBufferedWriter(conn)
		defer bufferedWriter.Release()

		responseWriter, err := WriteTCPResponse(request, bufferedWriter)
		if err != nil {
			log.Warning("Shadowsocks|Server: Failed to write response: ", err)
			return
		}
		defer responseWriter.Release()

		if payload, err := ray.InboundOutput().Read(); err == nil {
			responseWriter.Write(payload)
			bufferedWriter.SetCached(false)

			v2io.Pipe(ray.InboundOutput(), responseWriter)
		}
	}()

	v2io.Pipe(bodyReader, ray.InboundInput())
	ray.InboundInput().Close()

	writeFinish.Lock()
}

type ServerFactory struct{}

func (this *ServerFactory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_RawTCP},
	}
}

func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
	if !space.HasApp(dispatcher.APP_ID) {
		return nil, common.ErrBadConfiguration
	}
	return NewServer(rawConfig.(*ServerConfig), space, meta)
}
<commit_msg>refine shadowsocks user<commit_after>// R.I.P Shadowsocks
package shadowsocks

import (
	"sync"

	"errors"
	"v2ray.com/core/app"
	"v2ray.com/core/app/dispatcher"
	"v2ray.com/core/common"
	"v2ray.com/core/common/alloc"
	v2io "v2ray.com/core/common/io"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/proxy"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/internet/udp"
)

type Server struct {
	packetDispatcher dispatcher.PacketDispatcher
	config           *ServerConfig
	user             *protocol.User
	account          *ShadowsocksAccount
	meta             *proxy.InboundHandlerMeta
	accepting        bool
	tcpHub           *internet.TCPHub
	udpHub           *udp.UDPHub
	udpServer        *udp.UDPServer
}

func NewServer(config *ServerConfig, space app.Space, meta *proxy.InboundHandlerMeta) (*Server, error) {
	if config.GetUser() == nil {
		return nil, protocol.ErrUserMissing
	}

	rawAccount, err := config.User.GetTypedAccount()
	if err != nil {
		return nil, errors.New("Shadowsocks|Server: Failed to get user account: " + err.Error())
	}
	account := rawAccount.(*ShadowsocksAccount)

	s := &Server{
		config:  config,
		meta:    meta,
		user:    config.GetUser(),
		account: account,
	}

	space.InitializeApplication(func() error {
		if !space.HasApp(dispatcher.APP_ID) {
			return app.ErrMissingApplication
		}
		s.packetDispatcher = space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
		return nil
	})

	return s, nil
}

func (this *Server) Port() v2net.Port {
	return this.meta.Port
}

func (this *Server) Close() {
	this.accepting = false
	// TODO: synchronization
	if this.tcpHub != nil {
		this.tcpHub.Close()
		this.tcpHub = nil
	}

	if this.udpHub != nil {
		this.udpHub.Close()
		this.udpHub = nil
	}
}

func (this *Server) Start() error {
	if this.accepting {
		return nil
	}

	tcpHub, err := internet.ListenTCP(this.meta.Address, this.meta.Port, this.handleConnection, this.meta.StreamSettings)
	if err != nil {
		log.Error("Shadowsocks: Failed to listen TCP on ", this.meta.Address, ":", this.meta.Port, ": ", err)
		return err
	}
	this.tcpHub = tcpHub

	if this.config.UdpEnabled {
		this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher)
		udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, udp.ListenOption{Callback: this.handlerUDPPayload})
		if err != nil {
			log.Error("Shadowsocks: Failed to listen UDP on ", this.meta.Address, ":", this.meta.Port, ": ", err)
			return err
		}
		this.udpHub = udpHub
	}

	this.accepting = true

	return nil
}

func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.SessionInfo) {
	source := session.Source
	request, data, err := DecodeUDPPacket(this.user, payload)
	if err != nil {
		log.Info("Shadowsocks|Server: Skipping invalid UDP packet from: ", source, ": ", err)
		log.Access(source, "", log.AccessRejected, err)
		payload.Release()
		return
	}

	if request.Option.Has(RequestOptionOneTimeAuth) && this.account.OneTimeAuth == Account_Disabled {
		log.Info("Shadowsocks|Server: Client payload enables OTA but server doesn't allow it.")
		payload.Release()
		return
	}

	if !request.Option.Has(RequestOptionOneTimeAuth) && this.account.OneTimeAuth == Account_Enabled {
		log.Info("Shadowsocks|Server: Client payload disables OTA but server forces it.")
		payload.Release()
		return
	}

	dest := request.Destination()
	log.Access(source, dest, log.AccessAccepted, "")
	log.Info("Shadowsocks|Server: Tunnelling request to ", dest)

	this.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: dest, User: request.User}, data, func(destination v2net.Destination, payload *alloc.Buffer) {
		defer payload.Release()

		data, err := EncodeUDPPacket(request, payload)
		if err != nil {
			log.Warning("Shadowsocks|Server: Failed to encode UDP packet: ", err)
			return
		}
		defer data.Release()

		this.udpHub.WriteTo(data.Value, source)
	})
}

func (this *Server) handleConnection(conn internet.Connection) {
	defer conn.Close()

	timedReader := v2net.NewTimeOutReader(16, conn)
	defer timedReader.Release()

	bufferedReader := v2io.NewBufferedReader(timedReader)
	defer bufferedReader.Release()

	request, bodyReader, err := ReadTCPSession(this.user, bufferedReader)
	if err != nil {
		log.Access(conn.RemoteAddr(), "", log.AccessRejected, err)
		log.Info("Shadowsocks|Server: Failed to create request from: ", conn.RemoteAddr(), ": ", err)
		return
	}
	defer bodyReader.Release()

	bufferedReader.SetCached(false)

	userSettings := this.user.GetSettings()
	timedReader.SetTimeOut(userSettings.PayloadReadTimeout)

	dest := request.Destination()
	log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "")
	log.Info("Shadowsocks|Server: Tunnelling request to ", dest)

	ray := this.packetDispatcher.DispatchToOutbound(this.meta, &proxy.SessionInfo{
		Source:      v2net.DestinationFromAddr(conn.RemoteAddr()),
		Destination: dest,
		User:        request.User,
	})
	defer ray.InboundOutput().Release()

	var writeFinish sync.Mutex
	writeFinish.Lock()
	go func() {
		defer writeFinish.Unlock()

		bufferedWriter := v2io.NewBufferedWriter(conn)
		defer bufferedWriter.Release()

		responseWriter, err := WriteTCPResponse(request, bufferedWriter)
		if err != nil {
			log.Warning("Shadowsocks|Server: Failed to write response: ", err)
			return
		}
		defer responseWriter.Release()

		if payload, err := ray.InboundOutput().Read(); err == nil {
			responseWriter.Write(payload)
			bufferedWriter.SetCached(false)

			v2io.Pipe(ray.InboundOutput(), responseWriter)
		}
	}()

	v2io.Pipe(bodyReader, ray.InboundInput())
	ray.InboundInput().Close()

	writeFinish.Lock()
}

type ServerFactory struct{}

func (this *ServerFactory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_RawTCP},
	}
}

func (this *ServerFactory) Create(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
	if !space.HasApp(dispatcher.APP_ID) {
		return nil, common.ErrBadConfiguration
	}
	return NewServer(rawConfig.(*ServerConfig), space, meta)
}
<|endoftext|>


<commit_before>package aead

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"io"
	"time"
	"v2ray.com/core/common"
)

func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
	generatedAuthID := CreateAuthID(key[:], time.Now().Unix())

	connectionNonce := make([]byte, 8)
	if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil {
		panic(err.Error())
	}

	aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil)

	var headerPayloadDataLen uint16
	headerPayloadDataLen = uint16(len(data))

	common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))

	authidCheckValue := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(generatedAuthID[:]), string(aeadPayloadLengthSerializeBuffer.Bytes()), string(connectionNonce))

	aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()

	aeadPayloadLengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(generatedAuthID[:]), string(connectionNonce[:]))[:2]

	aeadPayloadLengthSerializedByte[0] = aeadPayloadLengthSerializedByte[0] ^ aeadPayloadLengthMask[0]
	aeadPayloadLengthSerializedByte[1] = aeadPayloadLengthSerializedByte[1] ^ aeadPayloadLengthMask[1]

	payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))

	payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]

	payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)

	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEADEncrypted := payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])

	var outputBuffer = bytes.NewBuffer(nil)

	common.Must2(outputBuffer.Write(generatedAuthID[:])) //16

	common.Must2(outputBuffer.Write(authidCheckValue)) //16

	common.Must2(outputBuffer.Write(aeadPayloadLengthSerializedByte)) //2

	common.Must2(outputBuffer.Write(connectionNonce)) //8

	common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))

	return outputBuffer.Bytes()
}

func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) {
	var authidCheckValue [16]byte
	var headerPayloadDataLen [2]byte
	var nonce [8]byte

	authidCheckValueReadBytesCounts, err := io.ReadFull(data, authidCheckValue[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts
	}

	headerPayloadDataLenReadBytesCounts, err := io.ReadFull(data, headerPayloadDataLen[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts
	}

	nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
	}

	//Unmask Length

	LengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(authid[:]), string(nonce[:]))[:2]

	headerPayloadDataLen[0] = headerPayloadDataLen[0] ^ LengthMask[0]
	headerPayloadDataLen[1] = headerPayloadDataLen[1] ^ LengthMask[1]

	authidCheckValueReceivedFromNetwork := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(authid[:]), string(headerPayloadDataLen[:]), string(nonce[:]))

	if !hmac.Equal(authidCheckValueReceivedFromNetwork, authidCheckValue[:]) {
		return nil, true, errCheckMismatch, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
	}

	var length uint16

	common.Must(binary.Read(bytes.NewReader(headerPayloadDataLen[:]), binary.BigEndian, &length))

	payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))

	payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]

	//16 == AEAD Tag size
	payloadHeaderAEADEncrypted := make([]byte, length+16)

	payloadHeaderAEADEncryptedReadedBytesCounts, err := io.ReadFull(data, payloadHeaderAEADEncrypted)
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
	}

	payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)

	if err != nil {
		panic(err.Error())
	}

	out, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])

	if erropenAEAD != nil {
		return nil, true, erropenAEAD, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
	}

	return out, false, nil, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
}

var errCheckMismatch = errors.New("check verify failed")
<commit_msg>Apply Coding Style<commit_after>package aead

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"io"
	"time"
	"v2ray.com/core/common"
)

func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
	generatedAuthID := CreateAuthID(key[:], time.Now().Unix())

	connectionNonce := make([]byte, 8)
	if _, err := io.ReadFull(rand.Reader, connectionNonce); err != nil {
		panic(err.Error())
	}

	aeadPayloadLengthSerializeBuffer := bytes.NewBuffer(nil)

	var headerPayloadDataLen uint16
	headerPayloadDataLen = uint16(len(data))

	common.Must(binary.Write(aeadPayloadLengthSerializeBuffer, binary.BigEndian, headerPayloadDataLen))

	authidCheckValue := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(generatedAuthID[:]), string(aeadPayloadLengthSerializeBuffer.Bytes()), string(connectionNonce))

	aeadPayloadLengthSerializedByte := aeadPayloadLengthSerializeBuffer.Bytes()

	aeadPayloadLengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(generatedAuthID[:]), string(connectionNonce[:]))[:2]

	aeadPayloadLengthSerializedByte[0] = aeadPayloadLengthSerializedByte[0] ^ aeadPayloadLengthMask[0]
	aeadPayloadLengthSerializedByte[1] = aeadPayloadLengthSerializedByte[1] ^ aeadPayloadLengthMask[1]

	payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))

	payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]

	payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)

	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEADEncrypted := payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])

	var outputBuffer = bytes.NewBuffer(nil)

	common.Must2(outputBuffer.Write(generatedAuthID[:])) //16

	common.Must2(outputBuffer.Write(authidCheckValue)) //16

	common.Must2(outputBuffer.Write(aeadPayloadLengthSerializedByte)) //2

	common.Must2(outputBuffer.Write(connectionNonce)) //8

	common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))

	return outputBuffer.Bytes()
}

func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) {
	var authidCheckValue [16]byte
	var headerPayloadDataLen [2]byte
	var nonce [8]byte

	authidCheckValueReadBytesCounts, err := io.ReadFull(data, authidCheckValue[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts
	}

	headerPayloadDataLenReadBytesCounts, err := io.ReadFull(data, headerPayloadDataLen[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts
	}

	nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
	}

	//Unmask Length

	LengthMask := KDF16(key[:], KDFSaltConst_VMessLengthMask, string(authid[:]), string(nonce[:]))[:2]

	headerPayloadDataLen[0] = headerPayloadDataLen[0] ^ LengthMask[0]
	headerPayloadDataLen[1] = headerPayloadDataLen[1] ^ LengthMask[1]

	authidCheckValueReceivedFromNetwork := KDF16(key[:], KDFSaltConst_VmessAuthIDCheckValue, string(authid[:]), string(headerPayloadDataLen[:]), string(nonce[:]))

	if !hmac.Equal(authidCheckValueReceivedFromNetwork, authidCheckValue[:]) {
		return nil, true, errCheckMismatch, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + nonceReadBytesCounts
	}

	var length uint16

	common.Must(binary.Read(bytes.NewReader(headerPayloadDataLen[:]), binary.BigEndian, &length))

	payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))

	payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]

	//16 == AEAD Tag size
	payloadHeaderAEADEncrypted := make([]byte, length+16)

	payloadHeaderAEADEncryptedReadedBytesCounts, err := io.ReadFull(data, payloadHeaderAEADEncrypted)
	if err != nil {
		return nil, false, err, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
	}

	payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
	if err != nil {
		panic(err.Error())
	}

	payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)

	if err != nil {
		panic(err.Error())
	}

	decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])

	if erropenAEAD != nil {
		return nil, true, erropenAEAD, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
	}

	return decryptedAEADHeaderPayload, false, nil, authidCheckValueReadBytesCounts + headerPayloadDataLenReadBytesCounts + payloadHeaderAEADEncryptedReadedBytesCounts + nonceReadBytesCounts
}

var errCheckMismatch = errors.New("check verify failed")
<|endoftext|>


<commit_before>package cron

var (
	// systemJobs 系统Job
	systemJobs = map[string]Jobx{}
)

func Register(name string, fn RunnerGetter, example string, description string) {
	AddSystemJob(name, fn, example, description)
}

// AddSystemJob 添加系统Job
func AddSystemJob(name string, fn RunnerGetter, example string, description string) {
	systemJobs[name] = Jobx{
		Example:      example,
		Description:  description,
		RunnerGetter: fn,
	}
}

type Jobx struct {
	Example      string //">funcName:param"
	Description  string
	RunnerGetter RunnerGetter
}
<commit_msg>update<commit_after>package cron

var (
	// systemJobs 系统Job
	systemJobs = map[string]Jobx{}
)

func Register(name string, fn RunnerGetter, example string, description string) {
	AddSystemJob(name, fn, example, description)
}

// AddSystemJob 添加系统Job
func AddSystemJob(name string, fn RunnerGetter, example string, description string) {
	systemJobs[name] = Jobx{
		Name:         name,
		Example:      example,
		Description:  description,
		RunnerGetter: fn,
	}
}

type Jobx struct {
	Name         string
	Example      string //">funcName:param"
	Description  string
	RunnerGetter RunnerGetter
}

func (j *Jobx) Register() {
	systemJobs[j.Name] = *j
}
<|endoftext|>