<commit_before>package persist

import (
	"encoding/json"
	"io"
	"os"
)

// Save saves json data to a writer.
func Save(meta Metadata, data interface{}, w io.Writer) error {
	b, err := json.MarshalIndent(data, "", "\t")
	if err != nil {
		return err
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(meta.Header); err != nil {
		return err
	}
	if err := enc.Encode(meta.Version); err != nil {
		return err
	}
	if _, err = w.Write(b); err != nil {
		return err
	}

	return nil
}

// Load loads json data from a reader.
func Load(meta Metadata, data interface{}, r io.Reader) error {
	var header, version string
	dec := json.NewDecoder(r)
	if err := dec.Decode(&header); err != nil {
		return err
	}
	if header != meta.Header {
		return ErrBadHeader
	}
	if err := dec.Decode(&version); err != nil {
		return err
	}
	if version != meta.Version {
		return ErrBadVersion
	}
	if err := dec.Decode(data); err != nil {
		return err
	}

	return nil
}

// SaveFile saves json data to a file.
func SaveFile(meta Metadata, data interface{}, filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	return Save(meta, data, file)
}

// LoadFile loads json data from a file.
func LoadFile(meta Metadata, data interface{}, filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	return Load(meta, data, file)
}
<commit_msg>stronger error messaging for json loading<commit_after>package persist

import (
	"encoding/json"
	"errors"
	"io"
	"os"
)

// Save saves json data to a writer.
func Save(meta Metadata, data interface{}, w io.Writer) error {
	b, err := json.MarshalIndent(data, "", "\t")
	if err != nil {
		return err
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(meta.Header); err != nil {
		return err
	}
	if err := enc.Encode(meta.Version); err != nil {
		return err
	}
	if _, err = w.Write(b); err != nil {
		return err
	}

	return nil
}

// Load loads json data from a reader.
func Load(meta Metadata, data interface{}, r io.Reader) error {
	var header, version string
	dec := json.NewDecoder(r)
	if err := dec.Decode(&header); err != nil {
		return err
	}
	if header != meta.Header {
		return ErrBadHeader
	}
	if err := dec.Decode(&version); err != nil {
		return err
	}
	if version != meta.Version {
		return ErrBadVersion
	}
	if err := dec.Decode(data); err != nil {
		return err
	}

	return nil
}

// SaveFile saves json data to a file.
func SaveFile(meta Metadata, data interface{}, filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = Save(meta, data, file)
	if err != nil {
		return errors.New("error saving " + filename + ": " + err.Error())
	}
	return nil
}

// LoadFile loads json data from a file.
func LoadFile(meta Metadata, data interface{}, filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	err = Load(meta, data, file)
	if err != nil {
		return errors.New("error loading " + filename + ": " + err.Error())
	}
	return nil
}
<|endoftext|>


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

package gldriver

import (
	"encoding/binary"
	"image"
	"image/color"
	"image/draw"

	"golang.org/x/exp/shiny/screen"
	"golang.org/x/mobile/gl"
)

type textureImpl struct {
	id   gl.Texture
	size image.Point
}

func (t *textureImpl) Size() image.Point       { return t.size }
func (t *textureImpl) Bounds() image.Rectangle { return image.Rectangle{Max: t.size} }

func (t *textureImpl) Release() {
	gl.DeleteTexture(t.id)
	t.id = gl.Texture{}
}

func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) {
	t.upload(dp, src, sr, sender, t)
}

func (t *textureImpl) upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender, u screen.Uploader) {
	// TODO: adjust if dp is outside dst bounds, or r is outside src bounds.
	gl.BindTexture(gl.TEXTURE_2D, t.id)
	m := src.RGBA().SubImage(sr).(*image.RGBA)
	b := m.Bounds()
	// TODO check m bounds smaller than t.size
	gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, b.Dx(), b.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, m.Pix)
	sender.Send(screen.UploadedEvent{Buffer: src, Uploader: u})
}

func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	// TODO.
}

var quadCoords = f32Bytes(binary.LittleEndian,
	0, 0, // top left
	1, 0, // top right
	0, 1, // bottom left
	1, 1, // bottom right
)

const textureVertexSrc = `#version 100
uniform mat3 mvp;
uniform mat3 uvp;
attribute vec3 pos;
attribute vec2 inUV;
varying vec2 uv;
void main() {
	vec3 p = pos;
	p.z = 1.0;
	gl_Position = vec4(mvp * p, 1);
	uv = (uvp * vec3(inUV, 1)).xy;
}
`

const textureFragmentSrc = `#version 100
precision mediump float;
varying vec2 uv;
uniform sampler2D sample;
void main() {
	gl_FragColor = texture2D(sample, uv);
}
`

const fillVertexSrc = `#version 100
uniform mat3 mvp;
attribute vec3 pos;
void main() {
	vec3 p = pos;
	p.z = 1.0;
	gl_Position = vec4(mvp * p, 1);
}
`

const fillFragmentSrc = `#version 100
precision mediump float;
uniform vec4 color;
void main() {
	gl_FragColor = color;
}
`
<commit_msg>shiny/driver/gldriver: allow Upload with a nil Sender.<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gldriver

import (
	"encoding/binary"
	"image"
	"image/color"
	"image/draw"

	"golang.org/x/exp/shiny/screen"
	"golang.org/x/mobile/gl"
)

type textureImpl struct {
	id   gl.Texture
	size image.Point
}

func (t *textureImpl) Size() image.Point       { return t.size }
func (t *textureImpl) Bounds() image.Rectangle { return image.Rectangle{Max: t.size} }

func (t *textureImpl) Release() {
	gl.DeleteTexture(t.id)
	t.id = gl.Texture{}
}

func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) {
	t.upload(dp, src, sr, sender, t)
}

func (t *textureImpl) upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender, u screen.Uploader) {
	// TODO: adjust if dp is outside dst bounds, or r is outside src bounds.
	gl.BindTexture(gl.TEXTURE_2D, t.id)
	m := src.RGBA().SubImage(sr).(*image.RGBA)
	b := m.Bounds()
	// TODO check m bounds smaller than t.size
	gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, b.Dx(), b.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, m.Pix)
	if sender != nil {
		sender.Send(screen.UploadedEvent{Buffer: src, Uploader: u})
	}
}

func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	// TODO.
}

var quadCoords = f32Bytes(binary.LittleEndian,
	0, 0, // top left
	1, 0, // top right
	0, 1, // bottom left
	1, 1, // bottom right
)

const textureVertexSrc = `#version 100
uniform mat3 mvp;
uniform mat3 uvp;
attribute vec3 pos;
attribute vec2 inUV;
varying vec2 uv;
void main() {
	vec3 p = pos;
	p.z = 1.0;
	gl_Position = vec4(mvp * p, 1);
	uv = (uvp * vec3(inUV, 1)).xy;
}
`

const textureFragmentSrc = `#version 100
precision mediump float;
varying vec2 uv;
uniform sampler2D sample;
void main() {
	gl_FragColor = texture2D(sample, uv);
}
`

const fillVertexSrc = `#version 100
uniform mat3 mvp;
attribute vec3 pos;
void main() {
	vec3 p = pos;
	p.z = 1.0;
	gl_Position = vec4(mvp * p, 1);
}
`

const fillFragmentSrc = `#version 100
precision mediump float;
uniform vec4 color;
void main() {
	gl_FragColor = color;
}
`
<|endoftext|>


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

// +build windows

package windriver

// TODO: implement a back buffer.

import (
	"image"
	"image/color"
	"image/draw"
	"syscall"
	"unsafe"

	"golang.org/x/exp/shiny/driver/internal/drawer"
	"golang.org/x/exp/shiny/driver/internal/event"
	"golang.org/x/exp/shiny/driver/internal/win32"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/image/math/f64"
	"golang.org/x/mobile/event/key"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/mouse"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/event/size"
)

type windowImpl struct {
	hwnd syscall.Handle

	event.Queue

	sz             size.Event
	lifecycleStage lifecycle.Stage
}

func (w *windowImpl) Release() {
	win32.Release(w.hwnd)
}

var msgUpload = win32.AddWindowMsg(handleUpload)

func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) {
	p := upload{
		dp:  dp,
		src: src.(*bufferImpl),
		sr:  sr,
	}
	win32.SendMessage(w.hwnd, msgUpload, 0, uintptr(unsafe.Pointer(&p)))
}

type upload struct {
	dp  image.Point
	src *bufferImpl
	sr  image.Rectangle
}

func handleUpload(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	u := (*upload)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	// TODO(brainman): move preUpload / postUpload out of handleUpload,
	// because handleUpload can only be executed by one (message pump)
	// thread only
	u.src.preUpload()
	defer u.src.postUpload()

	// TODO: adjust if dp is outside dst bounds, or sr is outside src bounds.
	dr := u.sr.Add(u.dp.Sub(u.sr.Min))
	err = copyBitmapToDC(dc, dr, u.src.hbitmap, u.sr, draw.Src)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

type handleWindowFillParams struct {
	dr    image.Rectangle
	color color.Color
	op    draw.Op
}

var msgWindowFill = win32.AddWindowMsg(handleWindowFill)

func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	p := handleWindowFillParams{
		dr:    dr,
		color: src,
		op:    op,
	}
	win32.SendMessage(w.hwnd, msgWindowFill, 0, uintptr(unsafe.Pointer(&p)))
}

func handleWindowFill(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	p := (*handleWindowFillParams)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	err = fill(dc, p.dr, p.color, p.op)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	// TODO
}

type handleCopyParams struct {
	dp  image.Point
	src syscall.Handle
	sr  image.Rectangle
	op  draw.Op
}

var msgCopy = win32.AddWindowMsg(handleCopy)

func (w *windowImpl) Copy(dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	if op != draw.Src && op != draw.Over {
		drawer.Copy(w, dp, src, sr, op, opts)
		return
	}
	p := handleCopyParams{
		dp:  dp,
		src: src.(*textureImpl).bitmap,
		sr:  sr,
		op:  op,
	}
	win32.SendMessage(w.hwnd, msgCopy, 0, uintptr(unsafe.Pointer(&p)))
}

