<commit_before>package docker

import (
	"archive/tar"
	"bytes"
	"errors"
	"io"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/NetSys/quilt/minion/ipdef"
	"github.com/NetSys/quilt/util"

	log "github.com/Sirupsen/logrus"
	dkc "github.com/fsouza/go-dockerclient"
)

var pullCacheTimeout = time.Minute

// ErrNoSuchContainer is the error returned when an operation is requested on a
// non-existent container.
var ErrNoSuchContainer = errors.New("container does not exist")

// A Container as returned by the docker client API.
type Container struct {
	ID     string
	EID    string
	Name   string
	Image  string
	IP     string
	Mac    string
	Path   string
	Args   []string
	Pid    int
	Env    map[string]string
	Labels map[string]string
}

// ContainerSlice is an alias for []Container to allow for joins
type ContainerSlice []Container

// A Client to the local docker daemon.
type Client struct {
	client
	*sync.Mutex
	imageCache map[string]time.Time
}

// RunOptions changes the behavior of the Run function.
type RunOptions struct {
	Name   string
	Image  string
	Args   []string
	Labels map[string]string
	Env    map[string]string

	NetworkMode string
	PidMode     string
	Privileged  bool
	VolumesFrom []string
}

type client interface {
	StartContainer(id string, hostConfig *dkc.HostConfig) error
	UploadToContainer(id string, opts dkc.UploadToContainerOptions) error
	DownloadFromContainer(id string, opts dkc.DownloadFromContainerOptions) error
	RemoveContainer(opts dkc.RemoveContainerOptions) error
	PullImage(opts dkc.PullImageOptions, auth dkc.AuthConfiguration) error
	ListContainers(opts dkc.ListContainersOptions) ([]dkc.APIContainers, error)
	InspectContainer(id string) (*dkc.Container, error)
	CreateContainer(dkc.CreateContainerOptions) (*dkc.Container, error)
	CreateNetwork(dkc.CreateNetworkOptions) (*dkc.Network, error)
}

// New creates client to the docker daemon.
func New(sock string) Client {
	var client *dkc.Client
	for {
		var err error
		client, err = dkc.NewClient(sock)
		if err != nil {
			log.WithError(err).Warn("Failed to create docker client.")
			time.Sleep(10 * time.Second)
			continue
		}
		break
	}

	return Client{client, &sync.Mutex{}, map[string]time.Time{}}
}

// Run creates and starts a new container in accordance RunOptions.
func (dk Client) Run(opts RunOptions) (string, error) {
	env := map[string]struct{}{}
	for k, v := range opts.Env {
		env[k+"="+v] = struct{}{}
	}

	hc := &dkc.HostConfig{
		NetworkMode: opts.NetworkMode,
		PidMode:     opts.PidMode,
		Privileged:  opts.Privileged,
		VolumesFrom: opts.VolumesFrom,
		DNSSearch:   []string{"q"},
	}

	id, err := dk.create(opts.Name, opts.Image, opts.Args, opts.Labels, env, hc, nil)
	if err != nil {
		return "", err
	}

	if err = dk.StartContainer(id, hc); err != nil {
		dk.RemoveID(id) // Remove the container to avoid a zombie.
		return "", err
	}

	return id, nil
}

// ConfigureNetwork makes a request to docker to create a network running on driver with
// the given subnet.
func (dk Client) ConfigureNetwork(driver string, subnet net.IPNet) error {
	_, err := dk.CreateNetwork(dkc.CreateNetworkOptions{
		Name:   driver,
		Driver: driver,
		IPAM: dkc.IPAMOptions{
			Config: []dkc.IPAMConfig{{
				Subnet:  ipdef.QuiltSubnet.String(),
				IPRange: subnet.String(),
				Gateway: ipdef.GatewayIP.String(),
			}},
		},
	})
	return err
}

// WriteToContainer writes the contents of SRC into the file at path DST on the
// container with id ID. Overwrites DST if it already exists.
func (dk Client) WriteToContainer(id, src, dst, archiveName string,
	permission int) error {

	tarBuf, err := util.ToTar(archiveName, permission, src)

	if err != nil {
		return err
	}

	err = dk.UploadToContainer(id, dkc.UploadToContainerOptions{
		InputStream: tarBuf,
		Path:        dst,
	})
	if err != nil {
		return err
	}

	return nil
}

// GetFromContainer returns a string containing the content of the file named
// SRC on the container with id ID.
func (dk Client) GetFromContainer(id string, src string) (string, error) {
	var buffIn bytes.Buffer
	var buffOut bytes.Buffer
	err := dk.DownloadFromContainer(id, dkc.DownloadFromContainerOptions{
		OutputStream: &buffIn,
		Path:         src,
	})
	if err != nil {
		return "", err
	}

	writer := io.Writer(&buffOut)

	for tr := tar.NewReader(&buffIn); err != io.EOF; _, err = tr.Next() {

		if err != nil {
			return "", err
		}

		_, err = io.Copy(writer, tr)
		if err != nil {
			return "", err
		}
	}

	return buffOut.String(), nil
}

// Remove stops and deletes the container with the given name.
func (dk Client) Remove(name string) error {
	id, err := dk.getID(name)
	if err != nil {
		return err
	}

	return dk.RemoveID(id)
}

// RemoveID stops and deletes the container with the given ID.
func (dk Client) RemoveID(id string) error {
	err := dk.RemoveContainer(dkc.RemoveContainerOptions{ID: id, Force: true})
	if err != nil {
		return err
	}

	return nil
}

// Pull retrieves the given docker image from an image cache.
// The `image` argument can be of the form <repo>, <repo>:<tag>, or
// <repo>:<tag>@<digestFormat>:<digest>.
// If no tag is specified, then the "latest" tag is applied.
func (dk Client) Pull(image string) error {
	dk.Lock()
	defer dk.Unlock()

	now := time.Now()
	if expiration, ok := dk.imageCache[image]; ok && now.Before(expiration) {
		return nil
	}

	repo, tag := dkc.ParseRepositoryTag(image)
	if tag == "" {
		tag = "latest"
	}

	log.Infof("Pulling docker image %s.", image)
	opts := dkc.PullImageOptions{Repository: repo, Tag: tag}
	if err := dk.PullImage(opts, dkc.AuthConfiguration{}); err != nil {
		return err
	}

	dk.imageCache[repo+":"+tag] = now.Add(pullCacheTimeout)
	return nil
}

// List returns a slice of all running containers.  The List can be be filtered with the
// supplied `filters` map.
func (dk Client) List(filters map[string][]string) ([]Container, error) {
	return dk.list(filters, false)
}

func (dk Client) list(filters map[string][]string, all bool) ([]Container, error) {
	opts := dkc.ListContainersOptions{All: all, Filters: filters}
	apics, err := dk.ListContainers(opts)
	if err != nil {
		return nil, err
	}

	var containers []Container
	for _, apic := range apics {
		c, err := dk.Get(apic.ID)
		if err != nil {
			log.WithError(err).Warnf("Failed to inspect container: %s",
				apic.ID)
			continue
		}

		containers = append(containers, c)
	}

	return containers, nil
}

// Get returns a Container corresponding to the supplied ID.
func (dk Client) Get(id string) (Container, error) {
	dkc, err := dk.InspectContainer(id)
	if err != nil {
		return Container{}, err
	}

	env := make(map[string]string)
	for _, value := range dkc.Config.Env {
		e := strings.Split(value, "=")
		if len(e) > 1 {
			env[e[0]] = e[1]
		}
	}

	c := Container{
		Name:   dkc.Name,
		ID:     dkc.ID,
		IP:     dkc.NetworkSettings.IPAddress,
		Mac:    dkc.NetworkSettings.MacAddress,
		EID:    dkc.NetworkSettings.EndpointID,
		Image:  dkc.Config.Image,
		Path:   dkc.Path,
		Args:   dkc.Args,
		Pid:    dkc.State.Pid,
		Env:    env,
		Labels: dkc.Config.Labels,
	}

	networks := keys(dkc.NetworkSettings.Networks)
	if len(networks) == 1 {
		config := dkc.NetworkSettings.Networks[networks[0]]
		c.IP = config.IPAddress
		c.Mac = config.MacAddress
		c.EID = config.EndpointID
	} else if len(networks) > 1 {
		log.Warnf("Multiple networks for container: %s", dkc.ID)
	}

	return c, nil
}

func keys(networks map[string]dkc.ContainerNetwork) []string {
	keySet := []string{}
	for key := range networks {
		keySet = append(keySet, key)
	}
	return keySet
}

// IsRunning returns true if the container with the given `name` is running.
func (dk Client) IsRunning(name string) (bool, error) {
	containers, err := dk.List(map[string][]string{
		"name": {name},
	})
	if err != nil {
		return false, err
	}
	return len(containers) != 0, nil
}

