<commit_before>package mount // import "github.com/docker/docker/pkg/mount"

import (
	"sort"
	"strconv"
	"strings"

	"github.com/sirupsen/logrus"
)

// mountError records an error from mount or unmount operation
type mountError struct {
	op             string
	source, target string
	flags          uintptr
	data           string
	err            error
}

func (e *mountError) Error() string {
	out := e.op + " "

	if e.source != "" {
		out += e.source + ":" + e.target
	} else {
		out += e.target
	}

	if e.flags != uintptr(0) {
		out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
	}
	if e.data != "" {
		out += ", data: " + e.data
	}

	out += ": " + e.err.Error()
	return out
}

// Cause returns the underlying cause of the error
func (e *mountError) Cause() error {
	return e.err
}

// FilterFunc is a type defining a callback function
// to filter out unwanted entries. It takes a pointer
// to an Info struct (not fully populated, currently
// only Mountpoint is filled in), and returns two booleans:
//  - skip: true if the entry should be skipped
//  - stop: true if parsing should be stopped after the entry
type FilterFunc func(*Info) (skip, stop bool)

// PrefixFilter discards all entries whose mount points
// do not start with a prefix specified
func PrefixFilter(prefix string) FilterFunc {
	return func(m *Info) (bool, bool) {
		skip := !strings.HasPrefix(m.Mountpoint, prefix)
		return skip, false
	}
}

// SingleEntryFilter looks for a specific entry
func SingleEntryFilter(mp string) FilterFunc {
	return func(m *Info) (bool, bool) {
		if m.Mountpoint == mp {
			return false, true // don't skip, stop now
		}
		return true, false // skip, keep going
	}
}

// ParentsFilter returns all entries whose mount points
// can be parents of a path specified, discarding others.
// For example, given `/var/lib/docker/something`, entries
// like `/var/lib/docker`, `/var` and `/` are returned.
func ParentsFilter(path string) FilterFunc {
	return func(m *Info) (bool, bool) {
		skip := !strings.HasPrefix(path, m.Mountpoint)
		return skip, false
	}
}

// GetMounts retrieves a list of mounts for the current running process,
// with an optional filter applied (use nil for no filter).
func GetMounts(f FilterFunc) ([]*Info, error) {
	return parseMountTable(f)
}

// Mounted determines if a specified mountpoint has been mounted.
// On Linux it looks at /proc/self/mountinfo.
func Mounted(mountpoint string) (bool, error) {
	entries, err := GetMounts(SingleEntryFilter(mountpoint))
	if err != nil {
		return false, err
	}

	return len(entries) > 0, nil
}

// Mount will mount filesystem according to the specified configuration.
// Options must be specified like the mount or fstab unix commands:
// "opt1=val1,opt2=val2". See flags.go for supported option flags.
func Mount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	return mount(device, target, mType, uintptr(flag), data)
}

// ForceMount will mount filesystem according to the specified configuration.
// Options must be specified like the mount or fstab unix commands:
// "opt1=val1,opt2=val2". See flags.go for supported option flags.
//
// Deprecated: use Mount instead.
func ForceMount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	return mount(device, target, mType, uintptr(flag), data)
}

// Unmount lazily unmounts a filesystem on supported platforms, otherwise
// does a normal unmount.
func Unmount(target string) error {
	return unmount(target, mntDetach)
}

// RecursiveUnmount unmounts the target and all mounts underneath, starting with
// the deepsest mount first.
func RecursiveUnmount(target string) error {
	mounts, err := parseMountTable(PrefixFilter(target))
	if err != nil {
		return err
	}

	// Make the deepest mount be first
	sort.Slice(mounts, func(i, j int) bool {
		return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint)
	})

	for i, m := range mounts {
		logrus.Debugf("Trying to unmount %s", m.Mountpoint)
		err = unmount(m.Mountpoint, mntDetach)
		if err != nil {
			if i == len(mounts)-1 { // last mount
				return err
			} else {
				// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
				logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint)
			}
		}

		logrus.Debugf("Unmounted %s", m.Mountpoint)
	}
	return nil
}
<commit_msg>fix linting in pkg/mount<commit_after>package mount // import "github.com/docker/docker/pkg/mount"

import (
	"sort"
	"strconv"
	"strings"

	"github.com/sirupsen/logrus"
)

// mountError records an error from mount or unmount operation
type mountError struct {
	op             string
	source, target string
	flags          uintptr
	data           string
	err            error
}

func (e *mountError) Error() string {
	out := e.op + " "

	if e.source != "" {
		out += e.source + ":" + e.target
	} else {
		out += e.target
	}

	if e.flags != uintptr(0) {
		out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
	}
	if e.data != "" {
		out += ", data: " + e.data
	}

	out += ": " + e.err.Error()
	return out
}

// Cause returns the underlying cause of the error
func (e *mountError) Cause() error {
	return e.err
}

// FilterFunc is a type defining a callback function
// to filter out unwanted entries. It takes a pointer
// to an Info struct (not fully populated, currently
// only Mountpoint is filled in), and returns two booleans:
//  - skip: true if the entry should be skipped
//  - stop: true if parsing should be stopped after the entry
type FilterFunc func(*Info) (skip, stop bool)

// PrefixFilter discards all entries whose mount points
// do not start with a prefix specified
func PrefixFilter(prefix string) FilterFunc {
	return func(m *Info) (bool, bool) {
		skip := !strings.HasPrefix(m.Mountpoint, prefix)
		return skip, false
	}
}

// SingleEntryFilter looks for a specific entry
func SingleEntryFilter(mp string) FilterFunc {
	return func(m *Info) (bool, bool) {
		if m.Mountpoint == mp {
			return false, true // don't skip, stop now
		}
		return true, false // skip, keep going
	}
}

// ParentsFilter returns all entries whose mount points
// can be parents of a path specified, discarding others.
// For example, given `/var/lib/docker/something`, entries
// like `/var/lib/docker`, `/var` and `/` are returned.
func ParentsFilter(path string) FilterFunc {
	return func(m *Info) (bool, bool) {
		skip := !strings.HasPrefix(path, m.Mountpoint)
		return skip, false
	}
}

// GetMounts retrieves a list of mounts for the current running process,
// with an optional filter applied (use nil for no filter).
func GetMounts(f FilterFunc) ([]*Info, error) {
	return parseMountTable(f)
}

// Mounted determines if a specified mountpoint has been mounted.
// On Linux it looks at /proc/self/mountinfo.
func Mounted(mountpoint string) (bool, error) {
	entries, err := GetMounts(SingleEntryFilter(mountpoint))
	if err != nil {
		return false, err
	}

	return len(entries) > 0, nil
}

// Mount will mount filesystem according to the specified configuration.
// Options must be specified like the mount or fstab unix commands:
// "opt1=val1,opt2=val2". See flags.go for supported option flags.
func Mount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	return mount(device, target, mType, uintptr(flag), data)
}

// ForceMount will mount filesystem according to the specified configuration.
// Options must be specified like the mount or fstab unix commands:
// "opt1=val1,opt2=val2". See flags.go for supported option flags.
//
// Deprecated: use Mount instead.
func ForceMount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	return mount(device, target, mType, uintptr(flag), data)
}

// Unmount lazily unmounts a filesystem on supported platforms, otherwise
// does a normal unmount.
func Unmount(target string) error {
	return unmount(target, mntDetach)
}

// RecursiveUnmount unmounts the target and all mounts underneath, starting with
// the deepsest mount first.
func RecursiveUnmount(target string) error {
	mounts, err := parseMountTable(PrefixFilter(target))
	if err != nil {
		return err
	}

	// Make the deepest mount be first
	sort.Slice(mounts, func(i, j int) bool {
		return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint)
	})

	for i, m := range mounts {
		logrus.Debugf("Trying to unmount %s", m.Mountpoint)
		err = unmount(m.Mountpoint, mntDetach)
		if err != nil {
			if i == len(mounts)-1 { // last mount
				return err
			}
			// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
			logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint)
		}

		logrus.Debugf("Unmounted %s", m.Mountpoint)
	}
	return nil
}
<|endoftext|>


<commit_before>package net

import (
	"context"
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	igd "github.com/emersion/go-upnp-igd"
	"github.com/ugorji/go/codec"
	"go.uber.org/zap"

	"nimona.io/internal/log"
	"nimona.io/pkg/crypto"
	"nimona.io/pkg/discovery"
	"nimona.io/pkg/net/peer"
	"nimona.io/pkg/object"
)

var (
	UseUPNP = false
)

func init() {
	UseUPNP, _ = strconv.ParseBool(os.Getenv("UPNP"))
}

// Network interface
type Network interface {
	Dial(ctx context.Context, address string) (*Connection, error)
	Listen(ctx context.Context, addrress string) (chan *Connection, error)

	GetPeerInfo() *peer.PeerInfo
	AttachMandate(m *crypto.Mandate) error
}

// New creates a new p2p network using an address book
func New(key *crypto.Key, hostname string, relayAddresses []string,
	discover discovery.Discoverer) (Network, error) {
	if key == nil {
		return nil, ErrMissingKey
	}

	if _, ok := key.Materialize().(*ecdsa.PrivateKey); !ok {
		return nil, ErrECDSAPrivateKeyRequired
	}

	return &network{
		key:            key,
		discoverer:     discover,
		hostname:       hostname,
		relayAddresses: relayAddresses,
	}, nil
}

// network allows dialing and listening for p2p connections
type network struct {
	key            *crypto.Key
	discoverer     discovery.Discoverer
	hostname       string
	addressesLock  sync.RWMutex
	addresses      []string
	relayAddresses []string
	mandate        *crypto.Mandate
}

