<commit_before>package anylisp

import (
	"fmt"
	"os"
)

type AnyLister interface {
	Fi() interface{}
	Sfi(v interface{}) interface{}
	Bf() AnyLister
	Sbf(v AnyLister) AnyLister
	La() AnyLister
}

type AnyList struct {
	fi interface{}
	bf AnyLister
}

var (
	Ps_      AnyLister
	C_       AnyLister
	TempRoot AnyLister
)

func Parse(code string) {
	TempRoot = &AnyList{"(sx)", nil}
	Ps_ = &AnyList{TempRoot, nil}
	C_ = &AnyList{&AnyList{TempRoot, nil}, nil}
	tok := ""
	for i := 0; i < len(code); i++ {
		if code[i] == ' ' || code[i] == '\t' || code[i] == '\n' {
			if tok == ")" {
				Assert(Ps_.Bf() != nil, "Parse WTF! Too many )s")
				Ps_ = Ps_.Bf()
			} else if len(tok) > 0 {
				var ls AnyLister
				if tok == "(" {
					ls = &AnyList{nil, nil}
				} else {
					ls = &AnyList{tok, nil}
				}
				if Ps_.Fi() == nil {
					Ps_.Bf().Fi().(AnyLister).Sfi(ls) // 1st token in list
				} else {
					Ps_.Fi().(AnyLister).Sbf(ls)
				}
				Ps_.Sfi(ls)
				if tok == "(" {
					Ps_ = &AnyList{nil, Ps_}
				}
			}
			tok = ""
		} else {
			tok += string(code[i])
		}
	}
	Assert(Ps_.Bf() == nil, "Parse WTF! Too few )s")
}

func Run() {
	for C_ != nil {
		frm := C_.Fi().(AnyLister)
		exp, ok := frm.Fi().(AnyLister)
		if !ok {
			fmt.Println("0")
			Ret(frm.Fi())
		} else {
			switch t := exp.Fi().(type) {
			case nil:
				Assert(false, "WTF! Can't call the empty set")
			case AnyLister:
				if frm.Bf() == nil {
					fmt.Println("a")
					C_ = &AnyList{&AnyList{t, nil}, C_}
				} else {
					fmt.Println("b")
					frm.Sfi(frm.Bf().Fi())
				}
			case string:
				switch t {
				case "(sx)":
					if exp.Bf() == nil {
						fmt.Println("c")
						Ret(nil)
					} else if frm.Bf() == nil {
						fmt.Println("d")
						frm.Sbf(&AnyList{exp.Bf(), nil})
					} else if frm.Bf().Fi() == nil {
						fmt.Println("e")
						Ret(frm.Bf().Bf().Fi())
					} else {
						fmt.Println("f")
						C_ = &AnyList{&AnyList{frm.Bf().Fi(), nil}, C_}
						frm.Sbf(&AnyList{frm.Bf().Fi().(AnyLister).Bf(), nil}) // what if cast fails?
					}
				case "(prn)":
					fmt.Println("g")
					s, ok := exp.Bf().Fi().(string)
					Assert(ok, "WTF! (prn) takes a string")
					fmt.Println(s)
					Ret(s)
				default:
					Assert(false, "WTF! Can't call undefined function \""+t+"\"")
				}
			}
		}
	}
}

func PrintTree(ls interface{}) {
	switch t := ls.(type) {
	case nil:
		fmt.Print("( ) ")
	case AnyLister:
		fmt.Print("( ")
		for ls != nil {
			PrintTree(ls.(AnyLister).Fi())
			ls = ls.(AnyLister).Bf()
		}
		fmt.Print(") ")
	case string:
		fmt.Print(t + " ")
	}
}

func Ret(v interface{}) {
	if C_.Bf() != nil {
		C_.Bf().Fi().(AnyLister).La().Sbf(&AnyList{v, nil})
	}
	C_ = C_.Bf()
}

// currently unused
/*func Ln(ls AnyLister) int {
	if ls == nil {
		return 0
	}
	if ls.Bf() == nil {
		return 1
	}
	return Ln(ls.Bf()) + 1
}

func Nth(ls AnyLister, n int) AnyLister {
	Assert(ls != nil, "WTF! Out of bounds when calling (nth.")
	if n > 0 {
		return Nth(ls.Bf(), n-1)
	}
	if n < 0 {
		return Nth(ls, Ln(ls)-n)
	}
	return ls
}*/

func (ls *AnyList) Fi() interface{} {
	return ls.fi
}

func (ls *AnyList) Sfi(v interface{}) interface{} {
	ls.fi = v
	return v
}

func (ls *AnyList) Bf() AnyLister {
	return ls.bf
}

func (ls *AnyList) Sbf(v AnyLister) AnyLister {
	ls.bf = v
	return v
}

func (ls *AnyList) La() AnyLister {
	if ls.bf == nil {
		return ls
	}
	return ls.bf.La()
}

func Assert(cond bool, msg string) {
	if !cond {
		fmt.Println(msg)
		os.Exit(2)
	}
}
<commit_msg>parse ints<commit_after>package anylisp

import (
	"fmt"
	"math/big"
	"os"
)

type AnyLister interface {
	Fi() interface{}
	Sfi(v interface{}) interface{}
	Bf() AnyLister
	Sbf(v AnyLister) AnyLister
	La() AnyLister
}

type AnyList struct {
	fi interface{}
	bf AnyLister
}

type AnyInter interface {
	Cmp(y *big.Int) (r int)
	Int64() int64
}

var (
	Ps_      AnyLister
	C_       AnyLister
	TempRoot AnyLister
)

func Parse(code string) {
	TempRoot = &AnyList{"(sx)", nil}
	Ps_ = &AnyList{TempRoot, nil}
	C_ = &AnyList{&AnyList{TempRoot, nil}, nil}
	tok := ""
	for i := 0; i < len(code); i++ {
		if code[i] == ' ' || code[i] == '\t' || code[i] == '\n' {
			if tok == ")" {
				Assert(Ps_.Bf() != nil, "Parse WTF! Too many )s")
				Ps_ = Ps_.Bf()
			} else if len(tok) > 0 {
				var ls AnyLister
				if tok == "(" {
					ls = &AnyList{nil, nil}
				} else if tok[0] == '[' && tok[len(tok)-1] == ']' {
					for j := 1; j < len(tok)-1; j++ {
						Assert(tok[j] == '-' || (tok[j] >= '0' && tok[j] <= '9') || (tok[j] >= 'a' && tok[j] <= 'f'),
							"Parse WTF! Bad character in number")
					}
					bi := new(big.Int)
					_, err := fmt.Sscanf(tok[1:len(tok)-1], "%x", bi)
					Assert(err == nil, "Parse WTF! Bad number")
					ls = &AnyList{bi, nil}
				} else {
					ls = &AnyList{tok, nil}
				}
				if Ps_.Fi() == nil {
					Ps_.Bf().Fi().(AnyLister).Sfi(ls) // 1st token in list
				} else {
					Ps_.Fi().(AnyLister).Sbf(ls)
				}
				Ps_.Sfi(ls)
				if tok == "(" {
					Ps_ = &AnyList{nil, Ps_}
				}
			}
			tok = ""
		} else {
			tok += string(code[i])
		}
	}
	Assert(Ps_.Bf() == nil, "Parse WTF! Too few )s")
}

func Run() {
	for C_ != nil {
		frm := C_.Fi().(AnyLister)
		exp, ok := frm.Fi().(AnyLister)
		if !ok {
			fmt.Println("0")
			Ret(frm.Fi())
		} else {
			switch t := exp.Fi().(type) {
			case nil:
				Assert(false, "WTF! Can't call the empty set")
			case AnyLister:
				if frm.Bf() == nil {
					fmt.Println("a")
					C_ = &AnyList{&AnyList{t, nil}, C_}
				} else {
					fmt.Println("b")
					frm.Sfi(frm.Bf().Fi())
				}
			case string:
				switch t {
				case "(sx)":
					if exp.Bf() == nil {
						fmt.Println("c")
						Ret(nil)
					} else if frm.Bf() == nil {
						fmt.Println("d")
						frm.Sbf(&AnyList{exp.Bf(), nil})
					} else if frm.Bf().Fi() == nil {
						fmt.Println("e")
						Ret(frm.Bf().Bf().Fi())
					} else {
						fmt.Println("f")
						C_ = &AnyList{&AnyList{frm.Bf().Fi(), nil}, C_}
						frm.Sbf(&AnyList{frm.Bf().Fi().(AnyLister).Bf(), nil}) // what if cast fails?
					}
				case "(prn)":
					fmt.Println("g")
					s := make([]uint8, Ln(exp) - 1)
					for i, arg := 0, exp.Bf(); arg != nil; i, arg = i+1, arg.Bf() {
						c, ok := arg.Fi().(AnyInter)
						Assert(ok && c.Cmp(big.NewInt(-1)) == 1 && c.Cmp(big.NewInt(256)) == -1,
							"WTF! (prn) takes a string")
						s[i] = uint8(c.Int64())
					}
					fmt.Print(string(s))
					Ret(s)
				default:
					Assert(false, "WTF! Can't call undefined function \""+t+"\"")
				}
			}
		}
	}
}

func PrintTree(ls interface{}) {
	switch t := ls.(type) {
	case nil:
		fmt.Print("( ) ")
	case AnyLister:
		fmt.Print("( ")
		for ls != nil {
			PrintTree(ls.(AnyLister).Fi())
			ls = ls.(AnyLister).Bf()
		}
		fmt.Print(") ")
	case string:
		fmt.Print(t + " ")
	}
}

func Ret(v interface{}) {
	if C_.Bf() != nil {
		C_.Bf().Fi().(AnyLister).La().Sbf(&AnyList{v, nil})
	}
	C_ = C_.Bf()
}

func Ln(ls AnyLister) int {
	if ls == nil {
		return 0
	}
	if ls.Bf() == nil {
		return 1
	}
	return Ln(ls.Bf()) + 1
}

// currently unused
/*func Nth(ls AnyLister, n int) AnyLister {
	Assert(ls != nil, "WTF! Out of bounds when calling (nth.")
	if n > 0 {
		return Nth(ls.Bf(), n-1)
	}
	if n < 0 {
		return Nth(ls, Ln(ls)-n)
	}
	return ls
}*/

func (ls *AnyList) Fi() interface{} {
	return ls.fi
}

func (ls *AnyList) Sfi(v interface{}) interface{} {
	ls.fi = v
	return v
}

func (ls *AnyList) Bf() AnyLister {
	return ls.bf
}

func (ls *AnyList) Sbf(v AnyLister) AnyLister {
	ls.bf = v
	return v
}

func (ls *AnyList) La() AnyLister {
	if ls.bf == nil {
		return ls
	}
	return ls.bf.La()
}