func (dk Client) create(name, image string, args []string, labels map[string]string,
	env map[string]struct{}, hc *dkc.HostConfig, nc *dkc.NetworkingConfig) (string,
	error) {

	if err := dk.Pull(image); err != nil {
		return "", err
	}

	envList := make([]string, len(env))
	for k := range env {
		envList = append(envList, k)
	}

	container, err := dk.CreateContainer(dkc.CreateContainerOptions{
		Name: name,
		Config: &dkc.Config{
			Image:  string(image),
			Cmd:    args,
			Labels: labels,
			Env:    envList},
		HostConfig:       hc,
		NetworkingConfig: nc,
	})
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

func (dk Client) getID(name string) (string, error) {
	containers, err := dk.list(map[string][]string{"name": {name}}, true)
	if err != nil {
		return "", err
	}

	if len(containers) > 0 {
		return containers[0].ID, nil
	}

	return "", ErrNoSuchContainer
}

// Get returns the value contained at the given index
func (cs ContainerSlice) Get(ii int) interface{} {
	return cs[ii]
}

// Len returns the number of items in the slice
func (cs ContainerSlice) Len() int {
	return len(cs)
}
<commit_msg>docker: Log image pull begin and end<commit_after>package docker

import (
	"archive/tar"
	"bytes"
	"errors"
	"io"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/NetSys/quilt/minion/ipdef"
	"github.com/NetSys/quilt/util"

	log "github.com/Sirupsen/logrus"
	dkc "github.com/fsouza/go-dockerclient"
)

var pullCacheTimeout = time.Minute

// ErrNoSuchContainer is the error returned when an operation is requested on a
// non-existent container.
var ErrNoSuchContainer = errors.New("container does not exist")

// A Container as returned by the docker client API.
type Container struct {
	ID     string
	EID    string
	Name   string
	Image  string
	IP     string
	Mac    string
	Path   string
	Args   []string
	Pid    int
	Env    map[string]string
	Labels map[string]string
}

// ContainerSlice is an alias for []Container to allow for joins
type ContainerSlice []Container

// A Client to the local docker daemon.
type Client struct {
	client
	*sync.Mutex
	imageCache map[string]time.Time
}

// RunOptions changes the behavior of the Run function.
type RunOptions struct {
	Name   string
	Image  string
	Args   []string
	Labels map[string]string
	Env    map[string]string

	NetworkMode string
	PidMode     string
	Privileged  bool
	VolumesFrom []string
}

type client interface {
	StartContainer(id string, hostConfig *dkc.HostConfig) error
	UploadToContainer(id string, opts dkc.UploadToContainerOptions) error
	DownloadFromContainer(id string, opts dkc.DownloadFromContainerOptions) error
	RemoveContainer(opts dkc.RemoveContainerOptions) error
	PullImage(opts dkc.PullImageOptions, auth dkc.AuthConfiguration) error
	ListContainers(opts dkc.ListContainersOptions) ([]dkc.APIContainers, error)
	InspectContainer(id string) (*dkc.Container, error)
	CreateContainer(dkc.CreateContainerOptions) (*dkc.Container, error)
	CreateNetwork(dkc.CreateNetworkOptions) (*dkc.Network, error)
}

// New creates client to the docker daemon.
func New(sock string) Client {
	var client *dkc.Client
	for {
		var err error
		client, err = dkc.NewClient(sock)
		if err != nil {
			log.WithError(err).Warn("Failed to create docker client.")
			time.Sleep(10 * time.Second)
			continue
		}
		break
	}

	return Client{client, &sync.Mutex{}, map[string]time.Time{}}
}

// Run creates and starts a new container in accordance RunOptions.
func (dk Client) Run(opts RunOptions) (string, error) {
	env := map[string]struct{}{}
	for k, v := range opts.Env {
		env[k+"="+v] = struct{}{}
	}

	hc := &dkc.HostConfig{
		NetworkMode: opts.NetworkMode,
		PidMode:     opts.PidMode,
		Privileged:  opts.Privileged,
		VolumesFrom: opts.VolumesFrom,
		DNSSearch:   []string{"q"},
	}

	id, err := dk.create(opts.Name, opts.Image, opts.Args, opts.Labels, env, hc, nil)
	if err != nil {
		return "", err
	}

	if err = dk.StartContainer(id, hc); err != nil {
		dk.RemoveID(id) // Remove the container to avoid a zombie.
		return "", err
	}

	return id, nil
}

// ConfigureNetwork makes a request to docker to create a network running on driver with
// the given subnet.
func (dk Client) ConfigureNetwork(driver string, subnet net.IPNet) error {
	_, err := dk.CreateNetwork(dkc.CreateNetworkOptions{
		Name:   driver,
		Driver: driver,
		IPAM: dkc.IPAMOptions{
			Config: []dkc.IPAMConfig{{
				Subnet:  ipdef.QuiltSubnet.String(),
				IPRange: subnet.String(),
				Gateway: ipdef.GatewayIP.String(),
			}},
		},
	})
	return err
}

// WriteToContainer writes the contents of SRC into the file at path DST on the
// container with id ID. Overwrites DST if it already exists.
func (dk Client) WriteToContainer(id, src, dst, archiveName string,
	permission int) error {

	tarBuf, err := util.ToTar(archiveName, permission, src)

	if err != nil {
		return err
	}

	err = dk.UploadToContainer(id, dkc.UploadToContainerOptions{
		InputStream: tarBuf,
		Path:        dst,
	})
	if err != nil {
		return err
	}

	return nil
}

// GetFromContainer returns a string containing the content of the file named
// SRC on the container with id ID.
func (dk Client) GetFromContainer(id string, src string) (string, error) {
	var buffIn bytes.Buffer
	var buffOut bytes.Buffer
	err := dk.DownloadFromContainer(id, dkc.DownloadFromContainerOptions{
		OutputStream: &buffIn,
		Path:         src,
	})
	if err != nil {
		return "", err
	}

	writer := io.Writer(&buffOut)

	for tr := tar.NewReader(&buffIn); err != io.EOF; _, err = tr.Next() {

		if err != nil {
			return "", err
		}

		_, err = io.Copy(writer, tr)
		if err != nil {
			return "", err
		}
	}

	return buffOut.String(), nil
}

// Remove stops and deletes the container with the given name.
func (dk Client) Remove(name string) error {
	id, err := dk.getID(name)
	if err != nil {
		return err
	}

	return dk.RemoveID(id)
}

// RemoveID stops and deletes the container with the given ID.
func (dk Client) RemoveID(id string) error {
	err := dk.RemoveContainer(dkc.RemoveContainerOptions{ID: id, Force: true})
	if err != nil {
		return err
	}

	return nil
}

// Pull retrieves the given docker image from an image cache.
// The `image` argument can be of the form <repo>, <repo>:<tag>, or
// <repo>:<tag>@<digestFormat>:<digest>.
// If no tag is specified, then the "latest" tag is applied.
func (dk Client) Pull(image string) error {
	dk.Lock()
	defer dk.Unlock()

	now := time.Now()
	if expiration, ok := dk.imageCache[image]; ok && now.Before(expiration) {
		return nil
	}

	repo, tag := dkc.ParseRepositoryTag(image)
	if tag == "" {
		tag = "latest"
	}

	log.WithField("image", image).Info("Begin image pull")
	opts := dkc.PullImageOptions{Repository: repo, Tag: tag}
	if err := dk.PullImage(opts, dkc.AuthConfiguration{}); err != nil {
		log.WithField("image", image).WithError(err).Error("Failed image pull")
		return err
	}

	dk.imageCache[repo+":"+tag] = now.Add(pullCacheTimeout)
	log.WithField("image", image).Info("Finish image pull")
	return nil
}

// List returns a slice of all running containers.  The List can be be filtered with the
// supplied `filters` map.
func (dk Client) List(filters map[string][]string) ([]Container, error) {
	return dk.list(filters, false)
}

func (dk Client) list(filters map[string][]string, all bool) ([]Container, error) {
	opts := dkc.ListContainersOptions{All: all, Filters: filters}
	apics, err := dk.ListContainers(opts)
	if err != nil {
		return nil, err
	}

	var containers []Container
	for _, apic := range apics {
		c, err := dk.Get(apic.ID)
		if err != nil {
			log.WithError(err).Warnf("Failed to inspect container: %s",
				apic.ID)
			continue
		}

		containers = append(containers, c)
	}

	return containers, nil
}

// Get returns a Container corresponding to the supplied ID.
func (dk Client) Get(id string) (Container, error) {
	dkc, err := dk.InspectContainer(id)
	if err != nil {
		return Container{}, err
	}

	env := make(map[string]string)
	for _, value := range dkc.Config.Env {
		e := strings.Split(value, "=")
		if len(e) > 1 {
			env[e[0]] = e[1]
		}
	}

	c := Container{
		Name:   dkc.Name,
		ID:     dkc.ID,
		IP:     dkc.NetworkSettings.IPAddress,
		Mac:    dkc.NetworkSettings.MacAddress,
		EID:    dkc.NetworkSettings.EndpointID,
		Image:  dkc.Config.Image,
		Path:   dkc.Path,
		Args:   dkc.Args,
		Pid:    dkc.State.Pid,
		Env:    env,
		Labels: dkc.Config.Labels,
	}

	networks := keys(dkc.NetworkSettings.Networks)
	if len(networks) == 1 {
		config := dkc.NetworkSettings.Networks[networks[0]]
		c.IP = config.IPAddress
		c.Mac = config.MacAddress
		c.EID = config.EndpointID
	} else if len(networks) > 1 {
		log.Warnf("Multiple networks for container: %s", dkc.ID)
	}

	return c, nil
}

func keys(networks map[string]dkc.ContainerNetwork) []string {
	keySet := []string{}
	for key := range networks {
		keySet = append(keySet, key)
	}
	return keySet
}

// IsRunning returns true if the container with the given `name` is running.
func (dk Client) IsRunning(name string) (bool, error) {
	containers, err := dk.List(map[string][]string{
		"name": {name},
	})
	if err != nil {
		return false, err
	}
	return len(containers) != 0, nil
}

func (dk Client) create(name, image string, args []string, labels map[string]string,
	env map[string]struct{}, hc *dkc.HostConfig, nc *dkc.NetworkingConfig) (string,
	error) {

	if err := dk.Pull(image); err != nil {
		return "", err
	}

	envList := make([]string, len(env))
	for k := range env {
		envList = append(envList, k)
	}

	container, err := dk.CreateContainer(dkc.CreateContainerOptions{
		Name: name,
		Config: &dkc.Config{
			Image:  string(image),
			Cmd:    args,
			Labels: labels,
			Env:    envList},
		HostConfig:       hc,
		NetworkingConfig: nc,
	})
	if err != nil {
		return "", err
	}

	return container.ID, nil
}

func (dk Client) getID(name string) (string, error) {
	containers, err := dk.list(map[string][]string{"name": {name}}, true)
	if err != nil {
		return "", err
	}

	if len(containers) > 0 {
		return containers[0].ID, nil
	}

	return "", ErrNoSuchContainer
}

// Get returns the value contained at the given index
func (cs ContainerSlice) Get(ii int) interface{} {
	return cs[ii]
}

// Len returns the number of items in the slice
func (cs ContainerSlice) Len() int {
	return len(cs)
}
<|endoftext|>


<commit_before>package p2p

import (
	// "bytes"
	"crypto/ecdsa"
	"crypto/rand"
	"fmt"
	// "io"

	"github.com/ethereum/go-ethereum/crypto"
	"github.com/obscuren/ecies"
	"github.com/obscuren/secp256k1-go"
)

var (
	sskLen int = 16                    // ecies.MaxSharedKeyLength(pubKey) / 2
	sigLen int = 65                    // elliptic S256
	keyLen int = 32                    // ECDSA
	msgLen int = sigLen + 3*keyLen + 1 // 162
	resLen int = 65
)

// aesSecret, macSecret, egressMac, ingress
type secretRW struct {
	aesSecret, macSecret, egressMac, ingressMac []byte
}

type cryptoId struct {
	prvKey    *ecdsa.PrivateKey
	pubKey    *ecdsa.PublicKey
	pubKeyDER []byte
}

func newCryptoId(id ClientIdentity) (self *cryptoId, err error) {
	// will be at server  init
	var prvKeyDER []byte = id.PrivKey()
	if prvKeyDER == nil {
		err = fmt.Errorf("no private key for client")
		return
	}
	// initialise ecies private key via importing DER encoded keys (known via our own clientIdentity)
	var prvKey = crypto.ToECDSA(prvKeyDER)
	if prvKey == nil {
		err = fmt.Errorf("invalid private key for client")
		return
	}
	self = &cryptoId{
		prvKey: prvKey,
		// initialise public key from the imported private key
		pubKey: &prvKey.PublicKey,
		// to be created at server init shared between peers and sessions
		// for reuse, call wth ReadAt, no reset seek needed
	}
	self.pubKeyDER = id.Pubkey()
	return
}

// initAuth is called by peer if it initiated the connection
func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byte, initNonce []byte, remotePubKey *ecdsa.PublicKey, err error) {
	// session init, common to both parties
	remotePubKey = crypto.ToECDSAPub(remotePubKeyDER)
	if remotePubKey == nil {
		err = fmt.Errorf("invalid remote public key")
		return
	}

	var tokenFlag byte
	if sessionToken == nil {
		// no session token found means we need to generate shared secret.
		// ecies shared secret is used as initial session token for new peers
		// generate shared key from prv and remote pubkey
		if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
			return
		}
		fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
		// tokenFlag = 0x00 // redundant
	} else {
		// for known peers, we use stored token from the previous session
		tokenFlag = 0x01
	}

	//E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	// E(remote-pubk, S(ecdhe-random, token^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x1)
	// allocate msgLen long message,
	var msg []byte = make([]byte, msgLen)
	// generate sskLen long nonce
	initNonce = msg[msgLen-keyLen-1 : msgLen-1]
	// nonce = msg[msgLen-sskLen-1 : msgLen-1]
	if _, err = rand.Read(initNonce); err != nil {
		return
	}
	// create known message
	// ecdh-shared-secret^nonce for new peers
	// token^nonce for old peers
	var sharedSecret = Xor(sessionToken, initNonce)

	// generate random keypair to use for signing
	var ecdsaRandomPrvKey *ecdsa.PrivateKey
	if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
		return
	}
	// sign shared secret (message known to both parties): shared-secret
	var signature []byte
	// signature = sign(ecdhe-random, shared-secret)
	// uses secp256k1.Sign
	if signature, err = crypto.Sign(sharedSecret, ecdsaRandomPrvKey); err != nil {
		return
	}
	fmt.Printf("signature generated: %v %x", len(signature), signature)

	// message
	// signed-shared-secret || H(ecdhe-random-pubk) || pubk || nonce || 0x0
	copy(msg, signature) // copy signed-shared-secret
	// H(ecdhe-random-pubk)
	copy(msg[sigLen:sigLen+keyLen], crypto.Sha3(crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey)))
	// pubkey copied to the correct segment.
	copy(msg[sigLen+keyLen:sigLen+2*keyLen], self.pubKeyDER)
	// nonce is already in the slice
	// stick tokenFlag byte to the end
	msg[msgLen-1] = tokenFlag

	fmt.Printf("plaintext message generated: %v %x", len(msg), msg)

	// encrypt using remote-pubk
	// auth = eciesEncrypt(remote-pubk, msg)

	if auth, err = crypto.Encrypt(remotePubKey, msg); err != nil {
		return
	}
	fmt.Printf("encrypted message generated: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(remotePubKey))

	return
}

