<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"time"
)

// Conn is a connection to a client/server
type Conn struct {
	// conn: The connection if we are actively connected.
	conn net.Conn

	// rw: Read/write handle to the connection
	rw *bufio.ReadWriter

	ioWait time.Duration

	IP net.IP
}

// NewConn initializes a Conn struct
func NewConn(conn net.Conn, ioWait time.Duration) Conn {
	tcpAddr, err := net.ResolveTCPAddr("tcp", conn.RemoteAddr().String())
	// This shouldn't happen.
	if err != nil {
		log.Fatalf("Unable to resolve TCP address: %s", err)
	}

	return Conn{
		conn:   conn,
		rw:     bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)),
		ioWait: ioWait,
		IP:     tcpAddr.IP,
	}
}

// Close closes the underlying connection
func (c Conn) Close() error {
	return c.conn.Close()
}

// RemoteAddr returns the remote network address.
func (c Conn) RemoteAddr() net.Addr {
	return c.conn.RemoteAddr()
}

// Read reads a line from the connection.
func (c Conn) Read() (string, error) {
	// Deadline so we will eventually give up.
	if err := c.conn.SetDeadline(time.Now().Add(c.ioWait)); err != nil {
		return "", fmt.Errorf("unable to set deadline: %s", err)
	}

	line, err := c.rw.ReadString('\n')
	if err != nil {
		return "", err
	}

	return line, nil
}

// Write writes a string to the connection
func (c Conn) Write(s string) error {
	// Deadline so we will eventually give up.
	if err := c.conn.SetDeadline(time.Now().Add(c.ioWait)); err != nil {
		return fmt.Errorf("unable to set deadline: %s", err)
	}

	sz, err := c.rw.WriteString(s)
	if err != nil {
		return err
	}

	if sz != len(s) {
		return fmt.Errorf("short write")
	}

	if err := c.rw.Flush(); err != nil {
		return fmt.Errorf("flush error: %s", err)
	}

	return nil
}
<commit_msg>Use separate read/write deadlines<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"time"
)

// Conn is a connection to a client/server
type Conn struct {
	conn   net.Conn
	rw     *bufio.ReadWriter
	ioWait time.Duration
	IP     net.IP
}

// NewConn initializes a Conn struct
func NewConn(conn net.Conn, ioWait time.Duration) Conn {
	tcpAddr, err := net.ResolveTCPAddr("tcp", conn.RemoteAddr().String())
	// This shouldn't happen.
	if err != nil {
		log.Fatalf("Unable to resolve TCP address: %s", err)
	}

	return Conn{
		conn:   conn,
		rw:     bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)),
		ioWait: ioWait,
		IP:     tcpAddr.IP,
	}
}

// Close closes the underlying connection
func (c Conn) Close() error {
	return c.conn.Close()
}

// RemoteAddr returns the remote network address.
func (c Conn) RemoteAddr() net.Addr {
	return c.conn.RemoteAddr()
}

// Read reads a line from the connection.
func (c Conn) Read() (string, error) {
	if err := c.conn.SetReadDeadline(time.Now().Add(c.ioWait)); err != nil {
		return "", fmt.Errorf("unable to set deadline: %s", err)
	}

	line, err := c.rw.ReadString('\n')
	if err != nil {
		return "", err
	}

	return line, nil
}

// Write writes a string to the connection
func (c Conn) Write(s string) error {
	if err := c.conn.SetWriteDeadline(time.Now().Add(c.ioWait)); err != nil {
		return fmt.Errorf("unable to set deadline: %s", err)
	}

	sz, err := c.rw.WriteString(s)
	if err != nil {
		return err
	}

	if sz != len(s) {
		return fmt.Errorf("short write")
	}

	if err := c.rw.Flush(); err != nil {
		return fmt.Errorf("flush error: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package critbitgo

import (
	"net"
)

var (
	mask32  = net.IPMask{0xff, 0xff, 0xff, 0xff}
	mask128 = net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

// IP routing table.
type Net struct {
	trie *Trie
}

// Add a route.
// If `r` is not IPv4/IPv6 network, returns an error.
func (n *Net) Add(r *net.IPNet, value interface{}) (err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		n.trie.Set(netIPNetToKey(ip, r.Mask), value)
	}
	return
}

// Add a route.
// If `s` is not CIDR notation, returns an error.
func (n *Net) AddCIDR(s string, value interface{}) (err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		n.Add(r, value)
	}
	return
}

// Delete a specific route.
// If `r` is not IP4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Delete(r *net.IPNet) (value interface{}, ok bool, err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		value, ok = n.trie.Delete(netIPNetToKey(ip, r.Mask))
	}
	return
}

// Delete a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) DeleteCIDR(s string) (value interface{}, ok bool, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		value, ok, err = n.Delete(r)
	}
	return
}

// Get a specific route.
// If `r` is not IPv4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Get(r *net.IPNet) (value interface{}, ok bool, err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		value, ok = n.trie.Get(netIPNetToKey(ip, r.Mask))
	}
	return
}

// Get a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) GetCIDR(s string) (value interface{}, ok bool, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		value, ok, err = n.Get(r)
	}
	return
}

// Return a specific route by using the longest prefix matching.
// If `r` is not IPv4/IPv6 network or a route is not found, `route` is nil.
func (n *Net) Match(r *net.IPNet) (route *net.IPNet, value interface{}, err error) {
	var ip net.IP
	if ip, _, err = netValidateIP(r.IP); err == nil {
		if k, v := n.match(netIPNetToKey(ip, r.Mask)); k != nil {
			route = netKeyToIPNet(k)
			value = v
		}
	}
	return
}

// Return a specific route by using the longest prefix matching.
// If `s` is not CIDR notation, or a route is not found, `route` is nil.
func (n *Net) MatchCIDR(s string) (route *net.IPNet, value interface{}, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		route, value, err = n.Match(r)
	}
	return
}

// Return a bool indicating whether a route would be found
func (n *Net) ContainedIP(ip net.IP) (contained bool, err error) {
	k, _, err := n.matchIP(ip)
	contained = k != nil
	return
}

// Return a specific route by using the longest prefix matching.
// If `ip` is invalid IP, or a route is not found, `route` is nil.
func (n *Net) MatchIP(ip net.IP) (route *net.IPNet, value interface{}, err error) {
	k, v, err := n.matchIP(ip)
	if k != nil {
		route = netKeyToIPNet(k)
		value = v
	}
	return
}

func (n *Net) matchIP(ip net.IP) (k []byte, v interface{}, err error) {
	var isV4 bool
	ip, isV4, err = netValidateIP(ip)
	if err != nil {
		return
	}
	var mask net.IPMask
	if isV4 {
		mask = mask32
	} else {
		mask = mask128
	}
	k, v = n.match(netIPNetToKey(ip, mask))
	return
}

func (n *Net) match(key []byte) ([]byte, interface{}) {
	if n.trie.size > 0 {
		if node := lookup(&n.trie.root, key, false); node != nil {
			return node.external.key, node.external.value
		}
	}
	return nil, nil
}

func lookup(p *node, key []byte, backtracking bool) *node {
	if p.internal != nil {
		var direction int
		if p.internal.offset == len(key)-1 {
			// selecting the larger side when comparing the mask
			direction = 1
		} else if backtracking {
			direction = 0
		} else {
			direction = p.internal.direction(key)
		}

		if c := lookup(&p.internal.child[direction], key, backtracking); c != nil {
			return c
		}
		if direction == 1 {
			// search other node
			return lookup(&p.internal.child[0], key, true)
		}
		return nil
	} else {
		nlen := len(p.external.key)
		if nlen != len(key) {
			return nil
		}

		// check mask
		mask := p.external.key[nlen-1]
		if mask > key[nlen-1] {
			return nil
		}

		// compare both keys with mask
		div := int(mask >> 3)
		for i := 0; i < div; i++ {
			if p.external.key[i] != key[i] {
				return nil
			}
		}
		if mod := uint(mask & 0x07); mod > 0 {
			bit := 8 - mod
			if p.external.key[div] != key[div]&(0xff>>bit<<bit) {
				return nil
			}
		}
		return p
	}
}

// Walk iterates routes from a given route.
// handle is called with arguments route and value (if handle returns `false`, the iteration is aborted)
func (n *Net) Walk(r *net.IPNet, handle func(*net.IPNet, interface{}) bool) {
	var key []byte
	if r != nil {
		if ip, _, err := netValidateIPNet(r); err == nil {
			key = netIPNetToKey(ip, r.Mask)
		}
	}
	n.trie.Walk(key, func(key []byte, value interface{}) bool {
		return handle(netKeyToIPNet(key), value)
	})
}

func walkMatch(p *node, key []byte, handle func(*net.IPNet, interface{}) bool) bool {
	if p.internal != nil {
		if !walkMatch(&p.internal.child[0], key, handle) {
			return false
		}

		if key[p.internal.offset]&p.internal.bit > 0 {
			return walkMatch(&p.internal.child[1], key, handle)
		}
		return true
	}

	mask := p.external.key[len(p.external.key)-1]
	if key[len(key)-1] < mask {
		return true
	}

	div := int(mask >> 3)
	for i := 0; i < div; i++ {
		if p.external.key[i] != key[i] {
			return true
		}
	}

	if mod := uint(mask & 0x07); mod > 0 {
		bit := 8 - mod
		if p.external.key[div] != key[div]&(0xff>>bit<<bit) {
			return true
		}
	}
	return handle(netKeyToIPNet(p.external.key), p.external.value)
}

// WalkMatch interates routes that match a given route.
// handle is called with arguments route and value (if handle returns `false`, the iteration is aborted)
func (n *Net) WalkMatch(r *net.IPNet, handle func(*net.IPNet, interface{}) bool) {
	if n.trie.size > 0 {
		walkMatch(&n.trie.root, netIPNetToKey(r.IP, r.Mask), handle)
	}
}

// Deletes all routes.
func (n *Net) Clear() {
	n.trie.Clear()
}

// Returns number of routes.
func (n *Net) Size() int {
	return n.trie.Size()
}

// Create IP routing table
func NewNet() *Net {
	return &Net{NewTrie()}
}

func netValidateIP(ip net.IP) (nIP net.IP, isV4 bool, err error) {
	if v4 := ip.To4(); v4 != nil {
		nIP = v4
		isV4 = true
	} else if ip.To16() != nil {
		nIP = ip
	} else {
		err = &net.AddrError{Err: "Invalid IP address", Addr: ip.String()}
	}
	return
}

func netValidateIPNet(r *net.IPNet) (nIP net.IP, isV4 bool, err error) {
	if r == nil {
		err = &net.AddrError{Err: "IP network is nil"}
		return
	}
	return netValidateIP(r.IP)
}

func netIPNetToKey(ip net.IP, mask net.IPMask) []byte {
	// +--------------+------+
	// | ip address.. | mask |
	// +--------------+------+
	ones, _ := mask.Size()
	return append(ip, byte(ones))
}

func netKeyToIPNet(k []byte) *net.IPNet {
	iplen := len(k) - 1
	return &net.IPNet{
		IP:   net.IP(k[:iplen]),
		Mask: net.CIDRMask(int(k[iplen]), iplen*8),
	}
}
<commit_msg>fix net.WalkMatch API to walk to the right regardless of mask bits<commit_after>package critbitgo

import (
	"net"
)

var (
	mask32  = net.IPMask{0xff, 0xff, 0xff, 0xff}
	mask128 = net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

// IP routing table.
type Net struct {
	trie *Trie
}

// Add a route.
// If `r` is not IPv4/IPv6 network, returns an error.
func (n *Net) Add(r *net.IPNet, value interface{}) (err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		n.trie.Set(netIPNetToKey(ip, r.Mask), value)
	}
	return
}

// Add a route.
// If `s` is not CIDR notation, returns an error.
func (n *Net) AddCIDR(s string, value interface{}) (err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		n.Add(r, value)
	}
	return
}

// Delete a specific route.
// If `r` is not IP4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Delete(r *net.IPNet) (value interface{}, ok bool, err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		value, ok = n.trie.Delete(netIPNetToKey(ip, r.Mask))
	}
	return
}

// Delete a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) DeleteCIDR(s string) (value interface{}, ok bool, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		value, ok, err = n.Delete(r)
	}
	return
}