func handleCopy(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	p := (*handleCopyParams)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	dr := p.sr.Add(p.dp.Sub(p.sr.Min))
	err = copyBitmapToDC(dc, dr, p.src, p.sr, p.op)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

func (w *windowImpl) Scale(dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	drawer.Scale(w, dr, src, sr, op, opts)
}

func (w *windowImpl) Publish() screen.PublishResult {
	// TODO
	return screen.PublishResult{}
}

func init() {
	send := func(hwnd syscall.Handle, e interface{}) {
		theScreen.mu.Lock()
		w := theScreen.windows[hwnd]
		theScreen.mu.Unlock()

		w.Send(e)
	}
	win32.MouseEvent = func(hwnd syscall.Handle, e mouse.Event) { send(hwnd, e) }
	win32.PaintEvent = func(hwnd syscall.Handle, e paint.Event) { send(hwnd, e) }
	win32.KeyEvent = func(hwnd syscall.Handle, e key.Event) { send(hwnd, e) }
	win32.LifecycleEvent = lifecycleEvent
	win32.SizeEvent = sizeEvent
}

func lifecycleEvent(hwnd syscall.Handle, to lifecycle.Stage) {
	theScreen.mu.Lock()
	w := theScreen.windows[hwnd]
	theScreen.mu.Unlock()

	if w.lifecycleStage == to {
		return
	}
	w.Send(lifecycle.Event{
		From: w.lifecycleStage,
		To:   to,
	})
	w.lifecycleStage = to
}

func sizeEvent(hwnd syscall.Handle, e size.Event) {
	theScreen.mu.Lock()
	w := theScreen.windows[hwnd]
	theScreen.mu.Unlock()

	w.Send(e)

	if e != w.sz {
		w.sz = e
		w.Send(paint.Event{})
	}
}
<commit_msg>shiny/driver/windriver: add references to thread affinity explanation<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package windriver

// TODO: implement a back buffer.

import (
	"image"
	"image/color"
	"image/draw"
	"syscall"
	"unsafe"

	"golang.org/x/exp/shiny/driver/internal/drawer"
	"golang.org/x/exp/shiny/driver/internal/event"
	"golang.org/x/exp/shiny/driver/internal/win32"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/image/math/f64"
	"golang.org/x/mobile/event/key"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/mouse"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/event/size"
)

// Code in this package must follow general Windows rules about
// thread affinity of user interface objects:
//
// part 1: Window handles
// https://blogs.msdn.microsoft.com/oldnewthing/20051010-09/?p=33843
//
// part 2: Device contexts
// https://blogs.msdn.microsoft.com/oldnewthing/20051011-10/?p=33823
//
// part 3: Menus, icons, cursors, and accelerator tables
// https://blogs.msdn.microsoft.com/oldnewthing/20051012-00/?p=33803
//
// part 4: GDI objects and other notes on affinity
// https://blogs.msdn.microsoft.com/oldnewthing/20051013-11/?p=33783
//
// part 5: Object clean-up
// https://blogs.msdn.microsoft.com/oldnewthing/20051014-19/?p=33763

type windowImpl struct {
	hwnd syscall.Handle

	event.Queue

	sz             size.Event
	lifecycleStage lifecycle.Stage
}

func (w *windowImpl) Release() {
	win32.Release(w.hwnd)
}

var msgUpload = win32.AddWindowMsg(handleUpload)

func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) {
	p := upload{
		dp:  dp,
		src: src.(*bufferImpl),
		sr:  sr,
	}
	win32.SendMessage(w.hwnd, msgUpload, 0, uintptr(unsafe.Pointer(&p)))
}

type upload struct {
	dp  image.Point
	src *bufferImpl
	sr  image.Rectangle
}

func handleUpload(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	u := (*upload)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	// TODO(brainman): move preUpload / postUpload out of handleUpload,
	// because handleUpload can only be executed by one (message pump)
	// thread only
	u.src.preUpload()
	defer u.src.postUpload()

	// TODO: adjust if dp is outside dst bounds, or sr is outside src bounds.
	dr := u.sr.Add(u.dp.Sub(u.sr.Min))
	err = copyBitmapToDC(dc, dr, u.src.hbitmap, u.sr, draw.Src)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

type handleWindowFillParams struct {
	dr    image.Rectangle
	color color.Color
	op    draw.Op
}

var msgWindowFill = win32.AddWindowMsg(handleWindowFill)

func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	p := handleWindowFillParams{
		dr:    dr,
		color: src,
		op:    op,
	}
	win32.SendMessage(w.hwnd, msgWindowFill, 0, uintptr(unsafe.Pointer(&p)))
}

func handleWindowFill(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	p := (*handleWindowFillParams)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	err = fill(dc, p.dr, p.color, p.op)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	// TODO
}

type handleCopyParams struct {
	dp  image.Point
	src syscall.Handle
	sr  image.Rectangle
	op  draw.Op
}

var msgCopy = win32.AddWindowMsg(handleCopy)

func (w *windowImpl) Copy(dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	if op != draw.Src && op != draw.Over {
		drawer.Copy(w, dp, src, sr, op, opts)
		return
	}
	p := handleCopyParams{
		dp:  dp,
		src: src.(*textureImpl).bitmap,
		sr:  sr,
		op:  op,
	}
	win32.SendMessage(w.hwnd, msgCopy, 0, uintptr(unsafe.Pointer(&p)))
}

func handleCopy(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) {
	p := (*handleCopyParams)(unsafe.Pointer(lParam))

	dc, err := win32.GetDC(hwnd)
	if err != nil {
		panic(err) // TODO handle errors
	}
	defer win32.ReleaseDC(hwnd, dc)

	dr := p.sr.Add(p.dp.Sub(p.sr.Min))
	err = copyBitmapToDC(dc, dr, p.src, p.sr, p.op)
	if err != nil {
		panic(err) // TODO handle errors
	}
}

func (w *windowImpl) Scale(dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	drawer.Scale(w, dr, src, sr, op, opts)
}

func (w *windowImpl) Publish() screen.PublishResult {
	// TODO
	return screen.PublishResult{}
}

func init() {
	send := func(hwnd syscall.Handle, e interface{}) {
		theScreen.mu.Lock()
		w := theScreen.windows[hwnd]
		theScreen.mu.Unlock()

		w.Send(e)
	}
	win32.MouseEvent = func(hwnd syscall.Handle, e mouse.Event) { send(hwnd, e) }
	win32.PaintEvent = func(hwnd syscall.Handle, e paint.Event) { send(hwnd, e) }
	win32.KeyEvent = func(hwnd syscall.Handle, e key.Event) { send(hwnd, e) }
	win32.LifecycleEvent = lifecycleEvent
	win32.SizeEvent = sizeEvent
}

func lifecycleEvent(hwnd syscall.Handle, to lifecycle.Stage) {
	theScreen.mu.Lock()
	w := theScreen.windows[hwnd]
	theScreen.mu.Unlock()

	if w.lifecycleStage == to {
		return
	}
	w.Send(lifecycle.Event{
		From: w.lifecycleStage,
		To:   to,
	})
	w.lifecycleStage = to
}

func sizeEvent(hwnd syscall.Handle, e size.Event) {
	theScreen.mu.Lock()
	w := theScreen.windows[hwnd]
	theScreen.mu.Unlock()

	w.Send(e)

	if e != w.sz {
		w.sz = e
		w.Send(paint.Event{})
	}
}
<|endoftext|>


<commit_before>package henchman

import (
	"bytes"
	"fmt"
	log "gopkg.in/Sirupsen/logrus.v0"
	"io/ioutil"
	"path"
	"strconv"

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

const (
	ECHO          = 53
	TTY_OP_ISPEED = 128
	TTY_OP_OSPEED = 129
)

func loadPEM(file string) (ssh.Signer, error) {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	key, err := ssh.ParsePrivateKey(buf)
	if err != nil {
		return nil, err
	}
	return key, nil
}

func ClientKeyAuth(keyFile string) (ssh.AuthMethod, error) {
	key, err := loadPEM(keyFile)
	return ssh.PublicKeys(key), err
}

func PasswordAuth(pass string) (ssh.AuthMethod, error) {
	return ssh.Password(pass), nil
}

type SSHTransport struct {
	Host   string
	Port   uint16
	Config *ssh.ClientConfig
}

func (sshTransport *SSHTransport) Initialize(config *TransportConfig) error {
	_config := *config

	// Get hostname and port
	sshTransport.Host = _config["hostname"]
	port, parseErr := strconv.ParseUint(_config["port"], 10, 16)
	if parseErr != nil || port == 0 {
		/*
			if Debug {
				log.Debug("Assuming default port to be 22")
			}
		*/
		sshTransport.Port = 22
	} else {
		sshTransport.Port = uint16(port)
	}
	if sshTransport.Host == "" {
		return fmt.Errorf("Need a hostname")
	}
	username := _config["username"]
	if username == "" {
		return fmt.Errorf("Need a username")
	}
	var auth ssh.AuthMethod
	var authErr error

	password, present := _config["password"]
	if password == "" || !present {
		keyfile, present := _config["keyfile"]
		if !present {
			return fmt.Errorf("Invalid SSH Keyfile")
		}
		auth, authErr = ClientKeyAuth(keyfile)
	} else {
		auth, authErr = PasswordAuth(password)
	}

	if authErr != nil {
		return authErr
	}
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{auth},
	}
	sshTransport.Config = sshConfig
	return nil
}

func (sshTransport *SSHTransport) getClientSession() (*ssh.Client, *ssh.Session, error) {
	address := fmt.Sprintf("%s:%d", sshTransport.Host, sshTransport.Port)
	client, err := ssh.Dial("tcp", address, sshTransport.Config)
	if err != nil {
		return nil, nil, err
	}
	session, err := client.NewSession()
	if err != nil {
		return nil, nil, err
	}
	return client, session, nil

}

func (sshTransport *SSHTransport) execCmd(session *ssh.Session, cmd string) (*bytes.Buffer, error) {
	var b bytes.Buffer
	modes := ssh.TerminalModes{
		ECHO:          0,
		TTY_OP_ISPEED: 14400,
		TTY_OP_OSPEED: 14400,
	}
	if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
		return nil, fmt.Errorf("request for psuedo terminal failed: %s", err.Error())
	}
	session.Stdout = &b
	if err := session.Run(cmd); err != nil {
		return nil, fmt.Errorf(b.String())
	}
	return &b, nil
}

func (sshTransport *SSHTransport) Exec(cmd string, stdin []byte, sudoEnabled bool) (*bytes.Buffer, error) {
	client, session, err := sshTransport.getClientSession()
	if err != nil {
		return nil, fmt.Errorf("Couldn't dial in to %s :: %s", sshTransport.Host, err.Error())
	}

	defer client.Close()
	defer session.Close()
	if sudoEnabled {
		cmd = fmt.Sprintf("/bin/bash -c 'sudo -H -u root %s'", cmd)
	}

	cmd = fmt.Sprintf("echo '%s' | %s", stdin, cmd)
	/*
		if Debug {
			log.Debug(cmd)
		}
	*/
	return sshTransport.execCmd(session, cmd)
}