// Dial to a peer and return a net.Conn or error
func (n *network) Dial(ctx context.Context, address string) (*Connection, error) {
	logger := log.Logger(ctx)

	addressType := strings.Split(address, ":")[0]
	switch addressType {
	case "peer":
		peerID := strings.Replace(address, "peer:", "", 1)
		if peerID == n.key.GetPublicKey().HashBase58() {
			return nil, errors.New("cannot dial our own peer")
		}
		logger.Debug("dialing peer", zap.String("peer", address))
		q := &peer.PeerInfoRequest{
			SignerKeyHash: peerID,
		}
		ps, err := n.discoverer.Discover(q)
		if err != nil {
			return nil, err
		}

		if len(ps) == 0 || len(ps[0].Addresses) == 0 {
			return nil, ErrNoAddresses
		}

		// TODO we should probably try all results
		for _, addr := range ps[0].Addresses {
			conn, err := n.Dial(ctx, addr)
			if err == nil {
				return conn, nil
			}
		}

		return nil, ErrAllAddressesFailed

	case "tcps":
		config := tls.Config{
			InsecureSkipVerify: true,
		}
		addr := strings.Replace(address, "tcps:", "", 1)
		dialer := net.Dialer{Timeout: time.Second}
		logger.Debug("dialing", zap.String("address", addr))
		tcpConn, err := tls.DialWithDialer(&dialer, "tcp", addr, &config)
		if err != nil {
			return nil, err
		}

		if tcpConn == nil {
			return nil, ErrAllAddressesFailed
		}

		conn := &Connection{
			Conn:          tcpConn,
			RemotePeerKey: nil, // we don't really know who the other side is
		}

		nonce := RandStringBytesMaskImprSrc(8)
		syn := &HandshakeSyn{
			Nonce:    nonce,
			PeerInfo: n.GetPeerInfo(),
		}
		so := syn.ToObject()
		if err := crypto.Sign(so, n.key); err != nil {
			return nil, err
		}

		if err := Write(so, conn); err != nil {
			return nil, err
		}

		synAckObj, err := Read(conn)
		if err != nil {
			return nil, err
		}

		synAck := &HandshakeSynAck{}
		if err := synAck.FromObject(synAckObj); err != nil {
			return nil, err
		}

		if synAck.Nonce != nonce {
			return nil, errors.New("invalid handhshake.syn-ack")
		}

		// store who is on the other side
		conn.RemotePeerKey = synAck.PeerInfo.SignerKey
		n.discoverer.Add(synAck.PeerInfo)

		ack := &HandshakeAck{
			Nonce: nonce,
		}
		ao := ack.ToObject()
		if err := crypto.Sign(ao, n.key); err != nil {
			return nil, err
		}

		if err := Write(ao, conn); err != nil {
			return nil, err
		}

		return conn, nil
	default:
		logger.Info("not sure how to dial", zap.String("address", address), zap.String("type", addressType))
	}

	return nil, ErrNoAddresses
}