// Get a specific route.
// If `r` is not IPv4/IPv6 network or a route is not found, `ok` is false.
func (n *Net) Get(r *net.IPNet) (value interface{}, ok bool, err error) {
	var ip net.IP
	if ip, _, err = netValidateIPNet(r); err == nil {
		value, ok = n.trie.Get(netIPNetToKey(ip, r.Mask))
	}
	return
}

// Get a specific route.
// If `s` is not CIDR notation or a route is not found, `ok` is false.
func (n *Net) GetCIDR(s string) (value interface{}, ok bool, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		value, ok, err = n.Get(r)
	}
	return
}

// Return a specific route by using the longest prefix matching.
// If `r` is not IPv4/IPv6 network or a route is not found, `route` is nil.
func (n *Net) Match(r *net.IPNet) (route *net.IPNet, value interface{}, err error) {
	var ip net.IP
	if ip, _, err = netValidateIP(r.IP); err == nil {
		if k, v := n.match(netIPNetToKey(ip, r.Mask)); k != nil {
			route = netKeyToIPNet(k)
			value = v
		}
	}
	return
}

// Return a specific route by using the longest prefix matching.
// If `s` is not CIDR notation, or a route is not found, `route` is nil.
func (n *Net) MatchCIDR(s string) (route *net.IPNet, value interface{}, err error) {
	var r *net.IPNet
	if _, r, err = net.ParseCIDR(s); err == nil {
		route, value, err = n.Match(r)
	}
	return
}

// Return a bool indicating whether a route would be found
func (n *Net) ContainedIP(ip net.IP) (contained bool, err error) {
	k, _, err := n.matchIP(ip)
	contained = k != nil
	return
}

// Return a specific route by using the longest prefix matching.
// If `ip` is invalid IP, or a route is not found, `route` is nil.
func (n *Net) MatchIP(ip net.IP) (route *net.IPNet, value interface{}, err error) {
	k, v, err := n.matchIP(ip)
	if k != nil {
		route = netKeyToIPNet(k)
		value = v
	}
	return
}

func (n *Net) matchIP(ip net.IP) (k []byte, v interface{}, err error) {
	var isV4 bool
	ip, isV4, err = netValidateIP(ip)
	if err != nil {
		return
	}
	var mask net.IPMask
	if isV4 {
		mask = mask32
	} else {
		mask = mask128
	}
	k, v = n.match(netIPNetToKey(ip, mask))
	return
}

func (n *Net) match(key []byte) ([]byte, interface{}) {
	if n.trie.size > 0 {
		if node := lookup(&n.trie.root, key, false); node != nil {
			return node.external.key, node.external.value
		}
	}
	return nil, nil
}

func lookup(p *node, key []byte, backtracking bool) *node {
	if p.internal != nil {
		var direction int
		if p.internal.offset == len(key)-1 {
			// selecting the larger side when comparing the mask
			direction = 1
		} else if backtracking {
			direction = 0
		} else {
			direction = p.internal.direction(key)
		}

		if c := lookup(&p.internal.child[direction], key, backtracking); c != nil {
			return c
		}
		if direction == 1 {
			// search other node
			return lookup(&p.internal.child[0], key, true)
		}
		return nil
	} else {
		nlen := len(p.external.key)
		if nlen != len(key) {
			return nil
		}

		// check mask
		mask := p.external.key[nlen-1]
		if mask > key[nlen-1] {
			return nil
		}

		// compare both keys with mask
		div := int(mask >> 3)
		for i := 0; i < div; i++ {
			if p.external.key[i] != key[i] {
				return nil
			}
		}
		if mod := uint(mask & 0x07); mod > 0 {
			bit := 8 - mod
			if p.external.key[div] != key[div]&(0xff>>bit<<bit) {
				return nil
			}
		}
		return p
	}
}

// Walk iterates routes from a given route.
// handle is called with arguments route and value (if handle returns `false`, the iteration is aborted)
func (n *Net) Walk(r *net.IPNet, handle func(*net.IPNet, interface{}) bool) {
	var key []byte
	if r != nil {
		if ip, _, err := netValidateIPNet(r); err == nil {
			key = netIPNetToKey(ip, r.Mask)
		}
	}
	n.trie.Walk(key, func(key []byte, value interface{}) bool {
		return handle(netKeyToIPNet(key), value)
	})
}

func walkMatch(p *node, key []byte, handle func(*net.IPNet, interface{}) bool) bool {
	if p.internal != nil {
		if !walkMatch(&p.internal.child[0], key, handle) {
			return false
		}

		if p.internal.offset >= len(key)-1 || key[p.internal.offset]&p.internal.bit > 0 {
			return walkMatch(&p.internal.child[1], key, handle)
		}
		return true
	}

	mask := p.external.key[len(p.external.key)-1]
	if key[len(key)-1] < mask {
		return true
	}

	div := int(mask >> 3)
	for i := 0; i < div; i++ {
		if p.external.key[i] != key[i] {
			return true
		}
	}

	if mod := uint(mask & 0x07); mod > 0 {
		bit := 8 - mod
		if p.external.key[div] != key[div]&(0xff>>bit<<bit) {
			return true
		}
	}
	return handle(netKeyToIPNet(p.external.key), p.external.value)
}

// WalkMatch interates routes that match a given route.
// handle is called with arguments route and value (if handle returns `false`, the iteration is aborted)
func (n *Net) WalkMatch(r *net.IPNet, handle func(*net.IPNet, interface{}) bool) {
	if n.trie.size > 0 {
		walkMatch(&n.trie.root, netIPNetToKey(r.IP, r.Mask), handle)
	}
}

// Deletes all routes.
func (n *Net) Clear() {
	n.trie.Clear()
}

// Returns number of routes.
func (n *Net) Size() int {
	return n.trie.Size()
}

// Create IP routing table
func NewNet() *Net {
	return &Net{NewTrie()}
}

func netValidateIP(ip net.IP) (nIP net.IP, isV4 bool, err error) {
	if v4 := ip.To4(); v4 != nil {
		nIP = v4
		isV4 = true
	} else if ip.To16() != nil {
		nIP = ip
	} else {
		err = &net.AddrError{Err: "Invalid IP address", Addr: ip.String()}
	}
	return
}

func netValidateIPNet(r *net.IPNet) (nIP net.IP, isV4 bool, err error) {
	if r == nil {
		err = &net.AddrError{Err: "IP network is nil"}
		return
	}
	return netValidateIP(r.IP)
}

func netIPNetToKey(ip net.IP, mask net.IPMask) []byte {
	// +--------------+------+
	// | ip address.. | mask |
	// +--------------+------+
	ones, _ := mask.Size()
	return append(ip, byte(ones))
}

func netKeyToIPNet(k []byte) *net.IPNet {
	iplen := len(k) - 1
	return &net.IPNet{
		IP:   net.IP(k[:iplen]),
		Mask: net.CIDRMask(int(k[iplen]), iplen*8),
	}
}
<|endoftext|>


<commit_before>package nsf

import (
	"errors"
	"io"
	"io/ioutil"
	"time"

	"github.com/mjibson/mog/codec/nsf/cpu6502"
)

const (
	// 1.79 MHz
	cpuClock   = 236250000 / 11 / 12
	SampleRate = 44100
)

var (
	ErrUnrecognized = errors.New("nsf: unrecognized format")
)

const (
	NSF_HEADER_LEN = 0x80
	NSF_VERSION    = 0x5
	NSF_SONGS      = 0x6
	NSF_START      = 0x7
	NSF_LOAD       = 0x8
	NSF_INIT       = 0xa
	NSF_PLAY       = 0xc
	NSF_SONG       = 0xe
	NSF_ARTIST     = 0x2e
	NSF_COPYRIGHT  = 0x4e
	NSF_SPEED_NTSC = 0x6e
	NSF_BANKSWITCH = 0x70
	NSF_SPEED_PAL  = 0x78
	NSF_PAL_NTSC   = 0x7a
	NSF_EXTRA      = 0x7b
	NSF_ZERO       = 0x7c
)

func ReadNSF(r io.Reader) (n *NSF, err error) {
	n = &NSF{}
	n.b, err = ioutil.ReadAll(r)
	if err != nil {
		return
	}
	if len(n.b) < NSF_HEADER_LEN ||
		string(n.b[0:NSF_VERSION]) != "NESM\u001a" {
		return nil, ErrUnrecognized
	}
	n.Version = n.b[NSF_VERSION]
	n.Songs = n.b[NSF_SONGS]
	n.Start = n.b[NSF_START]
	n.LoadAddr = bLEtoUint16(n.b[NSF_LOAD:])
	n.InitAddr = bLEtoUint16(n.b[NSF_INIT:])
	n.PlayAddr = bLEtoUint16(n.b[NSF_PLAY:])
	n.Song = bToString(n.b[NSF_SONG:])
	n.Artist = bToString(n.b[NSF_ARTIST:])
	n.Copyright = bToString(n.b[NSF_COPYRIGHT:])
	n.SpeedNTSC = bLEtoUint16(n.b[NSF_SPEED_NTSC:])
	copy(n.Bankswitch[:], n.b[NSF_BANKSWITCH:NSF_SPEED_PAL])
	n.SpeedPAL = bLEtoUint16(n.b[NSF_SPEED_PAL:])
	n.PALNTSC = n.b[NSF_PAL_NTSC]
	n.Extra = n.b[NSF_EXTRA]
	n.Data = n.b[NSF_HEADER_LEN:]
	return
}

type NSF struct {
	*Ram
	*cpu6502.Cpu

	b []byte // raw NSF data

	Version byte
	Songs   byte
	Start   byte

	LoadAddr uint16
	InitAddr uint16
	PlayAddr uint16

	Song      string
	Artist    string
	Copyright string

	SpeedNTSC  uint16
	Bankswitch [8]byte
	SpeedPAL   uint16
	PALNTSC    byte
	Extra      byte
	Data       []byte

	totalTicks  int64
	frameTicks  int64
	sampleTicks int64
	playTicks   int64
	samples     []float32
}

func (n *NSF) Tick() {
	n.Ram.A.Step()
	n.totalTicks++
	n.frameTicks++
	if n.frameTicks == cpuClock/240 {
		n.frameTicks = 0
		n.Ram.A.FrameStep()
	}
	n.sampleTicks++
	if n.sampleTicks >= cpuClock/SampleRate {
		n.sampleTicks = 0
		n.samples = append(n.samples, n.Ram.A.Volume())
	}
	n.playTicks++
}

func (n *NSF) Init(song byte) {
	n.Ram = new(Ram)
	n.Cpu = cpu6502.New(n.Ram)
	copy(n.Ram.M[n.LoadAddr:], n.Data)
	n.Ram.A.Init()
	n.Cpu.A = song - 1
	n.Cpu.PC = n.InitAddr
	n.Cpu.T = nil
	n.Cpu.Run()
	n.Cpu.T = n
}

func (n *NSF) Play(d time.Duration) []float32 {
	playDur := time.Duration(n.SpeedNTSC) * time.Nanosecond * 1000
	ticksPerPlay := int64(playDur / (time.Second / cpuClock))
	ticks := int64(d / (time.Second / cpuClock))
	n.samples = make([]float32, 0)
	n.totalTicks = 0
	for n.totalTicks < ticks {
		n.playTicks = 0
		n.Cpu.PC = n.PlayAddr
		n.Cpu.Halt = false
		for !n.Cpu.Halt {
			n.Cpu.Step()
		}
		for i := ticksPerPlay - n.playTicks; i > 0 && n.totalTicks < ticks; i-- {
			n.Tick()
		}
	}
	return n.samples
}

// little-endian [2]byte to uint16 conversion
func bLEtoUint16(b []byte) uint16 {
	return uint16(b[1])<<8 + uint16(b[0])
}

// null-terminated bytes to string
func bToString(b []byte) string {
	i := 0
	for i = range b {
		if b[i] == 0 {
			break
		}
	}
	return string(b[:i])
}

type Ram struct {
	M [0xffff + 1]byte
	A Apu
}

func (r *Ram) Read(v uint16) byte {
	if v == 0x4015 {
		return r.A.Read(v)
	} else {
		return r.M[v]
	}
}