func Assert(cond bool, msg string) {
	if !cond {
		fmt.Println(msg)
		os.Exit(2)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"golang.org/x/net/context"
	"google.golang.org/grpc/grpclog"
	"os"
	"sync"
	"sync/atomic"
	"time"

	pb "github.com/pandemicsyn/ort/api/proto"
)

type File struct {
	sync.RWMutex
	attr fuse.Attr
	path string
	fs   *CFS
	data []byte
}

// Probably need to acquire lock on the api server.
func (f *File) Attr(ctx context.Context, o *fuse.Attr) error {
	f.Lock()
	grpclog.Printf("Getting attrs for %s | %d", f.path, f.attr.Inode)

	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)

	a, err := f.fs.fc.GetAttr(rctx, &pb.FileRequest{Fpath: f.path, Inode: f.attr.Inode})
	if err != nil {
		grpclog.Fatalf("%v.GetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	f.attr.Mode = os.FileMode(a.Mode)
	f.attr.Size = a.Size
	f.attr.Mtime = time.Unix(a.Mtime, 0)
	*o = f.attr
	f.Unlock()
	return nil
}

func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
	grpclog.Printf("Calling open for %v", req)
	return f, nil
}

func (f *File) ReadAll(ctx context.Context) ([]byte, error) {
	f.RLock()
	out := make([]byte, len(f.data))
	grpclog.Printf("Getting attrs for %s | %d", f.path, f.attr.Inode)
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.Read(rctx, &pb.FileRequest{Fpath: f.path, Inode: f.attr.Inode})
	if err != nil {
		grpclog.Fatalf("%v.GetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	copy(out, rf.Payload)
	f.RUnlock()
	return out, nil
}

// Write only works with tiny writes right now and doesn't write/append chunks to the backend at all!
// We also write all data to memory AND the current chunk to the backend.
// So, the whole thing only sorta kinda works.
// TODO: Write chunks
// TODO: Update backend attrs (size!)
func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
	f.Lock()
	l := len(req.Data)
	end := int(req.Offset) + l
	if end > len(f.data) {
		delta := end - len(f.data)
		f.data = append(f.data, make([]byte, delta)...)
		f.attr.Size = uint64(len(f.data))
		atomic.AddInt64(&f.fs.size, int64(delta))
		grpclog.Printf("Updating attrs for %s | %d", f.path, f.attr.Inode)
		a := &pb.Attr{
			Parent: "something",
			Name:   f.path,
			Mode:   uint32(f.attr.Mode),
			Size:   f.attr.Size,
			Mtime:  f.attr.Mtime.Unix(),
		}
		rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
		rf, err := f.fs.fc.SetAttr(rctx, a)
		if err != nil {
			grpclog.Fatalf("%v.SetAttr(_) = _, %v: ", f.fs.fc, err)
		}
		grpclog.Printf("%v, Updated attrs: %+v", f.path, rf)
	}
	copy(f.data[req.Offset:end], req.Data)
	grpclog.Printf("Writing to backend for %s", f.path)
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.Write(rctx, &pb.File{Name: f.path, Payload: f.data})
	if err != nil {
		grpclog.Fatalf("%v.Write(_) = _, %v: ", f.fs.fc, err)
	}
	if rf.Status != 0 {
		grpclog.Println("Write status non zero")
	}
	copy(f.data[req.Offset:end], req.Data)
	resp.Size = l
	f.Unlock()
	return nil
}

func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest,
	resp *fuse.SetattrResponse) error {
	f.Lock()

	if req.Valid.Size() {
		delta := int(req.Size) - len(f.data)
		if delta > 0 {
			f.data = append(f.data, make([]byte, delta)...)
		} else {
			f.data = f.data[0:req.Size]
		}
		f.attr.Size = req.Size
		atomic.AddInt64(&f.fs.size, int64(delta))
	}

	if req.Valid.Mode() {
		f.attr.Mode = req.Mode
	}

	if req.Valid.Atime() {
		f.attr.Atime = req.Atime
	}

	if req.Valid.AtimeNow() {
		f.attr.Atime = time.Now()
	}

	if req.Valid.Mtime() {
		f.attr.Mtime = req.Mtime
	}

	if req.Valid.MtimeNow() {
		f.attr.Mtime = time.Now()
	}

	resp.Attr = f.attr
	grpclog.Printf("Writing attrs for %s", f.path)
	a := &pb.Attr{
		Parent: "something",
		Name:   f.path,
		Mode:   uint32(f.attr.Mode),
		Size:   f.attr.Size,
		Mtime:  f.attr.Mtime.Unix(),
	}
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.SetAttr(rctx, a)
	if err != nil {
		grpclog.Fatalf("%v.SetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	grpclog.Printf("%v, Updated attrs: %+v", f.path, rf)
	f.Unlock()
	return nil
}
<commit_msg>Update file write to use inode<commit_after>package main

import (
	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"golang.org/x/net/context"
	"google.golang.org/grpc/grpclog"
	"os"
	"sync"
	"sync/atomic"
	"time"

	pb "github.com/pandemicsyn/ort/api/proto"
)

type File struct {
	sync.RWMutex
	attr fuse.Attr
	path string
	fs   *CFS
	data []byte
}

// Probably need to acquire lock on the api server.
func (f *File) Attr(ctx context.Context, o *fuse.Attr) error {
	f.Lock()
	grpclog.Printf("Getting attrs for %s | %d", f.path, f.attr.Inode)

	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)

	a, err := f.fs.fc.GetAttr(rctx, &pb.FileRequest{Fpath: f.path, Inode: f.attr.Inode})
	if err != nil {
		grpclog.Fatalf("%v.GetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	f.attr.Mode = os.FileMode(a.Mode)
	f.attr.Size = a.Size
	f.attr.Mtime = time.Unix(a.Mtime, 0)
	*o = f.attr
	f.Unlock()
	return nil
}

func (f *File) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
	grpclog.Printf("Calling open for %v", req)
	return f, nil
}

func (f *File) ReadAll(ctx context.Context) ([]byte, error) {
	f.RLock()
	out := make([]byte, len(f.data))
	grpclog.Printf("Getting attrs for %s | %d", f.path, f.attr.Inode)
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.Read(rctx, &pb.FileRequest{Fpath: f.path, Inode: f.attr.Inode})
	if err != nil {
		grpclog.Fatalf("%v.GetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	copy(out, rf.Payload)
	f.RUnlock()
	return out, nil
}

// Write only works with tiny writes right now and doesn't write/append chunks to the backend at all!
// We also write all data to memory AND the current chunk to the backend.
// So, the whole thing only sorta kinda works.
// TODO: Write chunks
// TODO: Update backend attrs (size!)
func (f *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
	f.Lock()
	l := len(req.Data)
	end := int(req.Offset) + l
	if end > len(f.data) {
		delta := end - len(f.data)
		f.data = append(f.data, make([]byte, delta)...)
		f.attr.Size = uint64(len(f.data))
		atomic.AddInt64(&f.fs.size, int64(delta))
		grpclog.Printf("Updating attrs for %s | %d", f.path, f.attr.Inode)
		a := &pb.Attr{
			Parent: "something",
			Name:   f.path,
			Mode:   uint32(f.attr.Mode),
			Size:   f.attr.Size,
			Mtime:  f.attr.Mtime.Unix(),
		}
		rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
		rf, err := f.fs.fc.SetAttr(rctx, a)
		if err != nil {
			grpclog.Fatalf("%v.SetAttr(_) = _, %v: ", f.fs.fc, err)
		}
		grpclog.Printf("%v, Updated attrs: %+v", f.path, rf)
	}
	copy(f.data[req.Offset:end], req.Data)
	grpclog.Printf("Writing to backend for %s | f.attr.Inode", f.path)
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.Write(rctx, &pb.File{Name: f.path, Inode: f.attr.Inode, Payload: f.data})
	if err != nil {
		grpclog.Fatalf("%v.Write(_) = _, %v: ", f.fs.fc, err)
	}
	if rf.Status != 0 {
		grpclog.Println("Write status non zero")
	}
	copy(f.data[req.Offset:end], req.Data)
	resp.Size = l
	f.Unlock()
	return nil
}

func (f *File) Setattr(ctx context.Context, req *fuse.SetattrRequest,
	resp *fuse.SetattrResponse) error {
	f.Lock()

	if req.Valid.Size() {
		delta := int(req.Size) - len(f.data)
		if delta > 0 {
			f.data = append(f.data, make([]byte, delta)...)
		} else {
			f.data = f.data[0:req.Size]
		}
		f.attr.Size = req.Size
		atomic.AddInt64(&f.fs.size, int64(delta))
	}

	if req.Valid.Mode() {
		f.attr.Mode = req.Mode
	}

	if req.Valid.Atime() {
		f.attr.Atime = req.Atime
	}

	if req.Valid.AtimeNow() {
		f.attr.Atime = time.Now()
	}

	if req.Valid.Mtime() {
		f.attr.Mtime = req.Mtime
	}

	if req.Valid.MtimeNow() {
		f.attr.Mtime = time.Now()
	}

	resp.Attr = f.attr
	grpclog.Printf("Writing attrs for %s", f.path)
	a := &pb.Attr{
		Parent: "something",
		Name:   f.path,
		Mode:   uint32(f.attr.Mode),
		Size:   f.attr.Size,
		Mtime:  f.attr.Mtime.Unix(),
	}
	rctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	rf, err := f.fs.fc.SetAttr(rctx, a)
	if err != nil {
		grpclog.Fatalf("%v.SetAttr(_) = _, %v: ", f.fs.fc, err)
	}
	grpclog.Printf("%v, Updated attrs: %+v", f.path, rf)
	f.Unlock()
	return nil
}
<|endoftext|>


<commit_before>package turn

import (
	"bytes"
	"errors"
	"io"
)

// ChannelData represents the ChannelData Message.
//
// See RFC 5766 Section 11.4
type ChannelData struct {
	Data   []byte // can be subslice of Raw
	Length int    // ignored while encoding, len(Data) is used
	Number ChannelNumber
	Raw    []byte
}

// See https://tools.ietf.org/html/rfc5766#section-11:
//
// 0x4000 through 0x7FFF: These values are the allowed channel
// numbers (16,383 possible values).
const (
	maxChannelNumber = 0x7FFF
	minChannelNumber = 0x4000
)

// ErrInvalidChannelNumber means that channel number is not valid as by RFC 5766 Section 11.
var ErrInvalidChannelNumber = errors.New("channel number not in [0x4000, 0x7FFF]")

// isChannelNumberValid returns true if c complies to RFC 5766 Section 11.
func isChannelNumberValid(c ChannelNumber) bool {
	return c >= minChannelNumber && c <= maxChannelNumber
}

// Equal returns true if b == c.
func (c *ChannelData) Equal(b *ChannelData) bool {
	if c == nil && b == nil {
		return true
	}
	if c == nil || b == nil {
		return false
	}
	if c.Number != b.Number {
		return false
	}
	if len(c.Data) != len(b.Data) {
		return false
	}
	return bytes.Equal(c.Data, b.Data)
}

// grow ensures that internal buffer will fit v more bytes and
// increases it capacity if necessary.
func (c *ChannelData) grow(v int) {
	// Not performing any optimizations here
	// (e.g. preallocate len(buf) * 2 to reduce allocations)
	// because they are already done by []byte implementation.
	n := len(c.Raw) + v
	for cap(c.Raw) < n {
		c.Raw = append(c.Raw, 0)
	}
	c.Raw = c.Raw[:n]
}

// Reset resets ChannelData, data and underlying buffer length.
func (c *ChannelData) Reset() {
	c.Raw = c.Raw[:0]
	c.Length = 0
	c.Data = c.Data[:0]
}

// Encode encodes ChannelData Message to Raw.
func (c *ChannelData) Encode() {
	c.Raw = c.Raw[:0]
	c.WriteHeader()
	c.Raw = append(c.Raw, c.Data...)
}

// WriteHeader writes channel number and length.
func (c *ChannelData) WriteHeader() {
	if len(c.Raw) < channelDataHeaderSize {
		// Making WriteHeader call valid even when m.Raw
		// is nil or len(m.Raw) is less than needed for header.
		c.grow(channelDataHeaderSize)
	}
	// early bounds check to guarantee safety of writes below
	_ = c.Raw[:channelDataHeaderSize]
	bin.PutUint16(c.Raw[:channelNumberSize], uint16(c.Number))
	bin.PutUint16(c.Raw[channelNumberSize:channelDataHeaderSize],
		uint16(len(c.Data)),
	)
}

// ErrBadChannelDataLength means that channel data length is not equal
// to actual data length.
var ErrBadChannelDataLength = errors.New("channelData length != len(Data)")

// Decode decodes The ChannelData Message from Raw.
func (c *ChannelData) Decode() error {
	// Decoding message header.
	buf := c.Raw
	if len(buf) < channelDataHeaderSize {
		return io.ErrUnexpectedEOF
	}
	// Quick check for channel number.
	num := bin.Uint16(buf[0:channelNumberSize])
	c.Number = ChannelNumber(num)
	l := bin.Uint16(buf[channelNumberSize:channelDataHeaderSize])
	c.Data = buf[channelDataHeaderSize:]
	c.Length = int(l)
	if int(l) != len(buf[channelDataHeaderSize:]) {
		return ErrBadChannelDataLength
	}
	if !isChannelNumberValid(c.Number) {
		return ErrInvalidChannelNumber
	}
	return nil
}

const (
	channelDataLengthSize = channelNumberSize
	channelDataHeaderSize = channelNumberSize + channelDataLengthSize
)

// IsChannelData returns true if buf looks like the ChannelData Message.
func IsChannelData(buf []byte) bool {
	if len(buf) < channelDataHeaderSize {
		return false
	}
	// Quick check for channel number.
	num := bin.Uint16(buf[0:channelNumberSize])
	if !isChannelNumberValid(ChannelNumber(num)) {
		return false
	}
	// Check that length is valid.
	l := bin.Uint16(buf[channelNumberSize:channelDataHeaderSize])
	return int(l) == len(buf[channelDataHeaderSize:])
}
<commit_msg>chandata: remove misleading comment<commit_after>package turn

import (
	"bytes"
	"errors"
	"io"
)

// ChannelData represents the ChannelData Message.
//
// See RFC 5766 Section 11.4
type ChannelData struct {
	Data   []byte // can be subslice of Raw
	Length int    // ignored while encoding, len(Data) is used
	Number ChannelNumber
	Raw    []byte
}

// See https://tools.ietf.org/html/rfc5766#section-11:
//
// 0x4000 through 0x7FFF: These values are the allowed channel
// numbers (16,383 possible values).
const (
	maxChannelNumber = 0x7FFF
	minChannelNumber = 0x4000
)

// ErrInvalidChannelNumber means that channel number is not valid as by RFC 5766 Section 11.
var ErrInvalidChannelNumber = errors.New("channel number not in [0x4000, 0x7FFF]")

// isChannelNumberValid returns true if c complies to RFC 5766 Section 11.
func isChannelNumberValid(c ChannelNumber) bool {
	return c >= minChannelNumber && c <= maxChannelNumber
}

// Equal returns true if b == c.
func (c *ChannelData) Equal(b *ChannelData) bool {
	if c == nil && b == nil {
		return true
	}
	if c == nil || b == nil {
		return false
	}
	if c.Number != b.Number {
		return false
	}
	if len(c.Data) != len(b.Data) {
		return false
	}
	return bytes.Equal(c.Data, b.Data)
}

// grow ensures that internal buffer will fit v more bytes and
// increases it capacity if necessary.
func (c *ChannelData) grow(v int) {
	// Not performing any optimizations here
	// (e.g. preallocate len(buf) * 2 to reduce allocations)
	// because they are already done by []byte implementation.
	n := len(c.Raw) + v
	for cap(c.Raw) < n {
		c.Raw = append(c.Raw, 0)
	}
	c.Raw = c.Raw[:n]
}

// Reset resets ChannelData, data and underlying buffer length.
func (c *ChannelData) Reset() {
	c.Raw = c.Raw[:0]
	c.Length = 0
	c.Data = c.Data[:0]
}

// Encode encodes ChannelData Message to Raw.
func (c *ChannelData) Encode() {
	c.Raw = c.Raw[:0]
	c.WriteHeader()
	c.Raw = append(c.Raw, c.Data...)
}

// WriteHeader writes channel number and length.
func (c *ChannelData) WriteHeader() {
	if len(c.Raw) < channelDataHeaderSize {
		// Making WriteHeader call valid even when m.Raw
		// is nil or len(m.Raw) is less than needed for header.
		c.grow(channelDataHeaderSize)
	}
	// early bounds check to guarantee safety of writes below
	_ = c.Raw[:channelDataHeaderSize]
	bin.PutUint16(c.Raw[:channelNumberSize], uint16(c.Number))
	bin.PutUint16(c.Raw[channelNumberSize:channelDataHeaderSize],
		uint16(len(c.Data)),
	)
}

// ErrBadChannelDataLength means that channel data length is not equal
// to actual data length.
var ErrBadChannelDataLength = errors.New("channelData length != len(Data)")

// Decode decodes The ChannelData Message from Raw.
func (c *ChannelData) Decode() error {
	// Decoding message header.
	buf := c.Raw
	if len(buf) < channelDataHeaderSize {
		return io.ErrUnexpectedEOF
	}
	num := bin.Uint16(buf[0:channelNumberSize])
	c.Number = ChannelNumber(num)
	l := bin.Uint16(buf[channelNumberSize:channelDataHeaderSize])
	c.Data = buf[channelDataHeaderSize:]
	c.Length = int(l)
	if int(l) != len(buf[channelDataHeaderSize:]) {
		return ErrBadChannelDataLength
	}
	if !isChannelNumberValid(c.Number) {
		return ErrInvalidChannelNumber
	}
	return nil
}

const (
	channelDataLengthSize = channelNumberSize
	channelDataHeaderSize = channelNumberSize + channelDataLengthSize
)

// IsChannelData returns true if buf looks like the ChannelData Message.
func IsChannelData(buf []byte) bool {
	if len(buf) < channelDataHeaderSize {
		return false
	}
	// Quick check for channel number.
	num := bin.Uint16(buf[0:channelNumberSize])
	if !isChannelNumberValid(ChannelNumber(num)) {
		return false
	}
	// Check that length is valid.
	l := bin.Uint16(buf[channelNumberSize:channelDataHeaderSize])
	return int(l) == len(buf[channelDataHeaderSize:])
}
<|endoftext|>


<commit_before>// Unfancy resources embedding with Go.

package resources

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"text/template"
)

type File interface {
	io.Reader
	Stat() (os.FileInfo, error)
}

//Create a new Package.
func New() *Package {
	return &Package{
		Config: Config{
			Pkg:     "resources",
			Var:     "FS",
			Declare: true,
		},
		Files: make(map[string]File),
	}
}

//Configuration defines some details about the output Go file.
type Config struct {
	Pkg     string // Package name
	Var     string // Variable name to assign the file system to.
	Tag     string // Build tag, leave empty for no tag.
	Declare bool   // Dictates whatever there should be a defintion Variable
}

type Package struct {
	Config
	Files map[string]File
}

//Add a file to the package at the give path.
func (p *Package) Add(path string, file File) {
	p.Files[path] = file
}

//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(path string, file string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	p.Files[path] = f
	return nil
}

//Build the package
func (p *Package) Build(out io.Writer) error {
	return pkg.Execute(out, p)
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	return p.Build(f)
}

//Template

var pkg *template.Template

func reader(input io.Reader) (string, error) {

	var (
		buff       bytes.Buffer
		err        error
		blockwidth int = 12
		curblock   int = 0
	)

	b := make([]byte, blockwidth)

	for n, err := input.Read(b); err == nil; n, err = input.Read(b) {
		for i := 0; i < n; i++ {
			fmt.Fprintf(&buff, "0x%02x,", b[i])
			curblock++
			if curblock < blockwidth {
				continue
			}
			buff.WriteByte('\n')
			buff.Write([]byte{'\t', '\t'})
			curblock = 0
		}
	}

	return buff.String(), err
}

func init() {

	pkg = template.Must(template.New("file").Funcs(template.FuncMap{"reader": reader}).Parse(` File{
	  data: []byte{
	{{ reader . }}
  },
  fi: FileInfo {
	name:    "{{ .Stat.Name }}",
    size:    {{ .Stat.Size }},
	modTime: time.Unix({{ .Stat.ModTime.Unix }},{{ .Stat.ModTime.UnixNano }}),
    isDir:   {{ .Stat.IsDir }},
  },
}`))

	pkg = template.Must(pkg.New("pkg").Parse(`{{ if .Tag }}// +build {{ .Tag }}

{{ end }}//Generated by github.com/omeid/slurp/resources
package {{ .Pkg }}

import (
  "net/http"
  "time"
  "bytes"
  "os"
  "path/filepath"
  "strings"
  "errors"
)

{{ if .Declare }}
var {{ .Var }} http.FileSystem
{{ end }}

// Helper functions for easier file access.
func Open(name string) (http.File, error) {
	return {{ .Var }}.Open(name)
}

// http.FileSystem implementation.
type FileSystem struct {
	files map[string]File
}

func (fs *FileSystem) Open(name string) (http.File, error) {
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
	    strings.Contains(name, "\x00") {
		return nil, errors.New("http: invalid character in file path")
	}
	file, ok := fs.files[name]
	if !ok {
		files := []os.FileInfo{}
		for path, file := range fs.files {
			if strings.HasPrefix(path, name) {
				s, _ := file.Stat()
				files = append(files, s)
			}
		}

		if len(files) == 0 {
			return nil, os.ErrNotExist
		}

		//We have a directory.
		return &File{
		  fi: FileInfo{
				isDir: true,
				files: files,
			}}, nil
	}
	file.Reader = bytes.NewReader(file.data)
	return &file, nil
}

type File struct {
	*bytes.Reader
	data []byte
	fi FileInfo
}

// A noop-closer.
func (f *File) Close() error {
	return nil
}

func (f *File) Readdir(count int) ([]os.FileInfo, error) {
  return nil, os.ErrNotExist
}

func (f *File) Stat() (os.FileInfo, error) {
  return &f.fi, nil
}

type FileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	isDir   bool
	sys     interface{}

	files []os.FileInfo
}

func (f *FileInfo) Name() string {
	return f.name
}
func (f *FileInfo) Size() int64 {
	return f.size
}

func (f *FileInfo) Mode() os.FileMode {
	return f.mode
}

func (f *FileInfo) ModTime() time.Time {
	return f.modTime
}

func (f *FileInfo) IsDir() bool {
	return f.isDir
}

func (f *FileInfo) Readdir(count int) ([]os.FileInfo, error) {
	return f.files, nil
}

func (f *FileInfo) Sys() interface{} {
	return f.sys
}

func init() {
  {{ .Var }} = &FileSystem{
		files: map[string]File{
		  {{range $path, $file := .Files }} "/{{ $path }}": {{ template "file" $file }}, {{ end }}
		},
	  }
}
`))
}
<commit_msg>fix comments. Remove redundant API.<commit_after>// Unfancy resources embedding with Go.

package resources

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"text/template"
)

type File interface {
	io.Reader
	Stat() (os.FileInfo, error)
}

//Create a new Package.
func New() *Package {
	return &Package{
		Config: Config{
			Pkg:     "resources",
			Var:     "FS",
			Declare: true,
		},
		Files: make(map[string]File),
	}
}

//Configuration defines some details about the output Go file.
type Config struct {
	Pkg     string // Package name
	Var     string // Variable name to assign the file system to.
	Tag     string // Build tag, leave empty for no tag.
	Declare bool   // Dictates whatever there should be a defintion Variable
}

type Package struct {
	Config
	Files map[string]File
}

//Add a file to the package at the give path.
func (p *Package) Add(path string, file File) {
	p.Files[path] = file
}

//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(path string, file string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	p.Files[path] = f
	return nil
}

//Build the package
func (p *Package) Build(out io.Writer) error {
	return pkg.Execute(out, p)
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	return p.Build(f)
}

//Template

var pkg *template.Template

func reader(input io.Reader) (string, error) {

	var (
		buff       bytes.Buffer
		err        error
		blockwidth int = 12
		curblock   int = 0
	)

	b := make([]byte, blockwidth)

	for n, err := input.Read(b); err == nil; n, err = input.Read(b) {
		for i := 0; i < n; i++ {
			fmt.Fprintf(&buff, "0x%02x,", b[i])
			curblock++
			if curblock < blockwidth {
				continue
			}
			buff.WriteByte('\n')
			buff.Write([]byte{'\t', '\t'})
			curblock = 0
		}
	}

	return buff.String(), err
}

func init() {

	pkg = template.Must(template.New("file").Funcs(template.FuncMap{"reader": reader}).Parse(` File{
	  data: []byte{
	{{ reader . }}
  },
  fi: FileInfo {
	name:    "{{ .Stat.Name }}",
    size:    {{ .Stat.Size }},
	modTime: time.Unix({{ .Stat.ModTime.Unix }},{{ .Stat.ModTime.UnixNano }}),
    isDir:   {{ .Stat.IsDir }},
  },
}`))

	pkg = template.Must(pkg.New("pkg").Parse(`{{ if .Tag }}// +build {{ .Tag }}

{{ end }}//Generated by github.com/omeid/go-resources
package {{ .Pkg }}

import (
  "net/http"
  "time"
  "bytes"
  "os"
  "path/filepath"
  "strings"
  "errors"
)

{{ if .Declare }}
var {{ .Var }} http.FileSystem
{{ end }}

// http.FileSystem implementation.
type FileSystem struct {
	files map[string]File
}

func (fs *FileSystem) Open(name string) (http.File, error) {
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
	    strings.Contains(name, "\x00") {
		return nil, errors.New("http: invalid character in file path")
	}
	file, ok := fs.files[name]
	if !ok {
		files := []os.FileInfo{}
		for path, file := range fs.files {
			if strings.HasPrefix(path, name) {
				s, _ := file.Stat()
				files = append(files, s)
			}
		}

		if len(files) == 0 {
			return nil, os.ErrNotExist
		}

		//We have a directory.
		return &File{
		  fi: FileInfo{
				isDir: true,
				files: files,
			}}, nil
	}
	file.Reader = bytes.NewReader(file.data)
	return &file, nil
}

type File struct {
	*bytes.Reader
	data []byte
	fi FileInfo
}

// A noop-closer.
func (f *File) Close() error {
	return nil
}

func (f *File) Readdir(count int) ([]os.FileInfo, error) {
  return nil, os.ErrNotExist
}

func (f *File) Stat() (os.FileInfo, error) {
  return &f.fi, nil
}

type FileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	isDir   bool
	sys     interface{}

	files []os.FileInfo
}

func (f *FileInfo) Name() string {
	return f.name
}
func (f *FileInfo) Size() int64 {
	return f.size
}

func (f *FileInfo) Mode() os.FileMode {
	return f.mode
}

func (f *FileInfo) ModTime() time.Time {
	return f.modTime
}

func (f *FileInfo) IsDir() bool {
	return f.isDir
}

func (f *FileInfo) Readdir(count int) ([]os.FileInfo, error) {
	return f.files, nil
}

func (f *FileInfo) Sys() interface{} {
	return f.sys
}

func init() {
  {{ .Var }} = &FileSystem{
		files: map[string]File{
		  {{range $path, $file := .Files }} "/{{ $path }}": {{ template "file" $file }}, {{ end }}
		},
	  }
}
`))
}
<|endoftext|>


<commit_before>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dm

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"

	"github.com/docker/machine/libmachine/cert"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
)