func (sshTransport *SSHTransport) Put(source, destination string, dstType string) error {
	client, session, err := sshTransport.getClientSession()
	if err != nil {
		return fmt.Errorf("Couldn't dial in to %s :: %s", sshTransport.Host, err.Error())
	}
	defer client.Close()
	defer session.Close()
	sourceBuf, err := ioutil.ReadFile(source)
	if err != nil {
		return fmt.Errorf("Error reading file - %s: %s\n", source, err.Error())
	}
	_, sourcePath := path.Split(source)
	go func() {
		pipe, err := session.StdinPipe()
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Error opening pipe")
			return
		}
		defer pipe.Close()
		buf := string(sourceBuf)
		if dstType == "dir" {
			fmt.Fprintln(pipe, "C0700", len(buf), sourcePath)
		} else {
			fmt.Fprintln(pipe, "C0644", len(buf), sourcePath)
		}
		fmt.Fprint(pipe, buf)
		fmt.Fprint(pipe, "\x00")
	}()
	//default directory scp command
	remoteCommand := fmt.Sprintf("mkdir -p %s && cd %s && /usr/bin/scp -qrt ./", destination, destination)
	if dstType == "file" {
		remoteCommand = fmt.Sprintf("/usr/bin/scp -t %s", destination)
	}
	if err := session.Run(remoteCommand); err != nil {
		return fmt.Errorf("Error doing scp :: %s", err.Error())
	}
	return nil
}

func NewSSH(config *TransportConfig) (*SSHTransport, error) {
	ssht := SSHTransport{}
	return &ssht, ssht.Initialize(config)
}
<commit_msg>#76 finished ssh.go HenchErr style<commit_after>package henchman

import (
	"bytes"
	"fmt"
	log "gopkg.in/Sirupsen/logrus.v0"
	"io/ioutil"
	"path"
	"strconv"

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

const (
	ECHO          = 53
	TTY_OP_ISPEED = 128
	TTY_OP_OSPEED = 129
)

func loadPEM(file string) (ssh.Signer, error) {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	key, err := ssh.ParsePrivateKey(buf)
	if err != nil {
		return nil, err
	}
	return key, nil
}

func ClientKeyAuth(keyFile string) (ssh.AuthMethod, error) {
	key, err := loadPEM(keyFile)
	if err != nil {
		return nil, HenchErr(err, log.Fields{
			"key_file": keyFile,
		}, "")
	}
	return ssh.PublicKeys(key), err
}

func PasswordAuth(pass string) (ssh.AuthMethod, error) {
	return ssh.Password(pass), nil
}

type SSHTransport struct {
	Host   string
	Port   uint16
	Config *ssh.ClientConfig
}

func (sshTransport *SSHTransport) Initialize(config *TransportConfig) error {
	_config := *config

	// Get hostname and port
	sshTransport.Host = _config["hostname"]
	port, parseErr := strconv.ParseUint(_config["port"], 10, 16)
	if parseErr != nil || port == 0 {
		/*
			if Debug {
				log.Debug("Assuming default port to be 22")
			}
		*/
		sshTransport.Port = 22
	} else {
		sshTransport.Port = uint16(port)
	}
	if sshTransport.Host == "" {
		return HenchErr(fmt.Errorf("Need a hostname"), nil, "SSH transport")
	}
	username := _config["username"]
	if username == "" {
		return HenchErr(fmt.Errorf("Need a username"), nil, "SSH transport")
	}
	var auth ssh.AuthMethod
	var authErr error

	password, present := _config["password"]
	if password == "" || !present {
		keyfile, present := _config["keyfile"]
		if !present {
			return HenchErr(fmt.Errorf("Invalid SSH Keyfile"), nil, "SSH transport")
		}
		auth, authErr = ClientKeyAuth(keyfile)
	} else {
		auth, authErr = PasswordAuth(password)
	}

	if authErr != nil {
		return HenchErr(authErr, nil, "SSH transport auth error")
	}
	sshConfig := &ssh.ClientConfig{
		User: username,
		Auth: []ssh.AuthMethod{auth},
	}
	sshTransport.Config = sshConfig
	return nil
}

func (sshTransport *SSHTransport) getClientSession() (*ssh.Client, *ssh.Session, error) {
	address := fmt.Sprintf("%s:%d", sshTransport.Host, sshTransport.Port)
	client, err := ssh.Dial("tcp", address, sshTransport.Config)
	if err != nil {
		return nil, nil, HenchErr(err, nil, "")
	}
	session, err := client.NewSession()
	if err != nil {
		return nil, nil, HenchErr(err, nil, "")
	}
	return client, session, nil

}

func (sshTransport *SSHTransport) execCmd(session *ssh.Session, cmd string) (*bytes.Buffer, error) {
	var b bytes.Buffer
	modes := ssh.TerminalModes{
		ECHO:          0,
		TTY_OP_ISPEED: 14400,
		TTY_OP_OSPEED: 14400,
	}
	if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
		return nil, HenchErr(err, nil, "request for psuedo terminal failed")
	}
	session.Stdout = &b
	if err := session.Run(cmd); err != nil {
		return nil, HenchErr(fmt.Errorf(b.String()), nil, "")
	}
	return &b, nil
}

func (sshTransport *SSHTransport) Exec(cmd string, stdin []byte, sudoEnabled bool) (*bytes.Buffer, error) {
	client, session, err := sshTransport.getClientSession()
	if err != nil {
		return nil, HenchErr(err, log.Fields{
			"host": sshTransport.Host,
		}, fmt.Sprintf("Couldn't dial into %s", sshTransport.Host))
	}

	defer client.Close()
	defer session.Close()
	if sudoEnabled {
		cmd = fmt.Sprintf("/bin/bash -c 'sudo -H -u root %s'", cmd)
	}

	cmd = fmt.Sprintf("echo '%s' | %s", stdin, cmd)
	/*
		if Debug {
			log.Debug(cmd)
		}
	*/
	bytesBuf, err := sshTransport.execCmd(session, cmd)
	if err != nil {
		return nil, HenchErr(err, nil, "While executing command")
	}
	return bytesBuf, nil
}

func (sshTransport *SSHTransport) Put(source, destination string, dstType string) error {
	client, session, err := sshTransport.getClientSession()
	if err != nil {
		return HenchErr(err, log.Fields{
			"host": sshTransport.Host,
		}, fmt.Sprintf("Couldn't dial into %s", sshTransport.Host))
	}
	defer client.Close()
	defer session.Close()
	sourceBuf, err := ioutil.ReadFile(source)
	if err != nil {
		return HenchErr(err, log.Fields{
			"file": source,
		}, "")
	}
	_, sourcePath := path.Split(source)
	go func() {
		pipe, err := session.StdinPipe()
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Error opening pipe")
		}
		defer pipe.Close()
		buf := string(sourceBuf)
		if dstType == "dir" {
			fmt.Fprintln(pipe, "C0700", len(buf), sourcePath)
		} else {
			fmt.Fprintln(pipe, "C0644", len(buf), sourcePath)
		}
		fmt.Fprint(pipe, buf)
		fmt.Fprint(pipe, "\x00")
	}()
	//default directory scp command
	remoteCommand := fmt.Sprintf("mkdir -p %s && cd %s && /usr/bin/scp -qrt ./", destination, destination)
	if dstType == "file" {
		remoteCommand = fmt.Sprintf("/usr/bin/scp -t %s", destination)
	}
	if err := session.Run(remoteCommand); err != nil {
		return HenchErr(err, log.Fields{
			"host": sshTransport.Host,
		}, "Error doing scp")
	}
	return nil
}

func NewSSH(config *TransportConfig) (*SSHTransport, error) {
	ssht := SSHTransport{}
	return &ssht, ssht.Initialize(config)
}
<|endoftext|>


<commit_before>package quicproxy