// verifyAuth is called by peer if it accepted (but not initiated) the connection
func (self *cryptoId) verifyAuth(auth, sharedSecret []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, err error) {
	var msg []byte
	fmt.Printf("encrypted message received: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(self.pubKey))
	// they prove that msg is meant for me,
	// I prove I possess private key if i can read it
	if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil {
		return
	}

	// var remoteNonce []byte = msg[msgLen-skLen-1 : msgLen-1]
	initNonce = msg[msgLen-keyLen-1 : msgLen-1]
	// I prove that i own prv key (to derive shared secret, and read nonce off encrypted msg) and that I own shared secret
	// they prove they own the private key belonging to ecdhe-random-pubk
	var signedMsg = Xor(sharedSecret, initNonce)
	var remoteRandomPubKeyDER []byte
	if remoteRandomPubKeyDER, err = secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]); err != nil {
		return
	}
	remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER)
	if remoteRandomPubKey == nil {
		err = fmt.Errorf("invalid remote public key")
		return
	}

	var resp = make([]byte, 2*keyLen+1)
	// generate sskLen long nonce
	respNonce = msg[msgLen-keyLen-1 : msgLen-1]
	if _, err = rand.Read(respNonce); err != nil {
		return
	}
	// generate random keypair
	var ecdsaRandomPrvKey *ecdsa.PrivateKey
	if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
		return
	}
	// var ecdsaRandomPubKey *ecdsa.PublicKey
	//  ecdsaRandomPubKey= &ecdsaRandomPrvKey.PublicKey

	// message
	// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
	copy(resp[:keyLen], crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey))
	// pubkey copied to the correct segment.
	copy(resp[keyLen:2*keyLen], self.pubKeyDER)
	// nonce is already in the slice
	// stick tokenFlag byte to the end
	var tokenFlag byte
	if sharedSecret == nil {
	} else {
		// for known peers, we use stored token from the previous session
		tokenFlag = 0x01
	}
	resp[resLen] = tokenFlag

	// encrypt using remote-pubk
	// auth = eciesEncrypt(remote-pubk, msg)
	// why not encrypt with ecdhe-random-remote
	if authResp, err = crypto.Encrypt(remotePubKey, resp); err != nil {
		return
	}
	return
}

func (self *cryptoId) verifyAuthResp(auth []byte) (respNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, tokenFlag bool, err error) {
	var msg []byte
	// they prove that msg is meant for me,
	// I prove I possess private key if i can read it
	if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil {
		return
	}

	respNonce = msg[resLen-keyLen-1 : resLen-1]
	var remoteRandomPubKeyDER = msg[:keyLen]
	remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER)
	if remoteRandomPubKey == nil {
		err = fmt.Errorf("invalid ecdh random remote public key")
		return
	}
	if msg[resLen-1] == 0x01 {
		tokenFlag = true
	}
	return
}

func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
	// 3) Now we can trust ecdhe-random-pubk to derive new keys
	//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
	var dhSharedSecret []byte
	dhSharedSecret, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remoteRandomPubKey), sskLen, sskLen)
	if err != nil {
		return
	}
	// shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce))
	var sharedSecret = crypto.Sha3(append(dhSharedSecret, crypto.Sha3(append(respNonce, initNonce...))...))
	// token = crypto.Sha3(shared-secret)
	sessionToken = crypto.Sha3(sharedSecret)
	// aes-secret = crypto.Sha3(ecdhe-shared-secret || shared-secret)
	var aesSecret = crypto.Sha3(append(dhSharedSecret, sharedSecret...))
	// # destroy shared-secret
	// mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret)
	var macSecret = crypto.Sha3(append(dhSharedSecret, aesSecret...))
	// # destroy ecdhe-shared-secret
	// egress-mac = crypto.Sha3(mac-secret^nonce || auth)
	var egressMac = crypto.Sha3(append(Xor(macSecret, respNonce), auth...))
	// # destroy nonce
	// ingress-mac = crypto.Sha3(mac-secret^initiator-nonce || auth),
	var ingressMac = crypto.Sha3(append(Xor(macSecret, initNonce), auth...))
	// # destroy remote-nonce
	rw = &secretRW{
		aesSecret:  aesSecret,
		macSecret:  macSecret,
		egressMac:  egressMac,
		ingressMac: ingressMac,
	}
	return
}

// should use cipher.xorBytes from crypto/cipher/xor.go for fast xor
func Xor(one, other []byte) (xor []byte) {
	xor = make([]byte, len(one))
	for i := 0; i < len(one); i++ {
		xor[i] = one[i] ^ other[i]
	}
	return
}
<commit_msg>fix crash - add session token check and fallback to shared secret in responder call too - use explicit length for the types of new messages - fix typo resp[resLen-1] = tokenFlag<commit_after>package p2p

import (
	// "bytes"
	"crypto/ecdsa"
	"crypto/rand"
	"fmt"
	// "io"

	"github.com/ethereum/go-ethereum/crypto"
	"github.com/obscuren/ecies"
	"github.com/obscuren/secp256k1-go"
)

var (
	sskLen int = 16                    // ecies.MaxSharedKeyLength(pubKey) / 2
	sigLen int = 65                    // elliptic S256
	keyLen int = 32                    // ECDSA
	msgLen int = sigLen + 3*keyLen + 1 // 162
	resLen int = 65                    //
)

// aesSecret, macSecret, egressMac, ingress
type secretRW struct {
	aesSecret, macSecret, egressMac, ingressMac []byte
}

type cryptoId struct {
	prvKey    *ecdsa.PrivateKey
	pubKey    *ecdsa.PublicKey
	pubKeyDER []byte
}

func newCryptoId(id ClientIdentity) (self *cryptoId, err error) {
	// will be at server  init
	var prvKeyDER []byte = id.PrivKey()
	if prvKeyDER == nil {
		err = fmt.Errorf("no private key for client")
		return
	}
	// initialise ecies private key via importing DER encoded keys (known via our own clientIdentity)
	var prvKey = crypto.ToECDSA(prvKeyDER)
	if prvKey == nil {
		err = fmt.Errorf("invalid private key for client")
		return
	}
	self = &cryptoId{
		prvKey: prvKey,
		// initialise public key from the imported private key
		pubKey: &prvKey.PublicKey,
		// to be created at server init shared between peers and sessions
		// for reuse, call wth ReadAt, no reset seek needed
	}
	self.pubKeyDER = id.Pubkey()
	return
}

// initAuth is called by peer if it initiated the connection
func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byte, initNonce []byte, remotePubKey *ecdsa.PublicKey, err error) {
	// session init, common to both parties
	remotePubKey = crypto.ToECDSAPub(remotePubKeyDER)
	if remotePubKey == nil {
		err = fmt.Errorf("invalid remote public key")
		return
	}

	var tokenFlag byte
	if sessionToken == nil {
		// no session token found means we need to generate shared secret.
		// ecies shared secret is used as initial session token for new peers
		// generate shared key from prv and remote pubkey
		if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
			return
		}
		fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
		// tokenFlag = 0x00 // redundant
	} else {
		// for known peers, we use stored token from the previous session
		tokenFlag = 0x01
	}

	//E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	// E(remote-pubk, S(ecdhe-random, token^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x1)
	// allocate msgLen long message,
	var msg []byte = make([]byte, msgLen)
	// generate sskLen long nonce
	initNonce = msg[msgLen-keyLen-1 : msgLen-1]
	// nonce = msg[msgLen-sskLen-1 : msgLen-1]
	if _, err = rand.Read(initNonce); err != nil {
		return
	}
	// create known message
	// ecdh-shared-secret^nonce for new peers
	// token^nonce for old peers
	var sharedSecret = Xor(sessionToken, initNonce)

	// generate random keypair to use for signing
	var ecdsaRandomPrvKey *ecdsa.PrivateKey
	if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
		return
	}
	// sign shared secret (message known to both parties): shared-secret
	var signature []byte
	// signature = sign(ecdhe-random, shared-secret)
	// uses secp256k1.Sign
	if signature, err = crypto.Sign(sharedSecret, ecdsaRandomPrvKey); err != nil {
		return
	}
	fmt.Printf("signature generated: %v %x", len(signature), signature)

	// message
	// signed-shared-secret || H(ecdhe-random-pubk) || pubk || nonce || 0x0
	copy(msg, signature) // copy signed-shared-secret
	// H(ecdhe-random-pubk)
	copy(msg[sigLen:sigLen+keyLen], crypto.Sha3(crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey)))
	// pubkey copied to the correct segment.
	copy(msg[sigLen+keyLen:sigLen+2*keyLen], self.pubKeyDER)
	// nonce is already in the slice
	// stick tokenFlag byte to the end
	msg[msgLen-1] = tokenFlag

	fmt.Printf("plaintext message generated: %v %x", len(msg), msg)

	// encrypt using remote-pubk
	// auth = eciesEncrypt(remote-pubk, msg)

	if auth, err = crypto.Encrypt(remotePubKey, msg); err != nil {
		return
	}
	fmt.Printf("encrypted message generated: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(remotePubKey))

	return
}

// verifyAuth is called by peer if it accepted (but not initiated) the connection
func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, err error) {
	var msg []byte
	fmt.Printf("encrypted message received: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(self.pubKey))
	// they prove that msg is meant for me,
	// I prove I possess private key if i can read it
	if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil {
		return
	}
	fmt.Printf("\nplaintext message retrieved: %v %x\n", len(msg), msg)

	var tokenFlag byte
	if sessionToken == nil {
		// no session token found means we need to generate shared secret.
		// ecies shared secret is used as initial session token for new peers
		// generate shared key from prv and remote pubkey
		if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
			return
		}
		fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
		// tokenFlag = 0x00 // redundant
	} else {
		// for known peers, we use stored token from the previous session
		tokenFlag = 0x01
	}

	// the initiator nonce is read off the end of the message
	initNonce = msg[msgLen-keyLen-1 : msgLen-1]
	// I prove that i own prv key (to derive shared secret, and read nonce off encrypted msg) and that I own shared secret
	// they prove they own the private key belonging to ecdhe-random-pubk
	// we can now reconstruct the signed message and recover the peers pubkey
	var signedMsg = Xor(sessionToken, initNonce)
	var remoteRandomPubKeyDER []byte
	if remoteRandomPubKeyDER, err = secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]); err != nil {
		return
	}
	// convert to ECDSA standard
	remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER)
	if remoteRandomPubKey == nil {
		err = fmt.Errorf("invalid remote public key")
		return
	}

	// now we find ourselves a long task too, fill it random
	var resp = make([]byte, resLen)
	// generate keyLen long nonce
	respNonce = msg[resLen-keyLen-1 : msgLen-1]
	if _, err = rand.Read(respNonce); err != nil {
		return
	}
	// generate random keypair for session
	var ecdsaRandomPrvKey *ecdsa.PrivateKey
	if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
		return
	}
	// responder auth message
	// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
	copy(resp[:keyLen], crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey))
	// nonce is already in the slice
	resp[resLen-1] = tokenFlag

	// encrypt using remote-pubk
	// auth = eciesEncrypt(remote-pubk, msg)
	// why not encrypt with ecdhe-random-remote
	if authResp, err = crypto.Encrypt(remotePubKey, resp); err != nil {
		return
	}
	return
}