var storeBasePath = cmd.JoinWithUserDir(".tsuru", "installs")

type DockerMachine struct {
	name          string
	storePath     string
	certsPath     string
	API           dockermachine.DockerMachineAPI
	machinesCount uint64
	config        DockerMachineConfig
}

type DockerMachineConfig struct {
	CAPath          string      `yaml:"ca-path,omitempty"`
	DriverOpts      *DriverOpts `yaml:"driver,omitempty"`
	DockerHubMirror string      `yaml:"docker-hub-mirror,omitempty"`
	DockerFlags     []string    `yaml:"docker-flags,omitempty"`
}

type DriverOpts struct {
	Name    string
	Options map[string]interface{} `yaml:",omitempty"`
}

type MachineProvisioner interface {
	ProvisionMachine(map[string]interface{}) (*dockermachine.Machine, error)
}

func NewDockerMachine(config DockerMachineConfig, name string) (*DockerMachine, error) {
	storePath := filepath.Join(storeBasePath, name)
	certsPath := filepath.Join(storePath, "certs")
	dm, err := dockermachine.NewDockerMachine(dockermachine.DockerMachineConfig{
		CaPath:    config.CAPath,
		OutWriter: os.Stdout,
		ErrWriter: os.Stderr,
		StorePath: storePath,
	})
	if err != nil {
		return nil, err
	}
	return &DockerMachine{
		API:       dm,
		name:      name,
		certsPath: certsPath,
		storePath: storePath,
		config:    config,
	}, nil
}