import (
	"bytes"
	"net"
	"strconv"
	"sync/atomic"
	"time"

	"fmt"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/wire"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type packetData []byte

var _ = Describe("QUIC Proxy", func() {
	makePacket := func(p protocol.PacketNumber, payload []byte) []byte {
		b := &bytes.Buffer{}
		hdr := wire.Header{
			PacketNumber:     p,
			PacketNumberLen:  protocol.PacketNumberLen6,
			ConnectionID:     1337,
			OmitConnectionID: false,
		}
		hdr.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
		raw := b.Bytes()
		raw = append(raw, payload...)
		return raw
	}

	Context("Proxy setup and teardown", func() {
		It("sets up the UDPProxy", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())
			Expect(proxy.clientDict).To(HaveLen(0))

			// check that the proxy port is in use
			addr, err := net.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(proxy.LocalPort()))
			Expect(err).ToNot(HaveOccurred())
			_, err = net.ListenUDP("udp", addr)
			Expect(err).To(MatchError(fmt.Sprintf("listen udp 127.0.0.1:%d: bind: address already in use", proxy.LocalPort())))
			Expect(proxy.Close()).To(Succeed()) // stopping is tested in the next test
		})

		It("stops the UDPProxy", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())
			port := proxy.LocalPort()
			err = proxy.Close()
			Expect(err).ToNot(HaveOccurred())

			// check that the proxy port is not in use anymore
			addr, err := net.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(port))
			Expect(err).ToNot(HaveOccurred())
			// sometimes it takes a while for the OS to free the port
			Eventually(func() error {
				ln, err := net.ListenUDP("udp", addr)
				defer ln.Close()
				return err
			}).ShouldNot(HaveOccurred())
		})

		It("has the correct LocalAddr and LocalPort", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())

			Expect(proxy.LocalAddr().String()).To(Equal("127.0.0.1:" + strconv.Itoa(proxy.LocalPort())))
			Expect(proxy.LocalPort()).ToNot(BeZero())

			Expect(proxy.Close()).To(Succeed())
		})
	})

	Context("Proxy tests", func() {
		var (
			serverConn            *net.UDPConn
			serverNumPacketsSent  int32
			serverReceivedPackets chan packetData
			clientConn            *net.UDPConn
			proxy                 *QuicProxy
		)

		startProxy := func(opts *Opts) {
			var err error
			proxy, err = NewQuicProxy("localhost:0", protocol.VersionWhatever, opts)
			Expect(err).ToNot(HaveOccurred())
			clientConn, err = net.DialUDP("udp", nil, proxy.LocalAddr().(*net.UDPAddr))
			Expect(err).ToNot(HaveOccurred())
		}

		// getClientDict returns a copy of the clientDict map
		getClientDict := func() map[string]*connection {
			d := make(map[string]*connection)
			proxy.mutex.Lock()
			defer proxy.mutex.Unlock()
			for k, v := range proxy.clientDict {
				d[k] = v
			}
			return d
		}

		BeforeEach(func() {
			serverReceivedPackets = make(chan packetData, 100)
			atomic.StoreInt32(&serverNumPacketsSent, 0)

			// setup a dump UDP server
			// in production this would be a QUIC server
			raddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
			Expect(err).ToNot(HaveOccurred())
			serverConn, err = net.ListenUDP("udp", raddr)
			Expect(err).ToNot(HaveOccurred())

			go func() {
				for {
					buf := make([]byte, protocol.MaxPacketSize)
					// the ReadFromUDP will error as soon as the UDP conn is closed
					n, addr, err2 := serverConn.ReadFromUDP(buf)
					if err2 != nil {
						return
					}
					data := buf[0:n]
					serverReceivedPackets <- packetData(data)
					// echo the packet
					serverConn.WriteToUDP(data, addr)
					atomic.AddInt32(&serverNumPacketsSent, 1)
				}
			}()
		})

		AfterEach(func() {
			err := proxy.Close()
			Expect(err).ToNot(HaveOccurred())
			err = serverConn.Close()
			Expect(err).ToNot(HaveOccurred())
			err = clientConn.Close()
			Expect(err).ToNot(HaveOccurred())
			time.Sleep(200 * time.Millisecond)
		})

		Context("no packet drop", func() {
			It("relays packets from the client to the server", func() {
				startProxy(&Opts{RemoteAddr: serverConn.LocalAddr().String()})
				// send the first packet
				_, err := clientConn.Write(makePacket(1, []byte("foobar")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(getClientDict).Should(HaveLen(1))
				var conn *connection
				for _, conn = range getClientDict() {
					Expect(atomic.LoadUint64(&conn.incomingPacketCounter)).To(Equal(uint64(1)))
				}

				// send the second packet
				_, err = clientConn.Write(makePacket(2, []byte("decafbad")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(serverReceivedPackets).Should(HaveLen(2))
				Expect(getClientDict()).To(HaveLen(1))
				Expect(string(<-serverReceivedPackets)).To(ContainSubstring("foobar"))
				Expect(string(<-serverReceivedPackets)).To(ContainSubstring("decafbad"))
			})

			It("relays packets from the server to the client", func() {
				startProxy(&Opts{RemoteAddr: serverConn.LocalAddr().String()})
				// send the first packet
				_, err := clientConn.Write(makePacket(1, []byte("foobar")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(getClientDict).Should(HaveLen(1))
				var key string
				var conn *connection
				for key, conn = range getClientDict() {
					Eventually(func() uint64 { return atomic.LoadUint64(&conn.outgoingPacketCounter) }).Should(Equal(uint64(1)))
				}

				// send the second packet
				_, err = clientConn.Write(makePacket(2, []byte("decafbad")))
				Expect(err).ToNot(HaveOccurred())

				Expect(getClientDict()).To(HaveLen(1))
				Eventually(func() uint64 {
					conn := getClientDict()[key]
					return atomic.LoadUint64(&conn.outgoingPacketCounter)
				}).Should(BeEquivalentTo(2))

				clientReceivedPackets := make(chan packetData, 2)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				Eventually(serverReceivedPackets).Should(HaveLen(2))
				Expect(atomic.LoadInt32(&serverNumPacketsSent)).To(BeEquivalentTo(2))
				Eventually(clientReceivedPackets).Should(HaveLen(2))
				Expect(string(<-clientReceivedPackets)).To(ContainSubstring("foobar"))
				Expect(string(<-clientReceivedPackets)).To(ContainSubstring("decafbad"))
			})
		})

		Context("Drop Callbacks", func() {
			It("drops incoming packets", func() {
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					DropPacket: func(d Direction, p uint64) bool {
						return d == DirectionIncoming && p%2 == 0
					},
				}
				startProxy(opts)

				for i := 1; i <= 6; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				Consistently(serverReceivedPackets).Should(HaveLen(3))
			})

			It("drops outgoing packets", func() {
				const numPackets = 6
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					DropPacket: func(d Direction, p uint64) bool {
						return d == DirectionOutgoing && p%2 == 0
					},
				}
				startProxy(opts)

				clientReceivedPackets := make(chan packetData, numPackets)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				for i := 1; i <= numPackets; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}

				Eventually(clientReceivedPackets).Should(HaveLen(numPackets / 2))
				Consistently(clientReceivedPackets).Should(HaveLen(numPackets / 2))
			})
		})

		Context("Delay Callback", func() {
			expectDelay := func(startTime time.Time, rtt time.Duration, numRTTs int) {
				expectedReceiveTime := startTime.Add(time.Duration(numRTTs) * rtt)
				Expect(time.Now()).To(SatisfyAll(
					BeTemporally(">=", expectedReceiveTime),
					BeTemporally("<", expectedReceiveTime.Add(rtt/2)),
				))
			}

			It("delays incoming packets", func() {
				delay := 300 * time.Millisecond
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					// delay packet 1 by 200 ms
					// delay packet 2 by 400 ms
					// ...
					DelayPacket: func(d Direction, p uint64) time.Duration {
						if d == DirectionOutgoing {
							return 0
						}
						return time.Duration(p) * delay
					},
				}
				startProxy(opts)

				// send 3 packets
				start := time.Now()
				for i := 1; i <= 3; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				Eventually(serverReceivedPackets).Should(HaveLen(1))
				expectDelay(start, delay, 1)
				Eventually(serverReceivedPackets).Should(HaveLen(2))
				expectDelay(start, delay, 2)
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 3)
			})

			It("delays outgoing packets", func() {
				const numPackets = 3
				delay := 300 * time.Millisecond
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					// delay packet 1 by 200 ms
					// delay packet 2 by 400 ms
					// ...
					DelayPacket: func(d Direction, p uint64) time.Duration {
						if d == DirectionIncoming {
							return 0
						}
						return time.Duration(p) * delay
					},
				}
				startProxy(opts)

				clientReceivedPackets := make(chan packetData, numPackets)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				start := time.Now()
				for i := 1; i <= numPackets; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				// the packets should have arrived immediately at the server
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 0)
				Eventually(clientReceivedPackets).Should(HaveLen(1))
				expectDelay(start, delay, 1)
				Eventually(clientReceivedPackets).Should(HaveLen(2))
				expectDelay(start, delay, 2)
				Eventually(clientReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 3)
			})
		})
	})
})
<commit_msg>fix flaky proxy shutdown test<commit_after>package quicproxy

import (
	"bytes"
	"net"
	"strconv"
	"sync/atomic"
	"time"

	"fmt"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/wire"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type packetData []byte

var _ = Describe("QUIC Proxy", func() {
	makePacket := func(p protocol.PacketNumber, payload []byte) []byte {
		b := &bytes.Buffer{}
		hdr := wire.Header{
			PacketNumber:     p,
			PacketNumberLen:  protocol.PacketNumberLen6,
			ConnectionID:     1337,
			OmitConnectionID: false,
		}
		hdr.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
		raw := b.Bytes()
		raw = append(raw, payload...)
		return raw
	}

	Context("Proxy setup and teardown", func() {
		It("sets up the UDPProxy", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())
			Expect(proxy.clientDict).To(HaveLen(0))

			// check that the proxy port is in use
			addr, err := net.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(proxy.LocalPort()))
			Expect(err).ToNot(HaveOccurred())
			_, err = net.ListenUDP("udp", addr)
			Expect(err).To(MatchError(fmt.Sprintf("listen udp 127.0.0.1:%d: bind: address already in use", proxy.LocalPort())))
			Expect(proxy.Close()).To(Succeed()) // stopping is tested in the next test
		})

		It("stops the UDPProxy", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())
			port := proxy.LocalPort()
			err = proxy.Close()
			Expect(err).ToNot(HaveOccurred())

			// check that the proxy port is not in use anymore
			addr, err := net.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(port))
			Expect(err).ToNot(HaveOccurred())
			// sometimes it takes a while for the OS to free the port
			Eventually(func() error {
				ln, err := net.ListenUDP("udp", addr)
				if err != nil {
					return err
				}
				ln.Close()
				return nil
			}).ShouldNot(HaveOccurred())
		})

		It("has the correct LocalAddr and LocalPort", func() {
			proxy, err := NewQuicProxy("localhost:0", protocol.VersionWhatever, nil)
			Expect(err).ToNot(HaveOccurred())

			Expect(proxy.LocalAddr().String()).To(Equal("127.0.0.1:" + strconv.Itoa(proxy.LocalPort())))
			Expect(proxy.LocalPort()).ToNot(BeZero())

			Expect(proxy.Close()).To(Succeed())
		})
	})

	Context("Proxy tests", func() {
		var (
			serverConn            *net.UDPConn
			serverNumPacketsSent  int32
			serverReceivedPackets chan packetData
			clientConn            *net.UDPConn
			proxy                 *QuicProxy
		)

		startProxy := func(opts *Opts) {
			var err error
			proxy, err = NewQuicProxy("localhost:0", protocol.VersionWhatever, opts)
			Expect(err).ToNot(HaveOccurred())
			clientConn, err = net.DialUDP("udp", nil, proxy.LocalAddr().(*net.UDPAddr))
			Expect(err).ToNot(HaveOccurred())
		}

		// getClientDict returns a copy of the clientDict map
		getClientDict := func() map[string]*connection {
			d := make(map[string]*connection)
			proxy.mutex.Lock()
			defer proxy.mutex.Unlock()
			for k, v := range proxy.clientDict {
				d[k] = v
			}
			return d
		}

		BeforeEach(func() {
			serverReceivedPackets = make(chan packetData, 100)
			atomic.StoreInt32(&serverNumPacketsSent, 0)

			// setup a dump UDP server
			// in production this would be a QUIC server
			raddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
			Expect(err).ToNot(HaveOccurred())
			serverConn, err = net.ListenUDP("udp", raddr)
			Expect(err).ToNot(HaveOccurred())

			go func() {
				for {
					buf := make([]byte, protocol.MaxPacketSize)
					// the ReadFromUDP will error as soon as the UDP conn is closed
					n, addr, err2 := serverConn.ReadFromUDP(buf)
					if err2 != nil {
						return
					}
					data := buf[0:n]
					serverReceivedPackets <- packetData(data)
					// echo the packet
					serverConn.WriteToUDP(data, addr)
					atomic.AddInt32(&serverNumPacketsSent, 1)
				}
			}()
		})

		AfterEach(func() {
			err := proxy.Close()
			Expect(err).ToNot(HaveOccurred())
			err = serverConn.Close()
			Expect(err).ToNot(HaveOccurred())
			err = clientConn.Close()
			Expect(err).ToNot(HaveOccurred())
			time.Sleep(200 * time.Millisecond)
		})

		Context("no packet drop", func() {
			It("relays packets from the client to the server", func() {
				startProxy(&Opts{RemoteAddr: serverConn.LocalAddr().String()})
				// send the first packet
				_, err := clientConn.Write(makePacket(1, []byte("foobar")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(getClientDict).Should(HaveLen(1))
				var conn *connection
				for _, conn = range getClientDict() {
					Expect(atomic.LoadUint64(&conn.incomingPacketCounter)).To(Equal(uint64(1)))
				}

				// send the second packet
				_, err = clientConn.Write(makePacket(2, []byte("decafbad")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(serverReceivedPackets).Should(HaveLen(2))
				Expect(getClientDict()).To(HaveLen(1))
				Expect(string(<-serverReceivedPackets)).To(ContainSubstring("foobar"))
				Expect(string(<-serverReceivedPackets)).To(ContainSubstring("decafbad"))
			})

			It("relays packets from the server to the client", func() {
				startProxy(&Opts{RemoteAddr: serverConn.LocalAddr().String()})
				// send the first packet
				_, err := clientConn.Write(makePacket(1, []byte("foobar")))
				Expect(err).ToNot(HaveOccurred())

				Eventually(getClientDict).Should(HaveLen(1))
				var key string
				var conn *connection
				for key, conn = range getClientDict() {
					Eventually(func() uint64 { return atomic.LoadUint64(&conn.outgoingPacketCounter) }).Should(Equal(uint64(1)))
				}

				// send the second packet
				_, err = clientConn.Write(makePacket(2, []byte("decafbad")))
				Expect(err).ToNot(HaveOccurred())

				Expect(getClientDict()).To(HaveLen(1))
				Eventually(func() uint64 {
					conn := getClientDict()[key]
					return atomic.LoadUint64(&conn.outgoingPacketCounter)
				}).Should(BeEquivalentTo(2))

				clientReceivedPackets := make(chan packetData, 2)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				Eventually(serverReceivedPackets).Should(HaveLen(2))
				Expect(atomic.LoadInt32(&serverNumPacketsSent)).To(BeEquivalentTo(2))
				Eventually(clientReceivedPackets).Should(HaveLen(2))
				Expect(string(<-clientReceivedPackets)).To(ContainSubstring("foobar"))
				Expect(string(<-clientReceivedPackets)).To(ContainSubstring("decafbad"))
			})
		})

		Context("Drop Callbacks", func() {
			It("drops incoming packets", func() {
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					DropPacket: func(d Direction, p uint64) bool {
						return d == DirectionIncoming && p%2 == 0
					},
				}
				startProxy(opts)

				for i := 1; i <= 6; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				Consistently(serverReceivedPackets).Should(HaveLen(3))
			})

			It("drops outgoing packets", func() {
				const numPackets = 6
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					DropPacket: func(d Direction, p uint64) bool {
						return d == DirectionOutgoing && p%2 == 0
					},
				}
				startProxy(opts)

				clientReceivedPackets := make(chan packetData, numPackets)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				for i := 1; i <= numPackets; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}

				Eventually(clientReceivedPackets).Should(HaveLen(numPackets / 2))
				Consistently(clientReceivedPackets).Should(HaveLen(numPackets / 2))
			})
		})

		Context("Delay Callback", func() {
			expectDelay := func(startTime time.Time, rtt time.Duration, numRTTs int) {
				expectedReceiveTime := startTime.Add(time.Duration(numRTTs) * rtt)
				Expect(time.Now()).To(SatisfyAll(
					BeTemporally(">=", expectedReceiveTime),
					BeTemporally("<", expectedReceiveTime.Add(rtt/2)),
				))
			}

			It("delays incoming packets", func() {
				delay := 300 * time.Millisecond
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					// delay packet 1 by 200 ms
					// delay packet 2 by 400 ms
					// ...
					DelayPacket: func(d Direction, p uint64) time.Duration {
						if d == DirectionOutgoing {
							return 0
						}
						return time.Duration(p) * delay
					},
				}
				startProxy(opts)

				// send 3 packets
				start := time.Now()
				for i := 1; i <= 3; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				Eventually(serverReceivedPackets).Should(HaveLen(1))
				expectDelay(start, delay, 1)
				Eventually(serverReceivedPackets).Should(HaveLen(2))
				expectDelay(start, delay, 2)
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 3)
			})

			It("delays outgoing packets", func() {
				const numPackets = 3
				delay := 300 * time.Millisecond
				opts := &Opts{
					RemoteAddr: serverConn.LocalAddr().String(),
					// delay packet 1 by 200 ms
					// delay packet 2 by 400 ms
					// ...
					DelayPacket: func(d Direction, p uint64) time.Duration {
						if d == DirectionIncoming {
							return 0
						}
						return time.Duration(p) * delay
					},
				}
				startProxy(opts)

				clientReceivedPackets := make(chan packetData, numPackets)
				// receive the packets echoed by the server on client side
				go func() {
					for {
						buf := make([]byte, protocol.MaxPacketSize)
						// the ReadFromUDP will error as soon as the UDP conn is closed
						n, _, err2 := clientConn.ReadFromUDP(buf)
						if err2 != nil {
							return
						}
						data := buf[0:n]
						clientReceivedPackets <- packetData(data)
					}
				}()

				start := time.Now()
				for i := 1; i <= numPackets; i++ {
					_, err := clientConn.Write(makePacket(protocol.PacketNumber(i), []byte("foobar"+strconv.Itoa(i))))
					Expect(err).ToNot(HaveOccurred())
				}
				// the packets should have arrived immediately at the server
				Eventually(serverReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 0)
				Eventually(clientReceivedPackets).Should(HaveLen(1))
				expectDelay(start, delay, 1)
				Eventually(clientReceivedPackets).Should(HaveLen(2))
				expectDelay(start, delay, 2)
				Eventually(clientReceivedPackets).Should(HaveLen(3))
				expectDelay(start, delay, 3)
			})
		})
	})
})
<|endoftext|>


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

