<commit_before>// Package cmac implements CMAC as defined in RFC4493 and NIST SP800-38b.
package cmac

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/subtle"
	"errors"
	"hash"
)

const (
	_Rb128 = 0x87
	_Rb64  = 0x1b
)

func shifted(x []byte) []byte {
	d := make([]byte, len(x))
	copy(d, x)
	for i := range d {
		if i > 0 {
			d[i-1] |= d[i] >> 7
		}
		d[i] <<= 1
	}
	return d
}

func gensubkey(c cipher.Block, l []byte, rb byte) []byte {
	sk := shifted(l)
	sk[len(sk)-1] ^= byte(subtle.ConstantTimeSelect(int(l[0]>>7), int(rb), 0))
	return sk
}

func gensubkeys(c cipher.Block) ([]byte, []byte) {
	var rb byte

	switch c.BlockSize() {
	case 16:
		rb = _Rb128
	case 8:
		rb = _Rb64
	default:
		panic("cmac: invalid block size")

	}

	l := make([]byte, c.BlockSize())
	c.Encrypt(l, l)

	k1 := gensubkey(c, l, rb)
	return k1, gensubkey(c, k1, rb)
}

type cmac struct {
	c           cipher.Block
	k1, k2      []byte
	buf, x, tmp []byte
}

func newcmac(c cipher.Block) *cmac {
	k1, k2 := gensubkeys(c)
	x := make([]byte, c.BlockSize())
	tmp := make([]byte, c.BlockSize())
	m := &cmac{c: c, k1: k1, k2: k2, x: x, tmp: tmp}
	m.Reset()
	return m
}

func (m *cmac) block(b []byte) {
	for i := range m.tmp {
		m.tmp[i] = m.x[i] ^ b[i]
	}
	m.c.Encrypt(m.x, m.tmp)
}

func (m *cmac) Write(b []byte) (int, error) {
	d := append(m.buf, b...)

	for len(d) > m.c.BlockSize() {
		m.block(d[:m.c.BlockSize()])
		d = d[m.c.BlockSize():]
	}

	m.buf = d

	return len(b), nil
}

func (m *cmac) Sum(b []byte) []byte {
	if len(m.buf) == m.c.BlockSize() {
		for i := range m.tmp {
			m.tmp[i] = m.buf[i] ^ m.k1[i]
		}
	} else {
		for i := range m.buf {
			m.tmp[i] = m.buf[i] ^ m.k2[i]
		}
		m.tmp[len(m.buf)] = 0x80 ^ m.k2[len(m.buf)]
		for i := len(m.buf) + 1; i < len(m.tmp); i++ {
			m.tmp[i] = m.k2[i]
		}
	}

	for i := range m.tmp {
		m.tmp[i] ^= m.x[i]
	}
	m.c.Encrypt(m.tmp, m.tmp)

	return append(b, m.tmp...)
}

func (m *cmac) Reset() {
	m.buf = nil
	for i := range m.x {
		m.x[i] = 0
	}
}

func (m *cmac) Size() int {
	return m.c.BlockSize()
}

func (m *cmac) BlockSize() int {
	return m.c.BlockSize()
}

// New returns a hash.Hash computing AES-CMAC.
func New(key []byte) (hash.Hash, error) {
	c, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	return NewWithCipher(c)
}

// NewWithCipher returns a hash.Hash computing CMAC using the given
// cipher.Block. The block cipher should have a block length of 8 or 16 bytes.
func NewWithCipher(c cipher.Block) (hash.Hash, error) {
	switch c.BlockSize() {
	case 8, 16:
		return newcmac(c), nil
	default:
		return nil, errors.New("cmac: invalid blocksize")
	}
}
<commit_msg>Refactor hash to not allocate<commit_after>// Package cmac implements CMAC as defined in RFC4493 and NIST SP800-38b.
package cmac

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/subtle"
	"errors"
	"hash"
)

const (
	_Rb128 = 0x87
	_Rb64  = 0x1b
)

func shifted(x []byte) []byte {
	d := make([]byte, len(x))
	copy(d, x)
	for i := range d {
		if i > 0 {
			d[i-1] |= d[i] >> 7
		}
		d[i] <<= 1
	}
	return d
}

func gensubkey(c cipher.Block, l []byte, rb byte) []byte {
	sk := shifted(l)
	sk[len(sk)-1] ^= byte(subtle.ConstantTimeSelect(int(l[0]>>7), int(rb), 0))
	return sk
}

func gensubkeys(c cipher.Block) ([]byte, []byte) {
	var rb byte

	switch c.BlockSize() {
	case 16:
		rb = _Rb128
	case 8:
		rb = _Rb64
	default:
		panic("cmac: invalid block size")

	}

	l := make([]byte, c.BlockSize())
	c.Encrypt(l, l)

	k1 := gensubkey(c, l, rb)
	return k1, gensubkey(c, k1, rb)
}

type cmac struct {
	c       cipher.Block
	k1, k2  []byte
	buf, x  []byte
	scratch []byte
	cursor  int
}

func newcmac(c cipher.Block) *cmac {
	k1, k2 := gensubkeys(c)
	buf := make([]byte, c.BlockSize())
	x := make([]byte, c.BlockSize())
	m := &cmac{c: c, k1: k1, k2: k2, buf: buf, x: x}
	m.Reset()
	return m
}

func (m *cmac) Write(b []byte) (int, error) {
	totLen := len(b)

	n := copy(m.buf[m.cursor:], b)
	m.cursor += n
	b = b[n:]

	for len(b) > 0 {
		for i := range m.buf {
			m.buf[i] ^= m.x[i]
		}
		m.c.Encrypt(m.x, m.buf)

		m.cursor = copy(m.buf, b)
		b = b[m.cursor:]
	}

	return totLen, nil
}

func (m *cmac) Sum(b []byte) []byte {
	n := len(b)
	// I'm not sure why we need to do this: the second argument of
	// 	append(b, make([]byte, m.c.BlockSize())...)
	// shouldn't escape, so I'm not sure why it ends up getting heap
	// allocated (as of Go 1.4.2 at least).
	switch m.c.BlockSize() {
	case 8:
		b = append(b, 0, 0, 0, 0, 0, 0, 0, 0)
	case 16:
		b = append(b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
	default:
		panic("unexpected block size")
	}
	scratch := b[n:]

	if m.cursor == m.c.BlockSize() {
		for i := range scratch {
			scratch[i] = m.buf[i] ^ m.k1[i]
		}
	} else {
		for i := 0; i < m.cursor; i++ {
			scratch[i] = m.buf[i] ^ m.k2[i]
		}
		scratch[m.cursor] = 0x80 ^ m.k2[m.cursor]
		for i := m.cursor + 1; i < len(m.buf); i++ {
			scratch[i] = m.k2[i]
		}
	}

	for i := range scratch {
		scratch[i] ^= m.x[i]
	}
	m.c.Encrypt(scratch, scratch)

	return b
}

func (m *cmac) Reset() {
	for i := 0; i < m.c.BlockSize(); i++ {
		m.buf[i] = 0
		m.x[i] = 0
	}
	m.cursor = 0
}

func (m *cmac) Size() int {
	return m.c.BlockSize()
}

func (m *cmac) BlockSize() int {
	return m.c.BlockSize()
}

// New returns a hash.Hash computing AES-CMAC.
func New(key []byte) (hash.Hash, error) {
	c, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	return NewWithCipher(c)
}

// NewWithCipher returns a hash.Hash computing CMAC using the given
// cipher.Block. The block cipher should have a block length of 8 or 16 bytes.
func NewWithCipher(c cipher.Block) (hash.Hash, error) {
	switch c.BlockSize() {
	case 8, 16:
		return newcmac(c), nil
	default:
		return nil, errors.New("cmac: invalid blocksize")
	}
}
<|endoftext|>


<commit_before>package avatar

import (
	"bytes"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"os"
	"testing"
)

func TestInitialsAvatar_DrawToBytes(t *testing.T) {
	fontFile := os.Getenv("AVATAR_FONT")
	if fontFile == "" {
		t.Skip("Font file is needed")
	}

	av := New(fontFile)

	stuffs := []struct {
		name     string
		size     int
		encoding string
	}{
		{"Swordsmen", 22, "png"},
		{"Condor Heroes", 30, "jpeg"},
		{"Swordsmen", 0, "png"},
		{"*", 22, "png"},
	}

	for _, v := range stuffs {
		raw, err := av.DrawToBytes(v.name, v.size, v.encoding)
		if err != nil {
			if err == ErrUnsupportChar {
				t.Skip("ErrUnsupportChar")
			}
			t.Error(err)
		}
		switch v.encoding {
		case "png":
			if _, perr := png.Decode(bytes.NewReader(raw)); perr != nil {
				t.Error(perr)
			}
		case "jpeg":
			if _, perr := jpeg.Decode(bytes.NewReader(raw)); perr != nil {
				t.Error(perr, v)
			}
		}
	}
}

func TestGetInitials(t *testing.T) {
	names := []struct {
		full, intitials string
	}{
		{"David", "D"},
		{"Goliath", "G"},
		{"", ""},
		//		{"David Goliath", "DG"},
	}

	for _, v := range names {
		n := getInitials(v.full)
		if n != v.intitials {
			t.Errorf("expected %s got %s", v.intitials, n)
		}
	}
}

func TestGetTTL(t *testing.T) {
	fileNotExists := "xxxxxxx.ttf"
	_, err := getTTF(fileNotExists)
	if err == nil {
		t.Error("should return error")
	}

	_, err = newDrawer(fileNotExists)
	if err == nil {
		t.Error("should return error")
	}

	fileExistsButNotTTF, _ := ioutil.TempFile(os.TempDir(), "prefix")
	defer os.Remove(fileExistsButNotTTF.Name())

	_, err = getTTF(fileExistsButNotTTF.Name())
	if err == nil {
		t.Error("should return error")
	}
	_, err = newDrawer(fileExistsButNotTTF.Name())
	if err == nil {
		t.Error("should return error")
	}
}
<commit_msg>more test case<commit_after>package avatar

import (
	"bytes"
	"image/jpeg"
	"image/png"
	"io/ioutil"
	"os"
	"testing"
)

func TestInitialsAvatar_DrawToBytes(t *testing.T) {
	fontFile := os.Getenv("AVATAR_FONT")
	if fontFile == "" {
		t.Skip("Font file is needed")
	}

	av := New(fontFile)

	stuffs := []struct {
		name     string
		size     int
		encoding string
	}{
		{"Swordsmen", 22, "png"},
		{"Condor Heroes", 30, "jpeg"},
		{"孔子", 22, "png"},
		{"Swordsmen", 0, "png"},
		{"*", 22, "png"},
	}

	for _, v := range stuffs {
		raw, err := av.DrawToBytes(v.name, v.size, v.encoding)
		if err != nil {
			if err == ErrUnsupportChar {
				t.Skip("ErrUnsupportChar")
			}
			t.Error(err)
		}
		switch v.encoding {
		case "png":
			if _, perr := png.Decode(bytes.NewReader(raw)); perr != nil {
				t.Error(perr)
			}
		case "jpeg":
			if _, perr := jpeg.Decode(bytes.NewReader(raw)); perr != nil {
				t.Error(perr, v)
			}
		}
	}
}

func TestGetInitials(t *testing.T) {
	names := []struct {
		full, intitials string
	}{
		{"David", "D"},
		{"Goliath", "G"},
		{"", ""},
		//		{"David Goliath", "DG"},
	}

	for _, v := range names {
		n := getInitials(v.full)
		if n != v.intitials {
			t.Errorf("expected %s got %s", v.intitials, n)
		}
	}
}

func TestGetTTL(t *testing.T) {
	fileNotExists := "xxxxxxx.ttf"
	_, err := getTTF(fileNotExists)
	if err == nil {
		t.Error("should return error")
	}

	_, err = newDrawer(fileNotExists)
	if err == nil {
		t.Error("should return error")
	}

	fileExistsButNotTTF, _ := ioutil.TempFile(os.TempDir(), "prefix")
	defer os.Remove(fileExistsButNotTTF.Name())

	_, err = getTTF(fileExistsButNotTTF.Name())
	if err == nil {
		t.Error("should return error")
	}
	_, err = newDrawer(fileExistsButNotTTF.Name())
	if err == nil {
		t.Error("should return error")
	}
	_, err = newDrawer("")
	if err == nil {
		t.Error("should return error")
	}

}
<|endoftext|>


<commit_before>package revel

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"time"
)

type Controller struct {
	Name          string          // The controller name, e.g. "Application"
	Type          *ControllerType // A description of the controller type.
	MethodName    string          // The method name, e.g. "Index"
	MethodType    *MethodType     // A description of the invoked action type.
	AppController interface{}     // The controller that was instantiated.
	Action        string          // The fully qualified action name, e.g. "App.Index"

	Request  *Request
	Response *Response
	Result   Result

	Flash      Flash                  // User cookie, cleared after 1 request.
	Session    Session                // Session, stored in cookie, signed.
	Params     *Params                // Parameters from URL and form (including multipart).
	Args       map[string]interface{} // Per-request scratch space.
	RenderArgs map[string]interface{} // Args passed to the template.
	Validation *Validation            // Data validation helpers
}

func NewController(req *Request, resp *Response) *Controller {
	return &Controller{
		Request:  req,
		Response: resp,
		Params:   new(Params),
		Args:     map[string]interface{}{},
		RenderArgs: map[string]interface{}{
			"RunMode": RunMode,
			"DevMode": DevMode,
		},
	}
}