func (d *DockerMachine) ProvisionMachine(driverOpts map[string]interface{}) (*dockermachine.Machine, error) {
	m, err := d.CreateMachine(driverOpts)
	if err != nil {
		return nil, fmt.Errorf("error creating machine %s", err)
	}
	err = d.uploadRegistryCertificate(GetPrivateIP(m), m.Host.Driver.GetSSHUsername(), m.Host)
	if err != nil {
		return nil, fmt.Errorf("error uploading registry certificates to %s: %s", m.Base.Address, err)
	}
	return m, nil
}

func (d *DockerMachine) CreateMachine(driverOpts map[string]interface{}) (*dockermachine.Machine, error) {
	driverOpts["swarm-master"] = false
	driverOpts["swarm-host"] = ""
	driverOpts["engine-install-url"] = ""
	driverOpts["swarm-discovery"] = ""
	mergedOpts := make(map[string]interface{})
	for k, v := range d.config.DriverOpts.Options {
		mergedOpts[k] = v
	}
	for k, v := range driverOpts {
		mergedOpts[k] = v
	}
	m, err := d.API.CreateMachine(dockermachine.CreateMachineOpts{
		Name:           d.generateMachineName(),
		DriverName:     d.config.DriverOpts.Name,
		Params:         mergedOpts,
		RegistryMirror: d.config.DockerHubMirror,
		ArbitraryFlags: d.config.DockerFlags,
	})
	if err != nil {
		return nil, err
	}
	if m.Host.AuthOptions() != nil {
		m.Host.AuthOptions().ServerCertSANs = append(m.Host.AuthOptions().ServerCertSANs, GetPrivateIP(m))
		err = m.Host.ConfigureAuth()
		if err != nil {
			return nil, err
		}
	}
	return m, nil
}

func (d *DockerMachine) generateMachineName() string {
	atomic.AddUint64(&d.machinesCount, 1)
	return fmt.Sprintf("%s-%d", d.name, atomic.LoadUint64(&d.machinesCount))
}

func nixPathJoin(elem ...string) string {
	return strings.Join(elem, "/")
}