// +build android ios darwin,arm darwin,arm64

package opengl

import (
	"errors"
	"fmt"

	mgl "golang.org/x/mobile/gl"
)

type Texture mgl.Texture
type Framebuffer mgl.Framebuffer
type Shader mgl.Shader
type Program mgl.Program
type Buffer mgl.Buffer

type uniformLocation mgl.Uniform
type attribLocation mgl.Attrib

type programID uint32

var invalidFramebuffer = Framebuffer(mgl.Framebuffer{(1 << 32) - 1})

func (p Program) id() programID {
	return programID(p.Value)
}

func init() {
	Nearest = mgl.NEAREST
	Linear = mgl.LINEAR
	VertexShader = mgl.VERTEX_SHADER
	FragmentShader = mgl.FRAGMENT_SHADER
	ArrayBuffer = mgl.ARRAY_BUFFER
	ElementArrayBuffer = mgl.ELEMENT_ARRAY_BUFFER
	DynamicDraw = mgl.DYNAMIC_DRAW
	StaticDraw = mgl.STATIC_DRAW
	Triangles = mgl.TRIANGLES
	Lines = mgl.LINES

	zero = mgl.ZERO
	one = mgl.ONE
	srcAlpha = mgl.SRC_ALPHA
	dstAlpha = mgl.DST_ALPHA
	oneMinusSrcAlpha = mgl.ONE_MINUS_SRC_ALPHA
	oneMinusDstAlpha = mgl.ONE_MINUS_DST_ALPHA
}

type context struct {
	gl          mgl.Context
	worker      mgl.Worker
	initialized chan struct{}
}

func NewContext() (*Context, error) {
	c := &Context{
		locationCache:     newLocationCache(),
		lastCompositeMode: CompositeModeUnknown,
	}
	c.gl, c.worker = mgl.NewContext()
	c.initialized = make(chan struct{})
	go func() {
		// GL calls will just enqueue an task to the worker.
		// Since the worker is not avaialbe, this enqueuing should be done
		// in a goroutine.

		// Textures' pixel formats are alpha premultiplied.
		c.gl.Enable(mgl.BLEND)
		c.BlendFunc(CompositeModeSourceOver)
		f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
		c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
		close(c.initialized)
	}()
	return c, nil
}

func (c *Context) Reset() error {
	c.locationCache = newLocationCache()
	c.lastFramebuffer = invalidFramebuffer
	c.lastViewportWidth = 0
	c.lastViewportHeight = 0
	c.lastCompositeMode = CompositeModeUnknown
	c.gl.Enable(mgl.BLEND)
	c.BlendFunc(CompositeModeSourceOver)
	f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
	c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
	// TODO: Need to update screenFramebufferWidth/Height?
	return nil
}

func (c *Context) InitializedCh() <-chan struct{} {
	return c.initialized
}

func (c *Context) Worker() mgl.Worker {
	return c.worker
}

func (c *Context) BlendFunc(mode CompositeMode) {
	gl := c.gl
	if c.lastCompositeMode == mode {
		return
	}
	c.lastCompositeMode = mode
	s, d := operations(mode)
	gl.BlendFunc(mgl.Enum(s), mgl.Enum(d))
}

func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) {
	gl := c.gl
	t := gl.CreateTexture()
	if t.Value <= 0 {
		return Texture{}, errors.New("opengl: creating texture failed")
	}
	gl.PixelStorei(mgl.UNPACK_ALIGNMENT, 4)
	gl.BindTexture(mgl.TEXTURE_2D, t)

	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MAG_FILTER, int(filter))
	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MIN_FILTER, int(filter))

	var p []uint8
	if pixels != nil {
		p = pixels
	}
	gl.TexImage2D(mgl.TEXTURE_2D, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p)

	return Texture(t), nil
}

func (c *Context) bindFramebufferImpl(f Framebuffer) error {
	gl := c.gl
	gl.BindFramebuffer(mgl.FRAMEBUFFER, mgl.Framebuffer(f))
	return nil
}

func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) {
	gl := c.gl
	gl.Flush()

	c.bindFramebuffer(f)

	pixels := make([]uint8, 4*width*height)
	gl.ReadPixels(pixels, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE)
	if e := gl.GetError(); e != mgl.NO_ERROR {
		return nil, fmt.Errorf("opengl: glReadPixels: %d", e)
	}
	return pixels, nil
}

func (c *Context) BindTexture(t Texture) {
	gl := c.gl
	gl.BindTexture(mgl.TEXTURE_2D, mgl.Texture(t))
}

func (c *Context) DeleteTexture(t Texture) {
	gl := c.gl
	if !gl.IsTexture(mgl.Texture(t)) {
		return
	}
	gl.DeleteTexture(mgl.Texture(t))
}

func (c *Context) IsTexture(t Texture) bool {
	gl := c.gl
	return gl.IsTexture(mgl.Texture(t))
}

func (c *Context) TexSubImage2D(p []uint8, width, height int) {
	gl := c.gl
	gl.TexSubImage2D(mgl.TEXTURE_2D, 0, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p)
}

func (c *Context) BindScreenFramebuffer() error {
	return c.bindFramebuffer(c.screenFramebuffer)
}

func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) {
	gl := c.gl
	f := gl.CreateFramebuffer()
	if f.Value <= 0 {
		return Framebuffer{}, errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false")
	}
	c.bindFramebuffer(Framebuffer(f))

	gl.FramebufferTexture2D(mgl.FRAMEBUFFER, mgl.COLOR_ATTACHMENT0, mgl.TEXTURE_2D, mgl.Texture(texture), 0)
	s := gl.CheckFramebufferStatus(mgl.FRAMEBUFFER)
	if s != mgl.FRAMEBUFFER_COMPLETE {
		if s != 0 {
			return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
		}
		if e := gl.GetError(); e != mgl.NO_ERROR {
			return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
		}
		return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
	}
	return Framebuffer(f), nil
}

func (c *Context) setViewportImpl(width, height int) error {
	gl := c.gl
	gl.Viewport(0, 0, width, height)
	return nil
}

func (c *Context) FillFramebuffer(r, g, b, a float64) error {
	gl := c.gl
	gl.ClearColor(float32(r), float32(g), float32(b), float32(a))
	gl.Clear(mgl.COLOR_BUFFER_BIT)
	return nil
}