func (c *Controller) FlashParams() {
	for key, vals := range c.Params.Values {
		c.Flash.Out[key] = strings.Join(vals, ",")
	}
}

func (c *Controller) SetCookie(cookie *http.Cookie) {
	http.SetCookie(c.Response.Out, cookie)
}

func (c *Controller) RenderError(err error) Result {
	return ErrorResult{c.RenderArgs, err}
}

// Render a template corresponding to the calling Controller method.
// Arguments will be added to c.RenderArgs prior to rendering the template.
// They are keyed on their local identifier.
//
// For example:
//
//     func (c Users) ShowUser(id int) revel.Result {
//     	 user := loadUser(id)
//     	 return c.Render(user)
//     }
//
// This action will render views/Users/ShowUser.html, passing in an extra
// key-value "user": (User).
func (c *Controller) Render(extraRenderArgs ...interface{}) Result {
	// Get the calling function name.
	_, _, line, ok := runtime.Caller(1)
	if !ok {
		ERROR.Println("Failed to get Caller information")
	}

	// Get the extra RenderArgs passed in.
	if renderArgNames, ok := c.MethodType.RenderArgNames[line]; ok {
		if len(renderArgNames) == len(extraRenderArgs) {
			for i, extraRenderArg := range extraRenderArgs {
				c.RenderArgs[renderArgNames[i]] = extraRenderArg
			}
		} else {
			ERROR.Println(len(renderArgNames), "RenderArg names found for",
				len(extraRenderArgs), "extra RenderArgs")
		}
	} else {
		ERROR.Println("No RenderArg names found for Render call on line", line,
			"(Method", c.MethodType.Name, ")")
	}

	return c.RenderTemplate(c.Name + "/" + c.MethodType.Name + "." + c.Request.Format)
}

// A less magical way to render a template.
// Renders the given template, using the current RenderArgs.
func (c *Controller) RenderTemplate(templatePath string) Result {

	// Get the Template.
	template, err := MainTemplateLoader.Template(templatePath)
	if err != nil {
		return c.RenderError(err)
	}

	return &RenderTemplateResult{
		Template:   template,
		RenderArgs: c.RenderArgs,
	}
}

// Uses encoding/json.Marshal to return JSON to the client.
func (c *Controller) RenderJson(o interface{}) Result {
	return RenderJsonResult{o, ""}
}

// Renders a JSONP result using encoding/json.Marshal
func (c *Controller) RenderJsonP(callback string, o interface{}) Result {
	return RenderJsonResult{o, callback}
}

// Uses encoding/xml.Marshal to return XML to the client.
func (c *Controller) RenderXml(o interface{}) Result {
	return RenderXmlResult{o}
}

// Render plaintext in response, printf style.
func (c *Controller) RenderText(text string, objs ...interface{}) Result {
	finalText := text
	if len(objs) > 0 {
		finalText = fmt.Sprintf(text, objs...)
	}
	return &RenderTextResult{finalText}
}

// Render html in response
func (c *Controller) RenderHtml(html string) Result {
	return &RenderHtmlResult{html}
}

// Render a "todo" indicating that the action isn't done yet.
func (c *Controller) Todo() Result {
	c.Response.Status = http.StatusNotImplemented
	return c.RenderError(&Error{
		Title:       "TODO",
		Description: "This action is not implemented",
	})
}

func (c *Controller) NotFound(msg string, objs ...interface{}) Result {
	finalText := msg
	if len(objs) > 0 {
		finalText = fmt.Sprintf(msg, objs...)
	}
	c.Response.Status = http.StatusNotFound
	return c.RenderError(&Error{
		Title:       "Not Found",
		Description: finalText,
	})
}

func (c *Controller) Forbidden(msg string, objs ...interface{}) Result {
	finalText := msg
	if len(objs) > 0 {
		finalText = fmt.Sprintf(msg, objs...)
	}
	c.Response.Status = http.StatusForbidden
	return c.RenderError(&Error{
		Title:       "Forbidden",
		Description: finalText,
	})
}

// Return a file, either displayed inline or downloaded as an attachment.
// The name and size are taken from the file info.
func (c *Controller) RenderFile(file *os.File, delivery ContentDisposition) Result {
	var (
		modtime       = time.Now()
		fileInfo, err = file.Stat()
	)
	if err != nil {
		WARN.Println("RenderFile error:", err)
	}
	if fileInfo != nil {
		modtime = fileInfo.ModTime()
	}
	return c.RenderBinary(file, filepath.Base(file.Name()), delivery, modtime)
}

// RenderBinary is like RenderFile() except that it instead of a file on disk,
// it renders data from memory (which could be a file that has not been written,
// the output from some function, or bytes streamed from somewhere else, as long
// it implements io.Reader).  When called directly on something generated or
// streamed, modtime should mostly likely be time.Now().
func (c *Controller) RenderBinary(memfile io.Reader, filename string, delivery ContentDisposition, modtime time.Time) Result {
	return &BinaryResult{
		Reader:   memfile,
		Name:     filename,
		Delivery: delivery,
		Length:   -1, // http.ServeContent gets the length itself unless memfile is a stream.
		ModTime:  modtime,
	}
}

// Redirect to an action or to a URL.
//   c.Redirect(Controller.Action)
//   c.Redirect("/controller/action")
//   c.Redirect("/controller/%d/action", id)
func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
	if url, ok := val.(string); ok {
		if len(args) == 0 {
			return &RedirectToUrlResult{url}
		}
		return &RedirectToUrlResult{fmt.Sprintf(url, args...)}
	}
	return &RedirectToActionResult{val}
}

// Perform a message lookup for the given message name using the given arguments
// using the current language defined for this controller.
//
// The current language is set by the i18n plugin.
func (c *Controller) Message(message string, args ...interface{}) (value string) {
	return Message(c.Request.Locale, message, args...)
}

// SetAction sets the action that is being invoked in the current request.
// It sets the following properties: Name, Action, Type, MethodType
func (c *Controller) SetAction(controllerName, methodName string) error {

	// Look up the controller and method types.
	var ok bool
	if c.Type, ok = controllers[strings.ToLower(controllerName)]; !ok {
		return errors.New("revel/controller: failed to find controller " + controllerName)
	}
	if c.MethodType = c.Type.Method(methodName); c.MethodType == nil {
		return errors.New("revel/controller: failed to find action " + methodName)
	}

	c.Name, c.MethodName = c.Type.Type.Name(), methodName
	c.Action = c.Name + "." + c.MethodName

	// Instantiate the controller.
	c.AppController = initNewAppController(c.Type, c).Interface()

	return nil
}

// This is a helper that initializes (zeros) a new app controller value.
// Specifically, it sets all *revel.Controller embedded types to the provided controller.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType *ControllerType, c *Controller) reflect.Value {
	var (
		appControllerPtr = reflect.New(appControllerType.Type)
		appController    = appControllerPtr.Elem()
		cValue           = reflect.ValueOf(c)
	)
	for _, index := range appControllerType.ControllerIndexes {
		appController.FieldByIndex(index).Set(cValue)
	}
	return appControllerPtr
}

func findControllers(appControllerType reflect.Type) (indexes [][]int) {
	// It might be a multi-level embedding. To find the controllers, we follow
	// every anonymous field, using breadth-first search.
	type nodeType struct {
		val   reflect.Value
		index []int
	}
	appControllerPtr := reflect.New(appControllerType)
	queue := []nodeType{{appControllerPtr, []int{}}}
	for len(queue) > 0 {
		// Get the next value and de-reference it if necessary.
		var (
			node     = queue[0]
			elem     = node.val
			elemType = elem.Type()
		)
		if elemType.Kind() == reflect.Ptr {
			elem = elem.Elem()
			elemType = elem.Type()
		}
		queue = queue[1:]

		// Look at all the struct fields.
		for i := 0; i < elem.NumField(); i++ {
			// If this is not an anonymous field, skip it.
			structField := elemType.Field(i)
			if !structField.Anonymous {
				continue
			}

			fieldValue := elem.Field(i)
			fieldType := structField.Type

			// If it's a Controller, record the field indexes to get here.
			if fieldType == controllerPtrType {
				indexes = append(indexes, append(node.index, i))
				continue
			}

			queue = append(queue,
				nodeType{fieldValue, append(append([]int{}, node.index...), i)})
		}
	}
	return
}

// Controller registry and types.