func (d *DockerMachine) uploadRegistryCertificate(ip, user string, target sshTarget) error {
	registryCertPath := filepath.Join(d.certsPath, "registry-cert.pem")
	registryKeyPath := filepath.Join(d.certsPath, "registry-key.pem")
	var registryIP string
	if _, errReg := os.Stat(registryCertPath); os.IsNotExist(errReg) {
		errCreate := d.createRegistryCertificate(ip)
		if errCreate != nil {
			return errCreate
		}
		registryIP = ip
	} else {
		certData, errRead := ioutil.ReadFile(registryCertPath)
		if errRead != nil {
			return fmt.Errorf("failed to read registry-cert.pem: %s", errRead)
		}
		block, _ := pem.Decode(certData)
		cert, errRead := x509.ParseCertificate(block.Bytes)
		if errRead != nil {
			return fmt.Errorf("failed to parse registry certificate: %s", errRead)
		}
		registryIP = cert.IPAddresses[0].String()
	}
	fmt.Printf("Uploading registry certificate...\n")
	certsBasePath := fmt.Sprintf("/home/%s/certs/%s:5000", user, registryIP)
	if _, err := target.RunSSHCommand(fmt.Sprintf("mkdir -p %s", certsBasePath)); err != nil {
		return err
	}
	dockerCertsPath := "/etc/docker/certs.d"
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo mkdir -p %s", dockerCertsPath)); err != nil {
		return err
	}
	fileCopies := map[string]string{
		registryCertPath:                         nixPathJoin(certsBasePath, "registry-cert.pem"),
		registryKeyPath:                          nixPathJoin(certsBasePath, "registry-key.pem"),
		filepath.Join(d.certsPath, "ca-key.pem"): nixPathJoin(dockerCertsPath, "ca-key.pem"),
		filepath.Join(d.certsPath, "ca.pem"):     nixPathJoin(dockerCertsPath, "ca.pem"),
		filepath.Join(d.certsPath, "cert.pem"):   nixPathJoin(dockerCertsPath, "cert.pem"),
		filepath.Join(d.certsPath, "key.pem"):    nixPathJoin(dockerCertsPath, "key.pem"),
	}
	for src, dst := range fileCopies {
		errWrite := writeRemoteFile(target, src, dst)
		if errWrite != nil {
			return errWrite
		}
	}
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo cp -r /home/%s/certs/* %s/", user, dockerCertsPath)); err != nil {
		return err
	}
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo cat %s/ca.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt", dockerCertsPath)); err != nil {
		return err
	}
	_, err := target.RunSSHCommand("sudo mkdir -p /var/lib/registry/")
	return err
}

func (d *DockerMachine) createRegistryCertificate(hosts ...string) error {
	fmt.Printf("Creating registry certificate...\n")
	caOrg := mcnutils.GetUsername()
	org := caOrg + ".<bootstrap>"
	generator := &cert.X509CertGenerator{}
	certOpts := &cert.Options{
		Hosts:       hosts,
		CertFile:    filepath.Join(d.certsPath, "registry-cert.pem"),
		KeyFile:     filepath.Join(d.certsPath, "registry-key.pem"),
		CAFile:      filepath.Join(d.certsPath, "ca.pem"),
		CAKeyFile:   filepath.Join(d.certsPath, "ca-key.pem"),
		Org:         org,
		Bits:        2048,
		SwarmMaster: false,
	}
	return generator.GenerateCert(certOpts)
}

func (d *DockerMachine) DeleteAll() error {
	return d.API.DeleteAll()
}

func (d *DockerMachine) Close() error {
	return d.API.Close()
}
<commit_msg>installer: enables setting docker storage driver and engine install url<commit_after>// Copyright 2016 tsuru-client authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dm

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"sync/atomic"

	"github.com/docker/machine/libmachine/cert"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/tsuru/tsuru/cmd"
	"github.com/tsuru/tsuru/iaas/dockermachine"
)

var storeBasePath = cmd.JoinWithUserDir(".tsuru", "installs")

type DockerMachine struct {
	name          string
	storePath     string
	certsPath     string
	API           dockermachine.DockerMachineAPI
	machinesCount uint64
	config        DockerMachineConfig
}

type DockerMachineConfig struct {
	CAPath              string      `yaml:"ca-path,omitempty"`
	DriverOpts          *DriverOpts `yaml:"driver,omitempty"`
	DockerHubMirror     string      `yaml:"docker-hub-mirror,omitempty"`
	DockerFlags         []string    `yaml:"docker-flags,omitempty"`
	DockerStorageDriver string      `yaml:"docker-storage-driver,omitempty"`
	DockerInstallURL    string      `yaml:"docker-install-url,omitempty"`
}

type DriverOpts struct {
	Name    string
	Options map[string]interface{} `yaml:",omitempty"`
}

type MachineProvisioner interface {
	ProvisionMachine(map[string]interface{}) (*dockermachine.Machine, error)
}

func NewDockerMachine(config DockerMachineConfig, name string) (*DockerMachine, error) {
	storePath := filepath.Join(storeBasePath, name)
	certsPath := filepath.Join(storePath, "certs")
	dm, err := dockermachine.NewDockerMachine(dockermachine.DockerMachineConfig{
		CaPath:    config.CAPath,
		OutWriter: os.Stdout,
		ErrWriter: os.Stderr,
		StorePath: storePath,
	})
	if err != nil {
		return nil, err
	}
	return &DockerMachine{
		API:       dm,
		name:      name,
		certsPath: certsPath,
		storePath: storePath,
		config:    config,
	}, nil
}

func (d *DockerMachine) ProvisionMachine(driverOpts map[string]interface{}) (*dockermachine.Machine, error) {
	m, err := d.CreateMachine(driverOpts)
	if err != nil {
		return nil, fmt.Errorf("error creating machine %s", err)
	}
	err = d.uploadRegistryCertificate(GetPrivateIP(m), m.Host.Driver.GetSSHUsername(), m.Host)
	if err != nil {
		return nil, fmt.Errorf("error uploading registry certificates to %s: %s", m.Base.Address, err)
	}
	return m, nil
}

func (d *DockerMachine) CreateMachine(driverOpts map[string]interface{}) (*dockermachine.Machine, error) {
	driverOpts["swarm-master"] = false
	driverOpts["swarm-host"] = ""
	driverOpts["engine-install-url"] = ""
	driverOpts["swarm-discovery"] = ""
	mergedOpts := make(map[string]interface{})
	for k, v := range d.config.DriverOpts.Options {
		mergedOpts[k] = v
	}
	for k, v := range driverOpts {
		mergedOpts[k] = v
	}
	m, err := d.API.CreateMachine(dockermachine.CreateMachineOpts{
		Name:                      d.generateMachineName(),
		DriverName:                d.config.DriverOpts.Name,
		Params:                    mergedOpts,
		RegistryMirror:            d.config.DockerHubMirror,
		ArbitraryFlags:            d.config.DockerFlags,
		DockerEngineStorageDriver: d.config.DockerStorageDriver,
		DockerEngineInstallURL:    d.config.DockerInstallURL,
	})
	if err != nil {
		return nil, err
	}
	if m.Host.AuthOptions() != nil {
		m.Host.AuthOptions().ServerCertSANs = append(m.Host.AuthOptions().ServerCertSANs, GetPrivateIP(m))
		err = m.Host.ConfigureAuth()
		if err != nil {
			return nil, err
		}
	}
	return m, nil
}

func (d *DockerMachine) generateMachineName() string {
	atomic.AddUint64(&d.machinesCount, 1)
	return fmt.Sprintf("%s-%d", d.name, atomic.LoadUint64(&d.machinesCount))
}

func nixPathJoin(elem ...string) string {
	return strings.Join(elem, "/")
}

func (d *DockerMachine) uploadRegistryCertificate(ip, user string, target sshTarget) error {
	registryCertPath := filepath.Join(d.certsPath, "registry-cert.pem")
	registryKeyPath := filepath.Join(d.certsPath, "registry-key.pem")
	var registryIP string
	if _, errReg := os.Stat(registryCertPath); os.IsNotExist(errReg) {
		errCreate := d.createRegistryCertificate(ip)
		if errCreate != nil {
			return errCreate
		}
		registryIP = ip
	} else {
		certData, errRead := ioutil.ReadFile(registryCertPath)
		if errRead != nil {
			return fmt.Errorf("failed to read registry-cert.pem: %s", errRead)
		}
		block, _ := pem.Decode(certData)
		cert, errRead := x509.ParseCertificate(block.Bytes)
		if errRead != nil {
			return fmt.Errorf("failed to parse registry certificate: %s", errRead)
		}
		registryIP = cert.IPAddresses[0].String()
	}
	fmt.Printf("Uploading registry certificate...\n")
	certsBasePath := fmt.Sprintf("/home/%s/certs/%s:5000", user, registryIP)
	if _, err := target.RunSSHCommand(fmt.Sprintf("mkdir -p %s", certsBasePath)); err != nil {
		return err
	}
	dockerCertsPath := "/etc/docker/certs.d"
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo mkdir -p %s", dockerCertsPath)); err != nil {
		return err
	}
	fileCopies := map[string]string{
		registryCertPath:                         nixPathJoin(certsBasePath, "registry-cert.pem"),
		registryKeyPath:                          nixPathJoin(certsBasePath, "registry-key.pem"),
		filepath.Join(d.certsPath, "ca-key.pem"): nixPathJoin(dockerCertsPath, "ca-key.pem"),
		filepath.Join(d.certsPath, "ca.pem"):     nixPathJoin(dockerCertsPath, "ca.pem"),
		filepath.Join(d.certsPath, "cert.pem"):   nixPathJoin(dockerCertsPath, "cert.pem"),
		filepath.Join(d.certsPath, "key.pem"):    nixPathJoin(dockerCertsPath, "key.pem"),
	}
	for src, dst := range fileCopies {
		errWrite := writeRemoteFile(target, src, dst)
		if errWrite != nil {
			return errWrite
		}
	}
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo cp -r /home/%s/certs/* %s/", user, dockerCertsPath)); err != nil {
		return err
	}
	if _, err := target.RunSSHCommand(fmt.Sprintf("sudo cat %s/ca.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt", dockerCertsPath)); err != nil {
		return err
	}
	_, err := target.RunSSHCommand("sudo mkdir -p /var/lib/registry/")
	return err
}

func (d *DockerMachine) createRegistryCertificate(hosts ...string) error {
	fmt.Printf("Creating registry certificate...\n")
	caOrg := mcnutils.GetUsername()
	org := caOrg + ".<bootstrap>"
	generator := &cert.X509CertGenerator{}
	certOpts := &cert.Options{
		Hosts:       hosts,
		CertFile:    filepath.Join(d.certsPath, "registry-cert.pem"),
		KeyFile:     filepath.Join(d.certsPath, "registry-key.pem"),
		CAFile:      filepath.Join(d.certsPath, "ca.pem"),
		CAKeyFile:   filepath.Join(d.certsPath, "ca-key.pem"),
		Org:         org,
		Bits:        2048,
		SwarmMaster: false,
	}
	return generator.GenerateCert(certOpts)
}

func (d *DockerMachine) DeleteAll() error {
	return d.API.DeleteAll()
}

func (d *DockerMachine) Close() error {
	return d.API.Close()
}
<|endoftext|>


<commit_before>package slack

import (
	"context"
	"net/url"
	"strconv"

	"github.com/lestrrat/go-slack/objects"
	"github.com/pkg/errors"
)

// ChannelsHistoryCall is created via Channels.History() method
type ChannelsHistoryCall struct {
	service   *ChannelsService
	channel   string // channel ID
	count     int    // 1-1000
	inclusive bool
	latest    string // range of time (end)
	oldest    string // range of time (start)
	timestamp string // used only when retrieving a single message
	unreads   bool   // Include unread_count_display in the output
}

func (s *ChannelsService) History(id string) *ChannelsHistoryCall {
	return &ChannelsHistoryCall{
		service: s,
		channel: id,
	}
}

func (c *ChannelsHistoryCall) Values() url.Values {
	v := url.Values{
		"token":   {c.service.token},
		"channel": {c.channel},
	}

	if c.count > 0 {
		v.Set("count", strconv.Itoa(c.count))
	}

	if c.inclusive {
		v.Set("inclusive", "1")
	}

	if len(c.latest) > 0 {
		v.Set("latest", c.latest)
	}

	if len(c.oldest) > 0 {
		v.Set("oldest", c.oldest)
	}

	if len(c.timestamp) > 0 {
		v.Set("ts", c.timestamp)
	}

	if c.unreads {
		v.Set("unreads", "1")
	}

	return v
}

func (c *ChannelsHistoryCall) Latest(s string) *ChannelsHistoryCall {
	c.latest = s
	return c
}

func (c *ChannelsHistoryCall) Oldest(s string) *ChannelsHistoryCall {
	c.oldest = s
	return c
}

func (c *ChannelsHistoryCall) Inclusive(b bool) *ChannelsHistoryCall {
	c.inclusive = b
	return c
}

func (c *ChannelsHistoryCall) Count(i int) *ChannelsHistoryCall {
	c.count = i
	return c
}

func (c *ChannelsHistoryCall) Unreads(b bool) *ChannelsHistoryCall {
	c.unreads = b
	return c
}

func (c *ChannelsHistoryCall) Do(ctx context.Context) (*ChannelsHistoryResponse, error) {
	const endpoint = "channels.history"

	var res struct {
		SlackResponse
		*ChannelsHistoryResponse
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.ChannelsHistoryResponse, nil
}

// ChannelsInfoCall is created via Channels.Info() method
type ChannelsInfoCall struct {
	service *ChannelsService
	channel string // channel ID
}

// Info returns the result of channels.info API
func (s *ChannelsService) Info(id string) *ChannelsInfoCall {
	return &ChannelsInfoCall{
		service: s,
		channel: id,
	}
}

func (c *ChannelsInfoCall) Values() url.Values {
	return url.Values{
		"token":   {c.service.token},
		"channel": {c.channel},
	}
}

func (c *ChannelsInfoCall) Do(ctx context.Context) (*objects.Channel, error) {
	const endpoint = "channels.info"
	var res struct {
		SlackResponse
		*objects.Channel `json:"channel"`
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.Channel, nil
}

// ChannelsListCall is created via Channels.List() method
type ChannelsListCall struct {
	service      *ChannelsService
	exclArchived bool
}

// List returns the result of channels.list API
func (s *ChannelsService) List() *ChannelsListCall {
	return &ChannelsListCall{
		service: s,
	}
}

func (c *ChannelsListCall) Values() url.Values {
	v := url.Values{
		"token": {c.service.token},
	}
	if c.exclArchived {
		v.Set("exclude_archived", "true")
	}
	return v
}

func (c *ChannelsListCall) ExcludeArchive(b bool) *ChannelsListCall {
	c.exclArchived = b
	return c
}

func (c *ChannelsListCall) Do(ctx context.Context) (objects.ChannelList, error) {
	const endpoint = "channels.list"
	var res struct {
		SlackResponse
		objects.ChannelList `json:"channels"`
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.ChannelList, nil
}
<commit_msg>Add channels.archive<commit_after>package slack

import (
	"context"
	"net/url"
	"strconv"

	"github.com/lestrrat/go-slack/objects"
	"github.com/pkg/errors"
)

// ChannelsArchiveCall is created via Channels.Archive() method
type ChannelsArchiveCall struct {
	service   *ChannelsService
	channel   string // channel ID
}

func (s *ChannelsService) Archive(id string) *ChannelsArchiveCall {
	return &ChannelsArchiveCall{
		service: s,
		channel: id,
	}
}

func (c *ChannelsArchiveCall) Values() url.Values {
	v := url.Values{
		"token":   {c.service.token},
		"channel": {c.channel},
	}
	return v
}

func (c *ChannelsArchiveCall) Do(ctx context.Context) error {
	const endpoint = "channels.archive"

	var res SlackResponse

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return errors.New(res.Error.String())
	}

	return nil
}

// ChannelsHistoryCall is created via Channels.History() method
type ChannelsHistoryCall struct {
	service   *ChannelsService
	channel   string // channel ID
	count     int    // 1-1000
	inclusive bool
	latest    string // range of time (end)
	oldest    string // range of time (start)
	timestamp string // used only when retrieving a single message
	unreads   bool   // Include unread_count_display in the output
}

func (s *ChannelsService) History(id string) *ChannelsHistoryCall {
	return &ChannelsHistoryCall{
		service: s,
		channel: id,
	}
}

func (c *ChannelsHistoryCall) Values() url.Values {
	v := url.Values{
		"token":   {c.service.token},
		"channel": {c.channel},
	}

	if c.count > 0 {
		v.Set("count", strconv.Itoa(c.count))
	}

	if c.inclusive {
		v.Set("inclusive", "1")
	}

	if len(c.latest) > 0 {
		v.Set("latest", c.latest)
	}

	if len(c.oldest) > 0 {
		v.Set("oldest", c.oldest)
	}

	if len(c.timestamp) > 0 {
		v.Set("ts", c.timestamp)
	}

	if c.unreads {
		v.Set("unreads", "1")
	}

	return v
}

func (c *ChannelsHistoryCall) Latest(s string) *ChannelsHistoryCall {
	c.latest = s
	return c
}

func (c *ChannelsHistoryCall) Oldest(s string) *ChannelsHistoryCall {
	c.oldest = s
	return c
}

func (c *ChannelsHistoryCall) Inclusive(b bool) *ChannelsHistoryCall {
	c.inclusive = b
	return c
}

func (c *ChannelsHistoryCall) Count(i int) *ChannelsHistoryCall {
	c.count = i
	return c
}

func (c *ChannelsHistoryCall) Unreads(b bool) *ChannelsHistoryCall {
	c.unreads = b
	return c
}

func (c *ChannelsHistoryCall) Do(ctx context.Context) (*ChannelsHistoryResponse, error) {
	const endpoint = "channels.history"

	var res struct {
		SlackResponse
		*ChannelsHistoryResponse
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.ChannelsHistoryResponse, nil
}

// ChannelsInfoCall is created via Channels.Info() method
type ChannelsInfoCall struct {
	service *ChannelsService
	channel string // channel ID
}

// Info returns the result of channels.info API
func (s *ChannelsService) Info(id string) *ChannelsInfoCall {
	return &ChannelsInfoCall{
		service: s,
		channel: id,
	}
}

func (c *ChannelsInfoCall) Values() url.Values {
	return url.Values{
		"token":   {c.service.token},
		"channel": {c.channel},
	}
}

func (c *ChannelsInfoCall) Do(ctx context.Context) (*objects.Channel, error) {
	const endpoint = "channels.info"
	var res struct {
		SlackResponse
		*objects.Channel `json:"channel"`
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.Channel, nil
}

// ChannelsListCall is created via Channels.List() method
type ChannelsListCall struct {
	service      *ChannelsService
	exclArchived bool
}

// List returns the result of channels.list API
func (s *ChannelsService) List() *ChannelsListCall {
	return &ChannelsListCall{
		service: s,
	}
}

func (c *ChannelsListCall) Values() url.Values {
	v := url.Values{
		"token": {c.service.token},
	}
	if c.exclArchived {
		v.Set("exclude_archived", "true")
	}
	return v
}

func (c *ChannelsListCall) ExcludeArchive(b bool) *ChannelsListCall {
	c.exclArchived = b
	return c
}

func (c *ChannelsListCall) Do(ctx context.Context) (objects.ChannelList, error) {
	const endpoint = "channels.list"
	var res struct {
		SlackResponse
		objects.ChannelList `json:"channels"`
	}

	if err := c.service.client.postForm(ctx, endpoint, c.Values(), &res); err != nil {
		return nil, errors.Wrapf(err, `failed to post to %s`, endpoint)
	}

	if !res.OK {
		return nil, errors.New(res.Error.String())
	}

	return res.ChannelList, nil
}
<|endoftext|>


<commit_before>package chatwork

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.chatwork.com/v2/"

type ApiKey string

type Chatwork struct {
	apiKey ApiKey
}

func NewChatwork(apiKey string) *Chatwork {
	c := new(Chatwork)
	c.apiKey = ApiKey(apiKey)
	return c
}

type endpoint string

func newEndpoint(format string, a ...interface{}) endpoint {
	return endpoint(baseURL + fmt.Sprintf(format, a...))
}

type chatworkRequest interface {
	endpoint() endpoint
}

type chatworkPostRequest interface {
	chatworkRequest
	values() *url.Values
}

type chatworkGetRequest interface {
	chatworkRequest
	params() string
}

func (c *Chatwork) post(req chatworkPostRequest) *http.Response {
	reqBody := strings.NewReader(req.values().Encode())
	request, requestError := http.NewRequest("POST", string(req.endpoint()), reqBody)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func (c *Chatwork) get(req chatworkGetRequest) *http.Response {
	url, params := string(req.endpoint()), req.params()
	if len(params) > 0 {
		url = url + "?" + params
	}
	request, requestError := http.NewRequest("", url, nil)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func decodeBody(res *http.Response, out interface{}) error {
	defer res.Body.Close()
	decoder := json.NewDecoder(res.Body)
	return decoder.Decode(out)
}

type Text string
type RoomId int64

type CreateMessageRequest struct {
	roomId RoomId
	body   Text
}

func NewCreateMessageRequest(roomId int64, body string) *CreateMessageRequest {
	m := new(CreateMessageRequest)
	m.roomId = RoomId(roomId)
	m.body = Text(body)
	return m
}

func (m *CreateMessageRequest) endpoint() endpoint {
	return newEndpoint("rooms/%d/messages", m.roomId)
}

func (m *CreateMessageRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(m.body))
	return &vs
}

type CreateMessageResponse struct {
	MessageId string `json:"message_id"`
}

func (c *Chatwork) CreateMessage(req *CreateMessageRequest) *CreateMessageResponse {
	httpRes := c.post(req)

	var res CreateMessageResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

type UserId int64
type UserIds []UserId

type CreateTaskRequest struct {
	roomId    RoomId
	body      Text
	assignees UserIds
	due       *time.Time
}

func (t *CreateTaskRequest) endpoint() endpoint {
	return newEndpoint("rooms/%d/tasks", t.roomId)
}

func (t *CreateTaskRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(t.body))
	vs.Add("to_ids", t.assignees.toString(","))
	if t.due != nil {
		vs.Add("limit", strconv.FormatInt(t.due.Unix(), 10))
	}
	return &vs
}

type CreateTaskResponse struct {
	TaskIds []int64 `json:"task_ids"`
}

func NewCreateTaskRequest(roomId int64, body string, assignees []int64, due *time.Time) *CreateTaskRequest {
	t := new(CreateTaskRequest)
	t.roomId = RoomId(roomId)
	t.body = Text(body)
	t.assignees = make([]UserId, len(assignees))
	for i, a := range assignees {
		t.assignees[i] = UserId(a)
	}
	t.due = due
	return t
}

func (c *Chatwork) CreateTask(req *CreateTaskRequest) *CreateTaskResponse {
	httpRes := c.post(req)

	var res CreateTaskResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

func (ids UserIds) toString(sep string) string {
	buf := make([]string, len(ids))
	for i, id := range ids {
		buf[i] = strconv.FormatInt(int64(id), 10)
	}
	return strings.Join(buf, sep)
}
<commit_msg>Add new method GetMessage<commit_after>package chatwork

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.chatwork.com/v2/"

type ApiKey string

type Chatwork struct {
	apiKey ApiKey
}

func NewChatwork(apiKey string) *Chatwork {
	c := new(Chatwork)
	c.apiKey = ApiKey(apiKey)
	return c
}

type endpoint string

func newEndpoint(format string, a ...interface{}) endpoint {
	return endpoint(baseURL + fmt.Sprintf(format, a...))
}

type chatworkRequest interface {
	endpoint() endpoint
}

type chatworkPostRequest interface {
	chatworkRequest
	values() *url.Values
}

type chatworkGetRequest interface {
	chatworkRequest
	params() string
}

func (c *Chatwork) post(req chatworkPostRequest) *http.Response {
	reqBody := strings.NewReader(req.values().Encode())
	request, requestError := http.NewRequest("POST", string(req.endpoint()), reqBody)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func (c *Chatwork) get(req chatworkGetRequest) *http.Response {
	url, params := string(req.endpoint()), req.params()
	if len(params) > 0 {
		url = url + "?" + params
	}
	request, requestError := http.NewRequest("", url, nil)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func decodeBody(res *http.Response, out interface{}) error {
	defer res.Body.Close()
	decoder := json.NewDecoder(res.Body)
	return decoder.Decode(out)
}

type Text string
type RoomId int64
type MessageId string

type CreateMessageRequest struct {
	roomId RoomId
	body   Text
}

func NewCreateMessageRequest(roomId int64, body string) *CreateMessageRequest {
	m := new(CreateMessageRequest)
	m.roomId = RoomId(roomId)
	m.body = Text(body)
	return m
}

func (m *CreateMessageRequest) endpoint() endpoint {
	return newEndpoint("rooms/%d/messages", m.roomId)
}

func (m *CreateMessageRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(m.body))
	return &vs
}

type CreateMessageResponse struct {
	MessageId string `json:"message_id"`
}

func (c *Chatwork) CreateMessage(req *CreateMessageRequest) *CreateMessageResponse {
	httpRes := c.post(req)

	var res CreateMessageResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

type GetMessageRequest struct {
	roomId    RoomId
	messageId MessageId
}

func NewGetMessageRequest(roomId int64, messageId string) *GetMessageRequest {
	m := new(GetMessageRequest)
	m.roomId = RoomId(roomId)
	m.messageId = MessageId(messageId)
	return m
}

func (m *GetMessageRequest) endpoint() endpoint {
	return newEndpoint("rooms/%d/messages/%s", m.roomId, m.messageId)
}

func (m *GetMessageRequest) params() string {
	return ""
}

type GetMessageResponse struct {
	MessageId string `json:"message_id"`
	User      struct {
		UserId    int64  `json:"account_id"`
		Name      string `json:"name"`
		AvatarUrl string `json:"avatar_image_url"`
	} `json:"account"`
	Body     string `json:"body"`
	sendAt   int64  `json:"send_time"`
	updateAt int64  `json:"update_time"`
}

func (c *Chatwork) GetMessage(req *GetMessageRequest) *GetMessageResponse {
	httpRes := c.get(req)

	var res GetMessageResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

type UserId int64
type UserIds []UserId

type CreateTaskRequest struct {
	roomId    RoomId
	body      Text
	assignees UserIds
	due       *time.Time
}

func (t *CreateTaskRequest) endpoint() endpoint {
	return newEndpoint("rooms/%d/tasks", t.roomId)
}

func (t *CreateTaskRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(t.body))
	vs.Add("to_ids", t.assignees.toString(","))
	if t.due != nil {
		vs.Add("limit", strconv.FormatInt(t.due.Unix(), 10))
	}
	return &vs
}

type CreateTaskResponse struct {
	TaskIds []int64 `json:"task_ids"`
}

func NewCreateTaskRequest(roomId int64, body string, assignees []int64, due *time.Time) *CreateTaskRequest {
	t := new(CreateTaskRequest)
	t.roomId = RoomId(roomId)
	t.body = Text(body)
	t.assignees = make([]UserId, len(assignees))
	for i, a := range assignees {
		t.assignees[i] = UserId(a)
	}
	t.due = due
	return t
}

func (c *Chatwork) CreateTask(req *CreateTaskRequest) *CreateTaskResponse {
	httpRes := c.post(req)

	var res CreateTaskResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

func (ids UserIds) toString(sep string) string {
	buf := make([]string, len(ids))
	for i, id := range ids {
		buf[i] = strconv.FormatInt(int64(id), 10)
	}
	return strings.Join(buf, sep)
}
<|endoftext|>


<commit_before>package chatwork

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.chatwork.com/v2/"

type ApiKey string

type Chatwork struct {
	apiKey ApiKey
}

func NewChatwork(apiKey string) *Chatwork {
	c := new(Chatwork)
	c.apiKey = ApiKey(apiKey)
	return c
}

type endpoint string

func (c *Chatwork) post(endpoint endpoint, vs url.Values) *http.Response {
	reqBody := strings.NewReader(vs.Encode())
	request, requestError := http.NewRequest("POST", string(endpoint), reqBody)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func decodeBody(res *http.Response, out interface{}) error {
	defer res.Body.Close()
	decoder := json.NewDecoder(res.Body)
	return decoder.Decode(out)
}

type Text string
type RoomId int64

type Message struct {
	roomId RoomId
	body   Text
}

type NewMessageResponse struct {
	MessageId string `json:"message_id"`
}

func NewMessage(roomId int64, body string) *Message {
	m := new(Message)
	m.roomId = RoomId(roomId)
	m.body = Text(body)
	return m
}

func endpointFmt(format string, a ...interface{}) string {
	return fmt.Sprintf(format, a)
}

func (c *Chatwork) CreateMessage(message *Message) *NewMessageResponse {
	endpoint := endpoint(baseURL + fmt.Sprintf("rooms/%d/messages", message.roomId))
	vs := url.Values{}
	vs.Add("body", string(message.body))
	res := c.post(endpoint, vs)

	var newMessageResponse NewMessageResponse
	if err := decodeBody(res, &newMessageResponse); err != nil {
		log.Fatal(err)
	}
	return &newMessageResponse
}

type UserId int64
type UserIds []UserId

type Task struct {
	roomId    RoomId
	body      Text
	assignees UserIds
	due       *time.Time
}

type NewTaskResponse struct {
	TaskIds []int64 `json:"task_ids"`
}

func NewTask(roomId int64, body string, assignees []int64, due *time.Time) *Task {
	t := new(Task)
	t.roomId = RoomId(roomId)
	t.body = Text(body)
	t.assignees = make([]UserId, len(assignees))
	for i, a := range assignees {
		t.assignees[i] = UserId(a)
	}
	t.due = due
	return t
}

func (c *Chatwork) CreateTask(task *Task) *NewTaskResponse {
	endpoint := endpoint(baseURL + fmt.Sprintf("rooms/%d/tasks", task.roomId))
	vs := url.Values{}
	vs.Add("body", string(task.body))
	vs.Add("to_ids", task.assignees.toString(","))
	if task.due != nil {
		vs.Add("limit", strconv.FormatInt(task.due.Unix(), 10))
	}
	res := c.post(endpoint, vs)

	var newTaskResponse NewTaskResponse
	if err := decodeBody(res, &newTaskResponse); err != nil {
		log.Fatal(err)
	}
	return &newTaskResponse
}

func (ids UserIds) toString(sep string) string {
	buf := make([]string, len(ids))
	for i, id := range ids {
		buf[i] = strconv.FormatInt(int64(id), 10)
	}
	return strings.Join(buf, sep)
}
<commit_msg>Rename Message to CreateMessageRequest<commit_after>package chatwork

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const baseURL = "https://api.chatwork.com/v2/"

type ApiKey string

type Chatwork struct {
	apiKey ApiKey
}

func NewChatwork(apiKey string) *Chatwork {
	c := new(Chatwork)
	c.apiKey = ApiKey(apiKey)
	return c
}

type endpoint string

func (c *Chatwork) post(endpoint endpoint, vs *url.Values) *http.Response {
	reqBody := strings.NewReader(vs.Encode())
	request, requestError := http.NewRequest("POST", string(endpoint), reqBody)
	if requestError != nil {
		log.Fatal(requestError)
	}

	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Add("X-ChatWorkToken", string(c.apiKey))

	httpClient := new(http.Client)
	res, error := httpClient.Do(request)
	if error != nil {
		log.Fatal(error)
	}
	return res
}

func decodeBody(res *http.Response, out interface{}) error {
	defer res.Body.Close()
	decoder := json.NewDecoder(res.Body)
	return decoder.Decode(out)
}

type Text string
type RoomId int64

type CreateMessageRequest struct {
	roomId RoomId
	body   Text
}

func NewCreateMessageRequest(roomId int64, body string) *CreateMessageRequest {
	m := new(CreateMessageRequest)
	m.roomId = RoomId(roomId)
	m.body = Text(body)
	return m
}

func (m *CreateMessageRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(m.body))
	return &vs
}

type CreateMessageResponse struct {
	MessageId string `json:"message_id"`
}

func endpointFmt(format string, a ...interface{}) string {
	return fmt.Sprintf(format, a)
}

func (c *Chatwork) CreateMessage(req *CreateMessageRequest) *CreateMessageResponse {
	endpoint := endpoint(baseURL + fmt.Sprintf("rooms/%d/messages", req.roomId))
	httpRes := c.post(endpoint, req.values())

	var res CreateMessageResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

type UserId int64
type UserIds []UserId

type CreateTaskRequest struct {
	roomId    RoomId
	body      Text
	assignees UserIds
	due       *time.Time
}

func (t *CreateTaskRequest) values() *url.Values {
	vs := url.Values{}
	vs.Add("body", string(t.body))
	vs.Add("to_ids", t.assignees.toString(","))
	if t.due != nil {
		vs.Add("limit", strconv.FormatInt(t.due.Unix(), 10))
	}
	return &vs
}

type CreateTaskResponse struct {
	TaskIds []int64 `json:"task_ids"`
}

func NewCreateTaskRequest(roomId int64, body string, assignees []int64, due *time.Time) *CreateTaskRequest {
	t := new(CreateTaskRequest)
	t.roomId = RoomId(roomId)
	t.body = Text(body)
	t.assignees = make([]UserId, len(assignees))
	for i, a := range assignees {
		t.assignees[i] = UserId(a)
	}
	t.due = due
	return t
}

func (c *Chatwork) CreateTask(req *CreateTaskRequest) *CreateTaskResponse {
	endpoint := endpoint(baseURL + fmt.Sprintf("rooms/%d/tasks", req.roomId))
	httpRes := c.post(endpoint, req.values())

	var res CreateTaskResponse
	if err := decodeBody(httpRes, &res); err != nil {
		log.Fatal(err)
	}
	return &res
}

func (ids UserIds) toString(sep string) string {
	buf := make([]string, len(ids))
	for i, id := range ids {
		buf[i] = strconv.FormatInt(int64(id), 10)
	}
	return strings.Join(buf, sep)
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
	"github.com/AlekSi/pointer"
	"github.com/k8s-community/github-integration/models"
	"gopkg.in/reform.v1"
)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.processPush(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	case "create":
		h.Infolog.Printf("create hook (ID %s)", hook.Id)
		err = h.processCreate(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	default:
		h.Infolog.Printf("Warning! Don't know how to process hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusOK).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := h.Env["USERMAN_BASE_URL"]

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Installation.Account.Login)

	code, err := client.User.Sync(user)
	if err != nil {
		return err
	}

	h.Infolog.Printf("Service user-man, method sync, returned code: %d", code)

	return nil
}

// processPush is used for start CI/CD process for some repository from push hook
func (h *Handler) processPush(c *router.Control, hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	// ToDO: process somehow kind of hooks without HeadCommit
	if evt.HeadCommit == nil {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - no HeadCommit inside", hook.Id)
		return nil
	}

	h.setInstallationID(*evt.Repo.Owner.Name, *evt.Installation.ID)

	prefix := "refs/heads/" + h.Env["GITHUBINT_BRANCH"]
	if !strings.HasPrefix(*evt.Ref, prefix) {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - branch %s", hook.Id, *evt.Ref)
		return nil
	}

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	version := strings.Trim(*evt.Ref, prefix)
	commitID := *evt.HeadCommit.ID
	version += "_" + commitID[0:5]

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
		Task: cicd.TaskDeploy,
		Version: &version,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

func (h *Handler) processCreate(c *router.Control, hook *githubhook.Hook) error {
	evt := github.CreateEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	// Process only tags
	if evt.RefType == nil || *evt.RefType != "tag" {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - not a tag", hook.Id)
		return nil
	}

	h.setInstallationID(*evt.Repo.Owner.Name, *evt.Installation.ID)

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.Ref,
		Task: cicd.TaskDeploy,
		Version: evt.Ref,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation for commit status update
	err = h.setInstallationID(*evt.Installation.Account.Login, *evt.Installation.ID)
	if err != nil {
		h.Errlog.Printf("Couldn't save installation: %+v", err)
	}

	return nil
}

// installationID gets installation from DB
func (h *Handler) installationID(username string) (*int, error) {
	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil {
		return nil, err
	}
	inst := st.(*models.Installation)

	return pointer.ToInt(inst.InstallationID), nil
}

func (h *Handler) setInstallationID(username string, instID int) error {
	var inst = &models.Installation{}

	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil && err != reform.ErrNoRows {
		return err
	}

	if err == nil {
		inst = st.(*models.Installation)
	}

	inst.InstallationID = instID
	inst.Username = username

	err = h.DB.Save(inst)

	return err
}
<commit_msg>Fix version style<commit_after>package handlers

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/google/go-github/github"
	"github.com/k8s-community/cicd"
	userManClient "github.com/k8s-community/user-manager/client"
	"github.com/takama/router"
	githubhook "gopkg.in/rjz/githubhook.v0"
	"github.com/AlekSi/pointer"
	"github.com/k8s-community/github-integration/models"
	"gopkg.in/reform.v1"
)

// WebHookHandler is common handler for web hooks (installation, repositories installation, push)
func (h *Handler) WebHookHandler(c *router.Control) {
	secret := []byte(h.Env["GITHUBINT_TOKEN"])

	hook, err := githubhook.Parse(secret, c.Request)
	if err != nil {
		h.Errlog.Printf("cannot parse hook (ID %s): %s", hook.Id, err)
		return
	}

	switch hook.Event {
	case "integration_installation":
		// Triggered when an integration has been installed or uninstalled by user.
		h.Infolog.Printf("initialization web hook (ID %s)", hook.Id)
		err = h.saveInstallation(hook)

	case "integration_installation_repositories":
		// Triggered when a repository is added or removed from an installation.
		h.Infolog.Printf("initialization web hook for user repositories (ID %s)", hook.Id)
		err = h.initialUserManagement(hook)

	case "push":
		// Any Git push to a Repository, including editing tags or branches.
		// Commits via API actions that update references are also counted. This is the default event.
		h.Infolog.Printf("push hook (ID %s)", hook.Id)
		err = h.processPush(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}

	case "create":
		h.Infolog.Printf("create hook (ID %s)", hook.Id)
		// ToDo: keep it for the future
		/*err = h.processCreate(c, hook)
		if err != nil {
			h.Infolog.Printf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
			c.Code(http.StatusBadRequest).Body(nil)
			return
		}*/
		return

	default:
		h.Infolog.Printf("Warning! Don't know how to process hook (ID %s), event = %s", hook.Id, hook.Event)
		c.Code(http.StatusOK).Body(nil)
		return
	}

	if err != nil {
		h.Errlog.Printf("cannot process hook (ID %s): %s", hook.Id, err)
		c.Code(http.StatusInternalServerError).Body(nil)
		return
	}

	h.Infolog.Printf("finished to process hook (ID %s)", hook.Id)
	c.Code(http.StatusOK).Body(nil)
}