func (self *cryptoId) verifyAuthResp(auth []byte) (respNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, tokenFlag bool, err error) {
	var msg []byte
	// they prove that msg is meant for me,
	// I prove I possess private key if i can read it
	if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil {
		return
	}

	respNonce = msg[resLen-keyLen-1 : resLen-1]
	var remoteRandomPubKeyDER = msg[:keyLen]
	remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER)
	if remoteRandomPubKey == nil {
		err = fmt.Errorf("invalid ecdh random remote public key")
		return
	}
	if msg[resLen-1] == 0x01 {
		tokenFlag = true
	}
	return
}

func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
	// 3) Now we can trust ecdhe-random-pubk to derive new keys
	//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
	var dhSharedSecret []byte
	dhSharedSecret, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remoteRandomPubKey), sskLen, sskLen)
	if err != nil {
		return
	}
	// shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce))
	var sharedSecret = crypto.Sha3(append(dhSharedSecret, crypto.Sha3(append(respNonce, initNonce...))...))
	// token = crypto.Sha3(shared-secret)
	sessionToken = crypto.Sha3(sharedSecret)
	// aes-secret = crypto.Sha3(ecdhe-shared-secret || shared-secret)
	var aesSecret = crypto.Sha3(append(dhSharedSecret, sharedSecret...))
	// # destroy shared-secret
	// mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret)
	var macSecret = crypto.Sha3(append(dhSharedSecret, aesSecret...))
	// # destroy ecdhe-shared-secret
	// egress-mac = crypto.Sha3(mac-secret^nonce || auth)
	var egressMac = crypto.Sha3(append(Xor(macSecret, respNonce), auth...))
	// # destroy nonce
	// ingress-mac = crypto.Sha3(mac-secret^initiator-nonce || auth),
	var ingressMac = crypto.Sha3(append(Xor(macSecret, initNonce), auth...))
	// # destroy remote-nonce
	rw = &secretRW{
		aesSecret:  aesSecret,
		macSecret:  macSecret,
		egressMac:  egressMac,
		ingressMac: ingressMac,
	}
	return
}

// should use cipher.xorBytes from crypto/cipher/xor.go for fast xor
func Xor(one, other []byte) (xor []byte) {
	xor = make([]byte, len(one))
	for i := 0; i < len(one); i++ {
		xor[i] = one[i] ^ other[i]
	}
	return
}
<|endoftext|>


<commit_before>package sshvault

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/kr/pty"
	"github.com/ssh-vault/crypto"
	"github.com/ssh-vault/crypto/aead"
)

// zomg this is a race condition
func PtyWriteback(pty *os.File, msg string) {
	time.Sleep(500 * time.Millisecond)
	defer pty.Sync()
	pty.Write([]byte(msg))
}

// These are done in one function to avoid declaring global variables in a test
// file.
func TestVaultFunctions(t *testing.T) {
	dir, err := ioutil.TempDir("", "vault")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir) // clean up

	tmpfile := filepath.Join(dir, "vault")

	vault, err := New("test_data/id_rsa.pub", "", "create", tmpfile)
	if err != nil {
		t.Error(err)
	}

	key_pw := string("argle-bargle\n")
	pty, tty, err := pty.Open()
	if err != nil {
		t.Errorf("Unable to open pty: %s", err)
	}

	// File Descriptor magic. GetPasswordPrompt() reads the password
	// from stdin. For the test, we save stdin to a spare FD,
	// point stdin at the file, run the system under test, and
	// finally restore the original stdin
	old_stdin, _ := syscall.Dup(int(syscall.Stdin))
	syscall.Dup2(int(tty.Fd()), int(syscall.Stdin))

	go PtyWriteback(pty, key_pw)

	key_pw_test, err := vault.GetPasswordPrompt()

	syscall.Dup2(old_stdin, int(syscall.Stdin))

	if err != nil {
		t.Error(err)
	}
	if string(strings.Trim(key_pw, "\n")) != string(key_pw_test) {
		t.Errorf("password prompt: expected %s, got %s\n", key_pw, key_pw_test)
	}

	if err = vault.PKCS8(); err != nil {
		t.Error(err)
	}

	if vault.Password, err = crypto.GenerateNonce(32); err != nil {
		t.Error(err)
	}

	// Skip vault.Create because we don't need/want to interact with an editor
	// for tests.
	in := []byte("The quick brown fox jumps over the lazy dog")

	out, err := aead.Encrypt(vault.Password, in, []byte(vault.Fingerprint))
	if err != nil {
		t.Error(err)
	}

	if err = vault.Close(out); err != nil {
		t.Error(err)
	}

	enc1, err := ioutil.ReadFile(tmpfile)
	if err != nil {
		t.Error(err)
	}

	plaintext, err := vault.View()
	if err != nil {
		t.Error(err)
	}

	if !bytes.Equal(in, plaintext) {
		t.Error("in != out")
	}

	os.Setenv("EDITOR", "cat")
	edited, err := vault.Edit(plaintext)
	if err != nil {
		t.Error(err)
	}

	out, err = aead.Encrypt(vault.Password, edited, []byte(vault.Fingerprint))
	if err != nil {
		t.Error(err)
	}

	if err = vault.Close(out); err != nil {
		t.Error(err)
	}

	plaintext, err = vault.View()
	if err != nil {
		t.Error(err)
	}

	enc2, err := ioutil.ReadFile(tmpfile)
	if err != nil {
		t.Error(err)
	}

	if !bytes.Equal(edited, plaintext) {
		t.Error("edited != plaintext ")
	}

	if bytes.Equal(enc1, enc2) {
		t.Error("Expecting different encrypted outputs")
	}
}

func TestVaultNew(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expect(t, "ssh-vault", r.Header.Get("User-agent"))
		fmt.Fprintln(w, "ssh-rsa ABC")
	}))
	defer ts.Close()
	_, err := New("", ts.URL, "view", "")
	if err != nil {
		t.Error(err)
	}
}

func TestVaultNewNoKey(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expect(t, "ssh-vault", r.Header.Get("User-agent"))
	}))
	defer ts.Close()
	_, err := New("", ts.URL, "view", "")
	if err == nil {
		t.Error("Expecting error")
	}
}
<commit_msg>password prompting: redirect stdout to terminal also<commit_after>package sshvault

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
	"time"

	"github.com/kr/pty"
	"github.com/ssh-vault/crypto"
	"github.com/ssh-vault/crypto/aead"
)

// zomg this is a race condition
func PtyWriteback(pty *os.File, msg string) {
	time.Sleep(500 * time.Millisecond)
	defer pty.Sync()
	pty.Write([]byte(msg))
}

// These are done in one function to avoid declaring global variables in a test
// file.
func TestVaultFunctions(t *testing.T) {
	dir, err := ioutil.TempDir("", "vault")
	if err != nil {
		t.Error(err)
	}
	defer os.RemoveAll(dir) // clean up

	tmpfile := filepath.Join(dir, "vault")

	vault, err := New("test_data/id_rsa.pub", "", "create", tmpfile)
	if err != nil {
		t.Error(err)
	}

	key_pw := string("argle-bargle\n")
	pty, tty, err := pty.Open()
	if err != nil {
		t.Errorf("Unable to open pty: %s", err)
	}

	// File Descriptor magic. GetPasswordPrompt() reads the password
	// from stdin. For the test, we save stdin to a spare FD,
	// point stdin at the file, run the system under test, and
	// finally restore the original stdin
	old_stdin, _ := syscall.Dup(int(syscall.Stdin))
	old_stdout, _ := syscall.Dup(int(syscall.Stdout))
	syscall.Dup2(int(tty.Fd()), int(syscall.Stdin))
	syscall.Dup2(int(tty.Fd()), int(syscall.Stdout))

	go PtyWriteback(pty, key_pw)

	key_pw_test, err := vault.GetPasswordPrompt()

	syscall.Dup2(old_stdin,  int(syscall.Stdin))
	syscall.Dup2(old_stdout, int(syscall.Stdout))

	if err != nil {
		t.Error(err)
	}
	if string(strings.Trim(key_pw, "\n")) != string(key_pw_test) {
		t.Errorf("password prompt: expected %s, got %s\n", key_pw, key_pw_test)
	}

	if err = vault.PKCS8(); err != nil {
		t.Error(err)
	}

	if vault.Password, err = crypto.GenerateNonce(32); err != nil {
		t.Error(err)
	}

	// Skip vault.Create because we don't need/want to interact with an editor
	// for tests.
	in := []byte("The quick brown fox jumps over the lazy dog")

	out, err := aead.Encrypt(vault.Password, in, []byte(vault.Fingerprint))
	if err != nil {
		t.Error(err)
	}

	if err = vault.Close(out); err != nil {
		t.Error(err)
	}

	enc1, err := ioutil.ReadFile(tmpfile)
	if err != nil {
		t.Error(err)
	}

	plaintext, err := vault.View()
	if err != nil {
		t.Error(err)
	}

	if !bytes.Equal(in, plaintext) {
		t.Error("in != out")
	}

	os.Setenv("EDITOR", "cat")
	edited, err := vault.Edit(plaintext)
	if err != nil {
		t.Error(err)
	}

	out, err = aead.Encrypt(vault.Password, edited, []byte(vault.Fingerprint))
	if err != nil {
		t.Error(err)
	}

	if err = vault.Close(out); err != nil {
		t.Error(err)
	}

	plaintext, err = vault.View()
	if err != nil {
		t.Error(err)
	}

	enc2, err := ioutil.ReadFile(tmpfile)
	if err != nil {
		t.Error(err)
	}

	if !bytes.Equal(edited, plaintext) {
		t.Error("edited != plaintext ")
	}

	if bytes.Equal(enc1, enc2) {
		t.Error("Expecting different encrypted outputs")
	}
}

func TestVaultNew(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expect(t, "ssh-vault", r.Header.Get("User-agent"))
		fmt.Fprintln(w, "ssh-rsa ABC")
	}))
	defer ts.Close()
	_, err := New("", ts.URL, "view", "")
	if err != nil {
		t.Error(err)
	}
}

func TestVaultNewNoKey(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		expect(t, "ssh-vault", r.Header.Get("User-agent"))
	}))
	defer ts.Close()
	_, err := New("", ts.URL, "view", "")
	if err == nil {
		t.Error("Expecting error")
	}
}
<|endoftext|>


<commit_before>package boltqueue

import (
	"encoding/binary"
	"errors"
	"fmt"
	"time"

	"github.com/boltdb/bolt"
)

// TODO: Interfacification of messages

// Message represents a message in the priority queue
type Message struct {
	Priority int
	key      []byte
	value    []byte
}