type ControllerType struct {
	Type              reflect.Type
	Methods           []*MethodType
	ControllerIndexes [][]int // FieldByIndex to all embedded *Controllers
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	lowerName      string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

// Searches for a given exported method (case insensitive)
func (ct *ControllerType) Method(name string) *MethodType {
	lowerName := strings.ToLower(name)
	for _, method := range ct.Methods {
		if method.lowerName == lowerName {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

// Register a Controller and its Methods with Revel.
func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		m.lowerName = strings.ToLower(m.Name)
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[strings.ToLower(elem.Name())] = &ControllerType{
		Type:              elem,
		Methods:           methods,
		ControllerIndexes: findControllers(elem),
	}
	TRACE.Printf("Registered controller: %s", elem.Name())
}
<commit_msg>#428: improve error information when render failed<commit_after>package revel

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"time"
)

type Controller struct {
	Name          string          // The controller name, e.g. "Application"
	Type          *ControllerType // A description of the controller type.
	MethodName    string          // The method name, e.g. "Index"
	MethodType    *MethodType     // A description of the invoked action type.
	AppController interface{}     // The controller that was instantiated.
	Action        string          // The fully qualified action name, e.g. "App.Index"

	Request  *Request
	Response *Response
	Result   Result

	Flash      Flash                  // User cookie, cleared after 1 request.
	Session    Session                // Session, stored in cookie, signed.
	Params     *Params                // Parameters from URL and form (including multipart).
	Args       map[string]interface{} // Per-request scratch space.
	RenderArgs map[string]interface{} // Args passed to the template.
	Validation *Validation            // Data validation helpers
}

func NewController(req *Request, resp *Response) *Controller {
	return &Controller{
		Request:  req,
		Response: resp,
		Params:   new(Params),
		Args:     map[string]interface{}{},
		RenderArgs: map[string]interface{}{
			"RunMode": RunMode,
			"DevMode": DevMode,
		},
	}
}

func (c *Controller) FlashParams() {
	for key, vals := range c.Params.Values {
		c.Flash.Out[key] = strings.Join(vals, ",")
	}
}

func (c *Controller) SetCookie(cookie *http.Cookie) {
	http.SetCookie(c.Response.Out, cookie)
}

func (c *Controller) RenderError(err error) Result {
	return ErrorResult{c.RenderArgs, err}
}

// Render a template corresponding to the calling Controller method.
// Arguments will be added to c.RenderArgs prior to rendering the template.
// They are keyed on their local identifier.
//
// For example:
//
//     func (c Users) ShowUser(id int) revel.Result {
//     	 user := loadUser(id)
//     	 return c.Render(user)
//     }
//
// This action will render views/Users/ShowUser.html, passing in an extra
// key-value "user": (User).
func (c *Controller) Render(extraRenderArgs ...interface{}) Result {
	// Get the calling function name.
	_, _, line, ok := runtime.Caller(1)
	if !ok {
		ERROR.Println("Failed to get Caller information")
	}

	// Get the extra RenderArgs passed in.
	if renderArgNames, ok := c.MethodType.RenderArgNames[line]; ok {
		if len(renderArgNames) == len(extraRenderArgs) {
			for i, extraRenderArg := range extraRenderArgs {
				c.RenderArgs[renderArgNames[i]] = extraRenderArg
			}
		} else {
			ERROR.Println(len(renderArgNames), "RenderArg names found for",
				len(extraRenderArgs), "extra RenderArgs")
		}
	} else {
		ERROR.Println("No RenderArg names found for Render call on line", line,
			"(Action", c.Action, ")")
	}

	return c.RenderTemplate(c.Name + "/" + c.MethodType.Name + "." + c.Request.Format)
}

// A less magical way to render a template.
// Renders the given template, using the current RenderArgs.
func (c *Controller) RenderTemplate(templatePath string) Result {

	// Get the Template.
	template, err := MainTemplateLoader.Template(templatePath)
	if err != nil {
		return c.RenderError(err)
	}

	return &RenderTemplateResult{
		Template:   template,
		RenderArgs: c.RenderArgs,
	}
}

// Uses encoding/json.Marshal to return JSON to the client.
func (c *Controller) RenderJson(o interface{}) Result {
	return RenderJsonResult{o, ""}
}

// Renders a JSONP result using encoding/json.Marshal
func (c *Controller) RenderJsonP(callback string, o interface{}) Result {
	return RenderJsonResult{o, callback}
}

// Uses encoding/xml.Marshal to return XML to the client.
func (c *Controller) RenderXml(o interface{}) Result {
	return RenderXmlResult{o}
}

// Render plaintext in response, printf style.
func (c *Controller) RenderText(text string, objs ...interface{}) Result {
	finalText := text
	if len(objs) > 0 {
		finalText = fmt.Sprintf(text, objs...)
	}
	return &RenderTextResult{finalText}
}

// Render html in response
func (c *Controller) RenderHtml(html string) Result {
	return &RenderHtmlResult{html}
}

// Render a "todo" indicating that the action isn't done yet.
func (c *Controller) Todo() Result {
	c.Response.Status = http.StatusNotImplemented
	return c.RenderError(&Error{
		Title:       "TODO",
		Description: "This action is not implemented",
	})
}

func (c *Controller) NotFound(msg string, objs ...interface{}) Result {
	finalText := msg
	if len(objs) > 0 {
		finalText = fmt.Sprintf(msg, objs...)
	}
	c.Response.Status = http.StatusNotFound
	return c.RenderError(&Error{
		Title:       "Not Found",
		Description: finalText,
	})
}

func (c *Controller) Forbidden(msg string, objs ...interface{}) Result {
	finalText := msg
	if len(objs) > 0 {
		finalText = fmt.Sprintf(msg, objs...)
	}
	c.Response.Status = http.StatusForbidden
	return c.RenderError(&Error{
		Title:       "Forbidden",
		Description: finalText,
	})
}

// Return a file, either displayed inline or downloaded as an attachment.
// The name and size are taken from the file info.
func (c *Controller) RenderFile(file *os.File, delivery ContentDisposition) Result {
	var (
		modtime       = time.Now()
		fileInfo, err = file.Stat()
	)
	if err != nil {
		WARN.Println("RenderFile error:", err)
	}
	if fileInfo != nil {
		modtime = fileInfo.ModTime()
	}
	return c.RenderBinary(file, filepath.Base(file.Name()), delivery, modtime)
}

// RenderBinary is like RenderFile() except that it instead of a file on disk,
// it renders data from memory (which could be a file that has not been written,
// the output from some function, or bytes streamed from somewhere else, as long
// it implements io.Reader).  When called directly on something generated or
// streamed, modtime should mostly likely be time.Now().
func (c *Controller) RenderBinary(memfile io.Reader, filename string, delivery ContentDisposition, modtime time.Time) Result {
	return &BinaryResult{
		Reader:   memfile,
		Name:     filename,
		Delivery: delivery,
		Length:   -1, // http.ServeContent gets the length itself unless memfile is a stream.
		ModTime:  modtime,
	}
}

// Redirect to an action or to a URL.
//   c.Redirect(Controller.Action)
//   c.Redirect("/controller/action")
//   c.Redirect("/controller/%d/action", id)
func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
	if url, ok := val.(string); ok {
		if len(args) == 0 {
			return &RedirectToUrlResult{url}
		}
		return &RedirectToUrlResult{fmt.Sprintf(url, args...)}
	}
	return &RedirectToActionResult{val}
}

// Perform a message lookup for the given message name using the given arguments
// using the current language defined for this controller.
//
// The current language is set by the i18n plugin.
func (c *Controller) Message(message string, args ...interface{}) (value string) {
	return Message(c.Request.Locale, message, args...)
}

// SetAction sets the action that is being invoked in the current request.
// It sets the following properties: Name, Action, Type, MethodType
func (c *Controller) SetAction(controllerName, methodName string) error {

	// Look up the controller and method types.
	var ok bool
	if c.Type, ok = controllers[strings.ToLower(controllerName)]; !ok {
		return errors.New("revel/controller: failed to find controller " + controllerName)
	}
	if c.MethodType = c.Type.Method(methodName); c.MethodType == nil {
		return errors.New("revel/controller: failed to find action " + methodName)
	}

	c.Name, c.MethodName = c.Type.Type.Name(), methodName
	c.Action = c.Name + "." + c.MethodName

	// Instantiate the controller.
	c.AppController = initNewAppController(c.Type, c).Interface()

	return nil
}

// This is a helper that initializes (zeros) a new app controller value.
// Specifically, it sets all *revel.Controller embedded types to the provided controller.
// Returns a value representing a pointer to the new app controller.
func initNewAppController(appControllerType *ControllerType, c *Controller) reflect.Value {
	var (
		appControllerPtr = reflect.New(appControllerType.Type)
		appController    = appControllerPtr.Elem()
		cValue           = reflect.ValueOf(c)
	)
	for _, index := range appControllerType.ControllerIndexes {
		appController.FieldByIndex(index).Set(cValue)
	}
	return appControllerPtr
}

func findControllers(appControllerType reflect.Type) (indexes [][]int) {
	// It might be a multi-level embedding. To find the controllers, we follow
	// every anonymous field, using breadth-first search.
	type nodeType struct {
		val   reflect.Value
		index []int
	}
	appControllerPtr := reflect.New(appControllerType)
	queue := []nodeType{{appControllerPtr, []int{}}}
	for len(queue) > 0 {
		// Get the next value and de-reference it if necessary.
		var (
			node     = queue[0]
			elem     = node.val
			elemType = elem.Type()
		)
		if elemType.Kind() == reflect.Ptr {
			elem = elem.Elem()
			elemType = elem.Type()
		}
		queue = queue[1:]

		// Look at all the struct fields.
		for i := 0; i < elem.NumField(); i++ {
			// If this is not an anonymous field, skip it.
			structField := elemType.Field(i)
			if !structField.Anonymous {
				continue
			}

			fieldValue := elem.Field(i)
			fieldType := structField.Type

			// If it's a Controller, record the field indexes to get here.
			if fieldType == controllerPtrType {
				indexes = append(indexes, append(node.index, i))
				continue
			}

			queue = append(queue,
				nodeType{fieldValue, append(append([]int{}, node.index...), i)})
		}
	}
	return
}

// Controller registry and types.

type ControllerType struct {
	Type              reflect.Type
	Methods           []*MethodType
	ControllerIndexes [][]int // FieldByIndex to all embedded *Controllers
}

type MethodType struct {
	Name           string
	Args           []*MethodArg
	RenderArgNames map[int][]string
	lowerName      string
}

type MethodArg struct {
	Name string
	Type reflect.Type
}

// Searches for a given exported method (case insensitive)
func (ct *ControllerType) Method(name string) *MethodType {
	lowerName := strings.ToLower(name)
	for _, method := range ct.Methods {
		if method.lowerName == lowerName {
			return method
		}
	}
	return nil
}

var controllers = make(map[string]*ControllerType)

// Register a Controller and its Methods with Revel.
func RegisterController(c interface{}, methods []*MethodType) {
	// De-star the controller type
	// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
	var t reflect.Type = reflect.TypeOf(c)
	var elem reflect.Type = t.Elem()

	// De-star all of the method arg types too.
	for _, m := range methods {
		m.lowerName = strings.ToLower(m.Name)
		for _, arg := range m.Args {
			arg.Type = arg.Type.Elem()
		}
	}

	controllers[strings.ToLower(elem.Name())] = &ControllerType{
		Type:              elem,
		Methods:           methods,
		ControllerIndexes: findControllers(elem),
	}
	TRACE.Printf("Registered controller: %s", elem.Name())
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/swarmd/backends"
	"github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"os"
	"strings"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	// Load backend
	// FIXME: allow for multiple backends to be loaded.
	// This could be done by instantiating 1 engine per backend,
	// installing each backend in its respective engine,
	// then registering a Catchall on the frontent engine which
	// multiplexes across all backends (with routing / filtering
	// logic along the way).
	back := backends.New()
	backendName := c.String("backend")
	fmt.Printf("Loading backend '%s'\n", backendName)
	if err := back.Job(backendName).Run(); err != nil {
		Fatalf("%s: %v\n", backendName, err)
	}

	// Register the API entrypoint
	// (we register it as `argv[0]` so we can print usage messages straight from the job
	// stderr.
	front := engine.New()
	front.Logging = false
	// FIXME: server should expose an engine.Installer
	front.Register(c.App.Name, server.ServeApi)
	front.RegisterCatchall(func(job *engine.Job) engine.Status {
		fw := back.Job(job.Name, job.Args...)
		fw.Run()
		return engine.Status(fw.StatusCode())
	})

	// Call the API entrypoint
	go func() {
		serve := front.Job(c.App.Name, c.Args()...)
		serve.Stdout.Add(os.Stdout)
		serve.Stderr.Add(os.Stderr)
		if err := serve.Run(); err != nil {
			Fatalf("serveapi: %v", err)
		}
	}()
	// There is a race condition in engine.ServeApi.
	// As a workaround we sleep to give it time to register 'acceptconnections'.
	time.Sleep(1 * time.Second)
	// Notify that we're ready to receive connections
	if err := front.Job("acceptconnections").Run(); err != nil {
		Fatalf("acceptconnections: %v", err)
	}
	// Inifinite loop
	<-make(chan struct{})
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<commit_msg>Backends can receive arguments<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/swarmd/backends"
	"github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"strings"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	// Load backend
	// FIXME: allow for multiple backends to be loaded.
	// This could be done by instantiating 1 engine per backend,
	// installing each backend in its respective engine,
	// then registering a Catchall on the frontent engine which
	// multiplexes across all backends (with routing / filtering
	// logic along the way).
	back := backends.New()
	bName, bArgs, err := parseCmd(c.String("backend"))
	if err != nil {
		Fatalf("%v", err)
	}
	fmt.Printf("---> Loading backend '%s'\n", strings.Join(append([]string{bName}, bArgs...), " "))
	if err := back.Job(bName, bArgs...).Run(); err != nil {
		Fatalf("%s: %v\n", bName, err)
	}

	// Register the API entrypoint
	// (we register it as `argv[0]` so we can print usage messages straight from the job
	// stderr.
	front := engine.New()
	front.Logging = false
	// FIXME: server should expose an engine.Installer
	front.Register(c.App.Name, server.ServeApi)
	front.RegisterCatchall(func(job *engine.Job) engine.Status {
		fw := back.Job(job.Name, job.Args...)
		fw.Run()
		return engine.Status(fw.StatusCode())
	})

	// Call the API entrypoint
	go func() {
		serve := front.Job(c.App.Name, c.Args()...)
		serve.Stdout.Add(os.Stdout)
		serve.Stderr.Add(os.Stderr)
		if err := serve.Run(); err != nil {
			Fatalf("serveapi: %v", err)
		}
	}()
	// There is a race condition in engine.ServeApi.
	// As a workaround we sleep to give it time to register 'acceptconnections'.
	time.Sleep(1 * time.Second)
	// Notify that we're ready to receive connections
	if err := front.Job("acceptconnections").Run(); err != nil {
		Fatalf("acceptconnections: %v", err)
	}
	// Inifinite loop
	<-make(chan struct{})
}

func parseCmd(txt string) (string, []string, error) {
	l, err := shlex.NewLexer(strings.NewReader(txt))
	if err != nil {
		return "", nil, err
	}
	var cmd []string
	for {
		word, err := l.NextWord()
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", nil, err
		}
		cmd = append(cmd, word)
	}
	if len(cmd) == 0 {
		return "", nil, fmt.Errorf("parse error: empty command")
	}
	return cmd[0], cmd[1:], nil
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package turms

import (
	"github.com/ugorji/go/codec"
	"golang.org/x/net/context"
	"net"
	"sync"
	"time"
)

// A Conn represents a connection between two Peers.
type Conn interface {
	Read(context.Context) (Message, error)
	Send(context.Context, Message) error
	Close() error
}

type conn struct {
	conn net.Conn
	mr   *messageReader
	dec  *codec.Decoder
	enc  *codec.Encoder
	rmu  sync.Mutex
	wmu  sync.Mutex
}

// NewConn wraps a net.Conn
func NewConn(c net.Conn, h codec.Handle) Conn {
	mr := newMessageReader(c, 1024)
	// Force DecodeOptions.ErrorIfNoArrayExpand = false
	switch handle := h.(type) {
	case *codec.JsonHandle:
		handle.DecodeOptions.ErrorIfNoArrayExpand = false
		handle.EncodeOptions.StructToArray = true
	case *codec.MsgpackHandle:
		handle.DecodeOptions.ErrorIfNoArrayExpand = false
		handle.EncodeOptions.StructToArray = true
	}
	return &conn{
		conn: c,
		mr:   mr,
		dec:  codec.NewDecoder(mr, h),
		enc:  codec.NewEncoder(c, h),
	}
}

func (c *conn) Close() error {
	return c.conn.Close()
}

func (c *conn) Send(ctx context.Context, msg Message) error {
	res := make(chan error, 1)
	go func() {
		c.wmu.Lock()
		defer c.wmu.Unlock()
		err := c.enc.Encode(msg)
		res <- err
	}()
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-res:
		return err
	}
}

func (c *conn) Read(ctx context.Context) (Message, error) {
	type msgAndErr struct {
		msg Message
		err error
	}
	res := make(chan msgAndErr, 1)

	go func() {
		c.rmu.Lock()
		defer c.rmu.Unlock()

		var msgTyp [1]MessageType
		err := c.dec.Decode(&msgTyp)
		if err != nil {
			res <- msgAndErr{msg: nil, err: err}
			return
		}
		c.mr.ResetRead()
		msg := NewMessage(msgTyp[0])
		err = c.dec.Decode(msg)
		res <- msgAndErr{msg: msg, err: err}
		c.mr.Reset()
	}()

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case r := <-res:
		return r.msg, r.err
	}
}

func waitForMessage(parentCtx context.Context, c Conn, duration time.Duration) (Message, error) {
	ctx, cancel := context.WithTimeout(parentCtx, duration)
	defer cancel()
	return c.Read(ctx)
}
<commit_msg>reset message reader in conn.read before sending the value through channel, avoids the use of mutexes. Conn.Read and Conn.Write are not safe for concurrent use.<commit_after>package turms

import (
	"github.com/ugorji/go/codec"
	"golang.org/x/net/context"
	"net"
	"time"
)