func (c *Context) DeleteFramebuffer(f Framebuffer) {
	gl := c.gl
	if !gl.IsFramebuffer(mgl.Framebuffer(f)) {
		return
	}
	// If a framebuffer to be delted is bound, a newly bound framebuffer
	// will be a default framebuffer.
	// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
	if c.lastFramebuffer == f {
		c.lastFramebuffer = invalidFramebuffer
		c.lastViewportWidth = 0
		c.lastViewportHeight = 0
	}
	gl.DeleteFramebuffer(mgl.Framebuffer(f))
}

func (c *Context) NewShader(shaderType ShaderType, source string) (Shader, error) {
	gl := c.gl
	s := gl.CreateShader(mgl.Enum(shaderType))
	if s.Value == 0 {
		return Shader{}, errors.New("opengl: glCreateShader failed")
	}
	gl.ShaderSource(s, source)
	gl.CompileShader(s)

	v := gl.GetShaderi(s, mgl.COMPILE_STATUS)
	if v == mgl.FALSE {
		log := gl.GetShaderInfoLog(s)
		return Shader{}, fmt.Errorf("opengl: shader compile failed: %s", log)
	}
	return Shader(s), nil
}

func (c *Context) DeleteShader(s Shader) {
	gl := c.gl
	gl.DeleteShader(mgl.Shader(s))
}

func (c *Context) GlslHighpSupported() bool {
	gl := c.gl
	_, _, precision := gl.GetShaderPrecisionFormat(mgl.FRAGMENT_SHADER, mgl.HIGH_FLOAT)
	// On Android emulators, precision might be a wrong value (#239).
	// TODO: If possible, check if this is running on an emulator.
	if 64 <= precision {
		return false
	}
	return precision != 0
}

func (c *Context) NewProgram(shaders []Shader) (Program, error) {
	gl := c.gl
	p := gl.CreateProgram()
	if p.Value == 0 {
		return Program{}, errors.New("opengl: glCreateProgram failed")
	}

	for _, shader := range shaders {
		gl.AttachShader(p, mgl.Shader(shader))
	}
	gl.LinkProgram(p)
	v := gl.GetProgrami(p, mgl.LINK_STATUS)
	if v == mgl.FALSE {
		return Program{}, errors.New("opengl: program error")
	}
	return Program(p), nil
}

func (c *Context) UseProgram(p Program) {
	gl := c.gl
	gl.UseProgram(mgl.Program(p))
}

func (c *Context) DeleteProgram(p Program) {
	gl := c.gl
	gl.DeleteProgram(mgl.Program(p))
}

func (c *Context) getUniformLocationImpl(p Program, location string) uniformLocation {
	gl := c.gl
	u := uniformLocation(gl.GetUniformLocation(mgl.Program(p), location))
	if u.Value == -1 {
		panic("invalid uniform location: " + location)
	}
	return u
}

func (c *Context) UniformInt(p Program, location string, v int) {
	gl := c.gl
	gl.Uniform1i(mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location)), v)
}

func (c *Context) UniformFloats(p Program, location string, v []float32) {
	gl := c.gl
	l := mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location))
	switch len(v) {
	case 4:
		gl.Uniform4fv(l, v)
	case 16:
		gl.UniformMatrix4fv(l, v)
	default:
		panic("not reach")
	}
}

func (c *Context) getAttribLocationImpl(p Program, location string) attribLocation {
	gl := c.gl
	a := attribLocation(gl.GetAttribLocation(mgl.Program(p), location))
	if a.Value == ^uint(0) {
		panic("invalid attrib location: " + location)
	}
	return a
}

func (c *Context) VertexAttribPointer(p Program, location string, normalize bool, stride int, size int, v int) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.VertexAttribPointer(mgl.Attrib(l), size, mgl.SHORT, normalize, stride, v)
}

func (c *Context) EnableVertexAttribArray(p Program, location string) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.EnableVertexAttribArray(mgl.Attrib(l))
}

func (c *Context) DisableVertexAttribArray(p Program, location string) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.DisableVertexAttribArray(mgl.Attrib(l))
}

func uint16ToBytes(v []uint16) []byte {
	b := make([]byte, len(v)*2)
	for i, x := range v {
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	return b
}

func int16ToBytes(v []int16) []byte {
	b := make([]byte, len(v)*2)
	for i, x := range v {
		b[2*i] = byte(uint16(x))
		b[2*i+1] = byte(uint16(x) >> 8)
	}
	return b
}

func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage BufferUsage) Buffer {
	gl := c.gl
	b := gl.CreateBuffer()
	gl.BindBuffer(mgl.Enum(bufferType), b)
	switch v := v.(type) {
	case int:
		gl.BufferInit(mgl.Enum(bufferType), v, mgl.Enum(bufferUsage))
	case []uint16:
		gl.BufferData(mgl.Enum(bufferType), uint16ToBytes(v), mgl.Enum(bufferUsage))
	default:
		panic("not reach")
	}
	return Buffer(b)
}

func (c *Context) BindElementArrayBuffer(b Buffer) {
	gl := c.gl
	gl.BindBuffer(mgl.ELEMENT_ARRAY_BUFFER, mgl.Buffer(b))
}

func (c *Context) BufferSubData(bufferType BufferType, data []int16) {
	gl := c.gl
	gl.BufferSubData(mgl.Enum(bufferType), 0, int16ToBytes(data))
}

func (c *Context) DeleteBuffer(b Buffer) {
	gl := c.gl
	gl.DeleteBuffer(mgl.Buffer(b))
}

func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) {
	gl := c.gl
	gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, offsetInBytes)
}

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

// +build android ios darwin,arm darwin,arm64

package opengl

import (
	"errors"
	"fmt"

	mgl "golang.org/x/mobile/gl"
)

type Texture mgl.Texture
type Framebuffer mgl.Framebuffer
type Shader mgl.Shader
type Program mgl.Program
type Buffer mgl.Buffer

type uniformLocation mgl.Uniform
type attribLocation mgl.Attrib

type programID uint32

var invalidFramebuffer = Framebuffer(mgl.Framebuffer{(1 << 32) - 1})

func (p Program) id() programID {
	return programID(p.Value)
}

func init() {
	Nearest = mgl.NEAREST
	Linear = mgl.LINEAR
	VertexShader = mgl.VERTEX_SHADER
	FragmentShader = mgl.FRAGMENT_SHADER
	ArrayBuffer = mgl.ARRAY_BUFFER
	ElementArrayBuffer = mgl.ELEMENT_ARRAY_BUFFER
	DynamicDraw = mgl.DYNAMIC_DRAW
	StaticDraw = mgl.STATIC_DRAW
	Triangles = mgl.TRIANGLES
	Lines = mgl.LINES

	zero = mgl.ZERO
	one = mgl.ONE
	srcAlpha = mgl.SRC_ALPHA
	dstAlpha = mgl.DST_ALPHA
	oneMinusSrcAlpha = mgl.ONE_MINUS_SRC_ALPHA
	oneMinusDstAlpha = mgl.ONE_MINUS_DST_ALPHA
}

type context struct {
	gl          mgl.Context
	worker      mgl.Worker
	initialized chan struct{}
}

func NewContext() (*Context, error) {
	c := &Context{
		locationCache:     newLocationCache(),
		lastCompositeMode: CompositeModeUnknown,
	}
	c.gl, c.worker = mgl.NewContext()
	c.initialized = make(chan struct{})
	go func() {
		// GL calls will just enqueue an task to the worker.
		// Since the worker is not available, this enqueuing should be done
		// in a goroutine.

		// Textures' pixel formats are alpha premultiplied.
		c.gl.Enable(mgl.BLEND)
		c.BlendFunc(CompositeModeSourceOver)
		f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
		c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
		close(c.initialized)
	}()
	return c, nil
}

func (c *Context) Reset() error {
	c.locationCache = newLocationCache()
	c.lastFramebuffer = invalidFramebuffer
	c.lastViewportWidth = 0
	c.lastViewportHeight = 0
	c.lastCompositeMode = CompositeModeUnknown
	c.gl.Enable(mgl.BLEND)
	c.BlendFunc(CompositeModeSourceOver)
	f := c.gl.GetInteger(mgl.FRAMEBUFFER_BINDING)
	c.screenFramebuffer = Framebuffer(mgl.Framebuffer{uint32(f)})
	// TODO: Need to update screenFramebufferWidth/Height?
	return nil
}

func (c *Context) InitializedCh() <-chan struct{} {
	return c.initialized
}

func (c *Context) Worker() mgl.Worker {
	return c.worker
}

func (c *Context) BlendFunc(mode CompositeMode) {
	gl := c.gl
	if c.lastCompositeMode == mode {
		return
	}
	c.lastCompositeMode = mode
	s, d := operations(mode)
	gl.BlendFunc(mgl.Enum(s), mgl.Enum(d))
}

func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) {
	gl := c.gl
	t := gl.CreateTexture()
	if t.Value <= 0 {
		return Texture{}, errors.New("opengl: creating texture failed")
	}
	gl.PixelStorei(mgl.UNPACK_ALIGNMENT, 4)
	gl.BindTexture(mgl.TEXTURE_2D, t)

	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MAG_FILTER, int(filter))
	gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MIN_FILTER, int(filter))

	var p []uint8
	if pixels != nil {
		p = pixels
	}
	gl.TexImage2D(mgl.TEXTURE_2D, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p)

	return Texture(t), nil
}

func (c *Context) bindFramebufferImpl(f Framebuffer) error {
	gl := c.gl
	gl.BindFramebuffer(mgl.FRAMEBUFFER, mgl.Framebuffer(f))
	return nil
}

func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) {
	gl := c.gl
	gl.Flush()

	c.bindFramebuffer(f)

	pixels := make([]uint8, 4*width*height)
	gl.ReadPixels(pixels, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE)
	if e := gl.GetError(); e != mgl.NO_ERROR {
		return nil, fmt.Errorf("opengl: glReadPixels: %d", e)
	}
	return pixels, nil
}

func (c *Context) BindTexture(t Texture) {
	gl := c.gl
	gl.BindTexture(mgl.TEXTURE_2D, mgl.Texture(t))
}

func (c *Context) DeleteTexture(t Texture) {
	gl := c.gl
	if !gl.IsTexture(mgl.Texture(t)) {
		return
	}
	gl.DeleteTexture(mgl.Texture(t))
}

func (c *Context) IsTexture(t Texture) bool {
	gl := c.gl
	return gl.IsTexture(mgl.Texture(t))
}

func (c *Context) TexSubImage2D(p []uint8, width, height int) {
	gl := c.gl
	gl.TexSubImage2D(mgl.TEXTURE_2D, 0, 0, 0, width, height, mgl.RGBA, mgl.UNSIGNED_BYTE, p)
}

func (c *Context) BindScreenFramebuffer() error {
	return c.bindFramebuffer(c.screenFramebuffer)
}