func (r *Ram) Write(v uint16, b byte) {
	r.M[v] = b
	if v&0xf000 == 0x4000 {
		r.A.Write(v, b)
	}
}
<commit_msg>Stop playback when Play subroutine runs long<commit_after>package nsf

import (
	"errors"
	"io"
	"io/ioutil"
	"time"

	"github.com/mjibson/mog/codec/nsf/cpu6502"
)

const (
	// 1.79 MHz
	cpuClock   = 236250000 / 11 / 12
	SampleRate = 44100
)

var (
	ErrUnrecognized = errors.New("nsf: unrecognized format")
)

const (
	NSF_HEADER_LEN = 0x80
	NSF_VERSION    = 0x5
	NSF_SONGS      = 0x6
	NSF_START      = 0x7
	NSF_LOAD       = 0x8
	NSF_INIT       = 0xa
	NSF_PLAY       = 0xc
	NSF_SONG       = 0xe
	NSF_ARTIST     = 0x2e
	NSF_COPYRIGHT  = 0x4e
	NSF_SPEED_NTSC = 0x6e
	NSF_BANKSWITCH = 0x70
	NSF_SPEED_PAL  = 0x78
	NSF_PAL_NTSC   = 0x7a
	NSF_EXTRA      = 0x7b
	NSF_ZERO       = 0x7c
)

func ReadNSF(r io.Reader) (n *NSF, err error) {
	n = &NSF{}
	n.b, err = ioutil.ReadAll(r)
	if err != nil {
		return
	}
	if len(n.b) < NSF_HEADER_LEN ||
		string(n.b[0:NSF_VERSION]) != "NESM\u001a" {
		return nil, ErrUnrecognized
	}
	n.Version = n.b[NSF_VERSION]
	n.Songs = n.b[NSF_SONGS]
	n.Start = n.b[NSF_START]
	n.LoadAddr = bLEtoUint16(n.b[NSF_LOAD:])
	n.InitAddr = bLEtoUint16(n.b[NSF_INIT:])
	n.PlayAddr = bLEtoUint16(n.b[NSF_PLAY:])
	n.Song = bToString(n.b[NSF_SONG:])
	n.Artist = bToString(n.b[NSF_ARTIST:])
	n.Copyright = bToString(n.b[NSF_COPYRIGHT:])
	n.SpeedNTSC = bLEtoUint16(n.b[NSF_SPEED_NTSC:])
	copy(n.Bankswitch[:], n.b[NSF_BANKSWITCH:NSF_SPEED_PAL])
	n.SpeedPAL = bLEtoUint16(n.b[NSF_SPEED_PAL:])
	n.PALNTSC = n.b[NSF_PAL_NTSC]
	n.Extra = n.b[NSF_EXTRA]
	n.Data = n.b[NSF_HEADER_LEN:]
	return
}

type NSF struct {
	*Ram
	*cpu6502.Cpu

	b []byte // raw NSF data

	Version byte
	Songs   byte
	Start   byte

	LoadAddr uint16
	InitAddr uint16
	PlayAddr uint16

	Song      string
	Artist    string
	Copyright string

	SpeedNTSC  uint16
	Bankswitch [8]byte
	SpeedPAL   uint16
	PALNTSC    byte
	Extra      byte
	Data       []byte

	totalTicks  int64
	frameTicks  int64
	sampleTicks int64
	playTicks   int64
	samples     []float32
}

func (n *NSF) Tick() {
	n.Ram.A.Step()
	n.totalTicks++
	n.frameTicks++
	if n.frameTicks == cpuClock/240 {
		n.frameTicks = 0
		n.Ram.A.FrameStep()
	}
	n.sampleTicks++
	if n.sampleTicks >= cpuClock/SampleRate {
		n.sampleTicks = 0
		n.samples = append(n.samples, n.Ram.A.Volume())
	}
	n.playTicks++
}

func (n *NSF) Init(song byte) {
	n.Ram = new(Ram)
	n.Cpu = cpu6502.New(n.Ram)
	copy(n.Ram.M[n.LoadAddr:], n.Data)
	n.Ram.A.Init()
	n.Cpu.A = song - 1
	n.Cpu.PC = n.InitAddr
	n.Cpu.T = nil
	n.Cpu.Run()
	n.Cpu.T = n
}

func (n *NSF) Play(d time.Duration) []float32 {
	playDur := time.Duration(n.SpeedNTSC) * time.Nanosecond * 1000
	ticksPerPlay := int64(playDur / (time.Second / cpuClock))
	ticks := int64(d / (time.Second / cpuClock))
	n.samples = make([]float32, 0)
	n.totalTicks = 0
	for n.totalTicks < ticks {
		n.playTicks = 0
		n.Cpu.PC = n.PlayAddr
		n.Cpu.Halt = false
		for !n.Cpu.Halt && n.totalTicks < ticks {
			n.Cpu.Step()
		}
		for i := ticksPerPlay - n.playTicks; i > 0 && n.totalTicks < ticks; i-- {
			n.Tick()
		}
	}
	return n.samples
}

// little-endian [2]byte to uint16 conversion
func bLEtoUint16(b []byte) uint16 {
	return uint16(b[1])<<8 + uint16(b[0])
}

// null-terminated bytes to string
func bToString(b []byte) string {
	i := 0
	for i = range b {
		if b[i] == 0 {
			break
		}
	}
	return string(b[:i])
}

type Ram struct {
	M [0xffff + 1]byte
	A Apu
}

func (r *Ram) Read(v uint16) byte {
	if v == 0x4015 {
		return r.A.Read(v)
	} else {
		return r.M[v]
	}
}