// A Conn represents a connection between two Peers.
type Conn interface {
	Read(context.Context) (Message, error)
	Send(context.Context, Message) error
	Close() error
}

type conn struct {
	conn net.Conn
	mr   *messageReader
	dec  *codec.Decoder
	enc  *codec.Encoder
}

// NewConn wraps a net.Conn
func NewConn(c net.Conn, h codec.Handle) Conn {
	mr := newMessageReader(c, 1024)
	// Force DecodeOptions.ErrorIfNoArrayExpand = false
	// and DecodeOptions.StructToArray = true
	switch handle := h.(type) {
	case *codec.JsonHandle:
		handle.DecodeOptions.ErrorIfNoArrayExpand = false
		handle.EncodeOptions.StructToArray = true
	case *codec.MsgpackHandle:
		handle.DecodeOptions.ErrorIfNoArrayExpand = false
		handle.EncodeOptions.StructToArray = true
	}
	return &conn{
		conn: c,
		mr:   mr,
		dec:  codec.NewDecoder(mr, h),
		enc:  codec.NewEncoder(c, h),
	}
}

func (c *conn) Close() error {
	return c.conn.Close()
}

func (c *conn) Send(ctx context.Context, msg Message) error {
	res := make(chan error, 1)
	go func() {
		err := c.enc.Encode(msg)
		res <- err
	}()
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-res:
		return err
	}
}

func (c *conn) Read(ctx context.Context) (Message, error) {
	type msgAndErr struct {
		msg Message
		err error
	}
	res := make(chan msgAndErr, 1)

	go func() {
		var msgTyp [1]MessageType
		err := c.dec.Decode(&msgTyp)
		c.mr.ResetRead()
		if err != nil {
			res <- msgAndErr{msg: nil, err: err}
			return
		}
		msg := NewMessage(msgTyp[0])
		err = c.dec.Decode(msg)
		c.mr.Reset()
		res <- msgAndErr{msg: msg, err: err}
	}()

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case r := <-res:
		return r.msg, r.err
	}
}

func waitForMessage(parentCtx context.Context, c Conn, duration time.Duration) (Message, error) {
	ctx, cancel := context.WithTimeout(parentCtx, duration)
	defer cancel()
	return c.Read(ctx)
}
<|endoftext|>


<commit_before>package gosocks5

import (
	"io"
	//"log"
	"net"
	"sync"
	"time"
)

type Config struct {
	Methods        []uint8
	SelectMethod   func(methods ...uint8) uint8
	MethodSelected func(method uint8, conn net.Conn) (net.Conn, error)
}

func defaultConfig() *Config {
	return &Config{}
}

type Conn struct {
	c              net.Conn
	config         *Config
	method         uint8
	isClient       bool
	handshaked     bool
	handshakeMutex sync.Mutex
	handshakeErr   error
}

func ClientConn(conn net.Conn, config *Config) *Conn {
	return &Conn{
		c:        conn,
		config:   config,
		isClient: true,
	}
}

func ServerConn(conn net.Conn, config *Config) *Conn {
	return &Conn{
		c:      conn,
		config: config,
	}
}

func (conn *Conn) Handleshake() error {
	conn.handshakeMutex.Lock()
	defer conn.handshakeMutex.Unlock()

	if err := conn.handshakeErr; err != nil {
		return err
	}
	if conn.handshaked {
		return nil
	}

	if conn.isClient {
		conn.handshakeErr = conn.clientHandshake()
	} else {
		conn.handshakeErr = conn.serverHandshake()
	}

	return conn.handshakeErr
}

func (conn *Conn) clientHandshake() error {
	if conn.config == nil {
		conn.config = defaultConfig()
	}

	nm := len(conn.config.Methods)
	if nm == 0 {
		nm = 1
	}

	b := make([]byte, 2+nm)
	b[0] = Ver5
	b[1] = uint8(nm)
	copy(b[2:], conn.config.Methods)

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

	if _, err := io.ReadFull(conn.c, b[:2]); err != nil {
		return err
	}

	if b[0] != Ver5 {
		return ErrBadVersion
	}

	if conn.config.MethodSelected != nil {
		c, err := conn.config.MethodSelected(b[1], conn.c)
		if err != nil {
			return err
		}
		conn.c = c
	}
	conn.method = b[1]
	//log.Println("method:", conn.method)
	conn.handshaked = true
	return nil
}

func (conn *Conn) serverHandshake() error {
	if conn.config == nil {
		conn.config = defaultConfig()
	}

	methods, err := ReadMethods(conn.c)
	if err != nil {
		return err
	}

	method := MethodNoAuth
	if conn.config.SelectMethod != nil {
		method = conn.config.SelectMethod(methods...)
	}

	if _, err := conn.c.Write([]byte{Ver5, method}); err != nil {
		return err
	}

	if conn.config.MethodSelected != nil {
		c, err := conn.config.MethodSelected(method, conn.c)
		if err != nil {
			return err
		}
		conn.c = c
	}
	conn.method = method
	//log.Println("method:", method)
	conn.handshaked = true
	return nil
}

func (conn *Conn) Read(b []byte) (n int, err error) {
	if err = conn.Handleshake(); err != nil {
		return
	}
	return conn.c.Read(b)
}

func (conn *Conn) Write(b []byte) (n int, err error) {
	if err = conn.Handleshake(); err != nil {
		return
	}
	return conn.c.Write(b)
}

func (conn *Conn) Close() error {
	return conn.c.Close()
}

func (conn *Conn) LocalAddr() net.Addr {
	return conn.c.LocalAddr()
}

func (conn *Conn) RemoteAddr() net.Addr {
	return conn.c.RemoteAddr()
}

func (conn *Conn) SetDeadline(t time.Time) error {
	return conn.c.SetDeadline(t)
}

func (conn *Conn) SetReadDeadline(t time.Time) error {
	return conn.c.SetReadDeadline(t)
}

func (conn *Conn) SetWriteDeadline(t time.Time) error {
	return conn.c.SetWriteDeadline(t)
}
<commit_msg>add Selector interface<commit_after>package gosocks5

import (
	"io"
	//"log"
	"net"
	"sync"
	"time"
)

type Selector interface {
	// return supported methods
	Methods() []uint8
	// select method
	Select(methods ...uint8) (method uint8)
	// on method selected
	OnSelected(method uint8, conn net.Conn) (net.Conn, error)
}

type Conn struct {
	c              net.Conn
	selector       Selector
	method         uint8
	isClient       bool
	handshaked     bool
	handshakeMutex sync.Mutex
	handshakeErr   error
}

func ClientConn(conn net.Conn, selector Selector) *Conn {
	return &Conn{
		c:        conn,
		selector: selector,
		isClient: true,
	}
}

func ServerConn(conn net.Conn, selector Selector) *Conn {
	return &Conn{
		c:        conn,
		selector: selector,
	}
}

func (conn *Conn) Handleshake() error {
	conn.handshakeMutex.Lock()
	defer conn.handshakeMutex.Unlock()

	if err := conn.handshakeErr; err != nil {
		return err
	}
	if conn.handshaked {
		return nil
	}

	if conn.isClient {
		conn.handshakeErr = conn.clientHandshake()
	} else {
		conn.handshakeErr = conn.serverHandshake()
	}

	return conn.handshakeErr
}

func (conn *Conn) clientHandshake() error {
	var methods []uint8
	var nm int

	if conn.selector != nil {
		methods = conn.selector.Methods()
	}
	nm = len(methods)
	if nm == 0 {
		nm = 1
	}

	b := make([]byte, 2+nm)
	b[0] = Ver5
	b[1] = uint8(nm)
	copy(b[2:], methods)

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

	if _, err := io.ReadFull(conn.c, b[:2]); err != nil {
		return err
	}

	if b[0] != Ver5 {
		return ErrBadVersion
	}

	if conn.selector != nil {
		c, err := conn.selector.OnSelected(b[1], conn.c)
		if err != nil {
			return err
		}
		conn.c = c
	}
	conn.method = b[1]
	//log.Println("method:", conn.method)
	conn.handshaked = true
	return nil
}

func (conn *Conn) serverHandshake() error {
	methods, err := ReadMethods(conn.c)
	if err != nil {
		return err
	}

	method := MethodNoAuth
	if conn.selector != nil {
		method = conn.selector.Select(methods...)
	}

	if _, err := conn.c.Write([]byte{Ver5, method}); err != nil {
		return err
	}

	if conn.selector != nil {
		c, err := conn.selector.OnSelected(method, conn.c)
		if err != nil {
			return err
		}
		conn.c = c
	}
	conn.method = method
	//log.Println("method:", method)
	conn.handshaked = true
	return nil
}

func (conn *Conn) Read(b []byte) (n int, err error) {
	if err = conn.Handleshake(); err != nil {
		return
	}
	return conn.c.Read(b)
}

func (conn *Conn) Write(b []byte) (n int, err error) {
	if err = conn.Handleshake(); err != nil {
		return
	}
	return conn.c.Write(b)
}

func (conn *Conn) Close() error {
	return conn.c.Close()
}

func (conn *Conn) LocalAddr() net.Addr {
	return conn.c.LocalAddr()
}

func (conn *Conn) RemoteAddr() net.Addr {
	return conn.c.RemoteAddr()
}

func (conn *Conn) SetDeadline(t time.Time) error {
	return conn.c.SetDeadline(t)
}

func (conn *Conn) SetReadDeadline(t time.Time) error {
	return conn.c.SetReadDeadline(t)
}

func (conn *Conn) SetWriteDeadline(t time.Time) error {
	return conn.c.SetWriteDeadline(t)
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"
)

type Err interface {
	error
	Region() string
	Service() string
}

func NewAPIError(e error, region string, service string) Err {
	return &callErr{
		err:     e,
		region:  region,
		service: service,
	}
}

func (r *RawsErr) AppendError(regionErr string, serviceErr string, originErr error) {
	if originErr != nil {
		r.APIErrs = append(r.APIErrs, callErr{
			region:  regionErr,
			service: serviceErr,
			err:     originErr,
		})
	}
}

func (r RawsErr) Error() string {
	var output [][]string

	for _, callErr := range r.APIErrs {
		output = append(output, []string{callErr.region, callErr.service})
	}
	return fmt.Sprintf("%d error(s) occured: %s", len(r.APIErrs), output)
}

func (e *callErr) Error() string {
	return fmt.Sprintf("%s: error while using '%s' service - %s",
		e.region,
		e.service,
		e.err.Error())
}

func (e *callErr) Region() string {
	return e.region
}

func (e *callErr) Service() string {
	return e.service
}

type RawsErr struct {
	APIErrs []callErr
}

type callErr struct {
	err     error
	region  string
	service string
}
<commit_msg>error: bring RawsErr struct up, as it is exported<commit_after>package core

import (
	"fmt"
)

type Err interface {
	error
	Region() string
	Service() string
}

type RawsErr struct {
	APIErrs []callErr
}

func NewAPIError(e error, region string, service string) Err {
	return &callErr{
		err:     e,
		region:  region,
		service: service,
	}
}

func (r *RawsErr) AppendError(regionErr string, serviceErr string, originErr error) {
	if originErr != nil {
		r.APIErrs = append(r.APIErrs, callErr{
			region:  regionErr,
			service: serviceErr,
			err:     originErr,
		})
	}
}

func (r RawsErr) Error() string {
	var output [][]string

	for _, callErr := range r.APIErrs {
		output = append(output, []string{callErr.region, callErr.service})
	}
	return fmt.Sprintf("%d error(s) occured: %s", len(r.APIErrs), output)
}

func (e *callErr) Error() string {
	return fmt.Sprintf("%s: error while using '%s' service - %s",
		e.region,
		e.service,
		e.err.Error())
}

func (e *callErr) Region() string {
	return e.region
}

func (e *callErr) Service() string {
	return e.service
}