func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) {
	gl := c.gl
	f := gl.CreateFramebuffer()
	if f.Value <= 0 {
		return Framebuffer{}, errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false")
	}
	c.bindFramebuffer(Framebuffer(f))

	gl.FramebufferTexture2D(mgl.FRAMEBUFFER, mgl.COLOR_ATTACHMENT0, mgl.TEXTURE_2D, mgl.Texture(texture), 0)
	s := gl.CheckFramebufferStatus(mgl.FRAMEBUFFER)
	if s != mgl.FRAMEBUFFER_COMPLETE {
		if s != 0 {
			return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: %v", s)
		}
		if e := gl.GetError(); e != mgl.NO_ERROR {
			return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
		}
		return Framebuffer{}, fmt.Errorf("opengl: creating framebuffer failed: unknown error")
	}
	return Framebuffer(f), nil
}

func (c *Context) setViewportImpl(width, height int) error {
	gl := c.gl
	gl.Viewport(0, 0, width, height)
	return nil
}

func (c *Context) FillFramebuffer(r, g, b, a float64) error {
	gl := c.gl
	gl.ClearColor(float32(r), float32(g), float32(b), float32(a))
	gl.Clear(mgl.COLOR_BUFFER_BIT)
	return nil
}

func (c *Context) DeleteFramebuffer(f Framebuffer) {
	gl := c.gl
	if !gl.IsFramebuffer(mgl.Framebuffer(f)) {
		return
	}
	// If a framebuffer to be delted is bound, a newly bound framebuffer
	// will be a default framebuffer.
	// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glDeleteFramebuffers.xml
	if c.lastFramebuffer == f {
		c.lastFramebuffer = invalidFramebuffer
		c.lastViewportWidth = 0
		c.lastViewportHeight = 0
	}
	gl.DeleteFramebuffer(mgl.Framebuffer(f))
}

func (c *Context) NewShader(shaderType ShaderType, source string) (Shader, error) {
	gl := c.gl
	s := gl.CreateShader(mgl.Enum(shaderType))
	if s.Value == 0 {
		return Shader{}, errors.New("opengl: glCreateShader failed")
	}
	gl.ShaderSource(s, source)
	gl.CompileShader(s)

	v := gl.GetShaderi(s, mgl.COMPILE_STATUS)
	if v == mgl.FALSE {
		log := gl.GetShaderInfoLog(s)
		return Shader{}, fmt.Errorf("opengl: shader compile failed: %s", log)
	}
	return Shader(s), nil
}

func (c *Context) DeleteShader(s Shader) {
	gl := c.gl
	gl.DeleteShader(mgl.Shader(s))
}

func (c *Context) GlslHighpSupported() bool {
	gl := c.gl
	_, _, precision := gl.GetShaderPrecisionFormat(mgl.FRAGMENT_SHADER, mgl.HIGH_FLOAT)
	// On Android emulators, precision might be a wrong value (#239).
	// TODO: If possible, check if this is running on an emulator.
	if 64 <= precision {
		return false
	}
	return precision != 0
}

func (c *Context) NewProgram(shaders []Shader) (Program, error) {
	gl := c.gl
	p := gl.CreateProgram()
	if p.Value == 0 {
		return Program{}, errors.New("opengl: glCreateProgram failed")
	}

	for _, shader := range shaders {
		gl.AttachShader(p, mgl.Shader(shader))
	}
	gl.LinkProgram(p)
	v := gl.GetProgrami(p, mgl.LINK_STATUS)
	if v == mgl.FALSE {
		return Program{}, errors.New("opengl: program error")
	}
	return Program(p), nil
}

func (c *Context) UseProgram(p Program) {
	gl := c.gl
	gl.UseProgram(mgl.Program(p))
}

func (c *Context) DeleteProgram(p Program) {
	gl := c.gl
	gl.DeleteProgram(mgl.Program(p))
}

func (c *Context) getUniformLocationImpl(p Program, location string) uniformLocation {
	gl := c.gl
	u := uniformLocation(gl.GetUniformLocation(mgl.Program(p), location))
	if u.Value == -1 {
		panic("invalid uniform location: " + location)
	}
	return u
}

func (c *Context) UniformInt(p Program, location string, v int) {
	gl := c.gl
	gl.Uniform1i(mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location)), v)
}

func (c *Context) UniformFloats(p Program, location string, v []float32) {
	gl := c.gl
	l := mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location))
	switch len(v) {
	case 4:
		gl.Uniform4fv(l, v)
	case 16:
		gl.UniformMatrix4fv(l, v)
	default:
		panic("not reach")
	}
}

func (c *Context) getAttribLocationImpl(p Program, location string) attribLocation {
	gl := c.gl
	a := attribLocation(gl.GetAttribLocation(mgl.Program(p), location))
	if a.Value == ^uint(0) {
		panic("invalid attrib location: " + location)
	}
	return a
}

func (c *Context) VertexAttribPointer(p Program, location string, normalize bool, stride int, size int, v int) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.VertexAttribPointer(mgl.Attrib(l), size, mgl.SHORT, normalize, stride, v)
}

func (c *Context) EnableVertexAttribArray(p Program, location string) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.EnableVertexAttribArray(mgl.Attrib(l))
}

func (c *Context) DisableVertexAttribArray(p Program, location string) {
	gl := c.gl
	l := c.locationCache.GetAttribLocation(c, p, location)
	gl.DisableVertexAttribArray(mgl.Attrib(l))
}

func uint16ToBytes(v []uint16) []byte {
	b := make([]byte, len(v)*2)
	for i, x := range v {
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	return b
}

func int16ToBytes(v []int16) []byte {
	b := make([]byte, len(v)*2)
	for i, x := range v {
		b[2*i] = byte(uint16(x))
		b[2*i+1] = byte(uint16(x) >> 8)
	}
	return b
}

func (c *Context) NewBuffer(bufferType BufferType, v interface{}, bufferUsage BufferUsage) Buffer {
	gl := c.gl
	b := gl.CreateBuffer()
	gl.BindBuffer(mgl.Enum(bufferType), b)
	switch v := v.(type) {
	case int:
		gl.BufferInit(mgl.Enum(bufferType), v, mgl.Enum(bufferUsage))
	case []uint16:
		gl.BufferData(mgl.Enum(bufferType), uint16ToBytes(v), mgl.Enum(bufferUsage))
	default:
		panic("not reach")
	}
	return Buffer(b)
}

func (c *Context) BindElementArrayBuffer(b Buffer) {
	gl := c.gl
	gl.BindBuffer(mgl.ELEMENT_ARRAY_BUFFER, mgl.Buffer(b))
}

func (c *Context) BufferSubData(bufferType BufferType, data []int16) {
	gl := c.gl
	gl.BufferSubData(mgl.Enum(bufferType), 0, int16ToBytes(data))
}

func (c *Context) DeleteBuffer(b Buffer) {
	gl := c.gl
	gl.DeleteBuffer(mgl.Buffer(b))
}

func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) {
	gl := c.gl
	gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, offsetInBytes)
}

func (c *Context) Flush() {
	gl := c.gl
	gl.Flush()
}
<|endoftext|>


<commit_before>package clients

import (
	"encoding/json"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"

	"testing"

	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"
)

const expected = `package testclient

import (
	"github.com/youtube/vitess/go/rpcplus"
	"golang.org/x/net/context"
)

// New creates a new local Account rpc client
func NewAccount(client *rpcplus.Client) *Account {
	return &Account{
		client: client,
	}
}

// Account is for holding the api functions
type Account struct {
	client *rpcplus.Client
}

func (a *Account) Create(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Create", req, res)
}

func (a *Account) Delete(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Delete", req, res)
}

func (a *Account) One(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.One", req, res)
}

func (a *Account) Some(ctx context.Context, req *models.Account, res *[]*models.Account) error {
	return m.client.Call(ctx, "Account.Some", req, res)
}

func (a *Account) Update(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Update", req, res)
}
`

func TestConstructors(t *testing.T) {
	s := &schema.Schema{}
	if err := json.Unmarshal([]byte(testdata.JSON1), s); err != nil {
		t.Fatal(err.Error())
	}

	s = s.Resolve(nil)

	a, err := generate("test", s.Definitions["Account"])
	equals(t, nil, err)
	equals(t, expected, string(a))
}

func equals(tb testing.TB, exp, act interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
		tb.Fail()
	}
}
<commit_msg>gene: use new creational pattern<commit_after>package clients

import (
	"encoding/json"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"

	"testing"

	"github.com/cihangir/gene/config"
	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"
)

const expected = `package testclient

import (
	"github.com/youtube/vitess/go/rpcplus"
	"golang.org/x/net/context"
)

// New creates a new local Account rpc client
func NewAccount(client *rpcplus.Client) *Account {
	return &Account{
		client: client,
	}
}

// Account is for holding the api functions
type Account struct {
	client *rpcplus.Client
}

func (a *Account) Create(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Create", req, res)
}

func (a *Account) Delete(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Delete", req, res)
}

func (a *Account) One(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.One", req, res)
}

func (a *Account) Some(ctx context.Context, req *models.Account, res *[]*models.Account) error {
	return m.client.Call(ctx, "Account.Some", req, res)
}

func (a *Account) Update(ctx context.Context, req *models.Account, res *models.Account) error {
	return m.client.Call(ctx, "Account.Update", req, res)
}
`

func TestConstructors(t *testing.T) {
	s := &schema.Schema{}
	if err := json.Unmarshal([]byte(testdata.JSON1), s); err != nil {
		t.Fatal(err.Error())
	}

	s = s.Resolve(s)

	cl, err := NewClient(config.NewContext(), s)
	if err != nil {
		t.Fail()
	}

	a, err := cl.generate("test", s.Definitions["Account"])
	equals(t, nil, err)
	equals(t, expected, string(a))
}

func equals(tb testing.TB, exp, act interface{}) {
	if !reflect.DeepEqual(exp, act) {
		_, file, line, _ := runtime.Caller(1)
		fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
		tb.Fail()
	}
}
<|endoftext|>


<commit_before>package main

/* import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
) */

import (
	"errors"
	"fmt"
	//"strconv"
	//"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"encoding/json"
	//"regexp"
	//"time"
	"crypto/rand"
	//"io"
)

var logger = shim.NewLogger("CLDChaincode")

// Participant
const	SHIPPER      =  		"shipper"
const	LOGISTIC_PROVIDER   =  	"logistic_provider"
const	INSURENCE_COMPANY = 	"insurence_company"

// Status
const CREATED = "created"
const CANCEL = "cancel"
const SUCESS = "success"

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Volume struct {
	TrackId									string `json: trackId`
	Owner									string `json: owner`
	Shipper									string `json: owner`
	Status									string `json: status`
}