func (r *Ram) Write(v uint16, b byte) {
	r.M[v] = b
	if v&0xf000 == 0x4000 {
		r.A.Write(v, b)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bitbucket.org/davidwallace/go-opc/colorutils"
	"bufio"
	"fmt"
	"github.com/davecheney/profile"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

// read locations from JSON file into a slice of floats
func readLocations(fn string) []float64 {
	locations := make([]float64, 0)
	var file *os.File
	var err error
	if file, err = os.Open(fn); err != nil {
		panic(fmt.Sprintf("could not open layout file: %s", fn))
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) == 0 || line[0] == '[' || line[0] == ']' {
			continue
		}
		line = strings.Split(line, "[")[1]
		line = strings.Split(line, "]")[0]
		coordStrings := strings.Split(line, ", ")
		var x, y, z float64
		x, err = strconv.ParseFloat(coordStrings[0], 64)
		y, err = strconv.ParseFloat(coordStrings[1], 64)
		z, err = strconv.ParseFloat(coordStrings[2], 64)
		locations = append(locations, x, y, z)
	}
	fmt.Printf("Read %v pixel locations from %s\n", len(locations), fn)
	return locations
}

// Connect to an ip:port and send the values array with an OPC header in front of it.
func connectAndSend(ipPort string, values []byte) {
	// try to connect until we succeed
	// if we fail after several tries, just return
	triesLeft := 5
	var conn net.Conn
	var err error
	for {
		conn, err = net.Dial("tcp", ipPort)
		if err == nil {
			break
		}
		fmt.Println(triesLeft, err)
		time.Sleep(1 * time.Millisecond)
		triesLeft -= 1
		if triesLeft == 0 {
			return
		}
	}
	defer conn.Close()

	// make and send header
	channel := byte(0)
	command := byte(0)
	lenLowByte := byte(len(values) % 256)
	lenHighByte := byte(len(values) / 256)
	header := []byte{channel, command, lenHighByte, lenLowByte}
	_, err = conn.Write(header)
	if err != nil {
		fmt.Println(err)
		return
	}

	// send pixels
	_, err = conn.Write(values)
	if err != nil {
		fmt.Println(err)
	}
}

func main() {
	defer profile.Start(profile.CPUProfile).Stop()

	path := "circle.json"
	ipPort := "127.0.0.1:7890"

	LOCATIONS := readLocations(path)
	N_PIXELS := len(LOCATIONS) / 3
	VALUES := make([]byte, N_PIXELS*3)

	// fill in values over and over
	var pct, r, g, b, t float64
	var last_print = float64(time.Now().UnixNano()) / 1.0e9
	var frames = 0
	var start_time = last_print
	t = start_time
	for t < start_time+5 {
		t = float64(time.Now().UnixNano()) / 1.0e9
		frames += 1
		if t > last_print+1 {
			last_print = t
			fmt.Printf("%f ms (%d fps)\n", 1000.0/float64(frames), frames)
			frames = 0
		}
		for ii := 0; ii < N_PIXELS; ii++ {
			pct = float64(ii) / float64(N_PIXELS)

			r = pct
			g = pct
			b = pct

			VALUES[ii*3+0] = colorutils.FloatToByte(r)
			VALUES[ii*3+1] = colorutils.FloatToByte(g)
			VALUES[ii*3+2] = colorutils.FloatToByte(b)
		}

		connectAndSend(ipPort, VALUES)

		//for ii, v := range VALUES {
		//    fmt.Printf("VALUES[%d] = %d\n", ii, v)
		//}
	}

}
<commit_msg>Convert sender to a goroutine<commit_after>package main

import (
	"bitbucket.org/davidwallace/go-opc/colorutils"
	"bufio"
	"fmt"
	"github.com/davecheney/profile"
	"net"
	"os"
	"strconv"
	"strings"
	"time"
)

// read locations from JSON file into a slice of floats
func readLocations(fn string) []float64 {
	locations := make([]float64, 0)
	var file *os.File
	var err error
	if file, err = os.Open(fn); err != nil {
		panic(fmt.Sprintf("could not open layout file: %s", fn))
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if len(line) == 0 || line[0] == '[' || line[0] == ']' {
			continue
		}
		line = strings.Split(line, "[")[1]
		line = strings.Split(line, "]")[0]
		coordStrings := strings.Split(line, ", ")
		var x, y, z float64
		x, err = strconv.ParseFloat(coordStrings[0], 64)
		y, err = strconv.ParseFloat(coordStrings[1], 64)
		z, err = strconv.ParseFloat(coordStrings[2], 64)
		locations = append(locations, x, y, z)
	}
	fmt.Printf("Read %v pixel locations from %s\n", len(locations), fn)
	return locations
}

// Connect to an ip:port and send the values array with an OPC header in front of it.
func connectAndSend(networkWantsMore chan int, sendThisSlice chan []byte, ipPort string) {
	// try to connect until we succeed
	// if we fail after several tries, just return
	fmt.Printf("connecting to %v...\n", ipPort)
	triesLeft := 5
	var conn net.Conn
	var err error
	for {
		conn, err = net.Dial("tcp", ipPort)
		if err == nil {
			break
		}
		fmt.Println(triesLeft, err)
		time.Sleep(1 * time.Millisecond)
		triesLeft -= 1
		if triesLeft == 0 {
			return
		}
	}
	defer conn.Close()
	fmt.Println("    connected")

	// loop forever, getting slices to send
	for {
		// indicate we're idle
		networkWantsMore <- 1
		// wait to get a slice to send
		values := <-sendThisSlice

		// make and send header
		channel := byte(0)
		command := byte(0)
		lenLowByte := byte(len(values) % 256)
		lenHighByte := byte(len(values) / 256)
		header := []byte{channel, command, lenHighByte, lenLowByte}
		_, err = conn.Write(header)
		if err != nil {
			fmt.Println(err)
			continue
		}

		// send pixels
		_, err = conn.Write(values)
		if err != nil {
			fmt.Println(err)
		}
	}
}

func main() {
	defer profile.Start(profile.CPUProfile).Stop()

	path := "circle.json"
	ipPort := "127.0.0.1:7890"

	LOCATIONS := readLocations(path)
	N_PIXELS := len(LOCATIONS) / 3
	VALUES := make([][]byte, 2)
	VALUES[0] = make([]byte, N_PIXELS*3)
	VALUES[1] = make([]byte, N_PIXELS*3)

	writing, sending := 0, 1

	networkWantsMore := make(chan int,0)
	sendThisSlice := make(chan []byte,0)

	go connectAndSend(networkWantsMore, sendThisSlice, ipPort)

	// fill in values over and over
	var pct, r, g, b, t float64
	var last_print = float64(time.Now().UnixNano()) / 1.0e9
	var frames = 0
	var start_time = last_print
	t = start_time
	for t < start_time+5 {
		t = float64(time.Now().UnixNano()) / 1.0e9
		frames += 1
		if t > last_print+1 {
			last_print = t
			fmt.Printf("%f ms (%d fps)\n", 1000.0/float64(frames), frames)
			frames = 0
		}
		for ii := 0; ii < N_PIXELS; ii++ {
			pct = float64(ii) / float64(N_PIXELS)

			r = pct
			g = pct
			b = pct

			VALUES[writing][ii*3+0] = colorutils.FloatToByte(r)
			VALUES[writing][ii*3+1] = colorutils.FloatToByte(g)
			VALUES[writing][ii*3+2] = colorutils.FloatToByte(b)
		}

		// wait until the network is idle
		<-networkWantsMore
		// swap the slices
		writing, sending = sending, writing
		// tell the network to start sending the one we just finished making
		sendThisSlice <- VALUES[sending]

		//for ii, v := range VALUES {
		//    fmt.Printf("VALUES[%d] = %d\n", ii, v)
		//}
	}
}
<|endoftext|>


<commit_before>/**
 *  Copyright 2014 Paul Querna
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package otp

import (
	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"

	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"errors"
	"fmt"
	"hash"
	"image"
	"net/url"
	"strings"
)

// Error when attempting to convert the secret from base32 to raw bytes.
var ErrValidateSecretInvalidBase32 = errors.New("Decoding of secret as base32 failed.")

// The user provided passcode length was not expected.
var ErrValidateInputInvalidLength = errors.New("Input length unexpected")

// When generating a Key, the Issuer must be set.
var ErrGenerateMissingIssuer = errors.New("Issuer must be set")

// When generating a Key, the Account Name must be set.
var ErrGenerateMissingAccountName = errors.New("AccountName must be set")

// Key represents an TOTP or HTOP key.
type Key struct {
	orig string
	url  *url.URL
}

// NewKeyFromURL creates a new Key from an TOTP or HOTP url.
//
// The URL format is documented here:
//   https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
//
func NewKeyFromURL(orig string) (*Key, error) {
	u, err := url.Parse(orig)

	if err != nil {
		return nil, err
	}

	return &Key{
		orig: orig,
		url:  u,
	}, nil
}

func (k *Key) String() string {
	return k.orig
}

// Image returns an QR-Code image of the specified width and height,
// suitable for use by many clients like Google-Authenricator
// to enroll a user's TOTP/HOTP key.
func (k *Key) Image(width int, height int) (image.Image, error) {
	b, err := qr.Encode(k.orig, qr.M, qr.Auto)

	if err != nil {
		return nil, err
	}

	b, err = barcode.Scale(b, width, height)

	if err != nil {
		return nil, err
	}

	return b, nil
}

// Type returns "hotp" or "totp".
func (k *Key) Type() string {
	return k.url.Host
}

// Issuer returns the name of the issuing organization.
func (k *Key) Issuer() string {
	q := k.url.Query()

	issuer := q.Get("issuer")

	if issuer != "" {
		return issuer
	}

	p := strings.TrimPrefix(k.url.Path, "/")
	i := strings.Index(p, ":")

	if i == -1 {
		return ""
	}

	return p[:i]
}

// AccountName returns the name of the user's account.
func (k *Key) AccountName() string {
	p := strings.TrimPrefix(k.url.Path, "/")
	i := strings.Index(p, ":")

	if i == -1 {
		return p
	}

	return p[i+1:]
}

// Secret returns the opaque secret for this Key.
func (k *Key) Secret() string {
	q := k.url.Query()

	return q.Get("secret")
}

// Algorithm represents the hashing function to use in the HMAC
// operation needed for OTPs.
type Algorithm int

const (
	AlgorithmSHA1 Algorithm = iota
	AlgorithmSHA256
	AlgorithmSHA512
	AlgorithmMD5
)

func (a Algorithm) String() string {
	switch a {
	case AlgorithmSHA1:
		return "SHA1"
	case AlgorithmSHA256:
		return "SHA256"
	case AlgorithmSHA512:
		return "SHA512"
	case AlgorithmMD5:
		return "MD5"
	}
	panic("unreached")
}

func (a Algorithm) Hash() hash.Hash {
	switch a {
	case AlgorithmSHA1:
		return sha1.New()
	case AlgorithmSHA256:
		return sha256.New()
	case AlgorithmSHA512:
		return sha512.New()
	case AlgorithmMD5:
		return md5.New()
	}
	panic("unreached")
}

// Digits represents the number of digits present in the
// user's OTP passcode. Six and Eight are the most common values.
type Digits int

const (
	DigitsSix   Digits = 6
	DigitsEight Digits = 8
)

// Format converts an integer into the zero-filled size for this Digits.
func (d Digits) Format(in int32) string {
	f := fmt.Sprintf("%%0%dd", d)
	return fmt.Sprintf(f, in)
}

// Length returns the number of characters for this Digits.
func (d Digits) Length() int {
	return int(d)
}

func (d Digits) String() string {
	return fmt.Sprintf("%d", d)
}
<commit_msg>Update URL to OTP Key URL guide<commit_after>/**
 *  Copyright 2014 Paul Querna
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package otp

import (
	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"

	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"errors"
	"fmt"
	"hash"
	"image"
	"net/url"
	"strings"
)

// Error when attempting to convert the secret from base32 to raw bytes.
var ErrValidateSecretInvalidBase32 = errors.New("Decoding of secret as base32 failed.")

// The user provided passcode length was not expected.
var ErrValidateInputInvalidLength = errors.New("Input length unexpected")

// When generating a Key, the Issuer must be set.
var ErrGenerateMissingIssuer = errors.New("Issuer must be set")

// When generating a Key, the Account Name must be set.
var ErrGenerateMissingAccountName = errors.New("AccountName must be set")

// Key represents an TOTP or HTOP key.
type Key struct {
	orig string
	url  *url.URL
}

// NewKeyFromURL creates a new Key from an TOTP or HOTP url.
//
// The URL format is documented here:
//   https://github.com/google/google-authenticator/wiki/Key-Uri-Format
//
func NewKeyFromURL(orig string) (*Key, error) {
	u, err := url.Parse(orig)

	if err != nil {
		return nil, err
	}

	return &Key{
		orig: orig,
		url:  u,
	}, nil
}

func (k *Key) String() string {
	return k.orig
}

// Image returns an QR-Code image of the specified width and height,
// suitable for use by many clients like Google-Authenricator
// to enroll a user's TOTP/HOTP key.
func (k *Key) Image(width int, height int) (image.Image, error) {
	b, err := qr.Encode(k.orig, qr.M, qr.Auto)

	if err != nil {
		return nil, err
	}

	b, err = barcode.Scale(b, width, height)

	if err != nil {
		return nil, err
	}

	return b, nil
}

// Type returns "hotp" or "totp".
func (k *Key) Type() string {
	return k.url.Host
}

// Issuer returns the name of the issuing organization.
func (k *Key) Issuer() string {
	q := k.url.Query()

	issuer := q.Get("issuer")

	if issuer != "" {
		return issuer
	}

	p := strings.TrimPrefix(k.url.Path, "/")
	i := strings.Index(p, ":")

	if i == -1 {
		return ""
	}

	return p[:i]
}

// AccountName returns the name of the user's account.
func (k *Key) AccountName() string {
	p := strings.TrimPrefix(k.url.Path, "/")
	i := strings.Index(p, ":")

	if i == -1 {
		return p
	}

	return p[i+1:]
}

// Secret returns the opaque secret for this Key.
func (k *Key) Secret() string {
	q := k.url.Query()

	return q.Get("secret")
}

// Algorithm represents the hashing function to use in the HMAC
// operation needed for OTPs.
type Algorithm int

const (
	AlgorithmSHA1 Algorithm = iota
	AlgorithmSHA256
	AlgorithmSHA512
	AlgorithmMD5
)

func (a Algorithm) String() string {
	switch a {
	case AlgorithmSHA1:
		return "SHA1"
	case AlgorithmSHA256:
		return "SHA256"
	case AlgorithmSHA512:
		return "SHA512"
	case AlgorithmMD5:
		return "MD5"
	}
	panic("unreached")
}

func (a Algorithm) Hash() hash.Hash {
	switch a {
	case AlgorithmSHA1:
		return sha1.New()
	case AlgorithmSHA256:
		return sha256.New()
	case AlgorithmSHA512:
		return sha512.New()
	case AlgorithmMD5:
		return md5.New()
	}
	panic("unreached")
}

// Digits represents the number of digits present in the
// user's OTP passcode. Six and Eight are the most common values.
type Digits int

const (
	DigitsSix   Digits = 6
	DigitsEight Digits = 8
)

// Format converts an integer into the zero-filled size for this Digits.
func (d Digits) Format(in int32) string {
	f := fmt.Sprintf("%%0%dd", d)
	return fmt.Sprintf(f, in)
}

// Length returns the number of characters for this Digits.
func (d Digits) Length() int {
	return int(d)
}

func (d Digits) String() string {
	return fmt.Sprintf("%d", d)
}
<|endoftext|>


<commit_before>package dragon

import (
	"bytes"
	"fmt"
	"go/format"
	"io"
	"os"
	"path/filepath"
	"sort"
)

func out(libChan chan lib, w io.Writer) error {
	libs := map[string]lib{}
	ambiguous := map[string]bool{}
	var keys []string

	for lib := range libChan {
		full := lib.path
		key := lib.pkg + "." + lib.object
		if exist, ok := libs[key]; ok {
			if exist.path != full {
				ambiguous[key] = true
			}
		} else {
			libs[key] = lib
			keys = append(keys, key)
		}
	}
	sort.Strings(keys)

	var buf bytes.Buffer
	outf := func(format string, args ...interface{}) {
		fmt.Fprintf(&buf, format, args...)
	}
	outf("// AUTO-GENERATED BY dragon-imports\n\n")
	outf("package imports\n")
	outf("var stdlib = map[string]string{\n")

	for _, key := range keys {
		if ambiguous[key] {
			outf("\t// %q is ambiguous\n", key)
		} else {
			outf("\t%q: %q,\n", key, libs[key].path)
		}
	}
	outf("\n")
	for _, sym := range [...]string{"Alignof", "ArbitraryType", "Offsetof", "Pointer", "Sizeof"} {
		outf("\t%q: %q,\n", "unsafe."+sym, "unsafe")
	}
	outf("}\n")
	fmtbuf, _ := format.Source(buf.Bytes())
	_, err := w.Write(fmtbuf)
	return err
}

func outPath() string {
	for _, src := range srcDirs() {
		outPath := filepath.Join(src, "golang.org/x/tools/imports")
		if _, err := os.Stat(outPath); err == nil {
			return outPath
		}
	}
	return ""
}
<commit_msg>follow stdlib type changes<commit_after>package dragon

import (
	"bytes"
	"fmt"
	"go/format"
	"io"
	"os"
	"path/filepath"
)

func out(libChan chan lib, w io.Writer) error {
	libs := map[string]lib{}
	ambiguous := map[string]bool{}
	for lib := range libChan {
		full := lib.path
		key := lib.pkg + "." + lib.object
		if exist, ok := libs[key]; ok {
			if exist.path != full {
				ambiguous[key] = true
			}
		} else {
			libs[key] = lib
		}
	}

	stdlib := map[string]map[string]bool{
		"unsafe": map[string]bool{
			"Alignof":       true,
			"ArbitraryType": true,
			"Offsetof":      true,
			"Pointer":       true,
			"Sizeof":        true,
		},
	}
	for _, lib := range libs {
		if ambiguous[lib.pkg+"."+lib.object] {
			continue
		}
		objMap, ok := stdlib[lib.path]
		if !ok {
			objMap = make(map[string]bool)
		}
		objMap[lib.object] = true
		stdlib[lib.path] = objMap
	}

	var buf bytes.Buffer
	outf := func(format string, args ...interface{}) {
		fmt.Fprintf(&buf, format, args...)
	}
	outf("// AUTO-GENERATED BY dragon-imports\n\n")
	outf("package imports\n")
	outf("var stdlib = %#v\n", stdlib)

	fmtbuf, _ := format.Source(buf.Bytes())
	_, err := w.Write(fmtbuf)
	return err
}

func outPath() string {
	for _, src := range srcDirs() {
		outPath := filepath.Join(src, "golang.org/x/tools/imports")
		if _, err := os.Stat(outPath); err == nil {
			return outPath
		}
	}
	return ""
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, Bartosz Kratochwil
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.

//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.

//     * Neither the name of Aaron France nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package hpcloud

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

/*
 ListDBInstances will list all the available database instances

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-database-instances.html
*/
func (a Access) ListDBInstances() (*DBInstances, error) {
	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	dbs := &DBInstances{}
	err = json.Unmarshal(body, dbs)
	return dbs, err
}

/*
 This function takes instance ID and deletes database instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/delete-instance.html
*/
func (a Access) DeleteDBInstance(instanceID string) error {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID,
		instanceID)
	_, err := a.baseRequest(url, "DELETE", nil)
	return err
}