type callErr struct {
	err     error
	region  string
	service string
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	keybase_1 "github.com/keybase/client/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

type RemoteBaseIdentifyUI struct {
	sessionId int
	uicli     keybase_1.IdentifyUiClient
	logUI     libkb.LogUI
	strict    bool
}

type RemoteSelfIdentifyUI struct {
	RemoteBaseIdentifyUI
}

type IdentifyHandler struct {
	BaseHandler
}

func NewIdentifyHandler(xp *rpc2.Transport) *IdentifyHandler {
	return &IdentifyHandler{BaseHandler{xp: xp}}
}

func (h *IdentifyHandler) Identify(arg keybase_1.IdentifyArg) (keybase_1.IdentifyRes, error) {
	iarg := engine.ImportIdEngineArg(arg)
	res, err := h.identify(arg.SessionID, iarg, true)
	if err != nil {
		return keybase_1.IdentifyRes{}, err
	}
	return *(res.Export()), nil
}

func (h *IdentifyHandler) IdentifyDefault(arg keybase_1.IdentifyDefaultArg) (keybase_1.IdentifyRes, error) {
	iarg := engine.IdEngineArg{UserAssertion: arg.UserAssertion}
	res, err := h.identify(arg.SessionID, iarg, true)
	if err != nil {
		return keybase_1.IdentifyRes{}, err
	}
	return *(res.Export()), nil
}

func (h *IdentifyHandler) identify(sessionId int, iarg engine.IdEngineArg, doInteractive bool) (res *engine.IdRes, err error) {
	ctx := engine.Context{
		LogUI:      h.getLogUI(sessionId),
		IdentifyUI: h.NewRemoteIdentifyUI(sessionId),
	}
	eng := engine.NewIdEngine(&iarg)
	err = engine.RunEngine(eng, &ctx)
	res = eng.Result()
	return
}

var (
	__sessionId = 0
)

func nextSessionId() int {
	ret := __sessionId
	__sessionId++
	return ret
}

func (u *RemoteBaseIdentifyUI) FinishWebProofCheck(p keybase_1.RemoteProof, lcr keybase_1.LinkCheckResult) {
	u.uicli.FinishWebProofCheck(keybase_1.FinishWebProofCheckArg{
		SessionID: u.sessionId,
		Rp:        p,
		Lcr:       lcr,
	})
	return
}

func (u *RemoteBaseIdentifyUI) FinishSocialProofCheck(p keybase_1.RemoteProof, lcr keybase_1.LinkCheckResult) {
	u.uicli.FinishSocialProofCheck(keybase_1.FinishSocialProofCheckArg{
		SessionID: u.sessionId,
		Rp:        p,
		Lcr:       lcr,
	})
	return
}

func (u *RemoteBaseIdentifyUI) FinishAndPrompt(io *keybase_1.IdentifyOutcome) (keybase_1.FinishAndPromptRes, error) {
	return u.uicli.FinishAndPrompt(keybase_1.FinishAndPromptArg{SessionID: u.sessionId, Outcome: *io})
}

func (u *RemoteBaseIdentifyUI) DisplayCryptocurrency(c keybase_1.Cryptocurrency) {
	u.uicli.DisplayCryptocurrency(keybase_1.DisplayCryptocurrencyArg{SessionID: u.sessionId, C: c})
	return
}

func (u *RemoteBaseIdentifyUI) DisplayKey(k keybase_1.FOKID, d *keybase_1.TrackDiff) {
	u.uicli.DisplayKey(keybase_1.DisplayKeyArg{SessionID: u.sessionId, Fokid: k, Diff: d})
	return
}

func (u *RemoteBaseIdentifyUI) ReportLastTrack(t *keybase_1.TrackSummary) {
	u.uicli.ReportLastTrack(keybase_1.ReportLastTrackArg{SessionID: u.sessionId, Track: t})
	return
}

func (u *RemoteBaseIdentifyUI) DisplayTrackStatement(s string) error {
	return u.uicli.DisplayTrackStatement(keybase_1.DisplayTrackStatementArg{Stmt: s, SessionID: u.sessionId})
	// return
}

func (u *RemoteBaseIdentifyUI) LaunchNetworkChecks(id *keybase_1.Identity, user *keybase_1.User) {
	u.uicli.LaunchNetworkChecks(keybase_1.LaunchNetworkChecksArg{
		SessionID: u.sessionId,
		Id:        *id,
		User:      *user,
	})
	return
}

func (u *RemoteBaseIdentifyUI) Start(username string) {
	u.uicli.Start(keybase_1.StartArg{SessionID: u.sessionId, Username: username})
	return
}

func (u *RemoteBaseIdentifyUI) SetStrict(b bool) {
	u.strict = b
}

type RemoteIdentifyUI struct {
	RemoteBaseIdentifyUI
}
<commit_msg>using null logui for track statement<commit_after>package main

import (
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	keybase_1 "github.com/keybase/client/protocol/go"
	"github.com/maxtaco/go-framed-msgpack-rpc/rpc2"
)

type RemoteBaseIdentifyUI struct {
	sessionId int
	uicli     keybase_1.IdentifyUiClient
	logUI     libkb.LogUI
	strict    bool
}

type RemoteSelfIdentifyUI struct {
	RemoteBaseIdentifyUI
}

type IdentifyHandler struct {
	BaseHandler
}

func NewIdentifyHandler(xp *rpc2.Transport) *IdentifyHandler {
	return &IdentifyHandler{BaseHandler{xp: xp}}
}

func (h *IdentifyHandler) Identify(arg keybase_1.IdentifyArg) (keybase_1.IdentifyRes, error) {
	iarg := engine.ImportIdEngineArg(arg)
	res, err := h.identify(arg.SessionID, iarg, true)
	if err != nil {
		return keybase_1.IdentifyRes{}, err
	}
	return *(res.Export()), nil
}

func (h *IdentifyHandler) IdentifyDefault(arg keybase_1.IdentifyDefaultArg) (keybase_1.IdentifyRes, error) {
	iarg := engine.IdEngineArg{UserAssertion: arg.UserAssertion}
	res, err := h.identify(arg.SessionID, iarg, true)
	if err != nil {
		return keybase_1.IdentifyRes{}, err
	}
	return *(res.Export()), nil
}

func (h *IdentifyHandler) identify(sessionId int, iarg engine.IdEngineArg, doInteractive bool) (res *engine.IdRes, err error) {
	logui := h.getLogUI(sessionId)
	if iarg.TrackStatement {
		logui = libkb.NewNullLogger()
	}
	ctx := engine.Context{
		LogUI:      logui,
		IdentifyUI: h.NewRemoteIdentifyUI(sessionId),
	}
	eng := engine.NewIdEngine(&iarg)
	err = engine.RunEngine(eng, &ctx)
	res = eng.Result()
	return
}

var (
	__sessionId = 0
)

func nextSessionId() int {
	ret := __sessionId
	__sessionId++
	return ret
}

func (u *RemoteBaseIdentifyUI) FinishWebProofCheck(p keybase_1.RemoteProof, lcr keybase_1.LinkCheckResult) {
	u.uicli.FinishWebProofCheck(keybase_1.FinishWebProofCheckArg{
		SessionID: u.sessionId,
		Rp:        p,
		Lcr:       lcr,
	})
	return
}

func (u *RemoteBaseIdentifyUI) FinishSocialProofCheck(p keybase_1.RemoteProof, lcr keybase_1.LinkCheckResult) {
	u.uicli.FinishSocialProofCheck(keybase_1.FinishSocialProofCheckArg{
		SessionID: u.sessionId,
		Rp:        p,
		Lcr:       lcr,
	})
	return
}

func (u *RemoteBaseIdentifyUI) FinishAndPrompt(io *keybase_1.IdentifyOutcome) (keybase_1.FinishAndPromptRes, error) {
	return u.uicli.FinishAndPrompt(keybase_1.FinishAndPromptArg{SessionID: u.sessionId, Outcome: *io})
}

func (u *RemoteBaseIdentifyUI) DisplayCryptocurrency(c keybase_1.Cryptocurrency) {
	u.uicli.DisplayCryptocurrency(keybase_1.DisplayCryptocurrencyArg{SessionID: u.sessionId, C: c})
	return
}

func (u *RemoteBaseIdentifyUI) DisplayKey(k keybase_1.FOKID, d *keybase_1.TrackDiff) {
	u.uicli.DisplayKey(keybase_1.DisplayKeyArg{SessionID: u.sessionId, Fokid: k, Diff: d})
	return
}

func (u *RemoteBaseIdentifyUI) ReportLastTrack(t *keybase_1.TrackSummary) {
	u.uicli.ReportLastTrack(keybase_1.ReportLastTrackArg{SessionID: u.sessionId, Track: t})
	return
}

func (u *RemoteBaseIdentifyUI) DisplayTrackStatement(s string) error {
	return u.uicli.DisplayTrackStatement(keybase_1.DisplayTrackStatementArg{Stmt: s, SessionID: u.sessionId})
	// return
}

func (u *RemoteBaseIdentifyUI) LaunchNetworkChecks(id *keybase_1.Identity, user *keybase_1.User) {
	u.uicli.LaunchNetworkChecks(keybase_1.LaunchNetworkChecksArg{
		SessionID: u.sessionId,
		Id:        *id,
		User:      *user,
	})
	return
}

func (u *RemoteBaseIdentifyUI) Start(username string) {
	u.uicli.Start(keybase_1.StartArg{SessionID: u.sessionId, Username: username})
	return
}

func (u *RemoteBaseIdentifyUI) SetStrict(b bool) {
	u.strict = b
}

type RemoteIdentifyUI struct {
	RemoteBaseIdentifyUI
}
<|endoftext|>


<commit_before>package vsock

import (
	"crypto/tls"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/mdlayher/vsock"

	"github.com/lxc/lxd/shared"
)

// Dial connects to a remote vsock.
func Dial(cid, port uint32) (net.Conn, error) {
	return vsock.Dial(cid, port, nil)
}

// Listen listens for a connection.
func Listen(port uint32) (net.Listener, error) {
	return vsock.Listen(port, nil)
}

// HTTPClient provides an HTTP client for using over vsock.
func HTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, tlsServerCert string) (*http.Client, error) {
	client := &http.Client{}

	// Get the TLS configuration.
	tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, "", tlsServerCert, false)
	if err != nil {
		return nil, err
	}

	client.Transport = &http.Transport{
		TLSClientConfig: tlsConfig,
		// Setup a VM socket dialer.
		Dial: func(network, addr string) (net.Conn, error) {
			var conn net.Conn
			var err error

			// Retry for up to 1s at 100ms interval to handle various failures.
			for i := 0; i < 10; i++ {
				conn, err = Dial(uint32(vsockID), shared.HTTPSDefaultPort)
				if err == nil {
					break
				} else {
					// Handle some fatal errors.
					msg := err.Error()
					if strings.Contains(msg, "connection timed out") {
						// Retry once.
						conn, err = Dial(uint32(vsockID), shared.HTTPSDefaultPort)
						break
					} else if strings.Contains(msg, "connection refused") {
						break
					}

					// Retry the rest.
				}

				time.Sleep(100 * time.Millisecond)
			}
			if err != nil {
				return nil, err
			}

			tlsConn := tls.Client(conn, tlsConfig)

			// Validate the connection.
			err = tlsConn.Handshake()
			if err != nil {
				_ = conn.Close()
				return nil, err
			}

			return tlsConn, nil
		},
		DisableKeepAlives:     true,
		ExpectContinueTimeout: time.Second * 30,
		ResponseHeaderTimeout: time.Second * 3600,
		TLSHandshakeTimeout:   time.Second * 5,
	}

	// Setup redirect policy.
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		// Replicate the headers.
		req.Header = via[len(via)-1].Header

		return nil
	}

	return client, nil
}
<commit_msg>lxd/vsock: Use DialContext in vsock HTTP client.<commit_after>package vsock

import (
	"context"
	"crypto/tls"
	"net"
	"net/http"
	"strings"
	"time"

	"github.com/mdlayher/vsock"

	"github.com/lxc/lxd/shared"
)

// Dial connects to a remote vsock.
func Dial(cid, port uint32) (net.Conn, error) {
	return vsock.Dial(cid, port, nil)
}

// Listen listens for a connection.
func Listen(port uint32) (net.Listener, error) {
	return vsock.Listen(port, nil)
}

// HTTPClient provides an HTTP client for using over vsock.
func HTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, tlsServerCert string) (*http.Client, error) {
	client := &http.Client{}

	// Get the TLS configuration.
	tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, "", tlsServerCert, false)
	if err != nil {
		return nil, err
	}

	client.Transport = &http.Transport{
		TLSClientConfig: tlsConfig,
		// Setup a VM socket dialer.
		DialContext: func(_ context.Context, network, addr string) (net.Conn, error) {
			var conn net.Conn
			var err error

			// Retry for up to 1s at 100ms interval to handle various failures.
			for i := 0; i < 10; i++ {
				conn, err = Dial(uint32(vsockID), shared.HTTPSDefaultPort)
				if err == nil {
					break
				} else {
					// Handle some fatal errors.
					msg := err.Error()
					if strings.Contains(msg, "connection timed out") {
						// Retry once.
						conn, err = Dial(uint32(vsockID), shared.HTTPSDefaultPort)
						break
					} else if strings.Contains(msg, "connection refused") {
						break
					}

					// Retry the rest.
				}

				time.Sleep(100 * time.Millisecond)
			}
			if err != nil {
				return nil, err
			}

			tlsConn := tls.Client(conn, tlsConfig)

			// Validate the connection.
			err = tlsConn.Handshake()
			if err != nil {
				_ = conn.Close()
				return nil, err
			}

			return tlsConn, nil
		},
		DisableKeepAlives:     true,
		ExpectContinueTimeout: time.Second * 30,
		ResponseHeaderTimeout: time.Second * 3600,
		TLSHandshakeTimeout:   time.Second * 5,
	}

	// Setup redirect policy.
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		// Replicate the headers.
		req.Header = via[len(via)-1].Header

		return nil
	}

	return client, nil
}
<|endoftext|>


<commit_before>package eth

import (
	"errors"
	"fmt"
	"math/big"

	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/accounts/keystore"
	ethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/console"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/golang/glog"
	"github.com/livepeer/go-livepeer/common"
)

var (
	ErrAccountNotFound    = fmt.Errorf("ETH account not found")
	ErrLocked             = fmt.Errorf("account locked")
	ErrPassphraseMismatch = fmt.Errorf("passphrases do not match")
)

type AccountManager struct {
	Account accounts.Account

	unlocked bool
	keyStore *keystore.KeyStore
}