func main() {
	fmt.Println("Start Contract")

	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args [] string) ([]byte, error) {
    fmt.Println("invoke is running " + function)

    // Handle different functions
    if function == "init" {
        return t.Init(stub, "init", args)
	} else if function == "CreateVolume" {
		return t.CreateVolume(stub, args[0])
	} /*else if function == "shipperToLogisticProvider" {
        return t.shipperToLogisticProvider(stub, args)
    } else if function == "LogisticProviderToCustomer" {
		return t.LogisticProviderToCustomer(stub, args)
	} else if function == "LogisticProviderToLogisticProvider" {
		return t.LogisticProviderToLogisticProvider(stub, args)
	} else if function == "LogisticProviderToShipper" {
		return t.LogisticProviderToShipper(stub, args)
	} */

    fmt.Println("invoke did not find func: " + function)
	logger.Debug("invoke did not find func: ", function)

    return nil, errors.New("Received unknown function invocation")
}

func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Debug("query function: ", function)
	fmt.Println(args)

	if function == "get_volumes" {
		return t.get_volumes(stub, args)
	}

	return nil, errors.New("Received unknown function invocation " + function)
}

// Functions to Write
func (t *SimpleChaincode) CreateVolume(stub shim.ChaincodeStubInterface, shipper string) ([]byte, error) {
	var v Volume

	var err error
	var bytes []byte

	v.TrackId = GenerateRandomString(10)
	v.Owner = "SHIPPER"
	v.Shipper = shipper

 	fmt.Println("[Volume]: " + v.TrackId)

	bytes, err = json.Marshal(v)

	err = stub.PutState(v.TrackId, bytes)

	if err != nil { return nil, errors.New("Unable to put the state") }

	return nil, nil
}

func GenerateRandomString(n int) (string) {
    const letters = "0123456789"
    bytes := GenerateRandomBytes(n)

    for i, b := range bytes {
        bytes[i] = letters[b%byte(len(letters))]
    }

    return (string(bytes))
}

func GenerateRandomBytes(n int) ([]byte) {
    b := make([]byte, n)
    _, err := rand.Read(b)

    if err != nil {
        return nil
    }

    return b
}

func (t *SimpleChaincode) get_volumes(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	//select range
	resultsIterator, err := stub.RangeQueryState("0", "9999999999")

	if err != nil {
		return nil, errors.New("[IP][Query] Unknown error")
	}

	field := args[0]
	value := args[1]
	fmt.Println(field)
	fmt.Println(value)
	// logisticProviderId := args[1]
	// pendingOrder, err := strconv.ParseBool(args[2])
	// findAll, err := strconv.ParseBool(args[3])

	hasResult := false

	defer resultsIterator.Close()

	result := "{\"volumes\": ["

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()

		fmt.Println("[IP][Query] hack: " + queryKeyAsStr)

		if err != nil {
			return nil, errors.New("[IP][Query] Unknown error")
		}

		var volume Volume
		json.Unmarshal(queryValAsBytes, &volume)
		fmt.Println(string(queryValAsBytes));

		if field == "trackerId" {
			if volume.TrackId == value {
				result += string(queryValAsBytes) + ","
				hasResult = true
			}
		} else {
			result += string(queryValAsBytes) + ","
			hasResult = true
		}

		// clientIdOk := clientId == "-1" || volume.ClientId == clientId
		// logisticProviderIdOk := logisticProviderId == "-1" || volume.LogisticProviderId == logisticProviderId

		// var findPendingOk bool

		// if pendingOrder {
		// 	findPendingOk = (volume.LogisticProviderFinalShippingCost == 0)
		// } else {
		// 	findPendingOk = (volume.LogisticProviderFinalShippingCost != 0)
		// }

		// fmt.Println("[IP][Query] ClientId: " + clientId + " | LogisticProviderId: " + logisticProviderId + " | PendingOrder: " + strconv.FormatBool(pendingOrder) + " | ClientIdOk: " + strconv.FormatBool(clientIdOk) + " | LogisticProviderIdOk: " + strconv.FormatBool(logisticProviderIdOk) + " | FindPendingOk: " + strconv.FormatBool(findPendingOk) + " | FindAll: " + strconv.FormatBool(findAll))
	}

	if hasResult {
		result = result[:len(result)-1] + "]}"
	} else {
		result = result + "]}"
	}

	return []byte(result), nil
}

func (t *SimpleChaincode) get_volume(stub shim.ChaincodeStubInterface, trackerId string) (Volume, error) {
	//select range
	resultsIterator, err := stub.RangeQueryState("0", "9999999999")
    var volume Volume
	if err != nil {
		return volume, errors.New("[IP][Query] Unknown error")
	}

	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()

		fmt.Println("[IP][Query] hack: " + queryKeyAsStr)

		if err != nil {
			return volume, errors.New("[IP][Query] Unknown error")
		}

		json.Unmarshal(queryValAsBytes, &volume)
		fmt.Println(string(queryValAsBytes));

		return volume, nil
	}

	return volume, nil
}<commit_msg>Query<commit_after>package main

/* import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
) */

import (
	"errors"
	"fmt"
	//"strconv"
	//"strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"encoding/json"
	//"regexp"
	//"time"
	"crypto/rand"
	//"io"
)

var logger = shim.NewLogger("CLDChaincode")

// Participant
const	SHIPPER      =  		"shipper"
const	LOGISTIC_PROVIDER   =  	"logistic_provider"
const	INSURENCE_COMPANY = 	"insurence_company"

// Status
const CREATED = "created"
const CANCEL = "cancel"
const SUCESS = "success"

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Volume struct {
	TrackId									string `json: trackId`
	Owner									string `json: owner`
	Shipper									string `json: owner`
	Status									string `json: status`
}

func main() {
	fmt.Println("Start Contract")

	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args [] string) ([]byte, error) {
    fmt.Println("invoke is running " + function)

    // Handle different functions
    if function == "init" {
        return t.Init(stub, "init", args)
	} else if function == "CreateVolume" {
		return t.CreateVolume(stub, args[0])
	} /*else if function == "shipperToLogisticProvider" {
        return t.shipperToLogisticProvider(stub, args)
    } else if function == "LogisticProviderToCustomer" {
		return t.LogisticProviderToCustomer(stub, args)
	} else if function == "LogisticProviderToLogisticProvider" {
		return t.LogisticProviderToLogisticProvider(stub, args)
	} else if function == "LogisticProviderToShipper" {
		return t.LogisticProviderToShipper(stub, args)
	} */

    fmt.Println("invoke did not find func: " + function)
	logger.Debug("invoke did not find func: ", function)

    return nil, errors.New("Received unknown function invocation")
}

func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Debug("query function: ", function)
	fmt.Println(args)

	if function == "get_volumes" {
		return t.get_volumes(stub, args)
	}

	return nil, errors.New("Received unknown function invocation " + function)
}

// Functions to Write
func (t *SimpleChaincode) CreateVolume(stub shim.ChaincodeStubInterface, shipper string) ([]byte, error) {
	var v Volume

	var err error
	var bytes []byte

	v.TrackId = GenerateRandomString(10)
	v.Owner = "SHIPPER"
	v.Shipper = shipper

 	fmt.Println("[Volume]: " + v.TrackId)

	bytes, err = json.Marshal(v)

	err = stub.PutState(v.TrackId, bytes)

	if err != nil { return nil, errors.New("Unable to put the state") }

	return nil, nil
}

func GenerateRandomString(n int) (string) {
    const letters = "0123456789"
    bytes := GenerateRandomBytes(n)

    for i, b := range bytes {
        bytes[i] = letters[b%byte(len(letters))]
    }

    return (string(bytes))
}

func GenerateRandomBytes(n int) ([]byte) {
    b := make([]byte, n)
    _, err := rand.Read(b)

    if err != nil {
        return nil
    }

    return b
}

func (t *SimpleChaincode) get_volumes(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	//select range
	resultsIterator, err := stub.RangeQueryState("0", "9999999999")

	if err != nil {
		return nil, errors.New("[IP][Query] Unknown error")
	}

	field := args[0]
	value := args[1]
	fmt.Println(field)
	fmt.Println(value)
	// logisticProviderId := args[1]
	// pendingOrder, err := strconv.ParseBool(args[2])
	// findAll, err := strconv.ParseBool(args[3])

	hasResult := false

	defer resultsIterator.Close()

	result := "{\"volumes\": ["

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()

		fmt.Println("[IP][Query] hack: " + queryKeyAsStr)

		if err != nil {
			return nil, errors.New("[IP][Query] Unknown error")
		}

		var volume Volume
		json.Unmarshal(queryValAsBytes, &volume)
		fmt.Println(string(queryValAsBytes));

		if field == "trackerId" {
			if volume.TrackId == value {
				result += string(queryValAsBytes) + ","
				hasResult = true
			}
		} else if field == "shipper" {
			if volume.Shipper == value && volums.Status == "CRIADO" {
				result += string(queryValAsBytes) + ","
				hasResult = true
			}
		} else if field == "logistic_provider" {
			if volume.LogisticProvider == value {
				result += string(queryValAsBytes) + ","
				hasResult = true
			}
		} else {
			result += string(queryValAsBytes) + ","
			hasResult = true
		}

		// clientIdOk := clientId == "-1" || volume.ClientId == clientId
		// logisticProviderIdOk := logisticProviderId == "-1" || volume.LogisticProviderId == logisticProviderId

		// var findPendingOk bool

		// if pendingOrder {
		// 	findPendingOk = (volume.LogisticProviderFinalShippingCost == 0)
		// } else {
		// 	findPendingOk = (volume.LogisticProviderFinalShippingCost != 0)
		// }

		// fmt.Println("[IP][Query] ClientId: " + clientId + " | LogisticProviderId: " + logisticProviderId + " | PendingOrder: " + strconv.FormatBool(pendingOrder) + " | ClientIdOk: " + strconv.FormatBool(clientIdOk) + " | LogisticProviderIdOk: " + strconv.FormatBool(logisticProviderIdOk) + " | FindPendingOk: " + strconv.FormatBool(findPendingOk) + " | FindAll: " + strconv.FormatBool(findAll))
	}

	if hasResult {
		result = result[:len(result)-1] + "]}"
	} else {
		result = result + "]}"
	}

	return []byte(result), nil
}

func (t *SimpleChaincode) get_volume(stub shim.ChaincodeStubInterface, trackerId string) (Volume, error) {
	//select range
	resultsIterator, err := stub.RangeQueryState("0", "9999999999")
    var volume Volume
	if err != nil {
		return volume, errors.New("[IP][Query] Unknown error")
	}

	defer resultsIterator.Close()

	for resultsIterator.HasNext() {
		queryKeyAsStr, queryValAsBytes, err := resultsIterator.Next()

		fmt.Println("[IP][Query] hack: " + queryKeyAsStr)

		if err != nil {
			return volume, errors.New("[IP][Query] Unknown error")
		}

		json.Unmarshal(queryValAsBytes, &volume)
		fmt.Println(string(queryValAsBytes));

		return volume, nil
	}

	return volume, nil
}<|endoftext|>