/*
 This function takes instance ID and restarts DB instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/restart-instance.html
*/
func (a Access) RestartDBInstance(instanceID string) error {
	b := `{"restart":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, instanceID)
	_, err := a.baseRequest(url, "POST", strings.NewReader(b))
	return err
}

/*
 ListAllFlavors lists all available database flavors.
 This function implements interface as described in:-
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-flavors.html
*/
func (a Access) ListAllFlavors() (*DBFlavors, error) {
	url := fmt.Sprintf("%s%s/flavors", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavors{}
	err = json.Unmarshal(body, flv)
	return flv, err
}

/*
 This function returns flavor specs for given flavor.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-flavor.html
*/
func (a Access) GetDBFlavor(ID string) (*DBFlavor, error) {
	url := fmt.Sprintf("%s/flavors/%s", RDB_URL, ID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavor{}
	err = json.Unmarshal(body, flv)
	if err != nil {
		return nil, err
	}
	return flv, nil
}

/*
 CreateDBInstance creates new database instance in the HPCloud using
settings found in the DatabaseReq instance passed to this function

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/create-instance.html
*/
func (a Access) CreateDBInstance(db DatabaseReq) (*NewDBInstance, error) {
	b, err := db.MarshalJSON()
	if err != nil {
		return nil, err
	}

	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)

	body, err := a.baseRequest(url, "POST",
		strings.NewReader(string(b)))
	if err != nil {
		return nil, err
	}

	type respDB struct {
		Instance NewDBInstance `json:"instance"`
	}

	sr := &respDB{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.Instance, nil
}

/*
 This function retrieves details of the instance with provided ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-instance.html
*/
func (a Access) GetDBInstance(id string) (*InstDetails, error) {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID, id)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	det := &InstDetails{}
	err = json.Unmarshal(body, det)
	return det, err
}

/*
 This function takes instance ID and resets password for this instance. It
 returns a new instance password.

 This function implements the interface as decribed in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/reset-instance-password.html
*/
func (a Access) ResetDBPassword(id string) (*DBCredentials, error) {
	b := `{"reset-password":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, id)
	body, err := a.baseRequest(url, "POST", strings.NewReader(b))

	sr := &DBCredentials{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return sr, nil
}

/*
 This function lists all the security groups available for tenant.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-security-groups.html
*/
func (a Access) GetDBSecurityGroups() (*[]SecurityGroup, error) {
	url := fmt.Sprintf("%s%s/security-groups", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)

	type resp struct {
		SecurityGroups []SecurityGroup `json:"security_groups"`
	}
	sr := &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.SecurityGroups, nil
}

/*
 This function lists specific security group.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-security-group.html
*/
func (a Access) DBSecGroupDetails(sg string) (*SecurityGroup, error) {
	url := fmt.Sprintf("%s%s/security-groups/%s", RDB_URL, a.TenantID, sg)
	body, err := a.baseRequest(url, "GET", nil)

	type resp struct {
		SecurityGroup SecurityGroup `json:"security_group"`
	}

	sr := &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.SecurityGroup, nil
}

type DBInstance struct {
	Created string `json:"created"`
	Id      string `json:"id"`
	Links   []Link `json:"links"`
	Name    string `json:"name"`
	Status  string `json:"name"`
	Flavor  struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

type DBInstances struct {
	Instances []DBInstance `json:"instances"`
}

type Database struct {
	Name      string `json:"name"`
	FlavorRef string `json:"flavorRef"`
	Port      int    `json:"port"`
	DBType    struct {
		Name    string `json:"name"`
		Version string `json:"version"`
	} `json:"dbtype"`
}

type DBFlavors struct {
	Flavors []DBFlavor `json:"flavors"`
}

/*
 Instance Details type that is returned by server
*/
type InstDetails struct {
	Created        string          `json:"created"`
	Hostname       string          `json:"hostname"`
	ID             string          `json:"id"`
	Links          []Link          `json:"links"`
	Name           string          `json:"name"`
	Port           int             `json:"port"`
	SecurityGroups []SecurityGroup `json:"security_groups"`
	Status         string          `json:"status"`
	Updated        string          `json:"updated"`
	Flavor         struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

/*
 Type describing database flavor
*/
type DBFlavor struct {
	Id    int    `json:"id"`
	Links []Link `json:"links"`
	Name  string `json:"name"`
	Ram   int    `json:"ram"`
	Vcpu  int    `json:"vcpu"`
}

/*
 This type describes the JSON data which should be sent to the
create database instance resource.
*/
type DatabaseReq struct {
	Instance Database `json:"instance"`
}

/*
 This type describes JSON response from a successful CreateDBInstance
 call.
*/
type NewDBInstance struct {
	Created    string        `json:"created"`
	Credential DBCredentials `json:"credential"`
	Flavor     struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
	Hostname       string        `json:"hostname"`
	Id             string        `json:"id"`
	Links          []Link        `json:"links"`
	Name           string        `json:"name"`
	SecurityGroups []DBSecGroups `json:"security_groups"`
	Status         string        `json:"status"`
}

/*
 This type describes Database Security groups
*/
type DBSecGroups struct {
	Id    string `json:"id"`
	Links []Link `json:"links"`
}

/*
 This type describes Database Credentials
*/
type DBCredentials struct {
	Password string `json:"password"`
	Username string `json:"username"`
}

func (f DBFlavors) GetFlavorRef(fn string) string {
	for _, val := range f.Flavors {
		if val.Name == fn {
			return val.Links[0].HREF
		}
	}
	panic("Flavor not found")
}

func (db DatabaseReq) MarshalJSON() ([]byte, error) {
	b := bytes.NewBufferString(`{"instance":{`)
	if db.Instance.Name == "" {
		return nil, errors.New("A name is required")
	}
	b.WriteString(fmt.Sprintf(`"name":"%s",`, db.Instance.Name))
	if db.Instance.FlavorRef == "" {
		return nil, errors.New("Flavor is required")
	}
	b.WriteString(fmt.Sprintf(`"flavorRef":"%s",`,
		db.Instance.FlavorRef))
	if db.Instance.Port == 0 {
		b.WriteString(`"port":"3306",`)
	} else {
		b.WriteString(fmt.Sprintf(`"port":"%s",`, db.Instance.Port))
	}
	b.WriteString(`"dbtype":{`)
	b.WriteString(`"name":"mysql",`)
	b.WriteString(`"version":"5.5"}}}`)

	return b.Bytes(), nil
}
<commit_msg>added secrule structs and add secrule function<commit_after>// Copyright (c) 2013, Bartosz Kratochwil
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.

//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.

//     * Neither the name of Aaron France nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package hpcloud

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

/*
 ListDBInstances will list all the available database instances

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-database-instances.html
*/
func (a Access) ListDBInstances() (*DBInstances, error) {
	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	dbs := &DBInstances{}
	err = json.Unmarshal(body, dbs)
	return dbs, err
}

/*
 This function takes instance ID and deletes database instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/delete-instance.html
*/
func (a Access) DeleteDBInstance(instanceID string) error {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID,
		instanceID)
	_, err := a.baseRequest(url, "DELETE", nil)
	return err
}

/*
 This function takes instance ID and restarts DB instance with this ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/restart-instance.html
*/
func (a Access) RestartDBInstance(instanceID string) error {
	b := `{"restart":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, instanceID)
	_, err := a.baseRequest(url, "POST", strings.NewReader(b))
	return err
}

/*
 ListAllFlavors lists all available database flavors.
 This function implements interface as described in:-
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-flavors.html
*/
func (a Access) ListAllFlavors() (*DBFlavors, error) {
	url := fmt.Sprintf("%s%s/flavors", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavors{}
	err = json.Unmarshal(body, flv)
	return flv, err
}

/*
 This function returns flavor specs for given flavor.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-flavor.html
*/
func (a Access) GetDBFlavor(ID string) (*DBFlavor, error) {
	url := fmt.Sprintf("%s/flavors/%s", RDB_URL, ID)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}

	flv := &DBFlavor{}
	err = json.Unmarshal(body, flv)
	if err != nil {
		return nil, err
	}
	return flv, nil
}

/*
 CreateDBInstance creates new database instance in the HPCloud using
settings found in the DatabaseReq instance passed to this function

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/create-instance.html
*/
func (a Access) CreateDBInstance(db DatabaseReq) (*NewDBInstance, error) {
	b, err := db.MarshalJSON()
	if err != nil {
		return nil, err
	}

	url := fmt.Sprintf("%s%s/instances", RDB_URL, a.TenantID)

	body, err := a.baseRequest(url, "POST",
		strings.NewReader(string(b)))
	if err != nil {
		return nil, err
	}

	type respDB struct {
		Instance NewDBInstance `json:"instance"`
	}

	sr := &respDB{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.Instance, nil
}

/*
 This function retrieves details of the instance with provided ID.

This function implements the interface as described in:
http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-instance.html
*/
func (a Access) GetDBInstance(id string) (*InstDetails, error) {
	url := fmt.Sprintf("%s%s/instances/%s", RDB_URL, a.TenantID, id)
	body, err := a.baseRequest(url, "GET", nil)
	if err != nil {
		return nil, err
	}
	det := &InstDetails{}
	err = json.Unmarshal(body, det)
	return det, err
}

/*
 This function takes instance ID and resets password for this instance. It
 returns a new instance password.

 This function implements the interface as decribed in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/reset-instance-password.html
*/
func (a Access) ResetDBPassword(id string) (*DBCredentials, error) {
	b := `{"reset-password":{}}`
	url := fmt.Sprintf("%s%s/instances/%s/action", RDB_URL,
		a.TenantID, id)
	body, err := a.baseRequest(url, "POST", strings.NewReader(b))

	sr := &DBCredentials{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return sr, nil
}

/*
 This function lists all the security groups available for tenant.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/list-security-groups.html
*/
func (a Access) GetDBSecurityGroups() (*[]SecurityGroup, error) {
	url := fmt.Sprintf("%s%s/security-groups", RDB_URL, a.TenantID)
	body, err := a.baseRequest(url, "GET", nil)

	type resp struct {
		SecurityGroups []SecurityGroup `json:"security_groups"`
	}
	sr := &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.SecurityGroups, nil
}

/*
 This function lists specific security group.

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/get-security-group.html
*/
func (a Access) DBSecGroupDetails(sg string) (*SecurityGroup, error) {
	url := fmt.Sprintf("%s%s/security-groups/%s", RDB_URL, a.TenantID, sg)
	body, err := a.baseRequest(url, "GET", nil)

	type resp struct {
		SecurityGroup SecurityGroup `json:"security_group"`
	}

	sr := &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}
	return &sr.SecurityGroup, nil
}

/*
 Creates new security group rule

 This function implements the interface as described in:
 http://api-docs.hpcloud.com/hpcloud-rdb-mysql/1.0/content/create-security-group-rule.html
*/
func (a Access) CreateDBSecRule(Req DBSecRuleReq) (*DBSecRule, error) {
	url := fmt.Sprintf("%s%s/security-group-rules", RDB_URL, a.TenantID)
	b, err := Req.MarshalJSON()

	if err != nil {
		return nil, err
	}

	body, err := a.baseRequest(url, "POST",
		strings.NewReader(string(b)))

	type resp struct {
		SecurityGroupRule DBSecRule `json:"security_group_rule"`
	}

	sr := &resp{}
	err = json.Unmarshal(body, sr)
	if err != nil {
		return nil, err
	}

	return &sr.SecurityGroupRule, nil
}

type DBInstance struct {
	Created string `json:"created"`
	Id      string `json:"id"`
	Links   []Link `json:"links"`
	Name    string `json:"name"`
	Status  string `json:"name"`
	Flavor  struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

type DBInstances struct {
	Instances []DBInstance `json:"instances"`
}

type Database struct {
	Name      string `json:"name"`
	FlavorRef string `json:"flavorRef"`
	Port      int    `json:"port"`
	DBType    struct {
		Name    string `json:"name"`
		Version string `json:"version"`
	} `json:"dbtype"`
}

type DBFlavors struct {
	Flavors []DBFlavor `json:"flavors"`
}

/*
 Instance Details type that is returned by server
*/
type InstDetails struct {
	Created        string          `json:"created"`
	Hostname       string          `json:"hostname"`
	ID             string          `json:"id"`
	Links          []Link          `json:"links"`
	Name           string          `json:"name"`
	Port           int             `json:"port"`
	SecurityGroups []SecurityGroup `json:"security_groups"`
	Status         string          `json:"status"`
	Updated        string          `json:"updated"`
	Flavor         struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
}

/*
 Type describing database flavor
*/
type DBFlavor struct {
	Id    int    `json:"id"`
	Links []Link `json:"links"`
	Name  string `json:"name"`
	Ram   int    `json:"ram"`
	Vcpu  int    `json:"vcpu"`
}

/*
 This type describes the JSON data which should be sent to the
create database instance resource.
*/
type DatabaseReq struct {
	Instance Database `json:"instance"`
}

/*
 This type describes JSON response from a successful CreateDBInstance
 call.
*/
type NewDBInstance struct {
	Created    string        `json:"created"`
	Credential DBCredentials `json:"credential"`
	Flavor     struct {
		Name  string `json:"name"`
		ID    string `json:"id"`
		Links []Link `json:"links"`
	} `json:"flavor"`
	Hostname       string        `json:"hostname"`
	Id             string        `json:"id"`
	Links          []Link        `json:"links"`
	Name           string        `json:"name"`
	SecurityGroups []DBSecGroups `json:"security_groups"`
	Status         string        `json:"status"`
}

/*
 This type describes Database Security groups
*/
type DBSecGroups struct {
	Id    string `json:"id"`
	Links []Link `json:"links"`
}

/*
 This type describes Database Credentials
*/
type DBCredentials struct {
	Password string `json:"password"`
	Username string `json:"username"`
}

/*
 DB Security Group Create request struct
*/
type DBSecRuleReq struct {
	SecurityGroupID string `json:"security_group_rule"`
	Cidr            string `json:"cidr"`
	FromPort        int64  `json:"from_port"`
	ToPort          int64  `json:"to_port"`
}

type DBSecRule struct {
	ID              string `json:"id"`
	SecurityGroupID string `json:"security_group_rule"`
	Cidr            string `json:"cidr"`
	FromPort        int64  `json:"from_port"`
	ToPort          int64  `json:"to_port"`
	Created         string `json:"created"`
}

func (f DBFlavors) GetFlavorRef(fn string) string {
	for _, val := range f.Flavors {
		if val.Name == fn {
			return val.Links[0].HREF
		}
	}
	panic("Flavor not found")
}

/*
 Creates JSON string for Create DB request
*/
func (db DatabaseReq) MarshalJSON() ([]byte, error) {
	b := bytes.NewBufferString(`{"instance":{`)
	if db.Instance.Name == "" {
		return nil, errors.New("A name is required")
	}
	b.WriteString(fmt.Sprintf(`"name":"%s",`, db.Instance.Name))
	if db.Instance.FlavorRef == "" {
		return nil, errors.New("Flavor is required")
	}
	b.WriteString(fmt.Sprintf(`"flavorRef":"%s",`,
		db.Instance.FlavorRef))
	if db.Instance.Port == 0 {
		b.WriteString(`"port":"3306",`)
	} else {
		b.WriteString(fmt.Sprintf(`"port":"%s",`, db.Instance.Port))
	}
	b.WriteString(`"dbtype":{`)
	b.WriteString(`"name":"mysql",`)
	b.WriteString(`"version":"5.5"}}}`)

	return b.Bytes(), nil
}

func (rq DBSecRuleReq) MarshalJSON() ([]byte, error) {
	b := bytes.NewBufferString(`{"security_group_rule":{`)
	if rq.SecurityGroupID == "" {
		return nil, errors.New("Security group ID required")
	}
	b.WriteString(fmt.Sprintf(`"security_group_id":"%s",`,
		rq.SecurityGroupID))
	if rq.Cidr == "" {
		return nil, errors.New("Cidr is missing")
	}
	b.WriteString(fmt.Sprintf(`"cidr":"%s",`, rq.Cidr))
	if rq.FromPort == 0 {
		return nil, errors.New("from_port value is missing")
	}
	b.WriteString(fmt.Sprintf(`"from_port":"%s",`, rq.FromPort))
	if rq.ToPort == 0 {
		return nil, errors.New("to_port value is missing")
	}
	b.WriteString(fmt.Sprintf(`"to_port":"%s"}}`, rq.ToPort))

	return b.Bytes(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"net/http"

	"github.com/flynn/lorne/types"
	"github.com/flynn/rpcplus"
)

func rpcServer() {
	rpcplus.Register(&Host{})
	rpcplus.HandleHTTP()
	http.ListenAndServe(":1113", nil)
}

type Host struct{}

const stopTimeout = 10

func (h *Host) JobList(arg struct{}, res *map[string]lorne.Job) error {
	*res = state.Get()
	return nil
}

func (h *Host) GetJob(id string, res *lorne.Job) error {
	job := state.GetJob(id)
	if job != nil {
		*res = *job
	}
	return nil
}

func (h *Host) StopJob(id string, res *struct{}) error {
	job := state.GetJob(id)
	if job.Job == nil {
		return errors.New("lorne: unknown job")
	}
	if job.Status != lorne.StatusRunning {
		return errors.New("lorne: job is not running")
	}
	return Docker.StopContainer(job.ContainerID, stopTimeout)
}

func (h *Host) Stream(id string, stream rpcplus.Stream) error {
	ch := make(chan lorne.Event)
	state.AddListener(id, ch)
	defer func() {
		go func() {
			// drain to prevent deadlock while removing the listener
			for _ = range ch {
			}
		}()
		state.RemoveListener(id, ch)
		close(ch)
	}()
	for {
		select {
		case event := <-ch:
			select {
			case stream.Send <- event:
			case <-stream.Error:
				return nil
			}
		case <-stream.Error:
			return nil
		}
	}
}
<commit_msg>host: Fix stop<commit_after>package main

import (
	"errors"
	"net/http"

	"github.com/flynn/lorne/types"
	"github.com/flynn/rpcplus"
)

func rpcServer() {
	rpcplus.Register(&Host{})
	rpcplus.HandleHTTP()
	http.ListenAndServe(":1113", nil)
}

type Host struct{}

const stopTimeout = 1

func (h *Host) JobList(arg struct{}, res *map[string]lorne.Job) error {
	*res = state.Get()
	return nil
}

func (h *Host) GetJob(id string, res *lorne.Job) error {
	job := state.GetJob(id)
	if job != nil {
		*res = *job
	}
	return nil
}

func (h *Host) StopJob(id string, res *struct{}) error {
	job := state.GetJob(id)
	if job == nil {
		return errors.New("lorne: unknown job")
	}
	if job.Status != lorne.StatusRunning {
		return errors.New("lorne: job is not running")
	}
	return Docker.StopContainer(job.ContainerID, stopTimeout)
}

func (h *Host) Stream(id string, stream rpcplus.Stream) error {
	ch := make(chan lorne.Event)
	state.AddListener(id, ch)
	defer func() {
		go func() {
			// drain to prevent deadlock while removing the listener
			for _ = range ch {
			}
		}()
		state.RemoveListener(id, ch)
		close(ch)
	}()
	for {
		select {
		case event := <-ch:
			select {
			case stream.Send <- event:
			case <-stream.Error:
				return nil
			}
		case <-stream.Error:
			return nil
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Eiichiro Watanabe
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bufio"
	"net"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/osrg/gobgp/packet"
)

const rtrProtocolVersion uint8 = 0

type rtrConn struct {
	conn       *net.TCPConn
	sessionId  uint16
	remoteAddr net.Addr
}

type rtrServer struct {
	connCh     chan *rtrConn
	listenPort int
}

func newRTRServer(port int) *rtrServer {
	s := &rtrServer{
		connCh:     make(chan *rtrConn),
		listenPort: port,
	}
	return s
}

func stringToValues(str string) (net.IP, uint8, uint8, uint32) {
	arr := strings.Split(str, "-")
	_, n, _, _ := parseCIDR(arr[0])
	addr := n.IP
	m, _ := n.Mask.Size()
	maxLen, _ := strconv.ParseUint(arr[1], 10, 8)
	asn, _ := strconv.ParseUint(arr[2], 10, 32)
	return addr, uint8(m), uint8(maxLen), uint32(asn)
}

func (s *rtrServer) run() {
	service := ":" + strconv.Itoa(s.listenPort)
	addr, _ := net.ResolveTCPAddr("tcp", service)

	l, err := net.ListenTCP("tcp", addr)
	checkError(err)

	for i := 0; ; {
		conn, err := l.AcceptTCP()
		if err != nil {
			continue
		}
		i++
		c := &rtrConn{
			conn:       conn,
			sessionId:  uint16(i),
			remoteAddr: conn.RemoteAddr(),
		}
		s.connCh <- c
	}
}

func (rtr *rtrConn) sendDeltaPrefixes(rsrc *resource, peerSN uint32) error {
	var counter uint32
	for _, rf := range []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC} {
		counter = 0
		for _, add := range toBeAdded(rsrc.table[peerSN][rf], rsrc.table[rsrc.currentSN][rf]) {
			addr, plen, mlen, asn := stringToValues(add)
			if err := rtr.sendPDU(bgp.NewRTRIPPrefix(addr, plen, mlen, asn, bgp.ANNOUNCEMENT)); err != nil {
				return err
			}
			counter++
			log.Debugf("Sent %s Prefix PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, addr, plen, mlen, asn)
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: ANNOUNCE)", RFToIPVer(rf), counter, rtr.remoteAddr)
		}

		counter = 0
		for _, del := range toBeDeleted(rsrc.table[peerSN][rf], rsrc.table[rsrc.currentSN][rf]) {
			addr, plen, mlen, asn := stringToValues(del)
			if err := rtr.sendPDU(bgp.NewRTRIPPrefix(addr, plen, mlen, asn, bgp.WITHDRAWAL)); err != nil {
				return err
			}
			counter++
			log.Debugf("Sent %s PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: WITHDRAW)", RFToIPVer(rf), rtr.remoteAddr, addr, plen, mlen, asn)
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: WITHDRAW)", RFToIPVer(rf), counter, rtr.remoteAddr)
		}
	}
	return nil
}

func (rtr *rtrConn) sendAllPrefixes(rsrc *resource) error {
	var counter uint32
	for _, rf := range []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC} {
		counter = 0
		for _, v := range rsrc.table[rsrc.currentSN][rf].ToMap() {
			for _, w := range v.(*prefixResource).values {
				for _, x := range w.asns {
					if err := rtr.sendPDU(bgp.NewRTRIPPrefix(v.(*prefixResource).prefix, v.(*prefixResource).prefixLen, w.maxLen, x, bgp.ANNOUNCEMENT)); err != nil {
						return err
					}
					counter++
					log.Debugf("Sent %s Prefix PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, v.(*prefixResource).prefix, v.(*prefixResource).prefixLen, w.maxLen, x)
				}
			}
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: ANNOUNCE)", RFToIPVer(rf), counter, rtr.remoteAddr)
		}
	}
	return nil
}

func (rtr *rtrConn) sendPDU(pdu bgp.RTRMessage) error {
	data, _ := pdu.Serialize()
	_, err := rtr.conn.Write(data)
	if err != nil {
		return err
	}
	return nil
}

func RFToIPVer(rf bgp.RouteFamily) string {
	return strings.Split(rf.String(), "_")[1]
}

type errMsg struct {
	code uint16
	data []byte
}

func handleRTR(rtr *rtrConn, rsrc *resource) {
	bcastReceiver := rsrc.group.Join()
	scanner := bufio.NewScanner(bufio.NewReader(rtr.conn))
	scanner.Split(bgp.SplitRTR)

	msgCh := make(chan bgp.RTRMessage)
	errCh := make(chan *errMsg)
	go func() {
		defer func() {
			log.Infof("Connection to %v was closed. (ID: %v)", rtr.remoteAddr, rtr.sessionId)
			bcastReceiver.Close()
			rtr.conn.Close()
		}()

		for scanner.Scan() {
			buf := scanner.Bytes()
			if buf[0] != rtrProtocolVersion {
				errCh <- &errMsg{code: bgp.UNSUPPORTED_PROTOCOL_VERSION, data: buf}
			}
			m, err := bgp.ParseRTR(buf)
			if err != nil {
				errCh <- &errMsg{code: bgp.INVALID_REQUEST, data: buf}
			}
			msgCh <- m
		}
	}()

LOOP:
	for {
		select {
		case updatedResource := <-bcastReceiver.In:
			rsrc = updatedResource.(*resource)
			if rsrc.serialNotify {
				if err := rtr.sendPDU(bgp.NewRTRSerialNotify(rtr.sessionId, rsrc.currentSN)); err != nil {
					break LOOP
				}
				log.Infof("Sent Serial Notify PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
			}
		case msg := <-errCh:
			rtr.sendPDU(bgp.NewRTRErrorReport(msg.code, msg.data, nil))
			log.Infof("Sent Error Report PDU to %v (ID: %v, ErrorCode: %v)", rtr.remoteAddr, rtr.sessionId, msg.code)
			return
		case m := <-msgCh:
			switch msg := m.(type) {
			case *bgp.RTRSerialQuery:
				peerSN := msg.SerialNumber
				log.Infof("Received Serial Query PDU from %v (ID: %v, SN: %d)", rtr.remoteAddr, msg.SessionID, peerSN)
				if _, ok := rsrc.table[peerSN]; ok {
					if err := rtr.sendPDU(bgp.NewRTRCacheResponse(rtr.sessionId)); err == nil {
						log.Infof("Sent Cache Response PDU to %v (ID: %v)", rtr.remoteAddr, rtr.sessionId)
						if err := rtr.sendDeltaPrefixes(rsrc, peerSN); err == nil {
							if err := rtr.sendPDU(bgp.NewRTREndOfData(rtr.sessionId, rsrc.currentSN)); err == nil {
								log.Infof("Sent End of Data PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
								continue
							}
						}
					}
				} else {
					if err := rtr.sendPDU(bgp.NewRTRCacheReset()); err == nil {
						log.Infof("Sent Cache Reset PDU to %v", rtr.remoteAddr)
						continue
					}
				}
				break LOOP
			case *bgp.RTRResetQuery:
				log.Infof("Received Reset Query PDU from %v", rtr.remoteAddr)

				if err := rtr.sendPDU(bgp.NewRTRCacheResponse(rtr.sessionId)); err == nil {
					log.Infof("Sent Cache Response PDU to %v (ID: %v)", rtr.remoteAddr, rtr.sessionId)
					if rsrc == nil {
						rtr.sendPDU(bgp.NewRTRErrorReport(bgp.NO_DATA_AVAILABLE, nil, nil))
						return
					} else {
						if err := rtr.sendAllPrefixes(rsrc); err == nil {
							if err := rtr.sendPDU(bgp.NewRTREndOfData(rtr.sessionId, rsrc.currentSN)); err == nil {
								log.Infof("Sent End of Data PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
								continue
							}
						}
					}
				}
				break LOOP
			case *bgp.RTRErrorReport:
				log.Warnf("Received Error Report PDU from %v (%#v)", rtr.remoteAddr, msg)
				return
			default:
				pdu, _ := msg.Serialize()
				log.Warnf("Received unsupported PDU (type %d) from %v (%#v)", pdu[1], rtr.remoteAddr, msg)
				rtr.sendPDU(bgp.NewRTRErrorReport(bgp.UNSUPPORTED_PDU_TYPE, pdu, nil))
				return
			}
		}
	}
	rtr.sendPDU(bgp.NewRTRErrorReport(bgp.INTERNAL_ERROR, nil, nil))
	return
}
<commit_msg>Fix order of params<commit_after>// Copyright (C) 2015 Eiichiro Watanabe
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bufio"
	"net"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/osrg/gobgp/packet"
)

const rtrProtocolVersion uint8 = 0

type rtrConn struct {
	conn       *net.TCPConn
	sessionId  uint16
	remoteAddr net.Addr
}

type rtrServer struct {
	connCh     chan *rtrConn
	listenPort int
}

func newRTRServer(port int) *rtrServer {
	s := &rtrServer{
		connCh:     make(chan *rtrConn),
		listenPort: port,
	}
	return s
}

func stringToValues(str string) (net.IP, uint8, uint8, uint32) {
	arr := strings.Split(str, "-")
	_, n, _, _ := parseCIDR(arr[0])
	addr := n.IP
	m, _ := n.Mask.Size()
	maxLen, _ := strconv.ParseUint(arr[1], 10, 8)
	asn, _ := strconv.ParseUint(arr[2], 10, 32)
	return addr, uint8(m), uint8(maxLen), uint32(asn)
}

func (s *rtrServer) run() {
	service := ":" + strconv.Itoa(s.listenPort)
	addr, _ := net.ResolveTCPAddr("tcp", service)

	l, err := net.ListenTCP("tcp", addr)
	checkError(err)

	for i := 0; ; {
		conn, err := l.AcceptTCP()
		if err != nil {
			continue
		}
		i++
		c := &rtrConn{
			conn:       conn,
			sessionId:  uint16(i),
			remoteAddr: conn.RemoteAddr(),
		}
		s.connCh <- c
	}
}

func (rtr *rtrConn) sendDeltaPrefixes(rsrc *resource, peerSN uint32) error {
	var counter uint32
	for _, rf := range []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC} {
		counter = 0
		for _, add := range toBeAdded(rsrc.table[peerSN][rf], rsrc.table[rsrc.currentSN][rf]) {
			addr, plen, mlen, asn := stringToValues(add)
			if err := rtr.sendPDU(bgp.NewRTRIPPrefix(addr, plen, mlen, asn, bgp.ANNOUNCEMENT)); err != nil {
				return err
			}
			counter++
			log.Debugf("Sent %s Prefix PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, addr, plen, mlen, asn)
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, counter)
		}

		counter = 0
		for _, del := range toBeDeleted(rsrc.table[peerSN][rf], rsrc.table[rsrc.currentSN][rf]) {
			addr, plen, mlen, asn := stringToValues(del)
			if err := rtr.sendPDU(bgp.NewRTRIPPrefix(addr, plen, mlen, asn, bgp.WITHDRAWAL)); err != nil {
				return err
			}
			counter++
			log.Debugf("Sent %s PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: WITHDRAW)", RFToIPVer(rf), rtr.remoteAddr, addr, plen, mlen, asn)
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: WITHDRAW)", RFToIPVer(rf), rtr.remoteAddr, counter)
		}
	}
	return nil
}

func (rtr *rtrConn) sendAllPrefixes(rsrc *resource) error {
	var counter uint32
	for _, rf := range []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC} {
		counter = 0
		for _, v := range rsrc.table[rsrc.currentSN][rf].ToMap() {
			for _, w := range v.(*prefixResource).values {
				for _, x := range w.asns {
					if err := rtr.sendPDU(bgp.NewRTRIPPrefix(v.(*prefixResource).prefix, v.(*prefixResource).prefixLen, w.maxLen, x, bgp.ANNOUNCEMENT)); err != nil {
						return err
					}
					counter++
					log.Debugf("Sent %s Prefix PDU to %v (Prefix: %v/%v, Maxlen: %v, AS: %v, flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, v.(*prefixResource).prefix, v.(*prefixResource).prefixLen, w.maxLen, x)
				}
			}
		}
		if !commandOpts.Debug && counter != 0 {
			log.Infof("Sent %s Prefix PDU(s) to %v (%d ROA(s), flags: ANNOUNCE)", RFToIPVer(rf), rtr.remoteAddr, counter)
		}
	}
	return nil
}

func (rtr *rtrConn) sendPDU(pdu bgp.RTRMessage) error {
	data, _ := pdu.Serialize()
	_, err := rtr.conn.Write(data)
	if err != nil {
		return err
	}
	return nil
}

func RFToIPVer(rf bgp.RouteFamily) string {
	return strings.Split(rf.String(), "_")[1]
}

type errMsg struct {
	code uint16
	data []byte
}

func handleRTR(rtr *rtrConn, rsrc *resource) {
	bcastReceiver := rsrc.group.Join()
	scanner := bufio.NewScanner(bufio.NewReader(rtr.conn))
	scanner.Split(bgp.SplitRTR)

	msgCh := make(chan bgp.RTRMessage)
	errCh := make(chan *errMsg)
	go func() {
		defer func() {
			log.Infof("Connection to %v was closed. (ID: %v)", rtr.remoteAddr, rtr.sessionId)
			bcastReceiver.Close()
			rtr.conn.Close()
		}()

		for scanner.Scan() {
			buf := scanner.Bytes()
			if buf[0] != rtrProtocolVersion {
				errCh <- &errMsg{code: bgp.UNSUPPORTED_PROTOCOL_VERSION, data: buf}
			}
			m, err := bgp.ParseRTR(buf)
			if err != nil {
				errCh <- &errMsg{code: bgp.INVALID_REQUEST, data: buf}
			}
			msgCh <- m
		}
	}()

LOOP:
	for {
		select {
		case updatedResource := <-bcastReceiver.In:
			rsrc = updatedResource.(*resource)
			if rsrc.serialNotify {
				if err := rtr.sendPDU(bgp.NewRTRSerialNotify(rtr.sessionId, rsrc.currentSN)); err != nil {
					break LOOP
				}
				log.Infof("Sent Serial Notify PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
			}
		case msg := <-errCh:
			rtr.sendPDU(bgp.NewRTRErrorReport(msg.code, msg.data, nil))
			log.Infof("Sent Error Report PDU to %v (ID: %v, ErrorCode: %v)", rtr.remoteAddr, rtr.sessionId, msg.code)
			return
		case m := <-msgCh:
			switch msg := m.(type) {
			case *bgp.RTRSerialQuery:
				peerSN := msg.SerialNumber
				log.Infof("Received Serial Query PDU from %v (ID: %v, SN: %d)", rtr.remoteAddr, msg.SessionID, peerSN)
				if _, ok := rsrc.table[peerSN]; ok {
					if err := rtr.sendPDU(bgp.NewRTRCacheResponse(rtr.sessionId)); err == nil {
						log.Infof("Sent Cache Response PDU to %v (ID: %v)", rtr.remoteAddr, rtr.sessionId)
						if err := rtr.sendDeltaPrefixes(rsrc, peerSN); err == nil {
							if err := rtr.sendPDU(bgp.NewRTREndOfData(rtr.sessionId, rsrc.currentSN)); err == nil {
								log.Infof("Sent End of Data PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
								continue
							}
						}
					}
				} else {
					if err := rtr.sendPDU(bgp.NewRTRCacheReset()); err == nil {
						log.Infof("Sent Cache Reset PDU to %v", rtr.remoteAddr)
						continue
					}
				}
				break LOOP
			case *bgp.RTRResetQuery:
				log.Infof("Received Reset Query PDU from %v", rtr.remoteAddr)

				if err := rtr.sendPDU(bgp.NewRTRCacheResponse(rtr.sessionId)); err == nil {
					log.Infof("Sent Cache Response PDU to %v (ID: %v)", rtr.remoteAddr, rtr.sessionId)
					if rsrc == nil {
						rtr.sendPDU(bgp.NewRTRErrorReport(bgp.NO_DATA_AVAILABLE, nil, nil))
						return
					} else {
						if err := rtr.sendAllPrefixes(rsrc); err == nil {
							if err := rtr.sendPDU(bgp.NewRTREndOfData(rtr.sessionId, rsrc.currentSN)); err == nil {
								log.Infof("Sent End of Data PDU to %v (ID: %v, SN: %v)", rtr.remoteAddr, rtr.sessionId, rsrc.currentSN)
								continue
							}
						}
					}
				}
				break LOOP
			case *bgp.RTRErrorReport:
				log.Warnf("Received Error Report PDU from %v (%#v)", rtr.remoteAddr, msg)
				return
			default:
				pdu, _ := msg.Serialize()
				log.Warnf("Received unsupported PDU (type %d) from %v (%#v)", pdu[1], rtr.remoteAddr, msg)
				rtr.sendPDU(bgp.NewRTRErrorReport(bgp.UNSUPPORTED_PDU_TYPE, pdu, nil))
				return
			}
		}
	}
	rtr.sendPDU(bgp.NewRTRErrorReport(bgp.INTERNAL_ERROR, nil, nil))
	return
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "net"
import "os"
import "flag" // Cause all the cool kids use flags, not just argv
import "io/ioutil"
import "time"

// Create our semaphore (I don't know enough Go to be sure this is the 'best' way
var sem = make(chan int, 1)
var fuzzers = make([]Fuzzer, 0)

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

	// Do argument parsing
	pathPtr := flag.String("syncdir", "", "The sync directory your afl fuzzers are using")
	flag.Parse()

	if *pathPtr == "" {
		fmt.Println("syncdir is required")
		os.Exit(1)
	}

	// Verify that our path is actually a real path
	files, _ := ioutil.ReadDir(*pathPtr)
	for _, f := range files {
		fmt.Println("Added fuzzer: " + f.Name())
		fuzzy := Fuzzer{name: f.Name(), active: false}
		fuzzers = append(fuzzers, fuzzy) // Add the new fuzzer
	}

	if len(fuzzers) == 0 {
		fmt.Println("Look here, you silly sally. You don't have anything in your sync directory as yet. That's probably fine, but if it's not, you should fix it. Like, you know, if you were planning to resume a fuzz or something. Maybe you got the path wrong? I don't know, I don't judge, I'm just letting you know. Hey maybe it's your first time? You new around here? That's cool, I can dig it. In any case, I'll carry on under the assumption that you are new. So... yeah.")
	}

	// Begin listening for connections
	ln, err := net.Listen("tcp", ":8123")
	if err != nil {
		fmt.Println("Error creating socket server")
		os.Exit(1)
	}

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println("Incoming connection caused error")
			continue
		}
		go handleConnection(conn)
	}
}

func handleConnection(conn net.Conn) {
	fmt.Println("Connection started...")

	// Get an exclusive lock on our fuzzers
	sem <- 1

	// Check whether there is a fuzzer they can use
	potential := false
	for key, f := range fuzzers {
		if !f.active {
			// A non-active fuzzer we can assign
			fuzzers[key].active = true
			conn.Write([]byte(f.name))
			potential = true
			break
		}
	}
	if !potential {
		// We need to create a new fuzzer + name for them
		newname := fmt.Sprintf("fuzzer%03d", len(fuzzers)+1)
		newfuzzer := Fuzzer{name: newname, active: true}
		fuzzers = append(fuzzers, newfuzzer)
		conn.Write([]byte(newname))
	}
	// Release the lock
	<-sem
}

type Fuzzer struct {
	name       string
	active     bool
	lastReport time.Time // eventually we be used as a "they haven't reported in for x time, assume they're inactive"
}
<commit_msg>Add proper support for removing fuzzers<commit_after>package main

import "fmt"
import "net"
import "os"
import "flag" // Cause all the cool kids use flags, not just argv
import "io/ioutil"
import "time"
import "bufio"
import "strings"

// Create our semaphore (I don't know enough Go to be sure this is the 'best' way
var sem = make(chan int, 1)
var fuzzers = make([]Fuzzer, 0)

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

	// Do argument parsing
	pathPtr := flag.String("syncdir", "", "The sync directory your afl fuzzers are using")
	flag.Parse()

	if *pathPtr == "" {
		fmt.Println("syncdir is required")
		os.Exit(1)
	}

	// Verify that our path is actually a real path
	files, _ := ioutil.ReadDir(*pathPtr)
	for _, f := range files {
		fmt.Println("Added fuzzer: " + f.Name())
		fuzzy := Fuzzer{name: f.Name(), active: false}
		fuzzers = append(fuzzers, fuzzy) // Add the new fuzzer
	}

	if len(fuzzers) == 0 {
		fmt.Println("Look here, you silly sally. You don't have anything in your sync directory as yet. That's probably fine, but if it's not, you should fix it. Like, you know, if you were planning to resume a fuzz or something. Maybe you got the path wrong? I don't know, I don't judge, I'm just letting you know. Hey maybe it's your first time? You new around here? That's cool, I can dig it. In any case, I'll carry on under the assumption that you are new. So... yeah.")
	}

	// Begin listening for connections
	ln, err := net.Listen("tcp", ":8123")
	if err != nil {
		fmt.Println("Error creating socket server")
		os.Exit(1)
	}

	for {
		conn, err := ln.Accept()
		if err != nil {
			fmt.Println("Incoming connection caused error")
			continue
		}
		go handleConnection(conn)
	}
}

func handleConnection(conn net.Conn) {
	fmt.Println("Connection started...")

	// Connection reader
	reader := bufio.NewReader(conn)
	// Figure out what kind of thingy they're saying to us
	operation, _ := reader.ReadString('\n')
	operation = strings.TrimSpace(operation)
	switch {
	// An operation that requires further processing
	case operation == "new", operation == "stop":

	// Existing daemon pinging us
	case operation == "ping":
		// Not implemented yet
		conn.Close()
		return // Stop processing

	case true:
		// Guess it's invalid?
		conn.Write([]byte("Invalid operation specified: " + operation))
		conn.Close()
		return // Stop processing
	}

	// Get an exclusive lock on our fuzzers
	sem <- 1

	if operation == "new" {
		// Check whether there is a fuzzer they can use
		potential := false
		for key, f := range fuzzers {
			if !f.active {
				// A non-active fuzzer we can assign
				fuzzers[key].active = true
				conn.Write([]byte(f.name))
				potential = true
				break
			}
		}
		if !potential {
			// We need to create a new fuzzer + name for them
			newname := fmt.Sprintf("fuzzer%03d", len(fuzzers)+1)
			newfuzzer := Fuzzer{name: newname, active: true}
			fuzzers = append(fuzzers, newfuzzer)
			conn.Write([]byte(newname))
		}
	} else if operation == "stop" {
		// Read the name of the fuzzer
		fuzzername, _ := reader.ReadString('\n')
		fuzzername = strings.TrimSpace(fuzzername)
		for key, f := range fuzzers {
			if f.name == fuzzername {
				fuzzers[key].active = false
				break
			}
		}
	}
	// Release the lock
	<-sem

	// Close the connection gracefully
	conn.Close()
}

type Fuzzer struct {
	name       string
	active     bool
	lastReport time.Time // eventually we be used as a "they haven't reported in for x time, assume they're inactive"
}
<|endoftext|>


<commit_before>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"sync"
	"time"
)

func bootstrapTinzenite(path string) {
	// wait group so that the process will wait for a successful bootstrap
	var wg sync.WaitGroup
	wg.Add(1)
	if shared.IsTinzenite(path) {
		_, err := bootstrap.Load(path, func() {
			log.Println("DEBUG: Success, now what?")
			// on success --> notify of done
			wg.Done()
			loadTinzenite(path)
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err := bootstrap.Create(path, peerName, func() {
			log.Println("DEBUG: Success, now what?")
			// on success --> notify of done
			wg.Done()
			loadTinzenite(path)
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// wait for successful bootstrap
	wg.Wait()
	log.Println("DEBUG: can it be that this kills the successful function, leaving tinzenite hanging?")
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Your username:")
	password := getString("Enter a directory password:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	tinzenite.RegisterPeerValidation(allowPeer)
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.

TODO implement interrupts and close behaviour!
*/
func runTinzenite(t *core.Tinzenite) {
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<commit_msg>improvements, one bug<commit_after>package main

/*
loadTinzenite loads an existing Tinzenite directory and runs it.
*/import (
	"fmt"
	"github.com/tinzenite/bootstrap"
	"github.com/tinzenite/core"
	"github.com/tinzenite/shared"
	"log"
	"os"
	"os/signal"
	"sync"
	"time"
)

func bootstrapTinzenite(path string) {
	// wait group so that the process will wait for a successful bootstrap
	var wg sync.WaitGroup
	wg.Add(1)
	var boot *bootstrap.Bootstrap
	var err error
	if shared.IsTinzenite(path) {
		boot, err = bootstrap.Load(path, func() {
			log.Println("DEBUG: Success, now what?")
			// on success --> notify of done
			wg.Done()
			loadTinzenite(path)
		})
		if err != nil {
			logMain("Bootstrap load error:", err.Error())
			return
		}
	} else {
		peerName := getString("Enter the peer name for this Tinzenite directory:")
		boot, err = bootstrap.Create(path, peerName, func() {
			log.Println("DEBUG: Success, now what?")
			// on success --> notify of done
			wg.Done()
			loadTinzenite(path)
		})
		if err != nil {
			logMain("Bootstrap create error:", err.Error())
			return
		}
		// connect to:
		address := getString("Please enter the address of the peer to connect to:")
		err = boot.Start(address)
		if err != nil {
			logMain("Bootstrap start error:", err.Error())
			// return because we don't want to store a faulty bootstrap
			return
		}
		err = boot.Store()
		if err != nil {
			logMain("Bootstrap store error:", err.Error())
		}
	}
	// print information
	address, _ := boot.Address()
	fmt.Printf("Bootstrapping.\nID: %s\n", address)
	// wait for successful bootstrap
	wg.Wait()
	log.Println("DEBUG: can it be that this kills the successful function, leaving tinzenite hanging?")
}

func createTinzenite(path string) {
	if shared.IsTinzenite(path) {
		logMain("Directory is already a valid Tinzenite directory!")
		return
	}
	// get options
	peerName := getString("Enter the peer name for this Tinzenite directory:")
	userName := getString("Your username:")
	password := getString("Enter a directory password:")
	relPath := shared.CreatePathRoot(path)
	tinzenite, err := core.CreateTinzenite(relPath.LastElement(), relPath.FullPath(), peerName, userName, password)
	if err != nil {
		logMain("Creation error:", err.Error())
		return
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

func loadTinzenite(path string) {
	if !shared.IsTinzenite(path) {
		logMain("Directory is not a valid Tinzenite directory!")
		return
	}
	password := getString("Please enter the directory password:")
	tinzenite, err := core.LoadTinzenite(path, password)
	if err != nil {
		// TODO catch wrong password and allow retry
		logMain("Loading error:", err.Error())
		return
	}
	// run tinzenite until killed
	runTinzenite(tinzenite)
}

/*
runTinzenite runs the given Tinzenite instance.

TODO implement interrupts and close behaviour!
*/
func runTinzenite(t *core.Tinzenite) {
	// do this here so that it is guaranteed to be set
	t.RegisterPeerValidation(allowPeer)
	// print important info
	address, _ := t.Address()
	fmt.Printf("Running peer <%s>.\nID: %s\n", t.Name(), address)
	// run update and sync in intervalls
	var counter int
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	for {
		select {
		case <-time.Tick(time.Duration(10) * time.Second):
			if counter >= 5 {
				counter = 0
				err := t.SyncRemote()
				if err != nil {
					logMain("SyncRemote error:", err.Error())
				}
				continue
			}
			counter++
			err := t.SyncLocal()
			if err != nil {
				logMain("SyncLocal error:", err.Error())
			}
		case <-c:
			// on interrupt close tinzenite
			t.Close()
			return
		} // select
	} // for
}

/*
allowPeer asks the user whether to accept the given peer.
*/
func allowPeer(address string, wantsTrust bool) bool {
	// TODO actually ask!
	log.Println("TODO: Actually ask, for now accepting everything!", address)
	return true
}
<|endoftext|>