func NewAccountManager(accountAddr ethcommon.Address, keystoreDir string) (*AccountManager, error) {
	keyStore := keystore.NewKeyStore(keystoreDir, keystore.StandardScryptN, keystore.StandardScryptP)

	acctExists := keyStore.HasAddress(accountAddr)
	numAccounts := len(keyStore.Accounts())

	var acct accounts.Account
	var err error
	if numAccounts == 0 || ((accountAddr != ethcommon.Address{}) && !acctExists) {
		glog.Infof("Please create a new ETH account")

		// Account does not exist yet, set it up
		acct, err = createAccount(keyStore)
		if err != nil {
			return nil, err
		}
	} else {
		glog.V(common.SHORT).Infof("Found existing ETH account")

		// Account already exists or defaulting to first, load it from keystore
		acct, err = getAccount(accountAddr, keyStore)
		if err != nil {
			return nil, err
		}
	}

	glog.Infof("Using ETH account: %v", acct.Address.Hex())

	return &AccountManager{
		Account:  acct,
		unlocked: false,
		keyStore: keyStore,
	}, nil
}

// Unlock account indefinitely using underlying keystore
func (am *AccountManager) Unlock(passphrase string) error {
	var err error

	err = am.keyStore.Unlock(am.Account, passphrase)
	if err != nil {
		if passphrase != "" {
			return err
		}
		glog.Infof("Passphrase required to unlock ETH account %v", am.Account.Address.Hex())

		passphrase, err = getPassphrase(false)
		err = am.keyStore.Unlock(am.Account, passphrase)
		if err != nil {
			return err
		}
	}

	am.unlocked = true

	glog.Infof("Unlocked ETH account: %v", am.Account.Address.Hex())

	return nil
}

// Lock account using underlying keystore and remove associated private key from memory
func (am *AccountManager) Lock() error {
	err := am.keyStore.Lock(am.Account.Address)
	if err != nil {
		return err
	}

	am.unlocked = false

	return nil
}

// Create transact opts for client use - account must be unlocked
// Can optionally set gas limit and gas price used
func (am *AccountManager) CreateTransactOpts(gasLimit uint64, gasPrice *big.Int) (*bind.TransactOpts, error) {
	if !am.unlocked {
		return nil, ErrLocked
	}

	return &bind.TransactOpts{
		From:     am.Account.Address,
		GasLimit: gasLimit,
		GasPrice: gasPrice,
		Signer: func(signer types.Signer, address ethcommon.Address, tx *types.Transaction) (*types.Transaction, error) {
			if address != am.Account.Address {
				return nil, errors.New("not authorized to sign this account")
			}

			return am.SignTx(signer, tx)
		},
	}, nil
}

// Sign a transaction. Account must be unlocked
func (am *AccountManager) SignTx(signer types.Signer, tx *types.Transaction) (*types.Transaction, error) {
	signature, err := am.keyStore.SignHash(am.Account, signer.Hash(tx).Bytes())
	if err != nil {
		return nil, err
	}

	return tx.WithSignature(signer, signature)
}

// Sign byte array message. Account must be unlocked
func (am *AccountManager) Sign(msg []byte) ([]byte, error) {
	personalMsg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", 32, msg)
	personalHash := crypto.Keccak256([]byte(personalMsg))

	return am.keyStore.SignHash(am.Account, personalHash)
}

// Get account from keystore using hex address
// If no hex address is provided, default to the first account
func getAccount(accountAddr ethcommon.Address, keyStore *keystore.KeyStore) (accounts.Account, error) {
	accts := keyStore.Accounts()

	if (accountAddr != ethcommon.Address{}) {
		for _, acct := range accts {
			if acct.Address == accountAddr {
				return acct, nil
			}
		}

		return accounts.Account{}, ErrAccountNotFound
	} else {
		glog.V(common.SHORT).Infof("Defaulting to first ETH account in keystore %v", accts[0].Address.Hex())

		// Default to first account
		return accts[0], nil
	}
}

// Create account in keystore
func createAccount(keyStore *keystore.KeyStore) (accounts.Account, error) {
	passphrase, err := getPassphrase(true)
	if err != nil {
		return accounts.Account{}, err
	}

	return keyStore.NewAccount(passphrase)
}