var foundItem = errors.New("item found")
var lastTime int64 //keep track of the last UnixNano in case there's somehow a dup

// NewMessage generates a new priority queue message with a priority range of
// 0-255
func NewMessage(priority int, value string) *Message {
	if priority < 0 || priority > 255 {
		priority = 255
	}
	t := time.Now().UnixNano()
	if t <= lastTime {
		t = lastTime + 1
	}
	lastTime = t
	k := make([]byte, 8)
	binary.BigEndian.PutUint64(k, uint64(t))
	return &Message{priority, k, []byte(value)}
}

// ToString outputs the string representation of the message's value
func (m *Message) ToString() string {
	return string(m.value)
}

// PQueue is a priority queue backed by a Bolt database on disk
type PQueue struct {
	conn *bolt.DB
}

// NewPQueue loads or creates a new PQueue with the given filename
func NewPQueue(filename string) (*PQueue, error) {
	db, err := bolt.Open(filename, 0600, nil)
	if err != nil {
		return nil, err
	}
	return &PQueue{db}, nil
}

// Enqueue adds a message to the queue
func (b *PQueue) Enqueue(m *Message) error {
	if m.Priority < 0 || m.Priority > 255 {
		return fmt.Errorf("Invalid priority %d on Enqueue()", m.Priority)
	}
	p := make([]byte, 1)
	p[0] = byte(uint8(m.Priority))
	return b.conn.Update(func(tx *bolt.Tx) error {
		// Get bucket for this priority level
		pb, err := tx.CreateBucketIfNotExists(p)
		if err != nil {
			return err
		}
		// Add the message
		err = pb.Put(m.key, m.value)
		if err != nil {
			return err
		}
		return nil
	})
}