// Listen on an address
// TODO do we need to return a listener?
func (n *network) Listen(ctx context.Context, address string) (chan *Connection, error) {
	logger := log.Logger(ctx).Named("network")
	cert, err := crypto.GenerateCertificate(n.key)
	if err != nil {
		return nil, err
	}

	now := time.Now()
	config := tls.Config{
		Certificates: []tls.Certificate{*cert},
	}
	config.NextProtos = []string{"nimona/1"} // TODO(geoah) is this of any actual use?
	config.Time = func() time.Time { return now }
	config.Rand = rand.Reader
	tcpListener, err := tls.Listen("tcp", address, &config)
	if err != nil {
		return nil, err
	}

	port := tcpListener.Addr().(*net.TCPAddr).Port
	logger.Info("Listening and service nimona", zap.Int("port", port))
	addresses := GetAddresses(tcpListener)
	devices := make(chan igd.Device, 10)

	if n.hostname != "" {
		addresses = append(addresses, fmtAddress(n.hostname, port))
	}

	if UseUPNP {
		logger.Info("Trying to find external IP and open port")
		go func() {
			if err := igd.Discover(devices, 2*time.Second); err != nil {
				logger.Error("could not discover devices", zap.Error(err))
			}
		}()
		for device := range devices {
			externalAddress, err := device.GetExternalIPAddress()
			if err != nil {
				logger.Error("could not get external ip", zap.Error(err))
				continue
			}
			desc := "nimona"
			ttl := time.Hour * 24 * 365
			if _, err := device.AddPortMapping(igd.TCP, port, port, desc, ttl); err != nil {
				logger.Error("could not add port mapping", zap.Error(err))
			} else {
				addresses = append(addresses, fmtAddress(externalAddress.String(), port))
			}
		}
	}

	logger.Info("Started listening", zap.Strings("addresses", addresses))
	n.addAddress(addresses...)
	n.addAddress(n.relayAddresses...)

	cconn := make(chan *Connection, 10)
	go func() {

		for {
			tcpConn, err := tcpListener.Accept()
			if err != nil {
				log.DefaultLogger.Warn("could not accept connection", zap.Error(err))
				// TODO close conn?
				return
			}

			conn := &Connection{
				Conn:          tcpConn,
				RemotePeerKey: nil,
			}

			synObj, err := Read(conn)
			if err != nil {
				log.DefaultLogger.Warn("waiting for syn failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			syn := &HandshakeSyn{}
			if err := syn.FromObject(synObj); err != nil {
				log.DefaultLogger.Warn("could not convert obj to syn")
				// TODO close conn?
				continue
			}

			// store the remote peer
			conn.RemotePeerKey = syn.PeerInfo.SignerKey
			n.discoverer.Add(syn.PeerInfo)

			synAck := &HandshakeSynAck{
				Nonce:    syn.Nonce,
				PeerInfo: n.GetPeerInfo(),
			}
			sao := synAck.ToObject()
			if err := crypto.Sign(sao, n.key); err != nil {
				log.DefaultLogger.Warn("could not sign for syn ack object", zap.Error(err))
				// TODO close conn?
				continue
			}
			if err := Write(sao, conn); err != nil {
				log.DefaultLogger.Warn("sending for syn-ack failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			ackObj, err := Read(conn)
			if err != nil {
				log.DefaultLogger.Warn("waiting for ack failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			ack := &HandshakeAck{}
			if err := ack.FromObject(ackObj); err != nil {
				// TODO close conn?
				log.DefaultLogger.Warn("could not convert obj to syn ack")
				continue
			}

			if ack.Nonce != syn.Nonce {
				log.DefaultLogger.Warn("validating syn to ack nonce failed")
				// TODO close conn?
				continue
			}

			cconn <- conn
		}
	}()

	return cconn, nil
}
func (n *network) AttachMandate(m *crypto.Mandate) error {
	// TODO(geoah): Check if our peer key is the mandate's subject
	n.addressesLock.Lock()
	n.mandate = m
	n.addressesLock.Unlock()
	return nil
}

func Write(o *object.Object, conn *Connection) error {
	conn.Conn.SetWriteDeadline(time.Now().Add(time.Second))
	if o == nil {
		log.DefaultLogger.Error("object for fw cannot be nil")
		return errors.New("missing object")
	}

	b, err := object.Marshal(o)
	if err != nil {
		return err
	}

	ra := ""
	if conn.RemotePeerKey != nil {
		ra = conn.RemotePeerKey.HashBase58()
	}

	if os.Getenv("DEBUG_BLOCKS") == "true" {
		b, _ := json.MarshalIndent(o.ToMap(), "", "  ")
		log.DefaultLogger.Info(
			string(b),
			zap.String("remote_peer_hash", ra),
			zap.String("direction", "outgoing"),
		)
	}

	if _, err := conn.Conn.Write(b); err != nil {
		return err
	}

	SendObjectEvent(
		"outgoing",
		o.GetType(),
		len(b),
	)

	return nil
}

func Read(conn *Connection) (*object.Object, error) {
	logger := log.DefaultLogger

	pDecoder := codec.NewDecoder(conn.Conn, object.RawCborHandler())
	r := &codec.Raw{}
	if err := pDecoder.Decode(r); err != nil {
		return nil, err
	}

	defer func() {
		if r := recover(); r != nil {
			logger.Error("Recovered while processing", zap.Any("r", r))
		}
	}()

	o, err := object.FromBytes([]byte(*r))
	if err != nil {
		return nil, err
	}

	ra := ""
	if conn.RemotePeerKey != nil {
		ra = conn.RemotePeerKey.HashBase58()
	}

	if o.GetSignature() != nil {
		if err := crypto.Verify(o); err != nil {
			return nil, err
		}
	} else {
		fmt.Println("--------------------------------------------------------")
		fmt.Println("----- BLOCK NOT SIGNED ---------------------------------")
		fmt.Println("--------------------------------------------------------")
		fmt.Println("-----", o.GetType())
		fmt.Println("-----", o)
		fmt.Println("--------------------------------------------------------")
	}

	SendObjectEvent(
		"incoming",
		o.GetType(),
		pDecoder.NumBytesRead(),
	)
	if os.Getenv("DEBUG_BLOCKS") == "true" {
		b, _ := json.MarshalIndent(o.ToMap(), "", "  ")
		logger.Info(
			string(b),
			zap.String("remote_peer_hash", ra),
			zap.String("direction", "incoming"),
		)
	}
	return o, nil
}

func (n *network) addAddress(addrs ...string) {
	n.addressesLock.Lock()
	if n.addresses == nil {
		n.addresses = []string{}
	}
	n.addresses = append(n.addresses, addrs...)
	n.addressesLock.Unlock()
}

// GetPeerInfo returns the local peer info
func (n *network) GetPeerInfo() *peer.PeerInfo {
	// TODO cache peer info and reuse
	p := &peer.PeerInfo{
		SignerKey: n.key.GetPublicKey(),
	}

	n.addressesLock.RLock()
	p.Addresses = n.addresses
	if n.mandate != nil {
		p.AuthorityKey = n.mandate.Signer
		p.Mandate = n.mandate
	}
	n.addressesLock.RUnlock()

	o := p.ToObject()
	if err := crypto.Sign(o, n.key); err != nil {
		panic(err)
	}
	p.FromObject(o)
	return p
}
<commit_msg>Move dial to peer and address to funcs<commit_after>package net

import (
	"context"
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	igd "github.com/emersion/go-upnp-igd"
	"github.com/ugorji/go/codec"
	"go.uber.org/zap"

	"nimona.io/internal/log"
	"nimona.io/pkg/crypto"
	"nimona.io/pkg/discovery"
	"nimona.io/pkg/net/peer"
	"nimona.io/pkg/object"
)

var (
	UseUPNP = false
)

func init() {
	UseUPNP, _ = strconv.ParseBool(os.Getenv("UPNP"))
}

// Network interface
type Network interface {
	Dial(ctx context.Context, address string) (*Connection, error)
	Listen(ctx context.Context, addrress string) (chan *Connection, error)

	GetPeerInfo() *peer.PeerInfo
	AttachMandate(m *crypto.Mandate) error
}

// New creates a new p2p network using an address book
func New(key *crypto.Key, hostname string, relayAddresses []string,
	discover discovery.Discoverer) (Network, error) {
	if key == nil {
		return nil, ErrMissingKey
	}

	if _, ok := key.Materialize().(*ecdsa.PrivateKey); !ok {
		return nil, ErrECDSAPrivateKeyRequired
	}

	return &network{
		key:            key,
		discoverer:     discover,
		hostname:       hostname,
		relayAddresses: relayAddresses,
	}, nil
}

// network allows dialing and listening for p2p connections
type network struct {
	key            *crypto.Key
	discoverer     discovery.Discoverer
	hostname       string
	addressesLock  sync.RWMutex
	addresses      []string
	relayAddresses []string
	mandate        *crypto.Mandate
}

// Dial to a peer and return a net.Conn or error
func (n *network) Dial(ctx context.Context, address string) (
	*Connection, error) {
	logger := log.Logger(ctx)

	addressType := strings.Split(address, ":")[0]
	switch addressType {
	case "peer":
		return n.dialPeer(ctx, address)
	case "tcps":
		return n.dialAddress(ctx, address)
	default:
		logger.Info("not sure how to dial",
			zap.String("address", address),
			zap.String("type", addressType))
	}

	return nil, ErrNoAddresses
}

// Listen on an address
// TODO do we need to return a listener?
func (n *network) Listen(ctx context.Context, address string) (chan *Connection, error) {
	logger := log.Logger(ctx).Named("network")
	cert, err := crypto.GenerateCertificate(n.key)
	if err != nil {
		return nil, err
	}

	now := time.Now()
	config := tls.Config{
		Certificates: []tls.Certificate{*cert},
	}
	config.NextProtos = []string{"nimona/1"} // TODO(geoah) is this of any actual use?
	config.Time = func() time.Time { return now }
	config.Rand = rand.Reader
	tcpListener, err := tls.Listen("tcp", address, &config)
	if err != nil {
		return nil, err
	}

	port := tcpListener.Addr().(*net.TCPAddr).Port
	logger.Info("Listening and service nimona", zap.Int("port", port))
	addresses := GetAddresses(tcpListener)
	devices := make(chan igd.Device, 10)

	if n.hostname != "" {
		addresses = append(addresses, fmtAddress(n.hostname, port))
	}

	if UseUPNP {
		logger.Info("Trying to find external IP and open port")
		go func() {
			if err := igd.Discover(devices, 2*time.Second); err != nil {
				logger.Error("could not discover devices", zap.Error(err))
			}
		}()
		for device := range devices {
			externalAddress, err := device.GetExternalIPAddress()
			if err != nil {
				logger.Error("could not get external ip", zap.Error(err))
				continue
			}
			desc := "nimona"
			ttl := time.Hour * 24 * 365
			if _, err := device.AddPortMapping(igd.TCP, port, port, desc, ttl); err != nil {
				logger.Error("could not add port mapping", zap.Error(err))
			} else {
				addresses = append(addresses, fmtAddress(externalAddress.String(), port))
			}
		}
	}

	logger.Info("Started listening", zap.Strings("addresses", addresses))
	n.addAddress(addresses...)
	n.addAddress(n.relayAddresses...)

	cconn := make(chan *Connection, 10)
	go func() {

		for {
			tcpConn, err := tcpListener.Accept()
			if err != nil {
				log.DefaultLogger.Warn("could not accept connection", zap.Error(err))
				// TODO close conn?
				return
			}

			conn := &Connection{
				Conn:          tcpConn,
				RemotePeerKey: nil,
			}

			synObj, err := Read(conn)
			if err != nil {
				log.DefaultLogger.Warn("waiting for syn failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			syn := &HandshakeSyn{}
			if err := syn.FromObject(synObj); err != nil {
				log.DefaultLogger.Warn("could not convert obj to syn")
				// TODO close conn?
				continue
			}

			// store the remote peer
			conn.RemotePeerKey = syn.PeerInfo.SignerKey
			n.discoverer.Add(syn.PeerInfo)

			synAck := &HandshakeSynAck{
				Nonce:    syn.Nonce,
				PeerInfo: n.GetPeerInfo(),
			}
			sao := synAck.ToObject()
			if err := crypto.Sign(sao, n.key); err != nil {
				log.DefaultLogger.Warn("could not sign for syn ack object", zap.Error(err))
				// TODO close conn?
				continue
			}
			if err := Write(sao, conn); err != nil {
				log.DefaultLogger.Warn("sending for syn-ack failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			ackObj, err := Read(conn)
			if err != nil {
				log.DefaultLogger.Warn("waiting for ack failed", zap.Error(err))
				// TODO close conn?
				continue
			}

			ack := &HandshakeAck{}
			if err := ack.FromObject(ackObj); err != nil {
				// TODO close conn?
				log.DefaultLogger.Warn("could not convert obj to syn ack")
				continue
			}

			if ack.Nonce != syn.Nonce {
				log.DefaultLogger.Warn("validating syn to ack nonce failed")
				// TODO close conn?
				continue
			}

			cconn <- conn
		}
	}()

	return cconn, nil
}
func (n *network) AttachMandate(m *crypto.Mandate) error {
	// TODO(geoah): Check if our peer key is the mandate's subject
	n.addressesLock.Lock()
	n.mandate = m
	n.addressesLock.Unlock()
	return nil
}

func Write(o *object.Object, conn *Connection) error {
	conn.Conn.SetWriteDeadline(time.Now().Add(time.Second))
	if o == nil {
		log.DefaultLogger.Error("object for fw cannot be nil")
		return errors.New("missing object")
	}

	b, err := object.Marshal(o)
	if err != nil {
		return err
	}

	ra := ""
	if conn.RemotePeerKey != nil {
		ra = conn.RemotePeerKey.HashBase58()
	}

	if os.Getenv("DEBUG_BLOCKS") == "true" {
		b, _ := json.MarshalIndent(o.ToMap(), "", "  ")
		log.DefaultLogger.Info(
			string(b),
			zap.String("remote_peer_hash", ra),
			zap.String("direction", "outgoing"),
		)
	}

	if _, err := conn.Conn.Write(b); err != nil {
		return err
	}

	SendObjectEvent(
		"outgoing",
		o.GetType(),
		len(b),
	)

	return nil
}

func Read(conn *Connection) (*object.Object, error) {
	logger := log.DefaultLogger

	pDecoder := codec.NewDecoder(conn.Conn, object.RawCborHandler())
	r := &codec.Raw{}
	if err := pDecoder.Decode(r); err != nil {
		return nil, err
	}

	defer func() {
		if r := recover(); r != nil {
			logger.Error("Recovered while processing", zap.Any("r", r))
		}
	}()

	o, err := object.FromBytes([]byte(*r))
	if err != nil {
		return nil, err
	}

	ra := ""
	if conn.RemotePeerKey != nil {
		ra = conn.RemotePeerKey.HashBase58()
	}

	if o.GetSignature() != nil {
		if err := crypto.Verify(o); err != nil {
			return nil, err
		}
	} else {
		fmt.Println("--------------------------------------------------------")
		fmt.Println("----- BLOCK NOT SIGNED ---------------------------------")
		fmt.Println("--------------------------------------------------------")
		fmt.Println("-----", o.GetType())
		fmt.Println("-----", o)
		fmt.Println("--------------------------------------------------------")
	}

	SendObjectEvent(
		"incoming",
		o.GetType(),
		pDecoder.NumBytesRead(),
	)
	if os.Getenv("DEBUG_BLOCKS") == "true" {
		b, _ := json.MarshalIndent(o.ToMap(), "", "  ")
		logger.Info(
			string(b),
			zap.String("remote_peer_hash", ra),
			zap.String("direction", "incoming"),
		)
	}
	return o, nil
}

func (n *network) addAddress(addrs ...string) {
	n.addressesLock.Lock()
	if n.addresses == nil {
		n.addresses = []string{}
	}
	n.addresses = append(n.addresses, addrs...)
	n.addressesLock.Unlock()
}

// GetPeerInfo returns the local peer info
func (n *network) GetPeerInfo() *peer.PeerInfo {
	// TODO cache peer info and reuse
	p := &peer.PeerInfo{
		SignerKey: n.key.GetPublicKey(),
	}

	n.addressesLock.RLock()
	p.Addresses = n.addresses
	if n.mandate != nil {
		p.AuthorityKey = n.mandate.Signer
		p.Mandate = n.mandate
	}
	n.addressesLock.RUnlock()

	o := p.ToObject()
	if err := crypto.Sign(o, n.key); err != nil {
		panic(err)
	}
	p.FromObject(o)
	return p
}

func (n *network) dialPeer(ctx context.Context, address string) (
	*Connection, error) {
	logger := log.Logger(ctx)

	peerID := strings.Replace(address, "peer:", "", 1)
	if peerID == n.key.GetPublicKey().HashBase58() {
		return nil, errors.New("cannot dial our own peer")
	}
	logger.Debug("dialing peer", zap.String("peer", address))
	q := &peer.PeerInfoRequest{
		SignerKeyHash: peerID,
	}
	ps, err := n.discoverer.Discover(q)
	if err != nil {
		return nil, err
	}

	if len(ps) == 0 || len(ps[0].Addresses) == 0 {
		return nil, ErrNoAddresses
	}

	// TODO we should probably try all results
	for _, addr := range ps[0].Addresses {
		conn, err := n.Dial(ctx, addr)
		if err == nil {
			return conn, nil
		}
	}

	return nil, ErrAllAddressesFailed

}

func (n *network) dialAddress(ctx context.Context, address string) (
	*Connection, error) {

	// find dialer
	// execute middleware
	config := tls.Config{
		InsecureSkipVerify: true,
	}
	addr := strings.Replace(address, "tcps:", "", 1)
	dialer := net.Dialer{Timeout: time.Second}
	tcpConn, err := tls.DialWithDialer(&dialer, "tcp", addr, &config)
	if err != nil {
		return nil, err
	}

	if tcpConn == nil {
		return nil, ErrAllAddressesFailed
	}

	conn := &Connection{
		Conn:          tcpConn,
		RemotePeerKey: nil, // we don't really know who the other side is
	}

	nonce := RandStringBytesMaskImprSrc(8)
	syn := &HandshakeSyn{
		Nonce:    nonce,
		PeerInfo: n.GetPeerInfo(),
	}
	so := syn.ToObject()
	if err := crypto.Sign(so, n.key); err != nil {
		return nil, err
	}

	if err := Write(so, conn); err != nil {
		return nil, err
	}

	synAckObj, err := Read(conn)
	if err != nil {
		return nil, err
	}

	synAck := &HandshakeSynAck{}
	if err := synAck.FromObject(synAckObj); err != nil {
		return nil, err
	}

	if synAck.Nonce != nonce {
		return nil, errors.New("invalid handhshake.syn-ack")
	}

	// store who is on the other side
	conn.RemotePeerKey = synAck.PeerInfo.SignerKey
	n.discoverer.Add(synAck.PeerInfo)

	ack := &HandshakeAck{
		Nonce: nonce,
	}
	ao := ack.ToObject()
	if err := crypto.Sign(ao, n.key); err != nil {
		return nil, err
	}

	if err := Write(ao, conn); err != nil {
		return nil, err
	}

	return conn, nil
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"strconv"
	"strings"
	"unicode"

	"github.com/alecthomas/participle/v2/lexer"
)

var escapeTable = map[rune]rune{
	'0':  '\000',
	'a':  '\x07',
	'b':  '\x08',
	'e':  '\x1B',
	'f':  '\x0C',
	'n':  '\x0A',
	'r':  '\x0D',
	't':  '\x09',
	'v':  '\x0B',
	'\\': '\x5C',
	'\'': '\x27',
	'"':  '\x22',
	'?':  '\x3F',
}
var stateBase = map[unquoteState]int{
	uqHex: 16, uqOctal: 8,
}

type unquoteState int

const (
	uqDefault unquoteState = iota
	uqEscape
	uqHex
	uqOctal
)

// C-style unquoting - supports octal \DDD and hex \xDDD
func unquote(token lexer.Token) (lexer.Token, error) {
	kind := token.Value[0] // nolint: ifshort
	token.Value = token.Value[1 : len(token.Value)-1]
	// Single quoted, no escaping.
	if kind == '\'' {
		return token, nil
	}
	out := strings.Builder{}
	state := uqDefault
	// Digits being collected in hex/octal modes
	var digits string
	for _, rn := range token.Value {
		switch state {
		case uqEscape:
			if rn == 'x' { // nolint: gocritic
				state = uqHex
			} else if unicode.Is(unicode.Digit, rn) {
				state = uqOctal
				digits = string(rn)
			} else {
				escaped, ok := escapeTable[rn]
				if !ok {
					return token, fmt.Errorf("%s: %q: unknown escape sequence \"\\%c\"", token.Pos, token.Value, rn)
				}
				out.WriteRune(escaped)
				state = uqDefault
			}
		case uqHex:
			if unicode.Is(unicode.ASCII_Hex_Digit, rn) {
				digits += string(rn)
			} else {
				if err := flushDigits(digits, 16, &out); err != nil {
					return token, fmt.Errorf("%s: %w", token.Pos, err)
				}
				state = uqDefault
				digits = ""
			}
		case uqOctal:
			if unicode.IsDigit(rn) {
				digits += string(rn)
			} else {
				if err := flushDigits(digits, 8, &out); err != nil {
					return token, fmt.Errorf("%s: %w", token.Pos, err)
				}
				state = uqDefault
				digits = ""
			}
		case uqDefault:
			if rn == '\\' {
				state = uqEscape
			} else {
				out.WriteRune(rn)
			}
		default:
			panic(state)
		}
	}
	if digits != "" {
		if err := flushDigits(digits, stateBase[state], &out); err != nil {
			return token, fmt.Errorf("%s: %w", token.Pos, err)
		}
	}
	token.Value = out.String()
	return token, nil
}

func flushDigits(digits string, base int, out *strings.Builder) error {
	n, err := strconv.ParseUint(digits, base, 32)
	if err != nil {
		return fmt.Errorf("invalid base %d numeric value %s", base, digits)
	}
	out.WriteRune(rune(n))
	return nil
}
<commit_msg>Gofumpted unquoted.go to fix linter error<commit_after>package parser

import (
	"fmt"
	"strconv"
	"strings"
	"unicode"

	"github.com/alecthomas/participle/v2/lexer"
)

var escapeTable = map[rune]rune{
	'0':  '\000',
	'a':  '\x07',
	'b':  '\x08',
	'e':  '\x1B',
	'f':  '\x0C',
	'n':  '\x0A',
	'r':  '\x0D',
	't':  '\x09',
	'v':  '\x0B',
	'\\': '\x5C',
	'\'': '\x27',
	'"':  '\x22',
	'?':  '\x3F',
}

var stateBase = map[unquoteState]int{
	uqHex: 16, uqOctal: 8,
}

type unquoteState int

const (
	uqDefault unquoteState = iota
	uqEscape
	uqHex
	uqOctal
)

// C-style unquoting - supports octal \DDD and hex \xDDD
func unquote(token lexer.Token) (lexer.Token, error) {
	kind := token.Value[0] // nolint: ifshort
	token.Value = token.Value[1 : len(token.Value)-1]
	// Single quoted, no escaping.
	if kind == '\'' {
		return token, nil
	}
	out := strings.Builder{}
	state := uqDefault
	// Digits being collected in hex/octal modes
	var digits string
	for _, rn := range token.Value {
		switch state {
		case uqEscape:
			if rn == 'x' { // nolint: gocritic
				state = uqHex
			} else if unicode.Is(unicode.Digit, rn) {
				state = uqOctal
				digits = string(rn)
			} else {
				escaped, ok := escapeTable[rn]
				if !ok {
					return token, fmt.Errorf("%s: %q: unknown escape sequence \"\\%c\"", token.Pos, token.Value, rn)
				}
				out.WriteRune(escaped)
				state = uqDefault
			}
		case uqHex:
			if unicode.Is(unicode.ASCII_Hex_Digit, rn) {
				digits += string(rn)
			} else {
				if err := flushDigits(digits, 16, &out); err != nil {
					return token, fmt.Errorf("%s: %w", token.Pos, err)
				}
				state = uqDefault
				digits = ""
			}
		case uqOctal:
			if unicode.IsDigit(rn) {
				digits += string(rn)
			} else {
				if err := flushDigits(digits, 8, &out); err != nil {
					return token, fmt.Errorf("%s: %w", token.Pos, err)
				}
				state = uqDefault
				digits = ""
			}
		case uqDefault:
			if rn == '\\' {
				state = uqEscape
			} else {
				out.WriteRune(rn)
			}
		default:
			panic(state)
		}
	}
	if digits != "" {
		if err := flushDigits(digits, stateBase[state], &out); err != nil {
			return token, fmt.Errorf("%s: %w", token.Pos, err)
		}
	}
	token.Value = out.String()
	return token, nil
}

func flushDigits(digits string, base int, out *strings.Builder) error {
	n, err := strconv.ParseUint(digits, base, 32)
	if err != nil {
		return fmt.Errorf("invalid base %d numeric value %s", base, digits)
	}
	out.WriteRune(rune(n))
	return nil
}
<|endoftext|>


<commit_before>package build

import (
	"strconv"
	"strings"
)

type Index struct {
	Index []int
}

func NewIndex() *Index {
	index := Index{
		Index: make([]int, 1),
	}
	return &index
}

func (index *Index) Expand() {
	index.Index = append(index.Index, 0)
}

func (index *Index) Shrink() {
	index.Index = index.Index[:len(index.Index)-1]
}

func (index *Index) Set(i int) {
	index.Index[len(index.Index)-1] = i
}

func (index *Index) String() string {
	var str []string
	for _, i := range index.Index {
		str = append(str, strconv.Itoa(i+1))
	}
	return strings.Join(str, ".")
}

func (index *Index) Len() int {
	return len(index.Index)
}
<commit_msg>Code cleaning<commit_after>package build

import (
	"strconv"
	"strings"
)

// Index structure. This keeps track of steps in execution stack. For instance,
// Index will be [1, 2, 3] while running 3rd steps of the second step of the
// first step. This is used to print error location (error in step 1.2.3).
type Index struct {
	Index []int
}

// Make an index
func NewIndex() *Index {
	index := Index{
		Index: make([]int, 1),
	}
	return &index
}

// Expands the index, adding an element after the last
func (index *Index) Expand() {
	index.Index = append(index.Index, 0)
}

// Shrinks the index, removing the last element
func (index *Index) Shrink() {
	index.Index = index.Index[:len(index.Index)-1]
}

// Set the value of the last element
func (index *Index) Set(i int) {
	index.Index[len(index.Index)-1] = i
}

// Return string representation of the index ("1.2.3" for instance)
func (index *Index) String() string {
	var str []string
	for _, i := range index.Index {
		str = append(str, strconv.Itoa(i+1))
	}
	return strings.Join(str, ".")
}

// Return length of the index as an integer
func (index *Index) Len() int {
	return len(index.Index)
}
<|endoftext|>


<commit_before>package work_test

import (
	"errors"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	"github.com/cloudfoundry/bosh-utils/work"
)

var _ = Describe("Pool", func() {
	It("runs the given tasks", func() {
		pool := work.Pool{
			Count: 2,
		}

		resultsChan := make(chan int, 3)

		err := pool.ParallelDo(
			func() error {
				resultsChan <- 1
				return nil
			},
			func() error {
				resultsChan <- 2
				return nil
			},
			func() error {
				resultsChan <- 3
				return nil
			},
		)
		Expect(err).ToNot(HaveOccurred())

		Expect(resultsChan).To(Receive(Equal(1)))
		Expect(resultsChan).To(Receive(Equal(2)))
		Expect(resultsChan).To(Receive(Equal(3)))
	})

	It("bubbles up any errors", func() {
		pool := work.Pool{
			Count: 2,
		}

		err := pool.ParallelDo(
			func() error {
				return nil
			},
			func() error {
				return bosherr.ComplexError{
					Err:   errors.New("fake-error"),
					Cause: errors.New("fake-cause"),
				}
			},
			func() error {
				return nil
			},
		)

		Expect(err).To(HaveOccurred())
		Expect(err.Error()).To(ContainSubstring("fake-error"))
		Expect(err.Error()).To(ContainSubstring("fake-cause"))
	})

	It("stops working after the first error", func() {
		pool := work.Pool{
			Count: 1, // Force serial run
		}

		err := pool.ParallelDo(
			func() error {
				return nil
			},
			func() error {
				return bosherr.ComplexError{
					Err:   errors.New("fake-error"),
					Cause: errors.New("fake-cause"),
				}
			},
			func() error {
				Fail("Expected third test to not run")
				return nil
			},
			func() error {
				Fail("Expected fourth test to not run")
				return nil
			},
		)
		Expect(err).To(HaveOccurred())
		Expect(err.Error()).To(ContainSubstring("fake-error"))
		Expect(err.Error()).To(ContainSubstring("fake-cause"))
	})
})
<commit_msg>Fix flakey work pool test.<commit_after>package work_test

import (
	"errors"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	"github.com/cloudfoundry/bosh-utils/work"
)

var _ = Describe("Pool", func() {
	It("runs the given tasks", func() {
		pool := work.Pool{
			Count: 2,
		}

		resultsChan := make(chan int, 3)

		err := pool.ParallelDo(
			func() error {
				resultsChan <- 1
				return nil
			},
			func() error {
				resultsChan <- 2
				return nil
			},
			func() error {
				resultsChan <- 3
				return nil
			},
		)
		Expect(err).ToNot(HaveOccurred())
		close(resultsChan)

		results := []int{}
		for result := range resultsChan {
			results = append(results, result)
		}
		Expect(results).To(ContainElement(1))
		Expect(results).To(ContainElement(2))
		Expect(results).To(ContainElement(3))
	})

	It("bubbles up any errors", func() {
		pool := work.Pool{
			Count: 2,
		}

		err := pool.ParallelDo(
			func() error {
				return nil
			},
			func() error {
				return bosherr.ComplexError{
					Err:   errors.New("fake-error"),
					Cause: errors.New("fake-cause"),
				}
			},
			func() error {
				return nil
			},
		)

		Expect(err).To(HaveOccurred())
		Expect(err.Error()).To(ContainSubstring("fake-error"))
		Expect(err.Error()).To(ContainSubstring("fake-cause"))
	})

	It("stops working after the first error", func() {
		pool := work.Pool{
			Count: 1, // Force serial run
		}

		err := pool.ParallelDo(
			func() error {
				return nil
			},
			func() error {
				return bosherr.ComplexError{
					Err:   errors.New("fake-error"),
					Cause: errors.New("fake-cause"),
				}
			},
			func() error {
				Fail("Expected third test to not run")
				return nil
			},
			func() error {
				Fail("Expected fourth test to not run")
				return nil
			},
		)
		Expect(err).To(HaveOccurred())
		Expect(err.Error()).To(ContainSubstring("fake-error"))
		Expect(err.Error()).To(ContainSubstring("fake-cause"))
	})
})
<|endoftext|>


<commit_before>package wormhole

import (
	"errors"
	"os"
	"path"
	"path/filepath"
	"strings"
)

type Error interface {
	Error() string
}

type WormholeConfig struct {
	Addr    string            `yaml:"listen,omitempty"`
	Mapping map[string]string `yaml:"mapping"`
	App     map[string]string `yaml:"apps"`
}

func GetDefaultConfig() string {
	return path.Join(os.Getenv("HOME"), ".wormhole.yml")
}

func (this *WormholeConfig) GetAddr() string {
	if "" == this.Addr {
		return "127.0.0.1:5115"
	}

	return this.Addr
}

func (this *WormholeConfig) GetApp(key string) (app *App, err Error) {
	cmdline, ok := this.App[key]

	if !ok {
		return nil, errors.New("No mapping for '" + key + "'")
	}

	parts := strings.Split(cmdline, " ")
	return &App{
		Executable: parts[0],
		Args:       parts[1:],
	}, nil
}

func (this *WormholeConfig) GetAppWith(key string, args []string) (app *App, err Error) {
	if app, err = this.GetApp(key); err != nil {
		return app, err
	}

	app.MergeArguments(this.translatePaths(args))
	return app, nil
}

func (this *WormholeConfig) AvailableApps() string {
	var keys []string

	for key, _ := range this.App {
		keys = append(keys, key)
	}

	return strings.Join(keys, ", ")
}

func (this *WormholeConfig) translatePath(path string) string {
	for from, to := range this.Mapping {
		path = strings.Replace(path, from, to, 1)
	}

	return filepath.FromSlash(path)
}

func (this *WormholeConfig) translatePaths(paths []string) []string {
	for index, arg := range paths {
		paths[index] = this.translatePath(arg)
	}

	return paths
}

type App struct {
	Executable string
	Args       []string
}

func (this *App) MergeArguments(args []string) {
	this.Args = append(this.Args, args...)
}
<commit_msg>Revert splitting commandlines<commit_after>package wormhole

import (
	"errors"
	"os"
	"path"
	"path/filepath"
	"strings"
)

type Error interface {
	Error() string
}

type WormholeConfig struct {
	Addr    string            `yaml:"listen,omitempty"`
	Mapping map[string]string `yaml:"mapping"`
	App     map[string]string `yaml:"apps"`
}

func GetDefaultConfig() string {
	return path.Join(os.Getenv("HOME"), ".wormhole.yml")
}

func (this *WormholeConfig) GetAddr() string {
	if "" == this.Addr {
		return "127.0.0.1:5115"
	}

	return this.Addr
}

func (this *WormholeConfig) GetApp(key string) (app *App, err Error) {
	cmdline, ok := this.App[key]

	if !ok {
		return nil, errors.New("No mapping for '" + key + "'")
	}

	return &App{
		Executable: cmdline,
		Args:       []string{},
	}, nil
}

func (this *WormholeConfig) GetAppWith(key string, args []string) (app *App, err Error) {
	if app, err = this.GetApp(key); err != nil {
		return app, err
	}

	app.MergeArguments(this.translatePaths(args))
	return app, nil
}

func (this *WormholeConfig) AvailableApps() string {
	var keys []string

	for key, _ := range this.App {
		keys = append(keys, key)
	}

	return strings.Join(keys, ", ")
}

func (this *WormholeConfig) translatePath(path string) string {
	for from, to := range this.Mapping {
		path = strings.Replace(path, from, to, 1)
	}

	return filepath.FromSlash(path)
}

func (this *WormholeConfig) translatePaths(paths []string) []string {
	for index, arg := range paths {
		paths[index] = this.translatePath(arg)
	}

	return paths
}

type App struct {
	Executable string
	Args       []string
}

func (this *App) MergeArguments(args []string) {
	this.Args = append(this.Args, args...)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

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 agreedto 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 vtgate

import (
	"flag"
	"fmt"
	"net"
	"os"
	"sync/atomic"
	"syscall"
	"time"

	log "github.com/golang/glog"
	"golang.org/x/net/context"

	"github.com/youtube/vitess/go/mysql"
	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/vt/callerid"
	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/vttls"

	querypb "github.com/youtube/vitess/go/vt/proto/query"
	vtgatepb "github.com/youtube/vitess/go/vt/proto/vtgate"
)

var (
	mysqlServerPort               = flag.Int("mysql_server_port", -1, "If set, also listen for MySQL binary protocol connections on this port.")
	mysqlServerBindAddress        = flag.String("mysql_server_bind_address", "", "Binds on this address when listening to MySQL binary protocol. Useful to restrict listening to 'localhost' only for instance.")
	mysqlServerSocketPath         = flag.String("mysql_server_socket_path", "", "This option specifies the Unix socket file to use when listening for local connections. By default it will be empty and it won't listen to a unix socket")
	mysqlAuthServerImpl           = flag.String("mysql_auth_server_impl", "static", "Which auth server implementation to use.")
	mysqlAllowClearTextWithoutTLS = flag.Bool("mysql_allow_clear_text_without_tls", false, "If set, the server will allow the use of a clear text password over non-SSL connections.")

	mysqlSslCert = flag.String("mysql_server_ssl_cert", "", "Path to the ssl cert for mysql server plugin SSL")
	mysqlSslKey  = flag.String("mysql_server_ssl_key", "", "Path to ssl key for mysql server plugin SSL")
	mysqlSslCa   = flag.String("mysql_server_ssl_ca", "", "Path to ssl CA for mysql server plugin SSL. If specified, server will require and validate client certs.")

	mysqlSlowConnectWarnThreshold = flag.Duration("mysql_slow_connect_warn_threshold", 0, "Warn if it takes more than the given threshold for a mysql connection to establish")

	busyConnections int32
)

// vtgateHandler implements the Listener interface.
// It stores the Session in the ClientData of a Connection, if a transaction
// is in progress.
type vtgateHandler struct {
	vtg *VTGate
}

func newVtgateHandler(vtg *VTGate) *vtgateHandler {
	return &vtgateHandler{
		vtg: vtg,
	}
}

func (vh *vtgateHandler) NewConnection(c *mysql.Conn) {
}

func (vh *vtgateHandler) ConnectionClosed(c *mysql.Conn) {
	// Rollback if there is an ongoing transaction. Ignore error.
	ctx := context.Background()
	session, _ := c.ClientData.(*vtgatepb.Session)
	if session != nil {
		if session.InTransaction {
			defer atomic.AddInt32(&busyConnections, -1)
		}
		_, _, _ = vh.vtg.Execute(ctx, session, "rollback", make(map[string]*querypb.BindVariable))
	}
}

func (vh *vtgateHandler) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error {
	// FIXME(alainjobart): Add some kind of timeout to the context.
	ctx := context.Background()

	// Fill in the ImmediateCallerID with the UserData returned by
	// the AuthServer plugin for that user. If nothing was
	// returned, use the User. This lets the plugin map a MySQL
	// user used for authentication to a Vitess User used for
	// Table ACLs and Vitess authentication in general.
	im := c.UserData.Get()
	ef := callerid.NewEffectiveCallerID(
		c.User,                  /* principal: who */
		c.RemoteAddr().String(), /* component: running client process */
		"VTGate MySQL Connector" /* subcomponent: part of the client */)
	ctx = callerid.NewContext(ctx, ef, im)

	session, _ := c.ClientData.(*vtgatepb.Session)
	if session == nil {
		session = &vtgatepb.Session{
			Options: &querypb.ExecuteOptions{
				IncludedFields: querypb.ExecuteOptions_ALL,
			},
			Autocommit: true,
		}
		if c.Capabilities&mysql.CapabilityClientFoundRows != 0 {
			session.Options.ClientFoundRows = true
		}
	}

	if !session.InTransaction {
		atomic.AddInt32(&busyConnections, 1)
	}
	defer func() {
		if !session.InTransaction {
			atomic.AddInt32(&busyConnections, -1)
		}
	}()

	if c.SchemaName != "" {
		session.TargetString = c.SchemaName
	}
	if session.Options.Workload == querypb.ExecuteOptions_OLAP {
		err := vh.vtg.StreamExecute(ctx, session, query, make(map[string]*querypb.BindVariable), callback)
		return mysql.NewSQLErrorFromError(err)
	}
	session, result, err := vh.vtg.Execute(ctx, session, query, make(map[string]*querypb.BindVariable))
	c.ClientData = session
	err = mysql.NewSQLErrorFromError(err)
	if err != nil {
		return err
	}
	return callback(result)
}

var mysqlListener *mysql.Listener
var mysqlUnixListener *mysql.Listener

// initiMySQLProtocol starts the mysql protocol.
// It should be called only once in a process.
func initMySQLProtocol() {
	// Flag is not set, just return.
	if *mysqlServerPort < 0 && *mysqlServerSocketPath == "" {
		return
	}

	// If no VTGate was created, just return.
	if rpcVTGate == nil {
		return
	}

	// Initialize registered AuthServer implementations (or other plugins)
	for _, initFn := range pluginInitializers {
		initFn()
	}
	authServer := mysql.GetAuthServer(*mysqlAuthServerImpl)

	// Create a Listener.
	var err error
	vh := newVtgateHandler(rpcVTGate)
	if *mysqlServerPort >= 0 {
		mysqlListener, err = mysql.NewListener("tcp", net.JoinHostPort(*mysqlServerBindAddress, fmt.Sprintf("%v", *mysqlServerPort)), authServer, vh)
		if err != nil {
			log.Exitf("mysql.NewListener failed: %v", err)
		}
		if *mysqlSslCert != "" && *mysqlSslKey != "" {
			mysqlListener.TLSConfig, err = vttls.ServerConfig(*mysqlSslCert, *mysqlSslKey, *mysqlSslCa)
			if err != nil {
				log.Exitf("grpcutils.TLSServerConfig failed: %v", err)
				return
			}
		}
		mysqlListener.AllowClearTextWithoutTLS = *mysqlAllowClearTextWithoutTLS

		// Check for the connection threshold
		if *mysqlSlowConnectWarnThreshold != 0 {
			log.Infof("setting mysql slow connection threshold to %v", mysqlSlowConnectWarnThreshold)
			mysqlListener.SlowConnectWarnThreshold = *mysqlSlowConnectWarnThreshold
		}
		// Start listening for tcp
		go mysqlListener.Accept()
	}

	if *mysqlServerSocketPath != "" {
		// Let's create this unix socket with permissions to all users. In this way,
		// clients can connect to vtgate mysql server without being vtgate user
		oldMask := syscall.Umask(000)
		mysqlUnixListener, err = newMysqlUnixSocket(*mysqlServerSocketPath, authServer, vh)
		_ = syscall.Umask(oldMask)
		if err != nil {
			log.Exitf("mysql.NewListener failed: %v", err)
			return
		}
		// Listen for unix socket
		go mysqlUnixListener.Accept()
	}
}

// newMysqlUnixSocket creates a new unix socket mysql listener. If a socket file already exists, attempts
// to clean it up.
func newMysqlUnixSocket(address string, authServer mysql.AuthServer, handler mysql.Handler) (*mysql.Listener, error) {
	listener, err := mysql.NewListener("unix", address, authServer, handler)
	switch err := err.(type) {
	case nil:
		return listener, nil
	case *net.OpError:
		log.Warningf("Found existent socket when trying to create new unix mysql listener: %s, attempting to clean up", address)
		// err.Op should never be different from listen, just being extra careful
		// in case in the future other errors are returned here
		if err.Op != "listen" {
			return nil, err
		}
		_, dialErr := net.Dial("unix", address)
		if dialErr == nil {
			log.Errorf("Existent socket '%s' is still accepting connections, aborting", address)
			return nil, err
		}
		removeFileErr := os.Remove(address)
		if removeFileErr != nil {
			log.Errorf("Couldn't remove existent socket file: %s", address)
			return nil, err
		}
		listener, listenerErr := mysql.NewListener("unix", address, authServer, handler)
		return listener, listenerErr
	default:
		return nil, err
	}
}

func shutdownMysqlProtocolAndDrain() {
	if mysqlListener != nil {
		mysqlListener.Close()
		mysqlListener = nil
	}
	if mysqlUnixListener != nil {
		mysqlUnixListener.Close()
		mysqlUnixListener = nil
	}

	if atomic.LoadInt32(&busyConnections) > 0 {
		log.Infof("Waiting for all client connections to be idle (%d active)...", atomic.LoadInt32(&busyConnections))
		start := time.Now()
		reported := start
		for time.Since(start) < 30*time.Second {
			if atomic.LoadInt32(&busyConnections) == 0 {
				break
			}

			if time.Since(reported) > 2*time.Second {
				log.Infof("Still waiting for client connections to be idle (%d active)...", atomic.LoadInt32(&busyConnections))
				reported = time.Now()
			}

			time.Sleep(1 * time.Millisecond)
		}

		if atomic.LoadInt32(&busyConnections) > 0 {
			log.Infof("Client connections still not idle, exiting anyway (%d active)...", atomic.LoadInt32(&busyConnections))
		}
	}
}

func init() {
	servenv.OnRun(initMySQLProtocol)
	servenv.OnTermSync(shutdownMysqlProtocolAndDrain)
}

var pluginInitializers []func()

// RegisterPluginInitializer lets plugins register themselves to be init'ed at servenv.OnRun-time
func RegisterPluginInitializer(initializer func()) {
	pluginInitializers = append(pluginInitializers, initializer)
}
<commit_msg>remove the explicit shutdown timer since the OnTermSync has its own<commit_after>/*
Copyright 2017 Google Inc.

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 agreedto 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 vtgate

import (
	"flag"
	"fmt"
	"net"
	"os"
	"sync/atomic"
	"syscall"
	"time"

	log "github.com/golang/glog"
	"golang.org/x/net/context"

	"github.com/youtube/vitess/go/mysql"
	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/vt/callerid"
	"github.com/youtube/vitess/go/vt/servenv"
	"github.com/youtube/vitess/go/vt/vttls"

	querypb "github.com/youtube/vitess/go/vt/proto/query"
	vtgatepb "github.com/youtube/vitess/go/vt/proto/vtgate"
)

var (
	mysqlServerPort               = flag.Int("mysql_server_port", -1, "If set, also listen for MySQL binary protocol connections on this port.")
	mysqlServerBindAddress        = flag.String("mysql_server_bind_address", "", "Binds on this address when listening to MySQL binary protocol. Useful to restrict listening to 'localhost' only for instance.")
	mysqlServerSocketPath         = flag.String("mysql_server_socket_path", "", "This option specifies the Unix socket file to use when listening for local connections. By default it will be empty and it won't listen to a unix socket")
	mysqlAuthServerImpl           = flag.String("mysql_auth_server_impl", "static", "Which auth server implementation to use.")
	mysqlAllowClearTextWithoutTLS = flag.Bool("mysql_allow_clear_text_without_tls", false, "If set, the server will allow the use of a clear text password over non-SSL connections.")

	mysqlSslCert = flag.String("mysql_server_ssl_cert", "", "Path to the ssl cert for mysql server plugin SSL")
	mysqlSslKey  = flag.String("mysql_server_ssl_key", "", "Path to ssl key for mysql server plugin SSL")
	mysqlSslCa   = flag.String("mysql_server_ssl_ca", "", "Path to ssl CA for mysql server plugin SSL. If specified, server will require and validate client certs.")

	mysqlSlowConnectWarnThreshold = flag.Duration("mysql_slow_connect_warn_threshold", 0, "Warn if it takes more than the given threshold for a mysql connection to establish")

	busyConnections int32
)

// vtgateHandler implements the Listener interface.
// It stores the Session in the ClientData of a Connection, if a transaction
// is in progress.
type vtgateHandler struct {
	vtg *VTGate
}

func newVtgateHandler(vtg *VTGate) *vtgateHandler {
	return &vtgateHandler{
		vtg: vtg,
	}
}

func (vh *vtgateHandler) NewConnection(c *mysql.Conn) {
}

func (vh *vtgateHandler) ConnectionClosed(c *mysql.Conn) {
	// Rollback if there is an ongoing transaction. Ignore error.
	ctx := context.Background()
	session, _ := c.ClientData.(*vtgatepb.Session)
	if session != nil {
		if session.InTransaction {
			defer atomic.AddInt32(&busyConnections, -1)
		}
		_, _, _ = vh.vtg.Execute(ctx, session, "rollback", make(map[string]*querypb.BindVariable))
	}
}

func (vh *vtgateHandler) ComQuery(c *mysql.Conn, query string, callback func(*sqltypes.Result) error) error {
	// FIXME(alainjobart): Add some kind of timeout to the context.
	ctx := context.Background()

	// Fill in the ImmediateCallerID with the UserData returned by
	// the AuthServer plugin for that user. If nothing was
	// returned, use the User. This lets the plugin map a MySQL
	// user used for authentication to a Vitess User used for
	// Table ACLs and Vitess authentication in general.
	im := c.UserData.Get()
	ef := callerid.NewEffectiveCallerID(
		c.User,                  /* principal: who */
		c.RemoteAddr().String(), /* component: running client process */
		"VTGate MySQL Connector" /* subcomponent: part of the client */)
	ctx = callerid.NewContext(ctx, ef, im)

	session, _ := c.ClientData.(*vtgatepb.Session)
	if session == nil {
		session = &vtgatepb.Session{
			Options: &querypb.ExecuteOptions{
				IncludedFields: querypb.ExecuteOptions_ALL,
			},
			Autocommit: true,
		}
		if c.Capabilities&mysql.CapabilityClientFoundRows != 0 {
			session.Options.ClientFoundRows = true
		}
	}

	if !session.InTransaction {
		atomic.AddInt32(&busyConnections, 1)
	}
	defer func() {
		if !session.InTransaction {
			atomic.AddInt32(&busyConnections, -1)
		}
	}()

	if c.SchemaName != "" {
		session.TargetString = c.SchemaName
	}
	if session.Options.Workload == querypb.ExecuteOptions_OLAP {
		err := vh.vtg.StreamExecute(ctx, session, query, make(map[string]*querypb.BindVariable), callback)
		return mysql.NewSQLErrorFromError(err)
	}
	session, result, err := vh.vtg.Execute(ctx, session, query, make(map[string]*querypb.BindVariable))
	c.ClientData = session
	err = mysql.NewSQLErrorFromError(err)
	if err != nil {
		return err
	}
	return callback(result)
}

var mysqlListener *mysql.Listener
var mysqlUnixListener *mysql.Listener

// initiMySQLProtocol starts the mysql protocol.
// It should be called only once in a process.
func initMySQLProtocol() {
	// Flag is not set, just return.
	if *mysqlServerPort < 0 && *mysqlServerSocketPath == "" {
		return
	}

	// If no VTGate was created, just return.
	if rpcVTGate == nil {
		return
	}

	// Initialize registered AuthServer implementations (or other plugins)
	for _, initFn := range pluginInitializers {
		initFn()
	}
	authServer := mysql.GetAuthServer(*mysqlAuthServerImpl)

	// Create a Listener.
	var err error
	vh := newVtgateHandler(rpcVTGate)
	if *mysqlServerPort >= 0 {
		mysqlListener, err = mysql.NewListener("tcp", net.JoinHostPort(*mysqlServerBindAddress, fmt.Sprintf("%v", *mysqlServerPort)), authServer, vh)
		if err != nil {
			log.Exitf("mysql.NewListener failed: %v", err)
		}
		if *mysqlSslCert != "" && *mysqlSslKey != "" {
			mysqlListener.TLSConfig, err = vttls.ServerConfig(*mysqlSslCert, *mysqlSslKey, *mysqlSslCa)
			if err != nil {
				log.Exitf("grpcutils.TLSServerConfig failed: %v", err)
				return
			}
		}
		mysqlListener.AllowClearTextWithoutTLS = *mysqlAllowClearTextWithoutTLS

		// Check for the connection threshold
		if *mysqlSlowConnectWarnThreshold != 0 {
			log.Infof("setting mysql slow connection threshold to %v", mysqlSlowConnectWarnThreshold)
			mysqlListener.SlowConnectWarnThreshold = *mysqlSlowConnectWarnThreshold
		}
		// Start listening for tcp
		go mysqlListener.Accept()
	}

	if *mysqlServerSocketPath != "" {
		// Let's create this unix socket with permissions to all users. In this way,
		// clients can connect to vtgate mysql server without being vtgate user
		oldMask := syscall.Umask(000)
		mysqlUnixListener, err = newMysqlUnixSocket(*mysqlServerSocketPath, authServer, vh)
		_ = syscall.Umask(oldMask)
		if err != nil {
			log.Exitf("mysql.NewListener failed: %v", err)
			return
		}
		// Listen for unix socket
		go mysqlUnixListener.Accept()
	}
}

// newMysqlUnixSocket creates a new unix socket mysql listener. If a socket file already exists, attempts
// to clean it up.
func newMysqlUnixSocket(address string, authServer mysql.AuthServer, handler mysql.Handler) (*mysql.Listener, error) {
	listener, err := mysql.NewListener("unix", address, authServer, handler)
	switch err := err.(type) {
	case nil:
		return listener, nil
	case *net.OpError:
		log.Warningf("Found existent socket when trying to create new unix mysql listener: %s, attempting to clean up", address)
		// err.Op should never be different from listen, just being extra careful
		// in case in the future other errors are returned here
		if err.Op != "listen" {
			return nil, err
		}
		_, dialErr := net.Dial("unix", address)
		if dialErr == nil {
			log.Errorf("Existent socket '%s' is still accepting connections, aborting", address)
			return nil, err
		}
		removeFileErr := os.Remove(address)
		if removeFileErr != nil {
			log.Errorf("Couldn't remove existent socket file: %s", address)
			return nil, err
		}
		listener, listenerErr := mysql.NewListener("unix", address, authServer, handler)
		return listener, listenerErr
	default:
		return nil, err
	}
}

func shutdownMysqlProtocolAndDrain() {
	if mysqlListener != nil {
		mysqlListener.Close()
		mysqlListener = nil
	}
	if mysqlUnixListener != nil {
		mysqlUnixListener.Close()
		mysqlUnixListener = nil
	}

	if atomic.LoadInt32(&busyConnections) > 0 {
		log.Infof("Waiting for all client connections to be idle (%d active)...", atomic.LoadInt32(&busyConnections))
		start := time.Now()
		reported := start
		for atomic.LoadInt32(&busyConnections) != 0 {
			if time.Since(reported) > 2*time.Second {
				log.Infof("Still waiting for client connections to be idle (%d active)...", atomic.LoadInt32(&busyConnections))
				reported = time.Now()
			}

			time.Sleep(1 * time.Millisecond)
		}
	}
}

func init() {
	servenv.OnRun(initMySQLProtocol)
	servenv.OnTermSync(shutdownMysqlProtocolAndDrain)
}

var pluginInitializers []func()

// RegisterPluginInitializer lets plugins register themselves to be init'ed at servenv.OnRun-time
func RegisterPluginInitializer(initializer func()) {
	pluginInitializers = append(pluginInitializers, initializer)
}
<|endoftext|>


<commit_before>package config

import "bytes"
import "flag"
import "reflect"
import "strconv"
import "text/template"

var Flags = struct {
	UiIp *string
	UiExternalIp *string
	UiPort *int
	UiBridgePort *int
	UiAudioPort *int
	SpBridgeIp *string
	SpBridgePortServer *int
	SpBridgePortClient *int
	SpIp *string
	SpPort *int
	WsBufferByteSize *int
	Resolution *string
	StateFile *string
	Verbose *bool
	Debug *bool
	MaxTrackCount *int
	BootstrapTimeoutSeconds *int
}{
	flag.String("ui_ip", "127.0.0.1", "IP address for the UI server to bind to"),
	flag.String("ui_external_ip", "127.0.0.1", "IP address for the UI client to connect the websocket to"),
	flag.Int("ui_port", 80, "port number for the UI server to bind to"),
	flag.Int("ui_bridge_port", 4550, "port number for the UI end of the OSC bridge to bind to"),
	flag.Int("ui_audio_port", 8000, "port number for the streaming audio server"),
	flag.String("sp_bridge_ip", "127.0.0.1", "IP address for the Sonic Pi end of the OSC bridge to bind to"),
	flag.Int("sp_bridge_port_server", 4560, "port number for the Sonic Pi end of the OSC bridge to bind to for receiving messages"),
	flag.Int("sp_bridge_port_client", 4559, "port number for the Sonic Pi end of the OSC bridge to bind to for transmitting messages"),
	flag.String("sp_ip", "127.0.0.1", "IP address for the Sonic Pi server"),
	flag.Int("sp_port", 4557, "port number for the Sonic Pi server"),
	flag.Int("ws_buffer_byte_size", 10000, "the size in bytes of the UI websocket server message buffer"),
	flag.String("resolution", "1/4", "beat resolution of the Hive Jam server"),
	flag.String("state_file", "", "path to file in which to persist Hive Jam server state"),
	flag.Bool("verbose", false, "verbose output logging"),
	flag.Bool("debug", false, "debug level output logging (overrides --verbose)"),
	flag.Int("max_flag_count", 6, "maximum number of tracks allowed per grid"),
	flag.Int("bootstrap_timeout_millis", 1000, "timeout in milliseconds for bootstrapping files into Sonic Pi"),
}

type flagType int
const (
	stringFlag flagType = iota
	intFlag flagType = iota
	boolFlag flagType = iota
)

type flagValue struct {
	Type flagType
	String string
	Int int
	Bool bool
}

func (f flagValue) Js() string {
	return renderFlag(f)
}

func (f flagValue) Ruby() string {
	return renderFlag(f)
}

func flagMap() map[string]flagValue {
	t := reflect.TypeOf(Flags)
	v := reflect.ValueOf(Flags)
	values := make(map[string]flagValue)
	for i := 0; i < t.NumField(); i++ {
		key := t.Field(i).Name
		value := v.Field(i).Elem()
		switch value.Kind() {
		case reflect.String:
			values[key] = flagValue{ Type: stringFlag, String: value.String() }
		case reflect.Int:
			values[key] = flagValue{ Type: intFlag, Int: int(value.Int()) }
		case reflect.Bool:
			values[key] = flagValue{ Type: boolFlag, Bool: value.Bool() }
		default:
			panic("Unsupported flag type: " + value.Elem().String())
		}
	}
	return values
}

func renderFlag(f flagValue) string {
	switch f.Type {
	case stringFlag:
		return "\"" + f.String + "\""
	case intFlag:
		return strconv.Itoa(f.Int)
	case boolFlag:
		if f.Bool {
			return "true"
		} else {
			return "false"
		}
	}
	panic("Unknown flag type.")
}

const jsConfig = `
HJ_CONFIG = {
  {{range $key, $value := .}}
  {{$key}}: {{$value.Js}},
  {{end}}
}
`
const rubyConfig = `
define :_hj_config do
  {
    {{range $key, $value := .}}
    {{$key}}: {{$value.Ruby}},
    {{end}}
  }
end
`

// JavaScript and Ruby happen to have the same syntax
func render(templateString string) ([]byte, error) {
	var b bytes.Buffer
	t, err := template.New("template").Parse(templateString)
	if err != nil {
		return nil, err
	}
	values := flagMap()
	err = t.Execute(&b, values)
	if err != nil {
		return nil, err
	}
	return b.Bytes(), nil
}

func JsConfig() ([]byte, error) {
	return render(jsConfig)
}

func RubyConfig() ([]byte, error) {
	return render(rubyConfig)
}
<commit_msg>Revert "Bind UI server to port 80 by default."<commit_after>package config

import "bytes"
import "flag"
import "reflect"
import "strconv"
import "text/template"

var Flags = struct {
	UiIp *string
	UiExternalIp *string
	UiPort *int
	UiBridgePort *int
	UiAudioPort *int
	SpBridgeIp *string
	SpBridgePortServer *int
	SpBridgePortClient *int
	SpIp *string
	SpPort *int
	WsBufferByteSize *int
	Resolution *string
	StateFile *string
	Verbose *bool
	Debug *bool
	MaxTrackCount *int
	BootstrapTimeoutSeconds *int
}{
	flag.String("ui_ip", "127.0.0.1", "IP address for the UI server to bind to"),
	flag.String("ui_external_ip", "127.0.0.1", "IP address for the UI client to connect the websocket to"),
	flag.Int("ui_port", 8080, "port number for the UI server to bind to"),
	flag.Int("ui_bridge_port", 4550, "port number for the UI end of the OSC bridge to bind to"),
	flag.Int("ui_audio_port", 8000, "port number for the streaming audio server"),
	flag.String("sp_bridge_ip", "127.0.0.1", "IP address for the Sonic Pi end of the OSC bridge to bind to"),
	flag.Int("sp_bridge_port_server", 4560, "port number for the Sonic Pi end of the OSC bridge to bind to for receiving messages"),
	flag.Int("sp_bridge_port_client", 4559, "port number for the Sonic Pi end of the OSC bridge to bind to for transmitting messages"),
	flag.String("sp_ip", "127.0.0.1", "IP address for the Sonic Pi server"),
	flag.Int("sp_port", 4557, "port number for the Sonic Pi server"),
	flag.Int("ws_buffer_byte_size", 10000, "the size in bytes of the UI websocket server message buffer"),
	flag.String("resolution", "1/4", "beat resolution of the Hive Jam server"),
	flag.String("state_file", "", "path to file in which to persist Hive Jam server state"),
	flag.Bool("verbose", false, "verbose output logging"),
	flag.Bool("debug", false, "debug level output logging (overrides --verbose)"),
	flag.Int("max_flag_count", 6, "maximum number of tracks allowed per grid"),
	flag.Int("bootstrap_timeout_millis", 1000, "timeout in milliseconds for bootstrapping files into Sonic Pi"),
}

type flagType int
const (
	stringFlag flagType = iota
	intFlag flagType = iota
	boolFlag flagType = iota
)

type flagValue struct {
	Type flagType
	String string
	Int int
	Bool bool
}

func (f flagValue) Js() string {
	return renderFlag(f)
}

func (f flagValue) Ruby() string {
	return renderFlag(f)
}

func flagMap() map[string]flagValue {
	t := reflect.TypeOf(Flags)
	v := reflect.ValueOf(Flags)
	values := make(map[string]flagValue)
	for i := 0; i < t.NumField(); i++ {
		key := t.Field(i).Name
		value := v.Field(i).Elem()
		switch value.Kind() {
		case reflect.String:
			values[key] = flagValue{ Type: stringFlag, String: value.String() }
		case reflect.Int:
			values[key] = flagValue{ Type: intFlag, Int: int(value.Int()) }
		case reflect.Bool:
			values[key] = flagValue{ Type: boolFlag, Bool: value.Bool() }
		default:
			panic("Unsupported flag type: " + value.Elem().String())
		}
	}
	return values
}

func renderFlag(f flagValue) string {
	switch f.Type {
	case stringFlag:
		return "\"" + f.String + "\""
	case intFlag:
		return strconv.Itoa(f.Int)
	case boolFlag:
		if f.Bool {
			return "true"
		} else {
			return "false"
		}
	}
	panic("Unknown flag type.")
}

const jsConfig = `
HJ_CONFIG = {
  {{range $key, $value := .}}
  {{$key}}: {{$value.Js}},
  {{end}}
}
`
const rubyConfig = `
define :_hj_config do
  {
    {{range $key, $value := .}}
    {{$key}}: {{$value.Ruby}},
    {{end}}
  }
end
`

// JavaScript and Ruby happen to have the same syntax
func render(templateString string) ([]byte, error) {
	var b bytes.Buffer
	t, err := template.New("template").Parse(templateString)
	if err != nil {
		return nil, err
	}
	values := flagMap()
	err = t.Execute(&b, values)
	if err != nil {
		return nil, err
	}
	return b.Bytes(), nil
}

func JsConfig() ([]byte, error) {
	return render(jsConfig)
}

func RubyConfig() ([]byte, error) {
	return render(rubyConfig)
}
<|endoftext|>


<commit_before>package search

import (
	"fmt"
)

// Searcher is very nice
type Searcher struct {
	Keywords   string
	Pagination int
	Sort       string
	Lynx       bool
}

// Exec is scraping and viewing contents and selecting contents
func (s *Searcher) Exec() {
	for {
		contents, err := search(s.Keywords, s.Pagination, s.Sort)
		if err != nil {
			fmt.Println(err)
			break
		}
		viewList(contents)
		endPhase := scan(contents, s.Keywords, s.Lynx)
		if endPhase {
			break
		}
		s.Pagination++
	}
}

// Validate is that checking options
func (s Searcher) Validate() (err error) {
	if len(s.Keywords) < 1 {
		err = fmt.Errorf("%s is unknown value", s.Sort)
		return
	}

	switch s.Sort {
	case "rel", "created", "stock":
		return
	default:
		err = fmt.Errorf("failed to not argument of search keyword")
		return
	}
}
<commit_msg>Fix error message<commit_after>package search

import (
	"fmt"
)

// Searcher is very nice
type Searcher struct {
	Keywords   string
	Pagination int
	Sort       string
	Lynx       bool
}

// Exec is scraping and viewing contents and selecting contents
func (s *Searcher) Exec() {
	for {
		contents, err := search(s.Keywords, s.Pagination, s.Sort)
		if err != nil {
			fmt.Println(err)
			break
		}
		viewList(contents)
		endPhase := scan(contents, s.Keywords, s.Lynx)
		if endPhase {
			break
		}
		s.Pagination++
	}
}

// Validate is that checking options
func (s Searcher) Validate() (err error) {
	if len(s.Keywords) < 1 {
		err = fmt.Errorf("failed to not argument of search keyword")
		return
	}

	switch s.Sort {
	case "rel", "created", "stock":
		return
	default:
		err = fmt.Errorf("%s is unknown value", s.Sort)
		return
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Cayley Authors. All rights reserved.
//
// 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 iterator

// "Optional" is kind of odd. It's not an iterator in the strictest sense, but
// it's easier to implement as an iterator.
//
// Consider what it means. It means that we have a subconstraint which we do
// not want to constrain the query -- we just want it to return the matching
// subgraph if one matches at all. By analogy to regular expressions, it is the
// '?' operator.
//
// If it were a proper iterator of its own (and indeed, a reasonable refactor
// of this iterator would be to make it such) it would contain an all iterator
// -- all things in the graph. It matches everything (as does the regex "(a)?")

import (
	"github.com/google/cayley/graph"
)

// An optional iterator has the sub-constraint iterator we wish to be optional
// and whether the last check we received was true or false.
type Optional struct {
	uid       uint64
	tags      graph.Tagger
	subIt     graph.Iterator
	lastCheck bool
	result    graph.Value
}

// Creates a new optional iterator.
func NewOptional(it graph.Iterator) *Optional {
	return &Optional{
		uid:   NextUID(),
		subIt: it,
	}
}

func (it *Optional) UID() uint64 {
	return it.uid
}

func (it *Optional) Reset() {
	it.subIt.Reset()
	it.lastCheck = false
}

func (it *Optional) Close() error {
	return it.subIt.Close()
}

func (it *Optional) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *Optional) Clone() graph.Iterator {
	out := NewOptional(it.subIt.Clone())
	out.tags.CopyFrom(it)
	return out
}

// DEPRECATED
func (it *Optional) ResultTree() *graph.ResultTree {
	return graph.NewResultTree(it.Result())
}

func (it *Optional) Err() error {
	return it.subIt.Err()
}

func (it *Optional) Result() graph.Value {
	return it.result
}

// An optional iterator only has a next result if, (a) last time we checked
// we had any results whatsoever, and (b) there was another subresult in our
// optional subbranch.
func (it *Optional) NextPath() bool {
	if it.lastCheck {
		return it.subIt.NextPath()
	}
	return false
}

// No subiterators.
func (it *Optional) SubIterators() []graph.Iterator {
	return nil
}

// Contains() is the real hack of this iterator. It always returns true, regardless
// of whether the subiterator matched. But we keep track of whether the subiterator
// matched for results purposes.
func (it *Optional) Contains(val graph.Value) bool {
	checked := it.subIt.Contains(val)
	it.lastCheck = checked
	it.result = val
	return true
}

// If we failed the check, then the subiterator should not contribute to the result
// set. Otherwise, go ahead and tag it.
func (it *Optional) TagResults(dst map[string]graph.Value) {
	if it.lastCheck == false {
		return
	}
	it.subIt.TagResults(dst)
}

// Registers the optional iterator.
func (it *Optional) Type() graph.Type { return graph.Optional }

func (it *Optional) Describe() graph.Description {
	primary := it.subIt.Describe()
	return graph.Description{
		UID:      it.UID(),
		Type:     it.Type(),
		Tags:     it.tags.Tags(),
		Iterator: &primary,
	}
}

// There's nothing to optimize for an optional. Optimize the subiterator and
// potentially replace it.
func (it *Optional) Optimize() (graph.Iterator, bool) {
	newSub, changed := it.subIt.Optimize()
	if changed {
		it.subIt.Close()
		it.subIt = newSub
	}
	return it, false
}

// We're only as expensive as our subiterator. Except, we can't be nexted.
func (it *Optional) Stats() graph.IteratorStats {
	subStats := it.subIt.Stats()
	return graph.IteratorStats{
		ContainsCost: subStats.ContainsCost,
		NextCost:     int64(1 << 62),
		Size:         subStats.Size,
	}
}

// If you're empty and you know it, clap your hands.
func (it *Optional) Size() (int64, bool) {
	return 0, true
}
<commit_msg>Add an additional static type assertion<commit_after>// Copyright 2014 The Cayley Authors. All rights reserved.
//
// 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 iterator

// "Optional" is kind of odd. It's not an iterator in the strictest sense, but
// it's easier to implement as an iterator.
//
// Consider what it means. It means that we have a subconstraint which we do
// not want to constrain the query -- we just want it to return the matching
// subgraph if one matches at all. By analogy to regular expressions, it is the
// '?' operator.
//
// If it were a proper iterator of its own (and indeed, a reasonable refactor
// of this iterator would be to make it such) it would contain an all iterator
// -- all things in the graph. It matches everything (as does the regex "(a)?")

import (
	"github.com/google/cayley/graph"
)

// An optional iterator has the sub-constraint iterator we wish to be optional
// and whether the last check we received was true or false.
type Optional struct {
	uid       uint64
	tags      graph.Tagger
	subIt     graph.Iterator
	lastCheck bool
	result    graph.Value
}

// Creates a new optional iterator.
func NewOptional(it graph.Iterator) *Optional {
	return &Optional{
		uid:   NextUID(),
		subIt: it,
	}
}

func (it *Optional) UID() uint64 {
	return it.uid
}

func (it *Optional) Reset() {
	it.subIt.Reset()
	it.lastCheck = false
}

func (it *Optional) Close() error {
	return it.subIt.Close()
}

func (it *Optional) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *Optional) Clone() graph.Iterator {
	out := NewOptional(it.subIt.Clone())
	out.tags.CopyFrom(it)
	return out
}

// DEPRECATED
func (it *Optional) ResultTree() *graph.ResultTree {
	return graph.NewResultTree(it.Result())
}

func (it *Optional) Err() error {
	return it.subIt.Err()
}

func (it *Optional) Result() graph.Value {
	return it.result
}

// An optional iterator only has a next result if, (a) last time we checked
// we had any results whatsoever, and (b) there was another subresult in our
// optional subbranch.
func (it *Optional) NextPath() bool {
	if it.lastCheck {
		return it.subIt.NextPath()
	}
	return false
}

// No subiterators.
func (it *Optional) SubIterators() []graph.Iterator {
	return nil
}

// Contains() is the real hack of this iterator. It always returns true, regardless
// of whether the subiterator matched. But we keep track of whether the subiterator
// matched for results purposes.
func (it *Optional) Contains(val graph.Value) bool {
	checked := it.subIt.Contains(val)
	it.lastCheck = checked
	it.result = val
	return true
}

// If we failed the check, then the subiterator should not contribute to the result
// set. Otherwise, go ahead and tag it.
func (it *Optional) TagResults(dst map[string]graph.Value) {
	if it.lastCheck == false {
		return
	}
	it.subIt.TagResults(dst)
}

// Registers the optional iterator.
func (it *Optional) Type() graph.Type { return graph.Optional }

func (it *Optional) Describe() graph.Description {
	primary := it.subIt.Describe()
	return graph.Description{
		UID:      it.UID(),
		Type:     it.Type(),
		Tags:     it.tags.Tags(),
		Iterator: &primary,
	}
}

// There's nothing to optimize for an optional. Optimize the subiterator and
// potentially replace it.
func (it *Optional) Optimize() (graph.Iterator, bool) {
	newSub, changed := it.subIt.Optimize()
	if changed {
		it.subIt.Close()
		it.subIt = newSub
	}
	return it, false
}

// We're only as expensive as our subiterator. Except, we can't be nexted.
func (it *Optional) Stats() graph.IteratorStats {
	subStats := it.subIt.Stats()
	return graph.IteratorStats{
		ContainsCost: subStats.ContainsCost,
		NextCost:     int64(1 << 62),
		Size:         subStats.Size,
	}
}

// If you're empty and you know it, clap your hands.
func (it *Optional) Size() (int64, bool) {
	return 0, true
}

var _ graph.Iterator = &Optional{}
<|endoftext|>