// Prompt for passphrase
func getPassphrase(shouldConfirm bool) (string, error) {
	passphrase, err := console.Stdin.PromptPassword("Passphrase: ")
	if err != nil {
		return "", err
	}

	if shouldConfirm {
		confirmation, err := console.Stdin.PromptPassword("Repeat passphrase: ")
		if err != nil {
			return "", err
		}

		if passphrase != confirmation {
			return "", ErrPassphraseMismatch
		}
	}

	return passphrase, nil
}
<commit_msg>Improvements in prompt text (#640)<commit_after>package eth

import (
	"errors"
	"fmt"
	"math/big"

	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/accounts/keystore"
	ethcommon "github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/console"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/golang/glog"
	"github.com/livepeer/go-livepeer/common"
)

var (
	ErrAccountNotFound    = fmt.Errorf("ETH account not found")
	ErrLocked             = fmt.Errorf("account locked")
	ErrPassphraseMismatch = fmt.Errorf("passphrases do not match")
)

type AccountManager struct {
	Account accounts.Account

	unlocked bool
	keyStore *keystore.KeyStore
}

func NewAccountManager(accountAddr ethcommon.Address, keystoreDir string) (*AccountManager, error) {
	keyStore := keystore.NewKeyStore(keystoreDir, keystore.StandardScryptN, keystore.StandardScryptP)

	acctExists := keyStore.HasAddress(accountAddr)
	numAccounts := len(keyStore.Accounts())

	var acct accounts.Account
	var err error
	if numAccounts == 0 || ((accountAddr != ethcommon.Address{}) && !acctExists) {
		glog.Infof("No Ethereum account found. Creating a new account")
		glog.Infof("This process will create a new Ethereum account for this Livepeer node")
		glog.Infof("Please enter a passphrase to encrypt the Private Keystore file for the Ethereum account.")
		glog.Infof("This process will ask for this passphrase every time it is launched")
		glog.Infof("(no characters will appear in Terminal when the passphrase is entered)")

		// Account does not exist yet, set it up
		acct, err = createAccount(keyStore)
		if err != nil {
			return nil, err
		}
	} else {
		glog.V(common.SHORT).Infof("Found existing ETH account")

		// Account already exists or defaulting to first, load it from keystore
		acct, err = getAccount(accountAddr, keyStore)
		if err != nil {
			return nil, err
		}
	}

	glog.Infof("Using Ethereum account: %v", acct.Address.Hex())

	return &AccountManager{
		Account:  acct,
		unlocked: false,
		keyStore: keyStore,
	}, nil
}

// Unlock account indefinitely using underlying keystore
func (am *AccountManager) Unlock(passphrase string) error {
	var err error

	err = am.keyStore.Unlock(am.Account, passphrase)
	if err != nil {
		if passphrase != "" {
			return err
		}
		glog.Infof("Please enter the passphrase to unlock Ethereum account %v", am.Account.Address.Hex())

		passphrase, err = getPassphrase(false)
		err = am.keyStore.Unlock(am.Account, passphrase)
		if err != nil {
			return err
		}
	}

	am.unlocked = true

	glog.Infof("Unlocked ETH account: %v", am.Account.Address.Hex())

	return nil
}

// Lock account using underlying keystore and remove associated private key from memory
func (am *AccountManager) Lock() error {
	err := am.keyStore.Lock(am.Account.Address)
	if err != nil {
		return err
	}

	am.unlocked = false

	return nil
}

// Create transact opts for client use - account must be unlocked
// Can optionally set gas limit and gas price used
func (am *AccountManager) CreateTransactOpts(gasLimit uint64, gasPrice *big.Int) (*bind.TransactOpts, error) {
	if !am.unlocked {
		return nil, ErrLocked
	}

	return &bind.TransactOpts{
		From:     am.Account.Address,
		GasLimit: gasLimit,
		GasPrice: gasPrice,
		Signer: func(signer types.Signer, address ethcommon.Address, tx *types.Transaction) (*types.Transaction, error) {
			if address != am.Account.Address {
				return nil, errors.New("not authorized to sign this account")
			}

			return am.SignTx(signer, tx)
		},
	}, nil
}

// Sign a transaction. Account must be unlocked
func (am *AccountManager) SignTx(signer types.Signer, tx *types.Transaction) (*types.Transaction, error) {
	signature, err := am.keyStore.SignHash(am.Account, signer.Hash(tx).Bytes())
	if err != nil {
		return nil, err
	}

	return tx.WithSignature(signer, signature)
}

// Sign byte array message. Account must be unlocked
func (am *AccountManager) Sign(msg []byte) ([]byte, error) {
	personalMsg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", 32, msg)
	personalHash := crypto.Keccak256([]byte(personalMsg))

	return am.keyStore.SignHash(am.Account, personalHash)
}

// Get account from keystore using hex address
// If no hex address is provided, default to the first account
func getAccount(accountAddr ethcommon.Address, keyStore *keystore.KeyStore) (accounts.Account, error) {
	accts := keyStore.Accounts()

	if (accountAddr != ethcommon.Address{}) {
		for _, acct := range accts {
			if acct.Address == accountAddr {
				return acct, nil
			}
		}

		return accounts.Account{}, ErrAccountNotFound
	} else {
		glog.V(common.SHORT).Infof("Defaulting to first ETH account in keystore %v", accts[0].Address.Hex())

		// Default to first account
		return accts[0], nil
	}
}

// Create account in keystore
func createAccount(keyStore *keystore.KeyStore) (accounts.Account, error) {
	passphrase, err := getPassphrase(true)
	if err != nil {
		return accounts.Account{}, err
	}

	return keyStore.NewAccount(passphrase)
}

// Prompt for passphrase
func getPassphrase(shouldConfirm bool) (string, error) {
	passphrase, err := console.Stdin.PromptPassword("Passphrase: ")
	if err != nil {
		return "", err
	}

	if shouldConfirm {
		confirmation, err := console.Stdin.PromptPassword("Repeat passphrase: ")
		if err != nil {
			return "", err
		}

		if passphrase != confirmation {
			return "", ErrPassphraseMismatch
		}
	}

	return passphrase, nil
}
<|endoftext|>


<commit_before>package maestro

import (
	"bytes"
	"fmt"
	"github.com/marmelab/gaudi/container"
	"github.com/marmelab/gaudi/docker"
	"github.com/marmelab/gaudi/util"
	"io/ioutil"
	"launchpad.net/goyaml"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

const DEFAULT_BASE_IMAGE = "stackbrew/debian"
const DEFAULT_BASE_IMAGE_WITH_TAG = "stackbrew/debian:wheezy"

type Maestro struct {
	Applications map[string]*container.Container
}

type TemplateData struct {
	Maestro   *Maestro
	Container *container.Container
}

func (m *Maestro) InitFromFile(file string) {
	content, err := ioutil.ReadFile(file)
	if err != nil {
		panic(err)
	}

	m.InitFromString(string(content), filepath.Dir(file))
}

func (maestro *Maestro) InitFromString(content, relativePath string) {
	err := goyaml.Unmarshal([]byte(content), &maestro)
	if err != nil {
		panic(err)
	}
	if maestro.Applications == nil {
		panic("No application to start")
	}

	// Fill name & dependencies
	for name := range maestro.Applications {
		currentContainer := maestro.Applications[name]
		currentContainer.Name = name

		if currentContainer.IsGaudiManaged() {
			currentContainer.Image = "gaudi/" + name
		}

		for _, dependency := range currentContainer.Links {
			if depContainer, exists := maestro.Applications[dependency]; exists {
				currentContainer.AddDependency(depContainer)
			} else {
				panic(name + " references a non existing application : " + dependency)
			}
		}

		// Add relative path to volumes
		for volumeHost, volumeContainer := range currentContainer.Volumes {
			if string(volumeHost[0]) != "/" {
				delete(currentContainer.Volumes, volumeHost)

				if !util.IsDir(relativePath + "/" + volumeHost) {
					panic(relativePath + "/" + volumeHost + " should be a directory")
				}

				currentContainer.Volumes[relativePath+"/"+volumeHost] = volumeContainer
			} else if !util.IsDir(volumeHost) {
				panic(volumeHost + " should be a directory")
			}
		}

		// Check if the beforeScript is a file
		beforeScript := currentContainer.BeforeScript
		if len(beforeScript) != 0 {
			if util.IsFile(beforeScript) {
				currentContainer.BeforeScript = beforeScript
			} else if util.IsFile(relativePath + "/" + beforeScript) {
				currentContainer.BeforeScript = relativePath + "/" + beforeScript
			}
		}
	}
}

func (maestro *Maestro) createHiddenDir() {
	currentDir, _ := os.Getwd()
	err := os.MkdirAll(currentDir+"/.gaudi", 0755)
	if err != nil {
		panic(err)
	}
}

func (maestro *Maestro) parseTemplates() {
	// Running withmock doesn't include templates files in withmock's temporary dir
	path := os.Getenv("GOPATH")
	testPath := os.Getenv("ORIG_GOPATH")
	if len(testPath) > 0 {
		path = testPath
	}

	templateDir := path + "/src/github.com/marmelab/gaudi/templates/"
	parsedTemplateDir := "/tmp/gaudi/"
	templateData := TemplateData{maestro, nil}
	funcMap := template.FuncMap{
		"ToUpper": strings.ToUpper,
		"ToLower": strings.ToLower,
	}

	err := os.MkdirAll(parsedTemplateDir, 0700)
	if err != nil {
		panic(err)
	}

	for _, currentContainer := range maestro.Applications {
		if !currentContainer.IsGaudiManaged() {
			continue
		}

		files, err := ioutil.ReadDir(templateDir + currentContainer.Type)
		if err != nil {
			panic("Template not found for application : " + currentContainer.Type)
		}

		err = os.MkdirAll(parsedTemplateDir+currentContainer.Name, 0755)
		if err != nil {
			panic(err)
		}

		// Parse & copy files
		for _, file := range files {
			destination := parsedTemplateDir + currentContainer.Name + "/" + file.Name()
			if file.IsDir() {
				err := os.MkdirAll(destination, 0755)
				if err != nil {
					panic(err)
				}

				continue
			}

			// Read the template
			filePath := templateDir + currentContainer.Type + "/" + file.Name()
			content, err := ioutil.ReadFile(filePath)
			if err != nil {
				panic(err)
			}

			// Parse it (we need to change default delimiters because sometimes we have to parse values like ${{{ .Val }}}
			// which cause an error)
			tmpl, err := template.New(filePath).Funcs(funcMap).Delims("[[", "]]").Parse(string(content))
			if err != nil {
				panic(err)
			}

			templateData.Container = currentContainer
			var result bytes.Buffer
			err = tmpl.Execute(&result, templateData)
			if err != nil {
				panic(err)
			}

			// Create new file
			ioutil.WriteFile(destination, []byte(result.String()), 0644)
		}
	}
}

func (maestro *Maestro) Start() {
	maestro.createHiddenDir()
	maestro.parseTemplates()

	nbApplications := len(maestro.Applications)
	cleanChans := make(chan bool, nbApplications)
	hasGaudiManagedContainer := false

	// Clean all applications
	for _, currentContainer := range maestro.Applications {
		if currentContainer.IsGaudiManaged() {
			hasGaudiManagedContainer = true
		}

		go currentContainer.Clean(cleanChans)
	}
	<-cleanChans

	buildChans := make(chan bool, len(maestro.Applications))

	// Check if base image is pulled
	if hasGaudiManagedContainer && !docker.ImageExists(DEFAULT_BASE_IMAGE) {
		fmt.Println("Pulling base image (this may take a few minutes)  ...")

		docker.Pull(DEFAULT_BASE_IMAGE_WITH_TAG)
	}

	// Build all applications
	for _, currentContainer := range maestro.Applications {
		if currentContainer.IsPreBuild() {
			go currentContainer.Pull(buildChans)
		} else {
			go currentContainer.Build(buildChans)
		}
	}

	for i := 0; i < nbApplications; i++ {
		<-buildChans
	}

	startChans := make(map[string]chan bool)

	// Start all applications
	for name, currentContainer := range maestro.Applications {
		startChans[name] = make(chan bool)

		go maestro.startContainer(currentContainer, startChans)
	}

	// Waiting for all applications to start
	for containerName, _ := range maestro.Applications {
		<-startChans[containerName]
	}
}

func (maestro *Maestro) GetContainer(name string) *container.Container {
	return maestro.Applications[name]
}

func (maestro *Maestro) Check() {
	images, err := docker.SnapshotProcesses()
	if err != nil {
		panic(err)
	}

	for _, currentContainer := range maestro.Applications {
		if containerId, ok := images[currentContainer.Image]; ok {
			currentContainer.Id = containerId
			currentContainer.RetrieveIp()

			fmt.Println("Application", currentContainer.Name, "is running", "("+currentContainer.Ip+":"+currentContainer.GetFirstPort()+")")
		} else {
			fmt.Println("Application", currentContainer.Name, "is not running")
		}
	}
}

func (maestro *Maestro) Stop() {
	killChans := make(chan bool, len(maestro.Applications))

	for _, currentContainer := range maestro.Applications {
		go currentContainer.Kill(killChans, false)
	}

	<-killChans
}

func (maestro *Maestro) startContainer(currentContainer *container.Container, done map[string]chan bool) {
	// Waiting for dependencies to start
	for _, dependency := range currentContainer.Dependencies {
		<-done[dependency.Name]
	}

	currentContainer.Start()

	close(done[currentContainer.Name])
}
<commit_msg>Create mounted folder if needed<commit_after>package maestro

import (
	"bytes"
	"fmt"
	"github.com/marmelab/gaudi/container"
	"github.com/marmelab/gaudi/docker"
	"github.com/marmelab/gaudi/util"
	"io/ioutil"
	"launchpad.net/goyaml"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

const DEFAULT_BASE_IMAGE = "stackbrew/debian"
const DEFAULT_BASE_IMAGE_WITH_TAG = "stackbrew/debian:wheezy"

type Maestro struct {
	Applications map[string]*container.Container
}

type TemplateData struct {
	Maestro   *Maestro
	Container *container.Container
}

func (m *Maestro) InitFromFile(file string) {
	content, err := ioutil.ReadFile(file)
	if err != nil {
		panic(err)
	}

	m.InitFromString(string(content), filepath.Dir(file))
}

func (maestro *Maestro) InitFromString(content, relativePath string) {
	err := goyaml.Unmarshal([]byte(content), &maestro)
	if err != nil {
		panic(err)
	}
	if maestro.Applications == nil {
		panic("No application to start")
	}

	// Fill name & dependencies
	for name := range maestro.Applications {
		currentContainer := maestro.Applications[name]
		currentContainer.Name = name

		if currentContainer.IsGaudiManaged() {
			currentContainer.Image = "gaudi/" + name
		}

		for _, dependency := range currentContainer.Links {
			if depContainer, exists := maestro.Applications[dependency]; exists {
				currentContainer.AddDependency(depContainer)
			} else {
				panic(name + " references a non existing application : " + dependency)
			}
		}

		// Add relative path to volumes
		for volumeHost, volumeContainer := range currentContainer.Volumes {
			// Relative volume host
			if string(volumeHost[0]) != "/" {
				delete(currentContainer.Volumes, volumeHost)
				volumeHost = relativePath+"/"+volumeHost

				currentContainer.Volumes[volumeHost] = volumeContainer
			}

			// Check if directory exists
			if !util.IsDir(volumeHost) {
				err := os.MkdirAll(volumeHost, 0755)
				if err != nil {
					panic(err)
				}
			}
		}

		// Check if the beforeScript is a file
		beforeScript := currentContainer.BeforeScript
		if len(beforeScript) != 0 {
			if util.IsFile(beforeScript) {
				currentContainer.BeforeScript = beforeScript
			} else if util.IsFile(relativePath + "/" + beforeScript) {
				currentContainer.BeforeScript = relativePath + "/" + beforeScript
			}
		}
	}
}

func (maestro *Maestro) parseTemplates() {
	// Running withmock doesn't include templates files in withmock's temporary dir
	path := os.Getenv("GOPATH")
	testPath := os.Getenv("ORIG_GOPATH")
	if len(testPath) > 0 {
		path = testPath
	}

	templateDir := path + "/src/github.com/marmelab/gaudi/templates/"
	parsedTemplateDir := "/tmp/gaudi/"
	templateData := TemplateData{maestro, nil}
	funcMap := template.FuncMap{
		"ToUpper": strings.ToUpper,
		"ToLower": strings.ToLower,
	}

	err := os.MkdirAll(parsedTemplateDir, 0700)
	if err != nil {
		panic(err)
	}

	for _, currentContainer := range maestro.Applications {
		if !currentContainer.IsGaudiManaged() {
			continue
		}

		files, err := ioutil.ReadDir(templateDir + currentContainer.Type)
		if err != nil {
			panic("Template not found for application : " + currentContainer.Type)
		}

		err = os.MkdirAll(parsedTemplateDir+currentContainer.Name, 0755)
		if err != nil {
			panic(err)
		}

		// Parse & copy files
		for _, file := range files {
			destination := parsedTemplateDir + currentContainer.Name + "/" + file.Name()
			if file.IsDir() {
				err := os.MkdirAll(destination, 0755)
				if err != nil {
					panic(err)
				}

				continue
			}

			// Read the template
			filePath := templateDir + currentContainer.Type + "/" + file.Name()
			content, err := ioutil.ReadFile(filePath)
			if err != nil {
				panic(err)
			}

			// Parse it (we need to change default delimiters because sometimes we have to parse values like ${{{ .Val }}}
			// which cause an error)
			tmpl, err := template.New(filePath).Funcs(funcMap).Delims("[[", "]]").Parse(string(content))
			if err != nil {
				panic(err)
			}

			templateData.Container = currentContainer
			var result bytes.Buffer
			err = tmpl.Execute(&result, templateData)
			if err != nil {
				panic(err)
			}

			// Create new file
			ioutil.WriteFile(destination, []byte(result.String()), 0644)
		}
	}
}

func (maestro *Maestro) Start() {
	maestro.parseTemplates()

	nbApplications := len(maestro.Applications)
	cleanChans := make(chan bool, nbApplications)
	hasGaudiManagedContainer := false

	// Clean all applications
	for _, currentContainer := range maestro.Applications {
		if currentContainer.IsGaudiManaged() {
			hasGaudiManagedContainer = true
		}

		go currentContainer.Clean(cleanChans)
	}
	<-cleanChans

	buildChans := make(chan bool, len(maestro.Applications))

	// Check if base image is pulled
	if hasGaudiManagedContainer && !docker.ImageExists(DEFAULT_BASE_IMAGE) {
		fmt.Println("Pulling base image (this may take a few minutes)  ...")

		docker.Pull(DEFAULT_BASE_IMAGE_WITH_TAG)
	}

	// Build all applications
	for _, currentContainer := range maestro.Applications {
		if currentContainer.IsPreBuild() {
			go currentContainer.Pull(buildChans)
		} else {
			go currentContainer.Build(buildChans)
		}
	}

	for i := 0; i < nbApplications; i++ {
		<-buildChans
	}

	startChans := make(map[string]chan bool)

	// Start all applications
	for name, currentContainer := range maestro.Applications {
		startChans[name] = make(chan bool)

		go maestro.startContainer(currentContainer, startChans)
	}

	// Waiting for all applications to start
	for containerName, _ := range maestro.Applications {
		<-startChans[containerName]
	}
}

func (maestro *Maestro) GetContainer(name string) *container.Container {
	return maestro.Applications[name]
}

func (maestro *Maestro) Check() {
	images, err := docker.SnapshotProcesses()
	if err != nil {
		panic(err)
	}

	for _, currentContainer := range maestro.Applications {
		if containerId, ok := images[currentContainer.Image]; ok {
			currentContainer.Id = containerId
			currentContainer.RetrieveIp()

			fmt.Println("Application", currentContainer.Name, "is running", "("+currentContainer.Ip+":"+currentContainer.GetFirstPort()+")")
		} else {
			fmt.Println("Application", currentContainer.Name, "is not running")
		}
	}
}

func (maestro *Maestro) Stop() {
	killChans := make(chan bool, len(maestro.Applications))

	for _, currentContainer := range maestro.Applications {
		go currentContainer.Kill(killChans, false)
	}

	<-killChans
}

func (maestro *Maestro) startContainer(currentContainer *container.Container, done map[string]chan bool) {
	// Waiting for dependencies to start
	for _, dependency := range currentContainer.Dependencies {
		<-done[dependency.Name]
	}

	currentContainer.Start()

	close(done[currentContainer.Name])
}
<|endoftext|>


<commit_before>package cpgo

import (
	//"fmt"
	"strings"
	"sync"
	"syscall"
	"unsafe"

	ole "github.com/go-ole/go-ole"
	//"github.com/go-ole/go-ole/oleutil"
)

// peekmessage 로드
var (
	user32, _       = syscall.LoadLibrary("user32.dll")
	pPeekMessage, _ = syscall.GetProcAddress(user32, "PeekMessageW")
	//pDispatchMessage, _ = syscall.GetProcAddress(user32, "DispatchMessage")
	IID_IDibEvents, _    = ole.CLSIDFromString("{B8944520-09C3-11D4-8232-00105A7C4F8C}")
	IID_IDibSysEvents, _ = ole.CLSIDFromString("{60D7702A-57BA-4869-AF3F-292FDC909D75}")
	IID_IDibTrEvents, _  = ole.CLSIDFromString("{8B55AD34-73A3-4C33-B8CD-C95ED13823CB}")
)

// 사이보스플러스의 콜백메서드 인터페이스
type Receiver interface {
	Received(*CpClass)
}

// 사이보스플러스 객체를 구성하는 데이터묶음
type CpClass struct {
	unk  *ole.IUnknown
	obj  *ole.IDispatch
	evnt *dispCpEvent

	// for event
	cb     Receiver
	point  *ole.IConnectionPoint
	cookie uint32

	// dll name
	dll string
}

// 이벤트 수신을 위한 구조체
type dispCpEvent struct {
	lpVtbl *dispCpEventVtbl
	ref    int32
	host   *CpClass
}

// 가상함수 테이블
type dispCpEventVtbl struct {
	// IUnknown
	pQueryInterface uintptr
	pAddRef         uintptr
	pRelease        uintptr
	// IDispatch
	pGetTypeInfoCount uintptr
	pGetTypeInfo      uintptr
	pGetIDsOfNames    uintptr
	pInvoke           uintptr
}

// 사이보스플러스 객체 생성
func (c *CpClass) Create(name string) {
	// clsid 구함
	clsid, err := ole.CLSIDFromString(name)
	if err != nil {
		panic(err)
	}
	// unknown
	c.unk, err = ole.CreateInstance(clsid, ole.IID_IUnknown)
	if err != nil {
		panic(err)
	}
	// get obj
	c.obj, err = c.unk.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		panic(err)
	}

	// get name
	splits := strings.Split(name, ".")
	c.dll = splits[0]
}

// 객체 헤제
func (c *CpClass) Release() {
	if c.unk != nil {
		c.unk.Release()
		c.unk = nil
	}
	if c.obj != nil {
		c.obj.Release()
		c.obj = nil
	}
	if c.evnt != nil {
		//c.evnt.Release()
		dispRelease((*ole.IUnknown)(unsafe.Pointer(c.evnt)))
		c.evnt = nil
		if c.point != nil {
			c.UnbindEvent()
		}
	}
}

// 이벤트 지정
func (c *CpClass) BindEvent(callback Receiver) {

	var iid_evnt *ole.GUID

	if c.dll == "DSCBO1" {
		iid_evnt = IID_IDibEvents
	} else if c.dll == "CpSysDib" {
		iid_evnt = IID_IDibSysEvents
	} else if c.dll == "CpTrade" {
		iid_evnt = IID_IDibTrEvents
	} else {
		panic("이벤트 지정 실패")
	}

	if c.evnt == nil {
		// Callback method binding
		evnt := &dispCpEvent{}
		evnt.lpVtbl = &dispCpEventVtbl{}
		evnt.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface)
		evnt.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef)
		evnt.lpVtbl.pRelease = syscall.NewCallback(dispRelease)
		evnt.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount)
		evnt.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo)
		evnt.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames)
		evnt.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke)
		evnt.host = c
		// assign event
		c.evnt = evnt
	}
	c.cb = callback

	if c.point != nil {
		// 이미 포인트가 지정되어 있었으면?
		c.UnbindEvent()
	}
	// connectionpoint container
	unknown_con, err := c.obj.QueryInterface(ole.IID_IConnectionPointContainer)
	if err != nil {
		panic(err)
	}

	// get point
	container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown_con))
	var point *ole.IConnectionPoint

	err = container.FindConnectionPoint(iid_evnt, &point)
	if err != nil {
		panic(err)
	}

	// Advise
	cookie, err := point.Advise((*ole.IUnknown)(unsafe.Pointer(c.evnt)))
	container.Release()
	if err != nil {
		point.Release()
		panic(err)
	}
	c.point = point
	c.cookie = cookie
}