// initialUserManagement is used for user activation in k8s system
func (h *Handler) initialUserManagement(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationRepositoriesEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	userManagerURL := h.Env["USERMAN_BASE_URL"]

	client, err := userManClient.NewClient(nil, userManagerURL)
	if err != nil {
		return err
	}

	h.Infolog.Print("Try to activate (sync) user in k8s system: ", *evt.Sender.Login)

	user := userManClient.NewUser(*evt.Installation.Account.Login)

	code, err := client.User.Sync(user)
	if err != nil {
		return err
	}

	h.Infolog.Printf("Service user-man, method sync, returned code: %d", code)

	return nil
}

// processPush is used for start CI/CD process for some repository from push hook
func (h *Handler) processPush(c *router.Control, hook *githubhook.Hook) error {
	evt := github.PushEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	// ToDO: process somehow kind of hooks without HeadCommit
	if evt.HeadCommit == nil {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - no HeadCommit inside", hook.Id)
		return nil
	}

	h.setInstallationID(*evt.Repo.Owner.Name, *evt.Installation.ID)

	prefix := "refs/heads/" + h.Env["GITHUBINT_BRANCH"]
	if !strings.HasPrefix(*evt.Ref, prefix) {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - branch %s", hook.Id, *evt.Ref)
		return nil
	}

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	version := strings.Trim(*evt.Ref, prefix)
	commitID := *evt.HeadCommit.ID
	version += "-" + commitID[0:7]

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.HeadCommit.ID,
		Task: cicd.TaskDeploy,
		Version: &version,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

func (h *Handler) processCreate(c *router.Control, hook *githubhook.Hook) error {
	evt := github.CreateEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	// Process only tags
	if evt.RefType == nil || *evt.RefType != "tag" {
		h.Infolog.Printf("Warning! Don't know how to process hook %s - not a tag", hook.Id)
		return nil
	}

	h.setInstallationID(*evt.Repo.Owner.Name, *evt.Installation.ID)

	ciCdURL := h.Env["CICD_BASE_URL"]

	client := cicd.NewClient(ciCdURL)

	// run CICD process
	req := &cicd.BuildRequest{
		Username:   *evt.Repo.Owner.Name,
		Repository: *evt.Repo.Name,
		CommitHash: *evt.Ref,
		Task: cicd.TaskDeploy,
		Version: evt.Ref,
	}

	_, err = client.Build(req)
	if err != nil {
		return fmt.Errorf("cannot run ci/cd process for hook (ID %s): %s", hook.Id, err)
	}

	return nil
}

// saveInstallation saves installation in memory
func (h *Handler) saveInstallation(hook *githubhook.Hook) error {
	evt := github.IntegrationInstallationEvent{}

	err := hook.Extract(&evt)
	if err != nil {
		return err
	}

	h.Infolog.Printf("save installation for user %s (installation ID = %d)", *evt.Sender.Login, *evt.Installation.ID)

	// save installation for commit status update
	err = h.setInstallationID(*evt.Installation.Account.Login, *evt.Installation.ID)
	if err != nil {
		h.Errlog.Printf("Couldn't save installation: %+v", err)
	}

	return nil
}

// installationID gets installation from DB
func (h *Handler) installationID(username string) (*int, error) {
	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil {
		return nil, err
	}
	inst := st.(*models.Installation)

	return pointer.ToInt(inst.InstallationID), nil
}

func (h *Handler) setInstallationID(username string, instID int) error {
	var inst = &models.Installation{}

	st, err := h.DB.FindOneFrom(models.InstallationTable, "username", username)
	if err != nil && err != reform.ErrNoRows {
		return err
	}

	if err == nil {
		inst = st.(*models.Installation)
	}

	inst.InstallationID = instID
	inst.Username = username

	err = h.DB.Save(inst)

	return err
}
<|endoftext|>


<commit_before>package hap

import (
	"bytes"
	"io/ioutil"
	"log"
	"net"
	"sync"

	"github.com/brutella/hc/db"
	"github.com/brutella/hc/model/accessory"
	"github.com/brutella/hc/model/characteristic"
	"github.com/brutella/hc/model/container"
	"github.com/brutella/hc/netio"
	"github.com/brutella/hc/netio/event"
	"github.com/brutella/hc/server"
	"github.com/brutella/hc/util"
	"github.com/gosexy/to"
)

type ipTransport struct {
	context netio.HAPContext
	server  server.Server
	mutex   *sync.Mutex
	mdns    *MDNSService

	storage  util.Storage
	database db.Database

	name      string
	device    netio.SecuredDevice
	container *container.Container
}

// NewIPTransport creates a transport to provide accessories over IP.
// The pairing is secured using a 8-numbers password.
// If more than one accessory is provided, the first becomes a bridge in HomeKit.
// It's fine when the bridge has no explicit services.
//
// All accessory specific data (crypto keys, ids) is stored in a folder named after the first accessory.
// So changing the order of the accessories or renaming the first accessory makes the stored
// data inaccessible to the tranport. In this case new crypto keys are created and the accessory
// appears as a new one to clients.
func NewIPTransport(password string, a *accessory.Accessory, as ...*accessory.Accessory) (Transport, error) {
	// Find transport name which is visible in mDNS
	name := a.Name()
	if len(name) == 0 {
		log.Fatal("Invalid empty name for first accessory")
	}

	hapPassword, err := NewPassword(password)
	if err != nil {
		return nil, err
	}

	storage, err := util.NewFileStorage(name)
	if err != nil {
		return nil, err
	}

	// Find transport uuid which appears as "id" txt record in mDNS and
	// must be unique and stay the same over time
	uuid := transportUUIDInStorage(storage)
	database := db.NewDatabaseWithStorage(storage)
	device, err := netio.NewSecuredDevice(uuid, hapPassword, database)

	t := &ipTransport{
		database:  database,
		name:      name,
		device:    device,
		container: container.NewContainer(),
		mutex:     &sync.Mutex{},
		context:   netio.NewContextForSecuredDevice(device),
	}

	t.addAccessory(a)
	for _, a := range as {
		t.addAccessory(a)
	}

	return t, err
}

func (t *ipTransport) Start() {
	s := server.NewServer(t.context, t.database, t.container, t.device, t.mutex)
	t.server = s
	port := to.Int64(s.Port())

	mdns := NewMDNSService(t.name, t.device.Name(), int(port))
	t.mdns = mdns

	dns := t.database.DNSWithName(t.name)
	if dns == nil {
		dns = db.NewDNS(t.name, 1, 1)
		t.database.SaveDNS(dns)
	}
	mdns.Publish()
	// Listen until server.Stop() is called
	s.ListenAndServe()
}

// Stop stops the ip transport by unpublishing the mDNS service.
func (t *ipTransport) Stop() {
	if t.mdns != nil {
		t.mdns.Stop()
	}

	if t.server != nil {
		t.server.Stop()
	}
}

func (t *ipTransport) addAccessory(a *accessory.Accessory) {
	t.container.AddAccessory(a)

	for _, s := range a.Services {
		for _, c := range s.Characteristics {
			// When a characteristic value changes and events are enabled for this characteristic
			// all listeners are notified. Since we don't track which client is interested in
			// which characteristic change event, we send them to all active connections.
			onConnChange := func(conn net.Conn, c *characteristic.Characteristic, new, old interface{}) {
				if c.Events == true {
					t.notifyListener(a, c, conn)
				}
			}
			c.OnConnChange(onConnChange)

			onChange := func(c *characteristic.Characteristic, new, old interface{}) {
				if c.Events == true {
					t.notifyListener(a, c, nil)
				}
			}
			c.OnChange(onChange)
		}
	}
}

func (t *ipTransport) notifyListener(a *accessory.Accessory, c *characteristic.Characteristic, except net.Conn) {
	conns := t.context.ActiveConnections()
	for _, conn := range conns {
		if conn == except {
			continue
		}
		resp, err := event.New(a, c)
		if err != nil {
			log.Fatal(err)
		}

		// Write response into buffer to replace HTTP protocol
		// specifier with EVENT as required by HAP
		var buffer = new(bytes.Buffer)
		resp.Write(buffer)
		bytes, err := ioutil.ReadAll(buffer)
		bytes = event.FixProtocolSpecifier(bytes)
		log.Printf("[VERB] %s <- %s", conn.RemoteAddr(), string(bytes))
		conn.Write(bytes)
	}
}

// transportUUIDInStorage returns the uuid stored in storage or
// creates a new random uuid and stores it.
func transportUUIDInStorage(storage util.Storage) string {
	uuid, err := storage.Get("uuid")
	if len(uuid) == 0 || err != nil {
		str := util.RandomHexString()
		uuid = []byte(netio.MAC48Address(str))
		err := storage.Set("uuid", uuid)
		if err != nil {
			log.Fatal(err)
		}
	}
	return string(uuid)
}

// updateConfiguration increases the configuration value by 1 and re-announces the new TXT records.
// This method is currently not used.
func (t *ipTransport) updateConfiguration() {
	dns := t.database.DNSWithName(t.name)
	if dns != nil {
		dns.SetConfiguration(dns.Configuration() + 1)
		t.database.SaveDNS(dns)
		if t.mdns != nil {
			t.mdns.Update()
		}
	}
}
<commit_msg>Use github.com/brutella/log for event logging<commit_after>package hap

import (
	"bytes"
	"io/ioutil"
	"net"
	"sync"

	"github.com/brutella/hc/db"
	"github.com/brutella/hc/model/accessory"
	"github.com/brutella/hc/model/characteristic"
	"github.com/brutella/hc/model/container"
	"github.com/brutella/hc/netio"
	"github.com/brutella/hc/netio/event"
	"github.com/brutella/hc/server"
	"github.com/brutella/hc/util"
	"github.com/brutella/log"
	"github.com/gosexy/to"
)

type ipTransport struct {
	context netio.HAPContext
	server  server.Server
	mutex   *sync.Mutex
	mdns    *MDNSService

	storage  util.Storage
	database db.Database

	name      string
	device    netio.SecuredDevice
	container *container.Container
}

// NewIPTransport creates a transport to provide accessories over IP.
// The pairing is secured using a 8-numbers password.
// If more than one accessory is provided, the first becomes a bridge in HomeKit.
// It's fine when the bridge has no explicit services.
//
// All accessory specific data (crypto keys, ids) is stored in a folder named after the first accessory.
// So changing the order of the accessories or renaming the first accessory makes the stored
// data inaccessible to the tranport. In this case new crypto keys are created and the accessory
// appears as a new one to clients.
func NewIPTransport(password string, a *accessory.Accessory, as ...*accessory.Accessory) (Transport, error) {
	// Find transport name which is visible in mDNS
	name := a.Name()
	if len(name) == 0 {
		log.Fatal("Invalid empty name for first accessory")
	}

	hapPassword, err := NewPassword(password)
	if err != nil {
		return nil, err
	}

	storage, err := util.NewFileStorage(name)
	if err != nil {
		return nil, err
	}

	// Find transport uuid which appears as "id" txt record in mDNS and
	// must be unique and stay the same over time
	uuid := transportUUIDInStorage(storage)
	database := db.NewDatabaseWithStorage(storage)
	device, err := netio.NewSecuredDevice(uuid, hapPassword, database)

	t := &ipTransport{
		database:  database,
		name:      name,
		device:    device,
		container: container.NewContainer(),
		mutex:     &sync.Mutex{},
		context:   netio.NewContextForSecuredDevice(device),
	}

	t.addAccessory(a)
	for _, a := range as {
		t.addAccessory(a)
	}

	return t, err
}

func (t *ipTransport) Start() {
	s := server.NewServer(t.context, t.database, t.container, t.device, t.mutex)
	t.server = s
	port := to.Int64(s.Port())

	mdns := NewMDNSService(t.name, t.device.Name(), int(port))
	t.mdns = mdns

	dns := t.database.DNSWithName(t.name)
	if dns == nil {
		dns = db.NewDNS(t.name, 1, 1)
		t.database.SaveDNS(dns)
	}
	mdns.Publish()
	// Listen until server.Stop() is called
	s.ListenAndServe()
}

// Stop stops the ip transport by unpublishing the mDNS service.
func (t *ipTransport) Stop() {
	if t.mdns != nil {
		t.mdns.Stop()
	}

	if t.server != nil {
		t.server.Stop()
	}
}

func (t *ipTransport) addAccessory(a *accessory.Accessory) {
	t.container.AddAccessory(a)

	for _, s := range a.Services {
		for _, c := range s.Characteristics {
			// When a characteristic value changes and events are enabled for this characteristic
			// all listeners are notified. Since we don't track which client is interested in
			// which characteristic change event, we send them to all active connections.
			onConnChange := func(conn net.Conn, c *characteristic.Characteristic, new, old interface{}) {
				if c.Events == true {
					t.notifyListener(a, c, conn)
				}
			}
			c.OnConnChange(onConnChange)

			onChange := func(c *characteristic.Characteristic, new, old interface{}) {
				if c.Events == true {
					t.notifyListener(a, c, nil)
				}
			}
			c.OnChange(onChange)
		}
	}
}

func (t *ipTransport) notifyListener(a *accessory.Accessory, c *characteristic.Characteristic, except net.Conn) {
	conns := t.context.ActiveConnections()
	for _, conn := range conns {
		if conn == except {
			continue
		}
		resp, err := event.New(a, c)
		if err != nil {
			log.Fatal(err)
		}

		// Write response into buffer to replace HTTP protocol
		// specifier with EVENT as required by HAP
		var buffer = new(bytes.Buffer)
		resp.Write(buffer)
		bytes, err := ioutil.ReadAll(buffer)
		bytes = event.FixProtocolSpecifier(bytes)
		log.Printf("[VERB] %s <- %s", conn.RemoteAddr(), string(bytes))
		conn.Write(bytes)
	}
}

// transportUUIDInStorage returns the uuid stored in storage or
// creates a new random uuid and stores it.
func transportUUIDInStorage(storage util.Storage) string {
	uuid, err := storage.Get("uuid")
	if len(uuid) == 0 || err != nil {
		str := util.RandomHexString()
		uuid = []byte(netio.MAC48Address(str))
		err := storage.Set("uuid", uuid)
		if err != nil {
			log.Fatal(err)
		}
	}
	return string(uuid)
}

// updateConfiguration increases the configuration value by 1 and re-announces the new TXT records.
// This method is currently not used.
func (t *ipTransport) updateConfiguration() {
	dns := t.database.DNSWithName(t.name)
	if dns != nil {
		dns.SetConfiguration(dns.Configuration() + 1)
		t.database.SaveDNS(dns)
		if t.mdns != nil {
			t.mdns.Update()
		}
	}
}
<|endoftext|>


<commit_before>package heartbeat

import (
	"net"
	"sync"
	"time"

	"github.com/bahadley/mgc/log"
)

var (
	send bool

	wg sync.WaitGroup
)

func Transmit() {
	addrs := DstAddr()

	// Counting semaphore set to the number of addrs.
	wg.Add(len(addrs))

	// Launch all threads.  Each thread has a different destination.
	for _, addr := range addrs {
		go egress(addr)
	}

	// Wait for the threads to finish.
	wg.Wait()
}

func egress(addr string) {
	dstAddr, err := net.ResolveUDPAddr("udp",
		addr+":"+DstPort())
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	srcAddr, err := net.ResolveUDPAddr("udp",
		Addr()+":0")
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	conn, err := net.DialUDP("udp", srcAddr, dstAddr)
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	defer conn.Close()
	defer wg.Done()

	hbs := NumHeartbeats()
	delayInt := DelayInterval()
	msg := []byte("alive")

	for i := 0; i < hbs; i++ {
		log.Trace.Printf("Tx(%s): %s", dstAddr, msg)

		if !send {
			continue
		}

		_, err = conn.Write(msg)
		if err != nil {
			log.Warning.Println(err.Error())
		}

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

func init() {
	send = Send()
}
<commit_msg>Ensure delay interval is effective for no send executions<commit_after>package heartbeat

import (
	"net"
	"sync"
	"time"

	"github.com/bahadley/mgc/log"
)

var (
	send bool

	wg sync.WaitGroup
)

func Transmit() {
	addrs := DstAddr()

	// Counting semaphore set to the number of addrs.
	wg.Add(len(addrs))

	// Launch all threads.  Each thread has a different destination.
	for _, addr := range addrs {
		go egress(addr)
	}

	// Wait for the threads to finish.
	wg.Wait()
}

func egress(addr string) {
	dstAddr, err := net.ResolveUDPAddr("udp",
		addr+":"+DstPort())
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	srcAddr, err := net.ResolveUDPAddr("udp",
		Addr()+":0")
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	conn, err := net.DialUDP("udp", srcAddr, dstAddr)
	if err != nil {
		log.Error.Fatal(err.Error())
	}

	defer conn.Close()
	defer wg.Done()

	hbs := NumHeartbeats()
	delayInt := DelayInterval()
	msg := []byte("alive")

	for i := 0; i < hbs; i++ {
		log.Trace.Printf("Tx(%s): %s", dstAddr, msg)

		if send {
			_, err = conn.Write(msg)
			if err != nil {
				log.Warning.Println(err.Error())
			}
		}

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

func init() {
	send = Send()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/rpheuts/routery/config"
	"github.com/rpheuts/routery/frontends"
	"github.com/rpheuts/routery/logger"
	"github.com/rpheuts/routery/providers"
	"github.com/rpheuts/routery/router"
	"log"
)

func main() {
	// Load config file and set logging preferences
	cfg := config.GetConfig("config.yaml")
	logger.SetLogging(cfg.Logging.File, cfg.Logging.Path)
	log.Println("Config loaded...")

	// Initialize the providers that provide routing requests
	initializeProviders(cfg)

	// DEV: Idle until termination
	terminate := make(chan bool)
	defer close(terminate)
	<-terminate
}

func initializeProviders(cfg *config.RouteryConfig) {
	routeRequestChan := make(chan *router.RouteRequest)

	// Initialize Docker Providers
	for _, dockerConfig := range cfg.Docker {
		p := providers.DockerProvider{}
		p.Initialize(&providers.ProviderConfig{true, &dockerConfig})
		p.Provide(routeRequestChan)

		log.Printf("Registered Docker Provider. IP: %v Port: %v SSL: %v\n", dockerConfig.IP, dockerConfig.Port, dockerConfig.SSL)
	}

	// Initialize Frontends
	var listenerChannels = []chan *router.RouteRequest{}
	for _, frontendConfig := range cfg.Frontend {
		p := frontends.ForwardFrontend{}
		p.Initialize(&frontends.FrontendConfig{true, frontendConfig.Hostname, frontendConfig.Port})

		routeRequestListenerChan := make(chan *router.RouteRequest)
		p.Route(routeRequestListenerChan)
		listenerChannels = append(listenerChannels, routeRequestListenerChan)

		log.Printf("Registered Forwarder Frontend. Hostname: %v Port: %v\n", frontendConfig.Hostname, frontendConfig.Port)
	}

	// Start dispatching route requests
	go routeRequestDispatcher(listenerChannels, routeRequestChan)
}

func routeRequestDispatcher(listenerChannels []chan *router.RouteRequest, routeRequestChan chan *router.RouteRequest) {
	for {
		event := <-routeRequestChan

		// Broadcast on all channels
		for _, channel := range listenerChannels {
			channel <- event
		}
	}
}
<commit_msg>Added example config file<commit_after>package main

import (
	"github.com/rpheuts/routery/config"
	"github.com/rpheuts/routery/frontends"
	"github.com/rpheuts/routery/logger"
	"github.com/rpheuts/routery/providers"
	"github.com/rpheuts/routery/router"
	"log"
)

func main() {
	// Load config file and set logging preferences
	cfg := config.GetConfig("routery.yaml")
	logger.SetLogging(cfg.Logging.File, cfg.Logging.Path)
	log.Println("Config loaded...")

	// Initialize the providers that provide routing requests
	initializeProviders(cfg)

	// DEV: Idle until termination
	terminate := make(chan bool)
	defer close(terminate)
	<-terminate
}

func initializeProviders(cfg *config.RouteryConfig) {
	routeRequestChan := make(chan *router.RouteRequest)

	// Initialize Docker Providers
	for _, dockerConfig := range cfg.Docker {
		p := providers.DockerProvider{}
		p.Initialize(&providers.ProviderConfig{true, &dockerConfig})
		p.Provide(routeRequestChan)

		log.Printf("Registered Docker Provider. IP: %v Port: %v SSL: %v\n", dockerConfig.IP, dockerConfig.Port, dockerConfig.SSL)
	}

	// Initialize Frontends
	var listenerChannels = []chan *router.RouteRequest{}
	for _, frontendConfig := range cfg.Frontend {
		p := frontends.ForwardFrontend{}
		p.Initialize(&frontends.FrontendConfig{true, frontendConfig.Hostname, frontendConfig.Port})

		routeRequestListenerChan := make(chan *router.RouteRequest)
		p.Route(routeRequestListenerChan)
		listenerChannels = append(listenerChannels, routeRequestListenerChan)

		log.Printf("Registered Forwarder Frontend. Hostname: %v Port: %v\n", frontendConfig.Hostname, frontendConfig.Port)
	}

	// Start dispatching route requests
	go routeRequestDispatcher(listenerChannels, routeRequestChan)
}

func routeRequestDispatcher(listenerChannels []chan *router.RouteRequest, routeRequestChan chan *router.RouteRequest) {
	for {
		event := <-routeRequestChan

		// Broadcast on all channels
		for _, channel := range listenerChannels {
			channel <- event
		}
	}
}
<|endoftext|>