// Dequeue removes the oldest, highest priority message from the queue and
// returns it
func (b *PQueue) Dequeue() (*Message, error) {
	var m *Message
	err := b.conn.Update(func(tx *bolt.Tx) error {
		err := tx.ForEach(func(bname []byte, bucket *bolt.Bucket) error {
			if bucket.Stats().KeyN == 0 { //empty bucket
				return nil
			}
			cur := bucket.Cursor()
			k, v := cur.First() //Should not be empty by definition
			priority, _ := binary.Uvarint(bname)
			m = &Message{int(priority), cloneBytes(k), cloneBytes(v)}

			// Remove message
			if err := cur.Delete(); err != nil {
				return err
			}
			return foundItem //to stop the iteration
		})
		if err != nil && err != foundItem {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return m, nil
}

// Size returns the number of entries of a given priority from 1 to 5
func (b *PQueue) Size(priority int) (int, error) {
	if priority < 0 || priority > 255 {
		return 0, fmt.Errorf("Invalid priority %d for Size()", priority)
	}
	tx, err := b.conn.Begin(false)
	if err != nil {
		return 0, err
	}
	bucket := tx.Bucket([]byte{byte(uint8(priority))})
	if bucket == nil {
		return 0, nil
	}
	count := bucket.Stats().KeyN
	tx.Rollback()
	return count, nil
}

// Close closes the queue and releases all resources
func (b *PQueue) Close() error {
	err := b.conn.Close()
	if err != nil {
		return err
	}
	return nil
}

// taken from boltDB. Avoids corruption when re-queueing
func cloneBytes(v []byte) []byte {
	var clone = make([]byte, len(v))
	copy(clone, v)
	return clone
}
<commit_msg>use bucket auto-incrementer instead of time.Now.UnixNano()<commit_after>package boltqueue

import (
	"encoding/binary"
	"errors"
	"fmt"

	"github.com/boltdb/bolt"
)

// TODO: Interfacification of messages

// Message represents a message in the priority queue
type Message struct {
	Priority int
	key      []byte
	value    []byte
}

var foundItem = errors.New("item found")

// NewMessage generates a new priority queue message with a priority range of
// 0-255
func NewMessage(priority int, value string) *Message {
	if priority < 0 || priority > 255 {
		priority = 255
	}
	return &Message{Priority: priority, value: []byte(value)}
}

// ToString outputs the string representation of the message's value
func (m *Message) ToString() string {
	return string(m.value)
}

// PQueue is a priority queue backed by a Bolt database on disk
type PQueue struct {
	conn *bolt.DB
}

// NewPQueue loads or creates a new PQueue with the given filename
func NewPQueue(filename string) (*PQueue, error) {
	db, err := bolt.Open(filename, 0600, nil)
	if err != nil {
		return nil, err
	}
	return &PQueue{db}, nil
}

// Enqueue adds a message to the queue
func (b *PQueue) Enqueue(m *Message) error {
	if m.Priority < 0 || m.Priority > 255 {
		return fmt.Errorf("Invalid priority %d on Enqueue()", m.Priority)
	}
	p := make([]byte, 1)
	p[0] = byte(uint8(m.Priority))
	return b.conn.Update(func(tx *bolt.Tx) error {
		// Get bucket for this priority level
		pb, err := tx.CreateBucketIfNotExists(p)
		if err != nil {
			return err
		}
		// Add the message
		var key []byte
		if m.key == nil {
			key = make([]byte, 8)
			nextKey, err := pb.NextSequence()
			if err != nil {
				return err
			}
			binary.BigEndian.PutUint64(key, nextKey)
		} else {
			key = m.key
		}
		err = pb.Put(key, m.value)
		if err != nil {
			return err
		}
		return nil
	})
}

// Dequeue removes the oldest, highest priority message from the queue and
// returns it
func (b *PQueue) Dequeue() (*Message, error) {
	var m *Message
	err := b.conn.Update(func(tx *bolt.Tx) error {
		err := tx.ForEach(func(bname []byte, bucket *bolt.Bucket) error {
			if bucket.Stats().KeyN == 0 { //empty bucket
				return nil
			}
			cur := bucket.Cursor()
			k, v := cur.First() //Should not be empty by definition
			priority, _ := binary.Uvarint(bname)
			m = &Message{int(priority), cloneBytes(k), cloneBytes(v)}

			// Remove message
			if err := cur.Delete(); err != nil {
				return err
			}
			return foundItem //to stop the iteration
		})
		if err != nil && err != foundItem {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return m, nil
}

// Size returns the number of entries of a given priority from 1 to 5
func (b *PQueue) Size(priority int) (int, error) {
	if priority < 0 || priority > 255 {
		return 0, fmt.Errorf("Invalid priority %d for Size()", priority)
	}
	tx, err := b.conn.Begin(false)
	if err != nil {
		return 0, err
	}
	bucket := tx.Bucket([]byte{byte(uint8(priority))})
	if bucket == nil {
		return 0, nil
	}
	count := bucket.Stats().KeyN
	tx.Rollback()
	return count, nil
}

// Close closes the queue and releases all resources
func (b *PQueue) Close() error {
	err := b.conn.Close()
	if err != nil {
		return err
	}
	return nil
}

// taken from boltDB. Avoids corruption when re-queueing
func cloneBytes(v []byte) []byte {
	var clone = make([]byte, len(v))
	copy(clone, v)
	return clone
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 (
	"fmt"
	"os"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
)

func main() {

	// Set your region for future requests

	svc := ec2.New(session.New(),nil)

	// Call the DescribeInstances Operation
	regions, err := svc.DescribeRegions(nil)
	if err != nil {
		os.Exit(1)
	}
	fmt.Println("Success")
	for _, region := range regions.Regions {
		fmt.Println(*region.RegionName)
	}
	os.Exit(42)
}
<commit_msg>windows-iam: Fix copyright date<commit_after>// Copyright 2014-2016 Amazon.com, Inc. or its affiliates. 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. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 (
	"fmt"
	"os"

	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
)

func main() {

	// Set your region for future requests

	svc := ec2.New(session.New(), nil)

	// Call the DescribeInstances Operation
	regions, err := svc.DescribeRegions(nil)
	if err != nil {
		os.Exit(1)
	}
	fmt.Println("Success")
	for _, region := range regions.Regions {
		fmt.Println(*region.RegionName)
	}
	os.Exit(42)
}
<|endoftext|>


<commit_before>package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"

	"github.com/weaveworks/common/user"
	"github.com/weaveworks/cortex/configs"
	"github.com/weaveworks/cortex/configs/db"
)

// API implements the configs api.
type API struct {
	db db.DB
	http.Handler
}

// New creates a new API
func New(database db.DB) *API {
	a := &API{db: database}
	r := mux.NewRouter()
	a.RegisterRoutes(r)
	a.Handler = r
	return a
}

func (a *API) admin(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Content-Type", "text/html")
	fmt.Fprintf(w, `
<!doctype html>

	<title>configs :: configuration service</title>

configs :: configuration service

`)
}

// RegisterRoutes registers the configs API HTTP routes with the provided Router.
func (a *API) RegisterRoutes(r *mux.Router) {
	for _, route := range []struct {
		name, method, path string
		handler            http.HandlerFunc
	}{
		{"root", "GET", "/", a.admin},
		// Deprecated public APIs
		{"get_config", "GET", "/api/configs/org/cortex", a.getConfig},
		{"set_config", "POST", "/api/configs/org/cortex", a.setConfig},
		// Dedicated APIs for updating rules config. In the future, these *must*
		// be used.
		{"get_rules", "GET", "/api/prom/configs/rules", a.getConfig},
		{"set_rules", "POST", "/api/prom/configs/rules", a.setConfig},
		{"get_alertmanager_config", "GET", "/api/prom/configs/alertmanager", a.getConfig},
		{"set_alertmanager_config", "POST", "/api/prom/configs/alertmanager", a.setConfig},
		// Internal APIs.
		{"private_get_rules", "GET", "/private/api/prom/configs/rules", a.getConfigs},
		{"private_get_alertmanager_config", "GET", "/private/api/prom/configs/alertmanager", a.getConfigs},
	} {
		r.Handle(route.path, route.handler).Methods(route.method).Name(route.name)
	}
}

// getConfig returns the request configuration.
func (a *API) getConfig(w http.ResponseWriter, r *http.Request) {
	userID, _, err := user.ExtractFromHTTPRequest(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	cfg, err := a.db.GetConfig(userID)
	if err == sql.ErrNoRows {
		http.Error(w, "No configuration", http.StatusNotFound)
		return
	} else if err != nil {
		// XXX: Untested
		log.Errorf("Error getting config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error encoding config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func (a *API) setConfig(w http.ResponseWriter, r *http.Request) {
	userID, _, err := user.ExtractFromHTTPRequest(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	var cfg configs.Config
	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error decoding json body: %v", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	if err := a.db.SetConfig(userID, cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error storing config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// ConfigsView renders multiple configurations, mapping userID to ConfigView.
// Exposed only for tests.
type ConfigsView struct {
	Configs map[string]configs.ConfigView `json:"configs"`
}

func (a *API) getConfigs(w http.ResponseWriter, r *http.Request) {
	var cfgs map[string]configs.ConfigView
	var err error
	rawSince := r.FormValue("since")
	if rawSince == "" {
		cfgs, err = a.db.GetAllConfigs()
	} else {
		since, err := strconv.ParseUint(rawSince, 10, 0)
		if err != nil {
			log.Infof("Invalid config ID: %v", err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		cfgs, err = a.db.GetConfigs(configs.ID(since))
	}

	if err != nil {
		// XXX: Untested
		log.Errorf("Error getting configs: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	view := ConfigsView{Configs: cfgs}
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(view); err != nil {
		// XXX: Untested
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
<commit_msg>Remove old routes (#350)<commit_after>package api

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	log "github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"

	"github.com/weaveworks/common/user"
	"github.com/weaveworks/cortex/configs"
	"github.com/weaveworks/cortex/configs/db"
)

// API implements the configs api.
type API struct {
	db db.DB
	http.Handler
}

// New creates a new API
func New(database db.DB) *API {
	a := &API{db: database}
	r := mux.NewRouter()
	a.RegisterRoutes(r)
	a.Handler = r
	return a
}

func (a *API) admin(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Content-Type", "text/html")
	fmt.Fprintf(w, `
<!doctype html>

	<title>configs :: configuration service</title>

configs :: configuration service

`)
}

// RegisterRoutes registers the configs API HTTP routes with the provided Router.
func (a *API) RegisterRoutes(r *mux.Router) {
	for _, route := range []struct {
		name, method, path string
		handler            http.HandlerFunc
	}{
		{"root", "GET", "/", a.admin},
		// Dedicated APIs for updating rules config. In the future, these *must*
		// be used.
		{"get_rules", "GET", "/api/prom/configs/rules", a.getConfig},
		{"set_rules", "POST", "/api/prom/configs/rules", a.setConfig},
		{"get_alertmanager_config", "GET", "/api/prom/configs/alertmanager", a.getConfig},
		{"set_alertmanager_config", "POST", "/api/prom/configs/alertmanager", a.setConfig},
		// Internal APIs.
		{"private_get_rules", "GET", "/private/api/prom/configs/rules", a.getConfigs},
		{"private_get_alertmanager_config", "GET", "/private/api/prom/configs/alertmanager", a.getConfigs},
	} {
		r.Handle(route.path, route.handler).Methods(route.method).Name(route.name)
	}
}

// getConfig returns the request configuration.
func (a *API) getConfig(w http.ResponseWriter, r *http.Request) {
	userID, _, err := user.ExtractFromHTTPRequest(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	cfg, err := a.db.GetConfig(userID)
	if err == sql.ErrNoRows {
		http.Error(w, "No configuration", http.StatusNotFound)
		return
	} else if err != nil {
		// XXX: Untested
		log.Errorf("Error getting config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error encoding config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func (a *API) setConfig(w http.ResponseWriter, r *http.Request) {
	userID, _, err := user.ExtractFromHTTPRequest(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	var cfg configs.Config
	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error decoding json body: %v", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	if err := a.db.SetConfig(userID, cfg); err != nil {
		// XXX: Untested
		log.Errorf("Error storing config: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// ConfigsView renders multiple configurations, mapping userID to ConfigView.
// Exposed only for tests.
type ConfigsView struct {
	Configs map[string]configs.ConfigView `json:"configs"`
}

func (a *API) getConfigs(w http.ResponseWriter, r *http.Request) {
	var cfgs map[string]configs.ConfigView
	var err error
	rawSince := r.FormValue("since")
	if rawSince == "" {
		cfgs, err = a.db.GetAllConfigs()
	} else {
		since, err := strconv.ParseUint(rawSince, 10, 0)
		if err != nil {
			log.Infof("Invalid config ID: %v", err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		cfgs, err = a.db.GetConfigs(configs.ID(since))
	}

	if err != nil {
		// XXX: Untested
		log.Errorf("Error getting configs: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	view := ConfigsView{Configs: cfgs}
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(view); err != nil {
		// XXX: Untested
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
<|endoftext|>


<commit_before><commit_msg>add errors<commit_after><|endoftext|>


<commit_before>package gonp

import (
	"testing"
	"unicode/utf8"
)

func TestPatch(t *testing.T) {

	tests := []struct {
		a string
		b string
	}{
		{
			a: "",
			b: "",
		},
		{
			a: "a",
			b: "a",
		},
		{
			a: "abc",
			b: "",
		},
		{
			a: "",
			b: "def",
		},
		{
			a: "abc",
			b: "abd",
		},
		{
			a: "abcdef",
			b: "dacfea",
		},
		{
			a: "acbdeacbed",
			b: "acebdabbabed",
		},
		{
			a: "bokko",
			b: "bokkko",
		},
		{
			a: "abcbda",
			b: "bdcaba",
		},
		{
			a: "abcaaaaaaaaaaaaaabd",
			b: "abdaaaaaaaaaaaaaabc",
		},
		{
			a: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaesaaabcaaaaaaccc",
		},
		{
			a: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc",
		},
		{
			a: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc",
			b: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
		},
		{
			a: "aaaaaaaaaaaaa>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>aaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbaaaaaaaaaaaaaaaaaeaaaaaaaaaae&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&saaabcaaaaaaccc",
		},
	}

	for _, test := range tests {
		diff := New([]rune(test.a), []rune(test.b))
		diff.Compose()

		patchedSeq := diff.Patch([]rune(test.a))
		if string(patchedSeq) != test.b {
			t.Errorf("applying SES between '%s' and '%s' to '%s' is %s, but got %s", string(test.a), string(test.b), string(test.a), string(test.b), string(patchedSeq))
		}

		uniPatchedSeq, _ := diff.UniPatch([]rune(test.a), diff.UnifiedHunks())
		if string(uniPatchedSeq) != test.b {
			t.Errorf("applying unified format difference between '%s' and '%s' to '%s' is %s, but got %s", string(test.a), string(test.b), string(test.a), string(test.b), string(uniPatchedSeq))
		}
	}
}

func FuzzPatch(f *testing.F) {
	f.Add("aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb", "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc")
	f.Fuzz(func(t *testing.T, a, b string) {
		if !utf8.ValidString(a) || !utf8.ValidString(b) {
			return
		}

		diff := New([]rune(a), []rune(b))
		diff.Compose()

		patchedSeq := diff.Patch([]rune(a))
		if string(patchedSeq) != b {
			t.Errorf("applying SES between '%s' and '%s' to '%s' is %s, but got %s", a, b, a, b, string(patchedSeq))
		}

		uniPatchedSeq, _ := diff.UniPatch([]rune(a), diff.UnifiedHunks())
		if string(uniPatchedSeq) != b {
			t.Errorf("applying unified format difference between '%s' and '%s' to '%s' is %s, but got %s", a, b, a, b, string(uniPatchedSeq))
		}
	})
}
<commit_msg>test: added benchmark for Patch() and UniPatch().<commit_after>package gonp

import (
	"strings"
	"testing"
	"unicode/utf8"
)

func buildLongString(prefix, interfix, suffix string, n int) string {
	var sb strings.Builder
	sb.WriteString(prefix)
	for i := 0; i < n; i++ {
		sb.WriteString(interfix)
	}
	sb.WriteString(suffix)
	return sb.String()
}

func TestPatch(t *testing.T) {

	tests := []struct {
		a string
		b string
	}{
		{
			a: "",
			b: "",
		},
		{
			a: "a",
			b: "a",
		},
		{
			a: "abc",
			b: "",
		},
		{
			a: "",
			b: "def",
		},
		{
			a: "abc",
			b: "abd",
		},
		{
			a: "abcdef",
			b: "dacfea",
		},
		{
			a: "acbdeacbed",
			b: "acebdabbabed",
		},
		{
			a: "bokko",
			b: "bokkko",
		},
		{
			a: "abcbda",
			b: "bdcaba",
		},
		{
			a: "abcaaaaaaaaaaaaaabd",
			b: "abdaaaaaaaaaaaaaabc",
		},
		{
			a: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaesaaabcaaaaaaccc",
		},
		{
			a: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc",
		},
		{
			a: "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc",
			b: "aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
		},
		{
			a: "aaaaaaaaaaaaa>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>aaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
			b: "aaaaaaaaaaaaaaadasfdsafsadasdafbaaaaaaaaaaaaaaaaaeaaaaaaaaaae&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&saaabcaaaaaaccc",
		},
	}

	for _, test := range tests {
		diff := New([]rune(test.a), []rune(test.b))
		diff.Compose()

		patchedSeq := diff.Patch([]rune(test.a))
		if string(patchedSeq) != test.b {
			t.Errorf("applying SES between '%s' and '%s' to '%s' is %s, but got %s", string(test.a), string(test.b), string(test.a), string(test.b), string(patchedSeq))
		}

		uniPatchedSeq, _ := diff.UniPatch([]rune(test.a), diff.UnifiedHunks())
		if string(uniPatchedSeq) != test.b {
			t.Errorf("applying unified format difference between '%s' and '%s' to '%s' is %s, but got %s", string(test.a), string(test.b), string(test.a), string(test.b), string(uniPatchedSeq))
		}
	}
}

func BenchmarkPatchSmall(b *testing.B) {
	s1 := []rune("abc")
	s2 := []rune("abd")
	diff := New(s1, s2)
	diff.Compose()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = diff.Patch(s1)
	}
}

func BenchmarkUniPatchSmall(b *testing.B) {
	s1 := []rune("abc")
	s2 := []rune("abd")
	diff := New(s1, s2)
	diff.Compose()
	uniHunks := diff.UnifiedHunks()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, _ = diff.UniPatch(s1, uniHunks)
	}
}

func BenchmarkPatchLarge(b *testing.B) {
	s1 := []rune(buildLongString("abc", "a", "def", 1000))
	s2 := []rune(buildLongString("abd", "a", "ghi", 1000))
	diff := New([]rune(s1), []rune(s2))
	diff.Compose()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = diff.Patch(s1)
	}
}

func BenchmarkUniPatchLarge(b *testing.B) {
	s1 := []rune(buildLongString("abc", "a", "def", 1000))
	s2 := []rune(buildLongString("abd", "a", "ghi", 1000))
	diff := New(s1, s2)
	diff.Compose()
	uniHunks := diff.UnifiedHunks()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, _ = diff.UniPatch(s1, uniHunks)
	}
}

func FuzzPatch(f *testing.F) {
	f.Add("aaaaaaaaaaaaaaaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb", "aaaaaaaaaaaaaaadasfdsafsadasdafbdaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaesaaabcaaaaaaccc")
	f.Fuzz(func(t *testing.T, a, b string) {
		if !utf8.ValidString(a) || !utf8.ValidString(b) {
			return
		}

		diff := New([]rune(a), []rune(b))
		diff.Compose()

		patchedSeq := diff.Patch([]rune(a))
		if string(patchedSeq) != b {
			t.Errorf("applying SES between '%s' and '%s' to '%s' is %s, but got %s", a, b, a, b, string(patchedSeq))
		}

		uniPatchedSeq, _ := diff.UniPatch([]rune(a), diff.UnifiedHunks())
		if string(uniPatchedSeq) != b {
			t.Errorf("applying unified format difference between '%s' and '%s' to '%s' is %s, but got %s", a, b, a, b, string(uniPatchedSeq))
		}
	})
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package pbr

//------------------------------------------------------------------------------

import (
	"math"

	"github.com/drakmaniso/glam/gfx"
	"github.com/drakmaniso/glam/internal"
	math32 "github.com/drakmaniso/glam/math"
	"github.com/drakmaniso/glam/space"
)

//------------------------------------------------------------------------------

type Camera struct {
	buffer struct {
		ProjectionView space.Matrix
		CameraPosition space.Coord
		CameraExposure float32
	}

	projection space.Matrix
	view       space.Matrix

	aspectRatio float32
	fieldOfView float32
	near, far   float32

	current struct {
		position         space.Coord
		yaw, pitch, roll float32
	}

	previous struct {
		position         space.Coord
		yaw, pitch, roll float32
	}

	ubo gfx.UniformBuffer
}

//------------------------------------------------------------------------------

func NewCamera() *Camera {
	var c Camera
	c.ubo = gfx.NewUniformBuffer(&c.buffer, gfx.DynamicStorage)
	c.SetExposure(16.0, 1.0/125.0, 100.0)
	c.SetFieldOfView(math.Pi/4, 0.001, 1000.0)

	return &c
}

//------------------------------------------------------------------------------

func (c *Camera) SetFieldOfView(fov float32, near, far float32) {
	c.fieldOfView = fov
	c.near, c.far = near, far
	c.WindowResized()
}

//------------------------------------------------------------------------------

func (c *Camera) WindowResized() {
	sx, sy := float32(internal.Window.Width), float32(internal.Window.Height)
	r := sx / sy
	c.projection = space.Perspective(c.fieldOfView, r, c.near, c.far)
}

//------------------------------------------------------------------------------

func (c *Camera) SetPosition(p space.Coord) {
	c.current.position = p
}

func (c *Camera) Move(forward, lateral, vertical float32) {
	c.current.position.X += lateral*math32.Cos(c.current.yaw) - forward*math32.Sin(c.current.yaw)
	c.current.position.Z += lateral*math32.Sin(c.current.yaw) + forward*math32.Cos(c.current.yaw)
	c.current.position.Y += vertical
}

func (c *Camera) Position() space.Coord {
	return c.current.position
}

//------------------------------------------------------------------------------

func (c *Camera) SetOrientation(yaw, pitch, roll float32) {
	c.current.yaw = yaw
	c.current.pitch = pitch
	c.current.roll = roll
}

func (c *Camera) Rotate(yaw, pitch, roll float32) {
	c.current.yaw += yaw
	for c.current.yaw > math32.Pi {
		c.current.yaw -= 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.yaw -= 2 * math32.Pi
	}
	for c.current.yaw < -math32.Pi {
		c.current.yaw += 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.yaw += 2 * math32.Pi
	}

	c.current.pitch += pitch
	switch {
	case c.current.pitch < -math.Pi/2:
		c.current.pitch = -math.Pi / 2
	case c.current.pitch > +math.Pi/2:
		c.current.pitch = +math.Pi / 2
	}

	c.current.roll += roll
	for c.current.roll > math32.Pi {
		c.current.roll -= 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.roll -= 2 * math32.Pi
	}
	for c.current.roll < -math32.Pi {
		c.current.roll += 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.roll += 2 * math32.Pi
	}
}

func (c *Camera) Orientation() (yaw, pitch, roll float32) {
	return c.current.yaw, c.current.pitch, c.current.roll
}

//------------------------------------------------------------------------------

func (c *Camera) NextState() {
	c.previous = c.current
}

//------------------------------------------------------------------------------

func (c *Camera) SetExposure(aperture, shutterTime, sensitivity float64) {
	// See "Moving Frostbite to Physically Based Rendering", Lagarde, de Rousiers (SIGGRAPH 2014)
	ev100 := math.Log2((aperture * aperture) / shutterTime * 100.0 / sensitivity)
	maxLum := 1.2 * math.Pow(2.0, ev100)
	c.buffer.CameraExposure = float32(1.0 / maxLum)
}

//------------------------------------------------------------------------------

func (c *Camera) Bind() {
	c.updateView()
	c.buffer.ProjectionView = c.projection.Times(c.view)
	c.ubo.SubData(&c.buffer, 0)
	c.ubo.Bind(0)
}

//------------------------------------------------------------------------------

func (c *Camera) updateView() {
	a := float32(internal.DrawInterpolation)
	pos := c.previous.position.Times(1 - a).Plus(c.current.position.Times(a))
	yaw := c.previous.yaw*(1-a) + c.current.yaw*a
	pitch := c.previous.pitch*(1-a) + c.current.pitch*a
	roll := c.previous.roll*(1-a) + c.current.roll*a

	c.view = space.EulerZXY(pitch, yaw, roll)
	c.view = c.view.Times(space.Translation(pos.Inverse()))

	c.buffer.CameraPosition = pos
}

//------------------------------------------------------------------------------
<commit_msg>Tweak camera<commit_after>// Copyright (c) 2013-2017 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package pbr

//------------------------------------------------------------------------------

import (
	"math"

	"github.com/drakmaniso/glam/gfx"
	"github.com/drakmaniso/glam/internal"
	math32 "github.com/drakmaniso/glam/math"
	"github.com/drakmaniso/glam/space"
)

//------------------------------------------------------------------------------

//TODO: use quaternion or rotation matrix directly

type Camera struct {
	buffer struct {
		ProjectionView space.Matrix
		CameraPosition space.Coord
		CameraExposure float32
	}

	projection space.Matrix
	view       space.Matrix

	aspectRatio float32
	fieldOfView float32
	near, far   float32

	current struct {
		position         space.Coord
		yaw, pitch, roll float32
	}

	previous struct {
		position         space.Coord
		yaw, pitch, roll float32
	}

	ubo gfx.UniformBuffer
}

//------------------------------------------------------------------------------

func NewCamera() *Camera {
	var c Camera
	c.ubo = gfx.NewUniformBuffer(&c.buffer, gfx.DynamicStorage)
	c.SetExposure(16.0, 1.0/125.0, 100.0)
	c.SetFieldOfView(math.Pi/4, 0.001, 1000.0)

	return &c
}

//------------------------------------------------------------------------------

func (c *Camera) SetFieldOfView(fov float32, near, far float32) {
	c.fieldOfView = fov
	c.near, c.far = near, far
	c.WindowResized()
}

//------------------------------------------------------------------------------

func (c *Camera) WindowResized() {
	sx, sy := float32(internal.Window.Width), float32(internal.Window.Height)
	r := sx / sy
	c.projection = space.Perspective(c.fieldOfView, r, c.near, c.far)
}

//------------------------------------------------------------------------------

func (c *Camera) SetPosition(p space.Coord) {
	c.current.position = p
}

func (c *Camera) Move(forward, lateral, vertical float32) {
	c.current.position.X += lateral*math32.Cos(c.current.yaw) - forward*math32.Sin(c.current.yaw)
	c.current.position.Z += lateral*math32.Sin(c.current.yaw) + forward*math32.Cos(c.current.yaw)
	c.current.position.Y += vertical
}

func (c *Camera) Position() space.Coord {
	return c.current.position
}

//------------------------------------------------------------------------------

func (c *Camera) SetOrientation(yaw, pitch, roll float32) {
	c.current.yaw = yaw
	c.current.pitch = pitch
	c.current.roll = roll
}

func (c *Camera) Rotate(yaw, pitch, roll float32) {
	c.current.yaw += yaw
	for c.current.yaw > math32.Pi {
		c.current.yaw -= 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.yaw -= 2 * math32.Pi
	}
	for c.current.yaw < -math32.Pi {
		c.current.yaw += 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.yaw += 2 * math32.Pi
	}

	c.current.pitch += pitch
	switch {
	case c.current.pitch < -math.Pi/2:
		c.current.pitch = -math.Pi / 2
	case c.current.pitch > +math.Pi/2:
		c.current.pitch = +math.Pi / 2
	}

	c.current.roll += roll
	for c.current.roll > math32.Pi {
		c.current.roll -= 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.roll -= 2 * math32.Pi
	}
	for c.current.roll < -math32.Pi {
		c.current.roll += 2 * math32.Pi
		// Need to update previous state too, because of interpolation
		c.previous.roll += 2 * math32.Pi
	}
}

func (c *Camera) Orientation() (yaw, pitch, roll float32) {
	return c.current.yaw, c.current.pitch, c.current.roll
}

//------------------------------------------------------------------------------

func (c *Camera) NextState() {
	c.previous = c.current
}

//------------------------------------------------------------------------------

func (c *Camera) SetExposure(aperture, shutterTime, sensitivity float64) {
	// See "Moving Frostbite to Physically Based Rendering", Lagarde, de Rousiers (SIGGRAPH 2014)
	ev100 := math.Log2((aperture * aperture) / shutterTime * 100.0 / sensitivity)
	maxLum := 1.2 * math.Pow(2.0, ev100)
	c.buffer.CameraExposure = float32(1.0 / maxLum)
}

//------------------------------------------------------------------------------

func (c *Camera) Bind() {
	c.updateView()
	c.buffer.ProjectionView = c.projection.Times(c.view)
	c.ubo.SubData(&c.buffer, 0)
	c.ubo.Bind(0)
}

//------------------------------------------------------------------------------

func (c *Camera) updateView() {
	a := float32(internal.DrawInterpolation)
	pos := c.previous.position.Times(1 - a).Plus(c.current.position.Times(a))
	yaw := c.previous.yaw*(1-a) + c.current.yaw*a
	pitch := c.previous.pitch*(1-a) + c.current.pitch*a
	roll := c.previous.roll*(1-a) + c.current.roll*a

	c.view = space.EulerYXZ(pitch, yaw, roll)
	c.view = c.view.Times(space.Translation(pos.Inverse()))

	c.buffer.CameraPosition = pos
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"path"
	"reflect"
	"testing"
	"time"

	"golang.org/x/crypto/ssh"
)

func TestHandleConnection(t *testing.T) {
	dataDir := t.TempDir()
	key := pkcs8fileKey{}
	hostKey, err := key.generate(dataDir, ecdsa_key)
	if err != nil {
		t.Fatalf("Failed to generate host key: %v", err)
	}
	cfg := &config{
		Server: serverConfig{HostKeys: []string{hostKey}},
		Auth:   authConfig{NoAuth: true},
	}
	if err := cfg.setupSSHConfig(key); err != nil {
		t.Fatalf("Failed to setup SSH config: %v", err)
	}
	cfg.sshConfig.AddHostKey(mockSigner{signature: ecdsa_key})
	tempDir := t.TempDir()
	serverAddress := path.Join(tempDir, "server.sock")
	listener, err := net.Listen("unix", serverAddress)
	if err != nil {
		t.Fatalf("Failed to listen: %v", err)
	}
	defer listener.Close()
	resultChan := make(chan interface{})
	logBuffer := setupLogBuffer(cfg)
	go func() {
		defer func() { resultChan <- nil }()
		serverConn, err := listener.Accept()
		if err != nil {
			t.Errorf("Failed to accept conenction: %v", err)
			return
		}
		handleConnection(serverConn, cfg)
	}()
	clientAddress := path.Join(tempDir, "client.sock")
	clientConn, err := net.DialUnix("unix", &net.UnixAddr{Name: clientAddress, Net: "unix"}, &net.UnixAddr{Name: serverAddress, Net: "unix"})
	if err != nil {
		t.Fatalf("Failed to connect: %v", err)
	}
	defer clientConn.Close()
	clientSSHConn, channels, requests, err := ssh.NewClientConn(clientConn, "127.0.0.1:2022", &ssh.ClientConfig{
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	})
	if err != nil {
		t.Errorf("Failed to create client connection: %v", err)
		return
	}
	requestTypes := []string{}
	channelTypes := []string{}
	requestsDone := make(chan interface{})
	go func() {
		for request := range requests {
			requestTypes = append(requestTypes, request.Type)
		}
		requestsDone <- nil
	}()
	channelsDone := make(chan interface{})
	go func() {
		for channel := range channels {
			channelTypes = append(channelTypes, channel.ChannelType())
		}
		channelsDone <- nil
	}()
	_, _, _ = clientSSHConn.SendRequest("test", false, nil)
	_, _, _ = clientSSHConn.OpenChannel("test", nil)
	channel, _, err := clientSSHConn.OpenChannel("session", nil)
	if err != nil {
		t.Fatalf("Failed to request session channel: %v", err)
	}
	if channel.Close() != nil {
		t.Fatalf("Faield to close session channel: %v", err)
	}
	time.Sleep(10 * time.Millisecond)
	channel, _, err = clientSSHConn.OpenChannel("session", nil)
	if err != nil {
		t.Fatalf("Failed to request session channel: %v", err)
	}
	if channel.Close() != nil {
		t.Fatalf("Faield to close session channel: %v", err)
	}
	clientSSHConn.Close()
	<-resultChan
	<-channelsDone
	<-requestsDone
	expectedRequests := []string{"hostkeys-00@openssh.com"}
	if !reflect.DeepEqual(requestTypes, expectedRequests) {
		t.Errorf("requestTypes=%v, want %v", requestTypes, expectedRequests)
	}
	if len(channelTypes) != 0 {
		t.Errorf("len(channelTypes)=%v, want 0", len(channelTypes))
	}
	logs := logBuffer.String()
	expectedLogs := fmt.Sprintf(`[%[1]v] authentication for user "" without credentials accepted
[%[1]v] connection with client version "SSH-2.0-Go" established
[%[1]v] [channel 0] session requested
[%[1]v] [channel 0] closed
[%[1]v] [channel 1] session requested
[%[1]v] [channel 1] closed
[%[1]v] connection closed
`, clientAddress)
	if logs != expectedLogs {
		t.Errorf("logs=%v, want %v", string(logs), expectedLogs)
	}
}
<commit_msg>Extend connection_test with failure cases<commit_after>package main

import (
	"fmt"
	"net"
	"path"
	"reflect"
	"testing"
	"time"

	"golang.org/x/crypto/ssh"
)

type request struct {
	name    string
	data    []byte
	success bool
}

type channelResult int

const (
	rejected channelResult = iota
	accepted
	failed
)

type channel struct {
	name   string
	data   []byte
	result channelResult
}

func testConnection(t *testing.T, clientAddress string, clientRequests []request, clientChannels []channel) string {
	key := pkcs8fileKey{}
	hostKey, err := key.generate(t.TempDir(), ecdsa_key)
	if err != nil {
		t.Fatalf("Failed to generate host key: %v", err)
	}
	cfg := &config{
		Server: serverConfig{HostKeys: []string{hostKey}},
		Auth:   authConfig{NoAuth: true},
	}
	if err := cfg.setupSSHConfig(key); err != nil {
		t.Fatalf("Failed to setup SSH config: %v", err)
	}
	cfg.sshConfig.AddHostKey(mockSigner{signature: ecdsa_key})
	tempDir := t.TempDir()
	serverAddress := path.Join(tempDir, "server.sock")
	listener, err := net.Listen("unix", serverAddress)
	if err != nil {
		t.Fatalf("Failed to listen: %v", err)
	}
	defer listener.Close()
	resultChan := make(chan interface{})
	logBuffer := setupLogBuffer(cfg)
	go func() {
		defer func() { resultChan <- nil }()
		serverConn, err := listener.Accept()
		if err != nil {
			t.Errorf("Failed to accept conenction: %v", err)
			return
		}
		handleConnection(serverConn, cfg)
	}()
	clientConn, err := net.DialUnix("unix", &net.UnixAddr{Name: clientAddress, Net: "unix"}, &net.UnixAddr{Name: serverAddress, Net: "unix"})
	if err != nil {
		t.Fatalf("Failed to connect: %v", err)
	}
	defer clientConn.Close()
	clientSSHConn, channels, requests, err := ssh.NewClientConn(clientConn, "127.0.0.1:2022", &ssh.ClientConfig{
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	})
	if err != nil {
		t.Fatalf("Failed to create client connection: %v", err)
	}
	requestTypes := []string{}
	channelTypes := []string{}
	requestsDone := make(chan interface{})
	go func() {
		for request := range requests {
			requestTypes = append(requestTypes, request.Type)
		}
		requestsDone <- nil
	}()
	channelsDone := make(chan interface{})
	go func() {
		for channel := range channels {
			channelTypes = append(channelTypes, channel.ChannelType())
		}
		channelsDone <- nil
	}()
	time.Sleep(10 * time.Millisecond)
	for _, clientRequest := range clientRequests {
		_, _, _ = clientSSHConn.SendRequest(clientRequest.name, false, clientRequest.data)
		if !clientRequest.success {
			clientSSHConn.Wait()
			return logBuffer.String()
		}
	}
	for _, clientChannel := range clientChannels {
		channel, _, err := clientSSHConn.OpenChannel(clientChannel.name, clientChannel.data)
		switch clientChannel.result {
		case accepted:
			if err != nil {
				t.Fatalf("Failed to request channel: %v", err)
			}
			if err := channel.Close(); err != nil {
				t.Fatalf("Failed to close channel: %v", err)
			}
			time.Sleep(10 * time.Millisecond)
		case failed:
			clientSSHConn.Wait()
			return logBuffer.String()
		}
	}
	clientSSHConn.Close()
	<-resultChan
	<-channelsDone
	<-requestsDone
	expectedRequests := []string{"hostkeys-00@openssh.com"}
	if !reflect.DeepEqual(requestTypes, expectedRequests) {
		t.Errorf("requestTypes=%v, want %v", requestTypes, expectedRequests)
	}
	if len(channelTypes) != 0 {
		t.Errorf("len(channelTypes)=%v, want 0", len(channelTypes))
	}
	return logBuffer.String()
}

func TestHandleConnection(t *testing.T) {
	clientAddress := path.Join(t.TempDir(), "client.sock")
	logs := testConnection(t, clientAddress, []request{{"test", nil, true}}, []channel{{"test", nil, rejected}, {"session", nil, accepted}, {"session", nil, accepted}})
	expectedLogs := fmt.Sprintf(`[%[1]v] authentication for user "" without credentials accepted
[%[1]v] connection with client version "SSH-2.0-Go" established
[%[1]v] [channel 0] session requested
[%[1]v] [channel 0] closed
[%[1]v] [channel 1] session requested
[%[1]v] [channel 1] closed
[%[1]v] connection closed
`, clientAddress)
	if logs != expectedLogs {
		t.Errorf("logs=%v, want %v", string(logs), expectedLogs)
	}
}

func TestFailedRequestHandling(t *testing.T) {
	clientAddress := path.Join(t.TempDir(), "client.sock")
	logs := testConnection(t, clientAddress, []request{{"tcpip-forward", nil, false}}, []channel{})
	expectedLogs := fmt.Sprintf(`[%[1]v] authentication for user "" without credentials accepted
[%[1]v] connection with client version "SSH-2.0-Go" established
[%[1]v] connection closed
`, clientAddress)
	if logs != expectedLogs {
		t.Errorf("logs=%v, want %v", string(logs), expectedLogs)
	}
}

func TestFailedChannelHandling(t *testing.T) {
	clientAddress := path.Join(t.TempDir(), "client.sock")
	logs := testConnection(t, clientAddress, []request{}, []channel{{"direct-tcpip", nil, failed}})
	expectedLogs := fmt.Sprintf(`[%[1]v] authentication for user "" without credentials accepted
[%[1]v] connection with client version "SSH-2.0-Go" established
[%[1]v] connection closed
`, clientAddress)
	if logs != expectedLogs {
		t.Errorf("logs=%v, want %v", string(logs), expectedLogs)
	}
}
<|endoftext|>


<commit_before>package consul

import (
	"fmt"
	"net"
	"sync"
	"time"
)

// RaftLayer implements the raft.StreamLayer interface,
// so that we can use a single RPC layer for Raft and Consul
type RaftLayer struct {
	// Addr is the listener address to return
	addr net.Addr

	// connCh is used to accept connections
	connCh chan net.Conn

	// Tracks if we are closed
	closed    bool
	closeCh   chan struct{}
	closeLock sync.Mutex
}

// NewRaftLayer is used to initialize a new RaftLayer which can
// be used as a StreamLayer for Raft
func NewRaftLayer(addr net.Addr) *RaftLayer {
	layer := &RaftLayer{
		addr:    addr,
		connCh:  make(chan net.Conn),
		closeCh: make(chan struct{}),
	}
	return layer
}

// Handoff is used to hand off a connection to the
// RaftLayer. This allows it to be Accept()'ed
func (l *RaftLayer) Handoff(c net.Conn) error {
	select {
	case l.connCh <- c:
		return nil
	case <-l.closeCh:
		return fmt.Errorf("Raft RPC layer closed")
	}
}

// Accept is used to return connection which are
// dialed to be used with the Raft layer
func (l *RaftLayer) Accept() (net.Conn, error) {
	select {
	case conn := <-l.connCh:
		return conn, nil
	case <-l.closeCh:
		return nil, fmt.Errorf("Raft RPC layer closed")
	}
}

// Close is used to stop listening for Raft connections
func (l *RaftLayer) Close() error {
	l.closeLock.Lock()
	defer l.closeLock.Unlock()

	if !l.closed {
		l.closed = true
		close(l.closeCh)
	}
	return nil
}

// Addr is used to return the address of the listener
func (l *RaftLayer) Addr() net.Addr {
	return l.addr
}

// Dial is used to create a new outgoing connection
func (l *RaftLayer) Dial(address string, timeout time.Duration) (net.Conn, error) {
	conn, err := net.DialTimeout("tcp", address, timeout)
	if err != nil {
		return nil, err
	}

	// Write the Raft byte to set the mode
	conn.Write([]byte{byte(rpcRaft)})
	return conn, err
}
<commit_msg>Check for error when sending RPC byte<commit_after>package consul

import (
	"fmt"
	"net"
	"sync"
	"time"
)

// RaftLayer implements the raft.StreamLayer interface,
// so that we can use a single RPC layer for Raft and Consul
type RaftLayer struct {
	// Addr is the listener address to return
	addr net.Addr

	// connCh is used to accept connections
	connCh chan net.Conn

	// Tracks if we are closed
	closed    bool
	closeCh   chan struct{}
	closeLock sync.Mutex
}

// NewRaftLayer is used to initialize a new RaftLayer which can
// be used as a StreamLayer for Raft
func NewRaftLayer(addr net.Addr) *RaftLayer {
	layer := &RaftLayer{
		addr:    addr,
		connCh:  make(chan net.Conn),
		closeCh: make(chan struct{}),
	}
	return layer
}

// Handoff is used to hand off a connection to the
// RaftLayer. This allows it to be Accept()'ed
func (l *RaftLayer) Handoff(c net.Conn) error {
	select {
	case l.connCh <- c:
		return nil
	case <-l.closeCh:
		return fmt.Errorf("Raft RPC layer closed")
	}
}

// Accept is used to return connection which are
// dialed to be used with the Raft layer
func (l *RaftLayer) Accept() (net.Conn, error) {
	select {
	case conn := <-l.connCh:
		return conn, nil
	case <-l.closeCh:
		return nil, fmt.Errorf("Raft RPC layer closed")
	}
}

// Close is used to stop listening for Raft connections
func (l *RaftLayer) Close() error {
	l.closeLock.Lock()
	defer l.closeLock.Unlock()

	if !l.closed {
		l.closed = true
		close(l.closeCh)
	}
	return nil
}

// Addr is used to return the address of the listener
func (l *RaftLayer) Addr() net.Addr {
	return l.addr
}

// Dial is used to create a new outgoing connection
func (l *RaftLayer) Dial(address string, timeout time.Duration) (net.Conn, error) {
	conn, err := net.DialTimeout("tcp", address, timeout)
	if err != nil {
		return nil, err
	}

	// Write the Raft byte to set the mode
	_, err = conn.Write([]byte{byte(rpcRaft)})
	if err != nil {
		conn.Close()
		return nil, err
	}
	return conn, err
}
<|endoftext|>