// 이벤트 헤제
func (c *CpClass) UnbindEvent() {
	if c.point != nil {
		c.point.Unadvise(c.cookie)
		c.point.Release()
		c.point = nil
		c.cookie = 0
	}
}

// 이하 콜백 이벤트 바인딩하기 위한 함수 선언들
func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 {
	*punk = nil
	if ole.IsEqualGUID(iid, ole.IID_IUnknown) ||
		ole.IsEqualGUID(iid, ole.IID_IDispatch) ||
		ole.IsEqualGUID(iid, IID_IDibEvents) ||
		ole.IsEqualGUID(iid, IID_IDibSysEvents) ||
		ole.IsEqualGUID(iid, IID_IDibTrEvents) {
		dispAddRef(this)
		*punk = this
		return ole.S_OK
	}

	return ole.E_NOINTERFACE
}

func dispAddRef(this *ole.IUnknown) int32 {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	pthis.ref++
	return pthis.ref
}

func dispRelease(this *ole.IUnknown) int32 {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	pthis.ref--
	return pthis.ref
}
func dispGetIDsOfNames(args *uintptr) uint32 {
	p := (*[6]int32)(unsafe.Pointer(args))
	//this := (*ole.IDispatch)(unsafe.Pointer(uintptr(p[0])))
	//iid := (*ole.GUID)(unsafe.Pointer(uintptr(p[1])))
	wnames := *(*[]*uint16)(unsafe.Pointer(uintptr(p[2])))
	namelen := int(uintptr(p[3]))
	//lcid := int(uintptr(p[4]))
	pdisp := *(*[]int32)(unsafe.Pointer(uintptr(p[5])))
	for n := 0; n < namelen; n++ {
		s := ole.UTF16PtrToString(wnames[n])
		println(s)
		pdisp[n] = int32(n)
	}
	return ole.S_OK
}
func dispGetTypeInfoCount(this *ole.IUnknown, pcount *int) uint32 {
	if pcount != nil {
		*pcount = 0
	}
	return ole.S_OK
}

func dispGetTypeInfo(this *ole.IUnknown, namelen int, lcid int) uint32 {
	return ole.E_NOTIMPL
}
func dispInvoke(this *ole.IDispatch, dispid int, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	if dispid == 1 {
		if pthis.host.cb != nil {
			// instance callback
			pthis.host.cb.Received(pthis.host)
			return ole.S_OK
		}
	}
	return ole.E_NOTIMPL
}

//

func PeekMessage(msg *ole.Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32, RemoveMsg uint32) (ret int32, err error) {
	r0, _, err := syscall.Syscall6(uintptr(pPeekMessage), 5,
		uintptr(unsafe.Pointer(msg)),
		uintptr(hwnd),
		uintptr(MsgFilterMin),
		uintptr(MsgFilterMax),
		uintptr(RemoveMsg),
		0)

	ret = int32(r0)
	return
}

func PumpWaitingMessage() int32 {
	ret := int32(0)

	var msg ole.Msg

	mutex := &sync.Mutex{}
	mutex.Lock()
	for {
		r, _ := PeekMessage(&msg, 0, 0, 0, 1)
		if r == 0 {
			break
		}
		if msg.Message == 0x0012 { // WM_QUIT
			ret = int32(1)
			break
		}
		ole.DispatchMessage(&msg)
	}
	mutex.Unlock()
	return ret
}
<commit_msg>thread lock change<commit_after>package cpgo

import (
	//"fmt"
	"strings"
	//"sync"
	"runtime"
	"syscall"
	"unsafe"

	ole "github.com/go-ole/go-ole"
	//"github.com/go-ole/go-ole/oleutil"
)

// peekmessage 로드
var (
	user32, _       = syscall.LoadLibrary("user32.dll")
	pPeekMessage, _ = syscall.GetProcAddress(user32, "PeekMessageW")
	//pDispatchMessage, _ = syscall.GetProcAddress(user32, "DispatchMessage")
	IID_IDibEvents, _    = ole.CLSIDFromString("{B8944520-09C3-11D4-8232-00105A7C4F8C}")
	IID_IDibSysEvents, _ = ole.CLSIDFromString("{60D7702A-57BA-4869-AF3F-292FDC909D75}")
	IID_IDibTrEvents, _  = ole.CLSIDFromString("{8B55AD34-73A3-4C33-B8CD-C95ED13823CB}")
)

// 사이보스플러스의 콜백메서드 인터페이스
type Receiver interface {
	Received(*CpClass)
}

// 사이보스플러스 객체를 구성하는 데이터묶음
type CpClass struct {
	unk  *ole.IUnknown
	obj  *ole.IDispatch
	evnt *dispCpEvent

	// for event
	cb     Receiver
	point  *ole.IConnectionPoint
	cookie uint32

	// dll name
	dll string
}

// 이벤트 수신을 위한 구조체
type dispCpEvent struct {
	lpVtbl *dispCpEventVtbl
	ref    int32
	host   *CpClass
}

// 가상함수 테이블
type dispCpEventVtbl struct {
	// IUnknown
	pQueryInterface uintptr
	pAddRef         uintptr
	pRelease        uintptr
	// IDispatch
	pGetTypeInfoCount uintptr
	pGetTypeInfo      uintptr
	pGetIDsOfNames    uintptr
	pInvoke           uintptr
}

// 사이보스플러스 객체 생성
func (c *CpClass) Create(name string) {
	// clsid 구함
	clsid, err := ole.CLSIDFromString(name)
	if err != nil {
		panic(err)
	}
	// unknown
	c.unk, err = ole.CreateInstance(clsid, ole.IID_IUnknown)
	if err != nil {
		panic(err)
	}
	// get obj
	c.obj, err = c.unk.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		panic(err)
	}

	// get name
	splits := strings.Split(name, ".")
	c.dll = splits[0]
}

// 객체 헤제
func (c *CpClass) Release() {
	if c.unk != nil {
		c.unk.Release()
		c.unk = nil
	}
	if c.obj != nil {
		c.obj.Release()
		c.obj = nil
	}
	if c.evnt != nil {
		//c.evnt.Release()
		dispRelease((*ole.IUnknown)(unsafe.Pointer(c.evnt)))
		c.evnt = nil
		if c.point != nil {
			c.UnbindEvent()
		}
	}
}

// 이벤트 지정
func (c *CpClass) BindEvent(callback Receiver) {

	var iid_evnt *ole.GUID

	if c.dll == "DSCBO1" {
		iid_evnt = IID_IDibEvents
	} else if c.dll == "CpSysDib" {
		iid_evnt = IID_IDibSysEvents
	} else if c.dll == "CpTrade" {
		iid_evnt = IID_IDibTrEvents
	} else {
		panic("이벤트 지정 실패")
	}

	if c.evnt == nil {
		// Callback method binding
		evnt := &dispCpEvent{}
		evnt.lpVtbl = &dispCpEventVtbl{}
		evnt.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface)
		evnt.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef)
		evnt.lpVtbl.pRelease = syscall.NewCallback(dispRelease)
		evnt.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount)
		evnt.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo)
		evnt.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames)
		evnt.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke)
		evnt.host = c
		// assign event
		c.evnt = evnt
	}
	c.cb = callback

	if c.point != nil {
		// 이미 포인트가 지정되어 있었으면?
		c.UnbindEvent()
	}
	// connectionpoint container
	unknown_con, err := c.obj.QueryInterface(ole.IID_IConnectionPointContainer)
	if err != nil {
		panic(err)
	}

	// get point
	container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown_con))
	var point *ole.IConnectionPoint

	err = container.FindConnectionPoint(iid_evnt, &point)
	if err != nil {
		panic(err)
	}

	// Advise
	cookie, err := point.Advise((*ole.IUnknown)(unsafe.Pointer(c.evnt)))
	container.Release()
	if err != nil {
		point.Release()
		panic(err)
	}
	c.point = point
	c.cookie = cookie
}

// 이벤트 헤제
func (c *CpClass) UnbindEvent() {
	if c.point != nil {
		c.point.Unadvise(c.cookie)
		c.point.Release()
		c.point = nil
		c.cookie = 0
	}
}

// 이하 콜백 이벤트 바인딩하기 위한 함수 선언들
func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 {
	*punk = nil
	if ole.IsEqualGUID(iid, ole.IID_IUnknown) ||
		ole.IsEqualGUID(iid, ole.IID_IDispatch) ||
		ole.IsEqualGUID(iid, IID_IDibEvents) ||
		ole.IsEqualGUID(iid, IID_IDibSysEvents) ||
		ole.IsEqualGUID(iid, IID_IDibTrEvents) {
		dispAddRef(this)
		*punk = this
		return ole.S_OK
	}

	return ole.E_NOINTERFACE
}

func dispAddRef(this *ole.IUnknown) int32 {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	pthis.ref++
	return pthis.ref
}

func dispRelease(this *ole.IUnknown) int32 {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	pthis.ref--
	return pthis.ref
}
func dispGetIDsOfNames(args *uintptr) uint32 {
	p := (*[6]int32)(unsafe.Pointer(args))
	//this := (*ole.IDispatch)(unsafe.Pointer(uintptr(p[0])))
	//iid := (*ole.GUID)(unsafe.Pointer(uintptr(p[1])))
	wnames := *(*[]*uint16)(unsafe.Pointer(uintptr(p[2])))
	namelen := int(uintptr(p[3]))
	//lcid := int(uintptr(p[4]))
	pdisp := *(*[]int32)(unsafe.Pointer(uintptr(p[5])))
	for n := 0; n < namelen; n++ {
		s := ole.UTF16PtrToString(wnames[n])
		println(s)
		pdisp[n] = int32(n)
	}
	return ole.S_OK
}
func dispGetTypeInfoCount(this *ole.IUnknown, pcount *int) uint32 {
	if pcount != nil {
		*pcount = 0
	}
	return ole.S_OK
}

func dispGetTypeInfo(this *ole.IUnknown, namelen int, lcid int) uint32 {
	return ole.E_NOTIMPL
}
func dispInvoke(this *ole.IDispatch, dispid int, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr {
	pthis := (*dispCpEvent)(unsafe.Pointer(this))
	if dispid == 1 {
		if pthis.host.cb != nil {
			// instance callback
			pthis.host.cb.Received(pthis.host)
			return ole.S_OK
		}
	}
	return ole.E_NOTIMPL
}

//

func PeekMessage(msg *ole.Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32, RemoveMsg uint32) (ret int32, err error) {
	r0, _, err := syscall.Syscall6(uintptr(pPeekMessage), 5,
		uintptr(unsafe.Pointer(msg)),
		uintptr(hwnd),
		uintptr(MsgFilterMin),
		uintptr(MsgFilterMax),
		uintptr(RemoveMsg),
		0)

	ret = int32(r0)
	return
}

func PumpWaitingMessage() int32 {
	ret := int32(0)

	var msg ole.Msg

	//mutex := &sync.Mutex{}
	//mutex.Lock()
	runtime.LockOSThread()
	for {
		r, _ := PeekMessage(&msg, 0, 0, 0, 1)
		if r == 0 {
			break
		}
		if msg.Message == 0x0012 { // WM_QUIT
			ret = int32(1)
			break
		}
		ole.DispatchMessage(&msg)
	}
	//mutex.Unlock()
	runtime.UnlockOSThread()
	return ret
}
<|endoftext|>