<commit_before>package encoding

import (
	"bytes"
	"fmt"
	"math"
	"math/bits"
	"strconv"
	"testing"
	"unsafe"

	"github.com/xitongsys/parquet-go/parquet"
)

func TestReadPlainBOOLEAN(t *testing.T) {
	testData := [][]interface{}{
		{(true)},
		{(false)},
		{(false), (false)},
		{(false), (true)},
	}

	for _, data := range testData {
		res, _ := ReadPlainBOOLEAN(bytes.NewReader(WritePlainBOOLEAN(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainBOOLEAN err, expect %v, get %v", data, res)
		}
	}
}

func TestReadPlainINT32(t *testing.T) {
	testData := []struct {
		expected   []interface{}
		byteReader *bytes.Reader
	}{
		{[]interface{}{}, bytes.NewReader([]byte{})},
		{[]interface{}{int32(0)}, bytes.NewReader([]byte{0, 0, 0, 0})},
		{[]interface{}{int32(0), int32(1), int32(2)}, bytes.NewReader([]byte{0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0})},
	}

	for _, data := range testData {
		res, _ := ReadPlainINT32(data.byteReader, uint64(len(data.expected)))
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data.expected) {
			t.Errorf("ReadPlainINT32 error, expect %v, get %v", data.expected, res)
		}
	}
}

func TestReadPlainINT64(t *testing.T) {
	testData := []struct {
		expected   []interface{}
		byteReader *bytes.Reader
	}{
		{[]interface{}{}, bytes.NewReader([]byte{})},
		{[]interface{}{int64(0)}, bytes.NewReader([]byte{0, 0, 0, 0, 0, 0, 0, 0})},
		{[]interface{}{int64(0), int64(1), int64(2)}, bytes.NewReader([]byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0})},
	}

	for _, data := range testData {
		res, _ := ReadPlainINT64(data.byteReader, uint64(len(data.expected)))
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data.expected) {
			t.Errorf("ReadPlainINT64 error, expect %v, get %v", data.expected, res)
		}
	}
}

func TestReadPlainBYTE_ARRAY(t *testing.T) {
	testData := [][]interface{}{
		{("hello"), ("world")},
		{("good"), (""), ("a"), ("b")},
	}

	for _, data := range testData {
		res, _ := ReadPlainBYTE_ARRAY(bytes.NewReader(WritePlainBYTE_ARRAY(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainBYTE_ARRAY err, %v", data)
		}
	}
}

func TestReadPlainFIXED_LEN_BYTE_ARRAY(t *testing.T) {
	testData := [][]interface{}{
		{("hello"), ("world")},
		{("a"), ("b"), ("c"), ("d")},
	}

	for _, data := range testData {
		res, _ := ReadPlainFIXED_LEN_BYTE_ARRAY(bytes.NewReader(WritePlainFIXED_LEN_BYTE_ARRAY(data)), uint64(len(data)), uint64(len(data[0].(string))))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainFIXED_LEN_BYTE_ARRAY err, %v", data)
		}
	}
}

func TestReadPlainFLOAT(t *testing.T) {
	testData := [][]interface{}{
		{float32(0), float32(1), float32(2)},
		{float32(0), float32(0.1), float32(0.2)},
	}

	for _, data := range testData {
		res, _ := ReadPlainFLOAT(bytes.NewReader(WritePlainFLOAT(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainFLOAT err, %v", data)
		}
	}
}

func TestReadPlainDOUBLE(t *testing.T) {
	testData := [][]interface{}{
		{float64(0), float64(1), float64(2)},
		{float64(0), float64(0), float64(0)},
	}

	for _, data := range testData {
		res, _ := ReadPlainDOUBLE(bytes.NewReader(WritePlainDOUBLE(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainDOUBLE err, %v", data)
		}
	}
}

func TestReadUnsignedVarInt(t *testing.T) {
	i32 := int32(-1570499385)

	testData := []uint64{1, 2, 3, 11, 1570499385, uint64(i32), 111, 222, 333, 0}
	for _, data := range testData {
		res, _ := ReadUnsignedVarInt(bytes.NewReader(WriteUnsignedVarInt(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadUnsignedVarInt err, %v", data)
		}
	}
}

func TestReadRLEBitPackedHybrid(t *testing.T) {
	testData := [][]interface{}{
		{int64(1), int64(2), int64(3), int64(4)},
		{int64(0), int64(0), int64(0), int64(0), int64(0)},
	}
	for _, data := range testData {
		maxVal := uint64(data[len(data)-1].(int64))

		res, err := ReadRLEBitPackedHybrid(bytes.NewReader(WriteRLEBitPackedHybrid(data, int32(bits.Len64(maxVal)), parquet.Type_INT64)), uint64(bits.Len64(maxVal)), 0)
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadRLEBitpackedHybrid error, expect %v, get %v, err info:%v", data, res, err)
		}
	}
}

func TestReadDeltaBinaryPackedINT(t *testing.T) {
	testData := [][]interface{}{
		{int64(1), int64(2), int64(3), int64(4)},
		{int64(math.MaxInt64), int64(math.MinInt64), int64(-15654523568543623), int64(4354365463543632), int64(0)},
	}

	for _, data := range testData {
		fmt.Println(data)
		res, err := ReadDeltaBinaryPackedINT64(bytes.NewReader(WriteDeltaINT64(data)))
		if err != nil {
			t.Error(err)
		}

		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadRLEBitpackedHybrid error, expect %v, get %v", data, res)
		}
	}
}

func TestReadDeltaINT32(t *testing.T) {
	bInt32 := func(n int32) string { return strconv.FormatUint(uint64(*(*uint32)(unsafe.Pointer(&n))), 2) }
	buInt64 := func(n uint64) string { return strconv.FormatUint(n, 2) }
	testData := []int32{1, -1570499385, 3, -11, 1570499385, 111, 222, 333, 0}
	for _, data := range testData {
		fmt.Println("SRC32:", bInt32(data), data)
		u64 := uint64((data >> 31) ^ (data << 1))
		fmt.Println("SRC64:", buInt64(u64))
		resZigZag, err := ReadUnsignedVarInt(bytes.NewReader(WriteUnsignedVarInt(u64)))
		if err != nil {
			t.Error(err)
		}
		res32 := int32(resZigZag)
		var res int32 = int32(uint32(res32)>>1) ^ -(res32 & 1)
		fmt.Println("RES32:", bInt32(res), res)
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadUnsignedVarInt err, %v", data)
		}
	}
}

func TestReadDeltaBinaryPackedINT32(t *testing.T) {
	testData := [][]interface{}{
		{int32(1), int32(2), int32(3), int32(4)},
		{int32(-1570499385), int32(-1570499385), int32(-1570499386), int32(-1570499388), int32(-1570499385)},
	}

	for _, data := range testData {
		fmt.Println("source:", data)

		res, err := ReadDeltaBinaryPackedINT32(bytes.NewReader(WriteDeltaINT32(data)))
		if err != nil {
			t.Error(err)
		}
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadRLEBitpackedHybrid error, expect %v, get %v", data, res)
		}
	}
}

func TestReadDeltaByteArray(t *testing.T) {
	testData := [][]interface{}{
		{"Hello", "world"},
	}
	for _, data := range testData {
		res, _ := ReadDeltaByteArray(bytes.NewReader(WriteDeltaByteArray(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaByteArray err, expect %v, get %v", data, res)
		}
	}
}

func TestReadLengthDeltaByteArray(t *testing.T) {
	testData := [][]interface{}{
		{"Hello", "world"},
	}
	for _, data := range testData {
		res, _ := ReadDeltaLengthByteArray(bytes.NewReader(WriteDeltaLengthByteArray(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaByteArray err, expect %v, get %v", data, res)
		}
	}
}

func TestReadBitPacked(t *testing.T) {
	testData := [][]interface{}{
		{1, 2, 3, 4, 5, 6, 7, 8},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	}
	for _, data := range testData {
		ln := len(data)
		header := ((ln/8)<<1 | 1)
		bitWidth := uint64(bits.Len(uint(data[ln-1].(int))))
		res, _ := ReadBitPacked(bytes.NewReader(WriteBitPacked(data, int64(bitWidth), false)), uint64(header), bitWidth)
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data) {

		}
	}
}
<commit_msg>fix TestReadBitPacked<commit_after>package encoding

import (
	"bytes"
	"fmt"
	"math"
	"math/bits"
	"strconv"
	"testing"
	"unsafe"

	"github.com/xitongsys/parquet-go/parquet"
)

func TestReadPlainBOOLEAN(t *testing.T) {
	testData := [][]interface{}{
		{(true)},
		{(false)},
		{(false), (false)},
		{(false), (true)},
	}

	for _, data := range testData {
		res, _ := ReadPlainBOOLEAN(bytes.NewReader(WritePlainBOOLEAN(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainBOOLEAN err, expect %v, get %v", data, res)
		}
	}
}

func TestReadPlainINT32(t *testing.T) {
	testData := []struct {
		expected   []interface{}
		byteReader *bytes.Reader
	}{
		{[]interface{}{}, bytes.NewReader([]byte{})},
		{[]interface{}{int32(0)}, bytes.NewReader([]byte{0, 0, 0, 0})},
		{[]interface{}{int32(0), int32(1), int32(2)}, bytes.NewReader([]byte{0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0})},
	}

	for _, data := range testData {
		res, _ := ReadPlainINT32(data.byteReader, uint64(len(data.expected)))
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data.expected) {
			t.Errorf("ReadPlainINT32 error, expect %v, get %v", data.expected, res)
		}
	}
}

func TestReadPlainINT64(t *testing.T) {
	testData := []struct {
		expected   []interface{}
		byteReader *bytes.Reader
	}{
		{[]interface{}{}, bytes.NewReader([]byte{})},
		{[]interface{}{int64(0)}, bytes.NewReader([]byte{0, 0, 0, 0, 0, 0, 0, 0})},
		{[]interface{}{int64(0), int64(1), int64(2)}, bytes.NewReader([]byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0})},
	}

	for _, data := range testData {
		res, _ := ReadPlainINT64(data.byteReader, uint64(len(data.expected)))
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data.expected) {
			t.Errorf("ReadPlainINT64 error, expect %v, get %v", data.expected, res)
		}
	}
}

func TestReadPlainBYTE_ARRAY(t *testing.T) {
	testData := [][]interface{}{
		{("hello"), ("world")},
		{("good"), (""), ("a"), ("b")},
	}

	for _, data := range testData {
		res, _ := ReadPlainBYTE_ARRAY(bytes.NewReader(WritePlainBYTE_ARRAY(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainBYTE_ARRAY err, %v", data)
		}
	}
}

func TestReadPlainFIXED_LEN_BYTE_ARRAY(t *testing.T) {
	testData := [][]interface{}{
		{("hello"), ("world")},
		{("a"), ("b"), ("c"), ("d")},
	}

	for _, data := range testData {
		res, _ := ReadPlainFIXED_LEN_BYTE_ARRAY(bytes.NewReader(WritePlainFIXED_LEN_BYTE_ARRAY(data)), uint64(len(data)), uint64(len(data[0].(string))))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainFIXED_LEN_BYTE_ARRAY err, %v", data)
		}
	}
}

func TestReadPlainFLOAT(t *testing.T) {
	testData := [][]interface{}{
		{float32(0), float32(1), float32(2)},
		{float32(0), float32(0.1), float32(0.2)},
	}

	for _, data := range testData {
		res, _ := ReadPlainFLOAT(bytes.NewReader(WritePlainFLOAT(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainFLOAT err, %v", data)
		}
	}
}

func TestReadPlainDOUBLE(t *testing.T) {
	testData := [][]interface{}{
		{float64(0), float64(1), float64(2)},
		{float64(0), float64(0), float64(0)},
	}

	for _, data := range testData {
		res, _ := ReadPlainDOUBLE(bytes.NewReader(WritePlainDOUBLE(data)), uint64(len(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadPlainDOUBLE err, %v", data)
		}
	}
}

func TestReadUnsignedVarInt(t *testing.T) {
	i32 := int32(-1570499385)

	testData := []uint64{1, 2, 3, 11, 1570499385, uint64(i32), 111, 222, 333, 0}
	for _, data := range testData {
		res, _ := ReadUnsignedVarInt(bytes.NewReader(WriteUnsignedVarInt(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadUnsignedVarInt err, %v", data)
		}
	}
}

func TestReadRLEBitPackedHybrid(t *testing.T) {
	testData := [][]interface{}{
		{int64(1), int64(2), int64(3), int64(4)},
		{int64(0), int64(0), int64(0), int64(0), int64(0)},
	}
	for _, data := range testData {
		maxVal := uint64(data[len(data)-1].(int64))

		res, err := ReadRLEBitPackedHybrid(bytes.NewReader(WriteRLEBitPackedHybrid(data, int32(bits.Len64(maxVal)), parquet.Type_INT64)), uint64(bits.Len64(maxVal)), 0)
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadRLEBitpackedHybrid error, expect %v, get %v, err info:%v", data, res, err)
		}
	}
}

func TestReadDeltaBinaryPackedINT(t *testing.T) {
	testData := [][]interface{}{
		{int64(1), int64(2), int64(3), int64(4)},
		{int64(math.MaxInt64), int64(math.MinInt64), int64(-15654523568543623), int64(4354365463543632), int64(0)},
	}

	for _, data := range testData {
		fmt.Println(data)
		res, err := ReadDeltaBinaryPackedINT64(bytes.NewReader(WriteDeltaINT64(data)))
		if err != nil {
			t.Error(err)
		}

		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaBinaryPackedINT64 error, expect %v, get %v", data, res)
		}
	}
}

func TestReadDeltaINT32(t *testing.T) {
	bInt32 := func(n int32) string { return strconv.FormatUint(uint64(*(*uint32)(unsafe.Pointer(&n))), 2) }
	buInt64 := func(n uint64) string { return strconv.FormatUint(n, 2) }
	testData := []int32{1, -1570499385, 3, -11, 1570499385, 111, 222, 333, 0}
	for _, data := range testData {
		fmt.Println("SRC32:", bInt32(data), data)
		u64 := uint64((data >> 31) ^ (data << 1))
		fmt.Println("SRC64:", buInt64(u64))
		resZigZag, err := ReadUnsignedVarInt(bytes.NewReader(WriteUnsignedVarInt(u64)))
		if err != nil {
			t.Error(err)
		}
		res32 := int32(resZigZag)
		var res int32 = int32(uint32(res32)>>1) ^ -(res32 & 1)
		fmt.Println("RES32:", bInt32(res), res)
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadUnsignedVarInt err, %v", data)
		}
	}
}

func TestReadDeltaBinaryPackedINT32(t *testing.T) {
	testData := [][]interface{}{
		{int32(1), int32(2), int32(3), int32(4)},
		{int32(-1570499385), int32(-1570499385), int32(-1570499386), int32(-1570499388), int32(-1570499385)},
	}

	for _, data := range testData {
		fmt.Println("source:", data)

		res, err := ReadDeltaBinaryPackedINT32(bytes.NewReader(WriteDeltaINT32(data)))
		if err != nil {
			t.Error(err)
		}
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaBinaryPackedINT32 error, expect %v, get %v", data, res)
		}
	}
}

func TestReadDeltaByteArray(t *testing.T) {
	testData := [][]interface{}{
		{"Hello", "world"},
	}
	for _, data := range testData {
		res, _ := ReadDeltaByteArray(bytes.NewReader(WriteDeltaByteArray(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaByteArray err, expect %v, get %v", data, res)
		}
	}
}

func TestReadLengthDeltaByteArray(t *testing.T) {
	testData := [][]interface{}{
		{"Hello", "world"},
	}
	for _, data := range testData {
		res, _ := ReadDeltaLengthByteArray(bytes.NewReader(WriteDeltaLengthByteArray(data)))
		if fmt.Sprintf("%v", data) != fmt.Sprintf("%v", res) {
			t.Errorf("ReadDeltaLengthByteArray err, expect %v, get %v", data, res)
		}
	}
}

func TestReadBitPacked(t *testing.T) {
	testData := [][]interface{}{
		{1, 2, 3, 4, 5, 6, 7, 8},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	}
	for _, data := range testData {
		ln := len(data)
		header := ((ln/8)<<1 | 1)
		bitWidth := uint64(bits.Len(uint(data[ln-1].(int))))
		res, _ := ReadBitPacked(bytes.NewReader(WriteBitPacked(data, int64(bitWidth), false)), uint64(header), bitWidth)
		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", data) {
			t.Errorf("ReadBitPacked err, expect %v, get %v", data, res)
		}
	}
}
<|endoftext|>


<commit_before>package conf

import (
	"errors"

	"v2ray.com/core/common/loader"
	"v2ray.com/core/transport/internet/authenticators/http"
	"v2ray.com/core/transport/internet/authenticators/noop"
	"v2ray.com/core/transport/internet/authenticators/srtp"
	"v2ray.com/core/transport/internet/authenticators/utp"
)

type NoOpAuthenticator struct{}

func (NoOpAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(noop.Config)), nil
}

type NoOpConnectionAuthenticator struct{}

func (NoOpConnectionAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(noop.Config)), nil
}

type SRTPAuthenticator struct{}

func (SRTPAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(srtp.Config)), nil
}

type UTPAuthenticator struct{}

func (UTPAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(utp.Config)), nil
}

type HTTPAuthenticatorRequest struct {
	Version *string                `json:"version"`
	Method  *string                `json:"method"`
	Path    *StringList            `json:"path"`
	Headers map[string]*StringList `json:"headers"`
}

func (this *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) {
	config := &http.RequestConfig{
		Uri: []string{"/"},
		Header: []*http.Header{
			{
				Name:  "Host",
				Value: []string{"www.baidu.com", "www.bing.com"},
			},
			{
				Name: "User-Agent",
				Value: []string{
					"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
					"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
				},
			},
			{
				Name:  "Accept-Encoding",
				Value: []string{"gzip, deflate"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
		},
	}

	if this.Version != nil {
		config.Version = &http.Version{Value: *this.Version}
	}

	if this.Method != nil {
		config.Method = &http.Method{Value: *this.Method}
	}

	if this.Path != nil && this.Path.Len() > 0 {
		config.Uri = append([]string(nil), (*this.Path)...)
	}

	if len(this.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(this.Headers))
		for key, value := range this.Headers {
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}

type HTTPAuthenticatorResponse struct {
	Version *string                `json:"version"`
	Status  *string                `json:"status"`
	Reason  *string                `json:"reason"`
	Headers map[string]*StringList `json:"headers"`
}

func (this *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) {
	config := &http.ResponseConfig{
		Header: []*http.Header{
			{
				Name:  "Content-Type",
				Value: []string{"application/octet-stream", "video/mpeg"},
			},
			{
				Name:  "Transfer-Encoding",
				Value: []string{"chunked"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
		},
	}

	if this.Version != nil {
		config.Version = &http.Version{Value: *this.Version}
	}

	if this.Status != nil || this.Reason != nil {
		config.Status = &http.Status{
			Code:   "200",
			Reason: "OK",
		}
		if this.Status != nil {
			config.Status.Code = *this.Status
		}
		if this.Reason != nil {
			config.Status.Reason = *this.Reason
		}
	}

	if len(this.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(this.Headers))
		for key, value := range this.Headers {
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}

type HTTPAuthenticator struct {
	Request  *HTTPAuthenticatorRequest  `json:"request"`
	Response *HTTPAuthenticatorResponse `json:"response"`
}

func (this *HTTPAuthenticator) Build() (*loader.TypedSettings, error) {
	config := new(http.Config)
	if this.Request == nil {
		return nil, errors.New("HTTP request settings not set.")
	}
	requestConfig, err := this.Request.Build()
	if err != nil {
		return nil, err
	}
	config.Request = requestConfig

	if this.Response != nil {
		responseConfig, err := this.Response.Build()
		if err != nil {
			return nil, err
		}
		config.Response = responseConfig
	}

	return loader.NewTypedSettings(config), nil
}
<commit_msg>refine http header parsing<commit_after>package conf

import (
	"errors"

	"v2ray.com/core/common/loader"
	"v2ray.com/core/transport/internet/authenticators/http"
	"v2ray.com/core/transport/internet/authenticators/noop"
	"v2ray.com/core/transport/internet/authenticators/srtp"
	"v2ray.com/core/transport/internet/authenticators/utp"
)

type NoOpAuthenticator struct{}

func (NoOpAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(noop.Config)), nil
}

type NoOpConnectionAuthenticator struct{}

func (NoOpConnectionAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(noop.Config)), nil
}

type SRTPAuthenticator struct{}

func (SRTPAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(srtp.Config)), nil
}

type UTPAuthenticator struct{}

func (UTPAuthenticator) Build() (*loader.TypedSettings, error) {
	return loader.NewTypedSettings(new(utp.Config)), nil
}

type HTTPAuthenticatorRequest struct {
	Version string                 `json:"version"`
	Method  string                 `json:"method"`
	Path    StringList             `json:"path"`
	Headers map[string]*StringList `json:"headers"`
}

func (this *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) {
	config := &http.RequestConfig{
		Uri: []string{"/"},
		Header: []*http.Header{
			{
				Name:  "Host",
				Value: []string{"www.baidu.com", "www.bing.com"},
			},
			{
				Name: "User-Agent",
				Value: []string{
					"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
					"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
				},
			},
			{
				Name:  "Accept-Encoding",
				Value: []string{"gzip, deflate"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
		},
	}

	if len(this.Version) > 0 {
		config.Version = &http.Version{Value: this.Version}
	}

	if len(this.Method) > 0 {
		config.Method = &http.Method{Value: this.Method}
	}

	if len(this.Path) > 0 {
		config.Uri = append([]string(nil), (this.Path)...)
	}

	if len(this.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(this.Headers))
		for key, value := range this.Headers {
			if value == nil {
				return nil, errors.New("Empty HTTP header value: " + key)
			}
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}

type HTTPAuthenticatorResponse struct {
	Version string                 `json:"version"`
	Status  string                 `json:"status"`
	Reason  string                 `json:"reason"`
	Headers map[string]*StringList `json:"headers"`
}

func (this *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) {
	config := &http.ResponseConfig{
		Header: []*http.Header{
			{
				Name:  "Content-Type",
				Value: []string{"application/octet-stream", "video/mpeg"},
			},
			{
				Name:  "Transfer-Encoding",
				Value: []string{"chunked"},
			},
			{
				Name:  "Connection",
				Value: []string{"keep-alive"},
			},
			{
				Name:  "Pragma",
				Value: []string{"no-cache"},
			},
		},
	}

	if len(this.Version) > 0 {
		config.Version = &http.Version{Value: this.Version}
	}

	if len(this.Status) > 0 || len(this.Reason) > 0 {
		config.Status = &http.Status{
			Code:   "200",
			Reason: "OK",
		}
		if len(this.Status) > 0 {
			config.Status.Code = this.Status
		}
		if len(this.Reason) > 0 {
			config.Status.Reason = this.Reason
		}
	}

	if len(this.Headers) > 0 {
		config.Header = make([]*http.Header, 0, len(this.Headers))
		for key, value := range this.Headers {
			if value == nil {
				return nil, errors.New("Empty HTTP header value: " + key)
			}
			config.Header = append(config.Header, &http.Header{
				Name:  key,
				Value: append([]string(nil), (*value)...),
			})
		}
	}

	return config, nil
}

type HTTPAuthenticator struct {
	Request  HTTPAuthenticatorRequest  `json:"request"`
	Response HTTPAuthenticatorResponse `json:"response"`
}

func (this *HTTPAuthenticator) Build() (*loader.TypedSettings, error) {
	config := new(http.Config)
	requestConfig, err := this.Request.Build()
	if err != nil {
		return nil, err
	}
	config.Request = requestConfig

	responseConfig, err := this.Response.Build()
	if err != nil {
		return nil, err
	}
	config.Response = responseConfig

	return loader.NewTypedSettings(config), nil
}
<|endoftext|>


<commit_before>package application
<commit_msg>Added tests to the RecaptchaMiddleware type<commit_after>// Package application contains the server-side application code.
package application

/*
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
import (
    "testing"
    "net/http"
    "net/http/httptest"
)

const reCaptchaTestResponse = "03AHJ_VutING-ky641XG-W15BMWlC31rMqgdxuAFji7Pqk1o6jqBF20CfKSTknHDlXLQlVgleevn5HTHsldBinf78xGvNYAX-gIXSzOX7aQBBTvNAY7o4SlLzUzEEC3AXNTqxz76ueA4bx2-0BHN5gfTG2vUBpktWKa7BOsJLPgAS9b2IidWB41UUccQl7pEs9H28qUKXGYRnKZFECk23jcjqMPkvDVTFASctPXC3a40YtiYB2bzY7LfqDeaqYH0_nJf0BcY_SZfhQJetE6KPhL9bocIOgcWRoZQ8b0eXKHClMfbHRTCfu10k0Eu1gzx3T992KoQ643C_YPPj2VasIDiNx1FEX_5Yvs2jzSYjRy2jyAtVtNEUSKhFoEd3pwGJJtx7eh6FbYcbAWZKZTuWejmGzpAQaB6fMuD5ykY1AIFYiYjFFXjks_K3ZICH4pmU6WFUDUDVUxiT28-OVWCtYr7X_s0Ce9fQ6L9tZINVaaZeqazzuxfeNxYI66PEV2nMVUjcBTwrLdVtaWjoH9S3Cpc9xoXZZe3dtfXkw2nyhK6CFehEoKOBi96HepA5cY1YWUbAeJMIYoEp-lla6OmENGhrkLN28mUHF-iH68fe2LxwkhCGMic09GVOOXE5TUFhspvIHfgoOBE4-s1j4AWezUP2hniuJClPsO6xxiAQgIqA2dy0_NNKLI3Cyb3dTIFd8yv26U7kSJUGxmjI4BHlRxoNXniBuf854UX820VpIFr-oXkJj0GoqBAcrlgucq8PsjuPOCdHoh8u2zTYFitxppqDR1NP4wzdVoKuZ-BVhQkJ1C3IsfrAkLyesFfF5y8KQFo1smzhMnHmEiMLRDWe9y9hhd3CpkNdofvedcaE6PJ_l-dH8hdmhS_PgSaZPHGM3Wym2U3xICD2Yde1BWp1Imik6eM43OkYJfP6sh_IdX38cWi74B3RfCA_Na1Tci3_24cuEs8IfBHeQnxgN7V5FGL204ZLFffeGIxmXlbInAeZgFEqJw3YjQfu4lbddYXTKOE6WJZcKmRSjXazt8ZXaxKJ_0SefI7udyg"

// NoopHTTPHandler exists only to satisfy the reCAPTCHA middleware passing the request
type NoopHTTPHandler struct { }

func (f NoopHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.WriteHeader(200)
}

func TestRecaptchaMiddlewareForbiddenStatus(t *testing.T) {
    config, _ := LoadConfiguration("../conf/configuration.json")
    middleware := RecaptchaMiddleware{ Configuration: config }

    req, err := http.NewRequest("GET", "/", nil)
    if err != nil {
        t.Fatal(err)
    }

    rr := httptest.NewRecorder()
    handler := http.Handler(middleware.Middleware(nil))

    handler.ServeHTTP(rr, req)

    if status := rr.Code; status != http.StatusForbidden {
        t.Errorf("handler did not not return the correct status code -- %v -- vs -- %v --", status, http.StatusForbidden)
    }
}

func TestRecaptchaMiddleware200Status(t *testing.T) {
    configuration, _ := LoadConfiguration("../conf/configuration.json")
    middleware := RecaptchaMiddleware{ Configuration: configuration }

    req, _ := http.NewRequest("GET", "/?c=" + reCaptchaTestResponse, nil)
    handler := http.Handler(middleware.Middleware(NoopHTTPHandler{}))

    rr := httptest.NewRecorder()
    handler.ServeHTTP(rr, req)

    if status := rr.Code; status != http.StatusOK {
        t.Errorf("handler did not not return the correct status code -- %v -- vs -- %v --", status, http.StatusOK)
    }
}<|endoftext|>


<commit_before>package gcache

import (
	"container/list"
	"time"
)

// Discards the least recently used items first.
type LRUCache struct {
	baseCache
	items     map[interface{}]*list.Element
	evictList *list.List
}

func newLRUCache(cb *CacheBuilder) *LRUCache {
	c := &LRUCache{}
	buildCache(&c.baseCache, cb)

	c.evictList = list.New()
	c.items = make(map[interface{}]*list.Element, c.size+1)
	return c
}

func (c *LRUCache) set(key, value interface{}) (interface{}, error) {
	// Check for existing item
	var item *lruItem
	if it, ok := c.items[key]; ok {
		c.evictList.MoveToFront(it)
		item = it.Value.(*lruItem)
		item.value = value
	} else {
		// Verify size not exceeded
		if c.evictList.Len() >= c.size {
			c.evict(1)
		}
		item = &lruItem{
			key:   key,
			value: value,
		}
		c.items[key] = c.evictList.PushFront(item)
	}

	if c.expiration != nil {
		t := time.Now().Add(*c.expiration)
		item.expiration = &t
	}

	if c.addedFunc != nil {
		go (*c.addedFunc)(key, value)
	}

	return item, nil
}

// set a new key-value pair
func (c *LRUCache) Set(key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.set(key, value)
}

// Get a value from cache pool using key if it exists.
// If it dose not exists key and has LoaderFunc,
// generate a value using `LoaderFunc` method returns value.
func (c *LRUCache) Get(key interface{}) (interface{}, error) {
	c.mu.RLock()
	item, ok := c.items[key]
	c.mu.RUnlock()

	if ok {
		it := item.Value.(*lruItem)
		if !it.IsExpired(nil) {
			c.mu.Lock()
			defer c.mu.Unlock()
			return it.value, nil
		}
		c.removeElement(item)
	}

	if c.loaderFunc == nil {
		return nil, NotFoundKeyError
	}

	it, err := c.load(key, func(v interface{}, e error) (interface{}, error) {
		if e == nil {
			c.mu.Lock()
			defer c.mu.Unlock()
			return c.set(key, v)
		}
		return nil, e
	})
	if err != nil {
		return nil, err
	}
	return it.(*lruItem).value, nil
}

// evict removes the oldest item from the cache.
func (c *LRUCache) evict(count int) {
	for i := 0; i < count; i++ {
		ent := c.evictList.Back()
		if ent == nil {
			return
		} else {
			c.removeElement(ent)
		}
	}
}

// Removes the provided key from the cache.
func (c *LRUCache) Remove(key interface{}) bool {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.remove(key)
}

func (c *LRUCache) remove(key interface{}) bool {
	if ent, ok := c.items[key]; ok {
		c.removeElement(ent)
		return true
	}
	return false
}

func (c *LRUCache) removeElement(e *list.Element) {
	c.evictList.Remove(e)
	entry := e.Value.(*lruItem)
	delete(c.items, entry.key)
	if c.evictedFunc != nil {
		entry := e.Value.(*lruItem)
		go (*c.evictedFunc)(entry.key, entry.value)
	}
}

// Returns a slice of the keys in the cache.
func (c *LRUCache) Keys() []interface{} {
	c.mu.RLock()
	defer c.mu.RUnlock()

	keys := make([]interface{}, len(c.items))
	i := 0
	for k := range c.items {
		keys[i] = k
		i++
	}

	return keys
}

// Returns the number of items in the cache.
func (c *LRUCache) Len() int {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return len(c.items)
}

// Completely clear the cache
func (c *LRUCache) Purge() {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.evictList = list.New()
	c.items = make(map[interface{}]*list.Element, c.size)
}

// evict all expired entry
func (c *LRUCache) gc() {
	now := time.Now()
	keys := []interface{}{}
	c.mu.RLock()
	for k, item := range c.items {
		if item.Value.(*lruItem).IsExpired(&now) {
			keys = append(keys, k)
		}
	}
	c.mu.RUnlock()
	if len(keys) == 0 {
		return
	}
	c.mu.Lock()
	for _, k := range keys {
		c.remove(k)
	}
	c.mu.Unlock()
}

type lruItem struct {
	key        interface{}
	value      interface{}
	expiration *time.Time
}

// returns boolean value whether this item is expired or not.
func (it *lruItem) IsExpired(now *time.Time) bool {
	if it.expiration == nil {
		return false
	}
	if now == nil {
		t := time.Now()
		now = &t
	}
	return it.expiration.Before(*now)
}
<commit_msg>fix lru cache may memory leak when concurrency is high<commit_after>package gcache

import (
	"container/list"
	"time"
)

// Discards the least recently used items first.
type LRUCache struct {
	baseCache
	items     map[interface{}]*list.Element
	evictList *list.List
}

func newLRUCache(cb *CacheBuilder) *LRUCache {
	c := &LRUCache{}
	buildCache(&c.baseCache, cb)

	c.evictList = list.New()
	c.items = make(map[interface{}]*list.Element, c.size+1)
	return c
}

func (c *LRUCache) set(key, value interface{}) (interface{}, error) {
	// Check for existing item
	var item *lruItem
	if it, ok := c.items[key]; ok {
		c.evictList.MoveToFront(it)
		item = it.Value.(*lruItem)
		item.value = value
	} else {
		// Verify size not exceeded
		if c.evictList.Len() >= c.size {
			c.evict(1)
		}
		item = &lruItem{
			key:   key,
			value: value,
		}
		c.items[key] = c.evictList.PushFront(item)
	}

	if c.expiration != nil {
		t := time.Now().Add(*c.expiration)
		item.expiration = &t
	}

	if c.addedFunc != nil {
		go (*c.addedFunc)(key, value)
	}

	return item, nil
}

// set a new key-value pair
func (c *LRUCache) Set(key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.set(key, value)
}

// Get a value from cache pool using key if it exists.
// If it dose not exists key and has LoaderFunc,
// generate a value using `LoaderFunc` method returns value.
func (c *LRUCache) Get(key interface{}) (interface{}, error) {
	c.mu.RLock()
	item, ok := c.items[key]
	c.mu.RUnlock()

	if ok {
		it := item.Value.(*lruItem)
		if !it.IsExpired(nil) {
			c.mu.Lock()
			defer c.mu.Unlock()
			return it.value, nil
		}
		c.mu.Lock()
		c.removeElement(item)
		c.mu.Unlock()
	}

	if c.loaderFunc == nil {
		return nil, NotFoundKeyError
	}

	it, err := c.load(key, func(v interface{}, e error) (interface{}, error) {
		if e == nil {
			c.mu.Lock()
			defer c.mu.Unlock()
			return c.set(key, v)
		}
		return nil, e
	})
	if err != nil {
		return nil, err
	}
	return it.(*lruItem).value, nil
}

// evict removes the oldest item from the cache.
func (c *LRUCache) evict(count int) {
	for i := 0; i < count; i++ {
		ent := c.evictList.Back()
		if ent == nil {
			return
		} else {
			c.removeElement(ent)
		}
	}
}

// Removes the provided key from the cache.
func (c *LRUCache) Remove(key interface{}) bool {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.remove(key)
}

func (c *LRUCache) remove(key interface{}) bool {
	if ent, ok := c.items[key]; ok {
		c.removeElement(ent)
		return true
	}
	return false
}

func (c *LRUCache) removeElement(e *list.Element) {
	c.evictList.Remove(e)
	entry := e.Value.(*lruItem)
	delete(c.items, entry.key)
	if c.evictedFunc != nil {
		entry := e.Value.(*lruItem)
		go (*c.evictedFunc)(entry.key, entry.value)
	}
}

// Returns a slice of the keys in the cache.
func (c *LRUCache) Keys() []interface{} {
	c.mu.RLock()
	defer c.mu.RUnlock()

	keys := make([]interface{}, len(c.items))
	i := 0
	for k := range c.items {
		keys[i] = k
		i++
	}

	return keys
}

// Returns the number of items in the cache.
func (c *LRUCache) Len() int {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return len(c.items)
}

// Completely clear the cache
func (c *LRUCache) Purge() {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.evictList = list.New()
	c.items = make(map[interface{}]*list.Element, c.size)
}

// evict all expired entry
func (c *LRUCache) gc() {
	now := time.Now()
	keys := []interface{}{}
	c.mu.RLock()
	for k, item := range c.items {
		if item.Value.(*lruItem).IsExpired(&now) {
			keys = append(keys, k)
		}
	}
	c.mu.RUnlock()
	if len(keys) == 0 {
		return
	}
	c.mu.Lock()
	for _, k := range keys {
		c.remove(k)
	}
	c.mu.Unlock()
}

type lruItem struct {
	key        interface{}
	value      interface{}
	expiration *time.Time
}

// returns boolean value whether this item is expired or not.
func (it *lruItem) IsExpired(now *time.Time) bool {
	if it.expiration == nil {
		return false
	}
	if now == nil {
		t := time.Now()
		now = &t
	}
	return it.expiration.Before(*now)
}
<|endoftext|>


<commit_before>package torrent

import (
	"fmt"

	"github.com/cenkalti/rain/torrent/internal/peerprotocol"
	"github.com/cenkalti/rain/torrent/internal/verifier"
)

func (t *Torrent) handleVerificationDone(ve *verifier.Verifier) {
	if t.verifier != ve {
		panic("invalid verifier")
	}
	t.verifier = nil

	if ve.Error != nil {
		t.stop(fmt.Errorf("file verification error: %s", ve.Error))
		return
	}

	// Now we have a constructed and verified bitfield.
	t.bitfield = ve.Bitfield

	// Save the bitfield to resume db.
	if t.resume != nil {
		err := t.resume.WriteBitfield(t.bitfield.Bytes())
		if err != nil {
			t.stop(fmt.Errorf("cannot write bitfield to resume db: %s", err))
			return
		}
	}

	// Tell connected peers that pieces we have.
	for pe := range t.peers {
		for i := uint32(0); i < t.bitfield.Len(); i++ {
			if t.bitfield.Test(i) {
				msg := peerprotocol.HaveMessage{Index: i}
				pe.SendMessage(msg)
			}
		}
		t.updateInterestedState(pe)
	}

	t.checkCompletion()
	t.processQueuedMessages()
	t.startAcceptor()
	t.startAnnouncers()
	t.startPieceDownloaders()
	t.startUnchokeTimers()
}
<commit_msg>mark downloaded pieces<commit_after>package torrent

import (
	"fmt"

	"github.com/cenkalti/rain/torrent/internal/peerprotocol"
	"github.com/cenkalti/rain/torrent/internal/verifier"
)

func (t *Torrent) handleVerificationDone(ve *verifier.Verifier) {
	if t.verifier != ve {
		panic("invalid verifier")
	}
	t.verifier = nil

	if ve.Error != nil {
		t.stop(fmt.Errorf("file verification error: %s", ve.Error))
		return
	}

	// Now we have a constructed and verified bitfield.
	t.bitfield = ve.Bitfield

	// Save the bitfield to resume db.
	if t.resume != nil {
		err := t.resume.WriteBitfield(t.bitfield.Bytes())
		if err != nil {
			t.stop(fmt.Errorf("cannot write bitfield to resume db: %s", err))
			return
		}
	}

	// Mark downloaded pieces.
	for i := uint32(0); i < t.bitfield.Len(); i++ {
		t.pieces[i].Done = t.bitfield.Test(i)
	}

	// Tell connected peers that pieces we have.
	for pe := range t.peers {
		for i := uint32(0); i < t.bitfield.Len(); i++ {
			if t.bitfield.Test(i) {
				msg := peerprotocol.HaveMessage{Index: i}
				pe.SendMessage(msg)
			}
		}
		t.updateInterestedState(pe)
	}

	t.checkCompletion()
	t.processQueuedMessages()
	t.startAcceptor()
	t.startAnnouncers()
	t.startPieceDownloaders()
	t.startUnchokeTimers()
}
<|endoftext|>


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

// Primitive HTTP client. See RFC 2616.

package http

import (
	"bufio"
	"encoding/base64"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Used in Send to implement io.ReadCloser by bundling together the
// io.BufReader through which we read the response, and the underlying
// network connection.
type readClose struct {
	io.Reader
	io.Closer
}

// Send issues an HTTP request.  Caller should close resp.Body when done reading it.
//
// TODO: support persistent connections (multiple requests on a single connection).
// send() method is nonpublic because, when we refactor the code for persistent
// connections, it may no longer make sense to have a method with this signature.
func send(req *Request) (resp *Response, err os.Error) {
	if req.URL.Scheme != "http" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":http"
	}
	info := req.URL.Userinfo
	if len(info) > 0 {
		enc := base64.URLEncoding
		encoded := make([]byte, enc.EncodedLen(len(info)))
		enc.Encode(encoded, strings.Bytes(info))
		if req.Header == nil {
			req.Header = make(map[string]string)
		}
		req.Header["Authorization"] = "Basic " + string(encoded)
	}
	conn, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return nil, err
	}

	reader := bufio.NewReader(conn)
	resp, err = ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}

// True if the specified HTTP status code is one for which the Get utility should
// automatically redirect.
func shouldRedirect(statusCode int) bool {
	switch statusCode {
	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
		return true
	}
	return false
}

// Get issues a GET to the specified URL.  If the response is one of the following
// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
//
//    301 (Moved Permanently)
//    302 (Found)
//    303 (See Other)
//    307 (Temporary Redirect)
//
// finalURL is the URL from which the response was fetched -- identical to the
// input URL unless redirects were followed.
//
// Caller should close r.Body when done reading it.
func Get(url string) (r *Response, finalURL string, err os.Error) {
	// TODO: if/when we add cookie support, the redirected request shouldn't
	// necessarily supply the same cookies as the original.
	// TODO: set referrer header on redirects.
	for redirect := 0; ; redirect++ {
		if redirect >= 10 {
			err = os.ErrorString("stopped after 10 redirects")
			break
		}

		var req Request
		if req.URL, err = ParseURL(url); err != nil {
			break
		}
		if r, err = send(&req); err != nil {
			break
		}
		if shouldRedirect(r.StatusCode) {
			r.Body.Close()
			if url = r.GetHeader("Location"); url == "" {
				err = os.ErrorString(fmt.Sprintf("%d response missing Location header", r.StatusCode))
				break
			}
			continue
		}
		finalURL = url
		return
	}

	err = &URLError{"Get", url, err}
	return
}

// Post issues a POST to the specified URL.
//
// Caller should close r.Body when done reading it.
func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type": bodyType,
		"Transfer-Encoding": "chunked",
	}

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() os.Error { return nil }
<commit_msg>http: fix bug in Post<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Primitive HTTP client. See RFC 2616.

package http

import (
	"bufio"
	"encoding/base64"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Used in Send to implement io.ReadCloser by bundling together the
// io.BufReader through which we read the response, and the underlying
// network connection.
type readClose struct {
	io.Reader
	io.Closer
}

// Send issues an HTTP request.  Caller should close resp.Body when done reading it.
//
// TODO: support persistent connections (multiple requests on a single connection).
// send() method is nonpublic because, when we refactor the code for persistent
// connections, it may no longer make sense to have a method with this signature.
func send(req *Request) (resp *Response, err os.Error) {
	if req.URL.Scheme != "http" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":http"
	}
	info := req.URL.Userinfo
	if len(info) > 0 {
		enc := base64.URLEncoding
		encoded := make([]byte, enc.EncodedLen(len(info)))
		enc.Encode(encoded, strings.Bytes(info))
		if req.Header == nil {
			req.Header = make(map[string]string)
		}
		req.Header["Authorization"] = "Basic " + string(encoded)
	}
	conn, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}

	err = req.Write(conn)
	if err != nil {
		conn.Close()
		return nil, err
	}

	reader := bufio.NewReader(conn)
	resp, err = ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}

// True if the specified HTTP status code is one for which the Get utility should
// automatically redirect.
func shouldRedirect(statusCode int) bool {
	switch statusCode {
	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
		return true
	}
	return false
}

// Get issues a GET to the specified URL.  If the response is one of the following
// redirect codes, it follows the redirect, up to a maximum of 10 redirects:
//
//    301 (Moved Permanently)
//    302 (Found)
//    303 (See Other)
//    307 (Temporary Redirect)
//
// finalURL is the URL from which the response was fetched -- identical to the
// input URL unless redirects were followed.
//
// Caller should close r.Body when done reading it.
func Get(url string) (r *Response, finalURL string, err os.Error) {
	// TODO: if/when we add cookie support, the redirected request shouldn't
	// necessarily supply the same cookies as the original.
	// TODO: set referrer header on redirects.
	for redirect := 0; ; redirect++ {
		if redirect >= 10 {
			err = os.ErrorString("stopped after 10 redirects")
			break
		}

		var req Request
		if req.URL, err = ParseURL(url); err != nil {
			break
		}
		if r, err = send(&req); err != nil {
			break
		}
		if shouldRedirect(r.StatusCode) {
			r.Body.Close()
			if url = r.GetHeader("Location"); url == "" {
				err = os.ErrorString(fmt.Sprintf("%d response missing Location header", r.StatusCode))
				break
			}
			continue
		}
		finalURL = url
		return
	}

	err = &URLError{"Get", url, err}
	return
}

// Post issues a POST to the specified URL.
//
// Caller should close r.Body when done reading it.
func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
	var req Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Body = nopCloser{body}
	req.Header = map[string]string{
		"Content-Type": bodyType,
	}
	req.TransferEncoding = []string{"chunked"}

	req.URL, err = ParseURL(url)
	if err != nil {
		return nil, err
	}

	return send(&req)
}

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() os.Error { return nil }
<|endoftext|>


<commit_before>package auth

import (
	"encoding/base64"
	"errors"
	"net/http"
	"strings"

	"code.google.com/p/go.crypto/bcrypt"
)

type Handler struct {
	Handler        http.Handler
	Username       string
	HashedPassword string
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	header := r.Header.Get("Authorization")
	username, password, err := ExtractUsernameAndPassword(header)
	if err != nil {
		h.unauthorized(w)
		return
	}

	if h.correctCredentials(username, password) {
		h.Handler.ServeHTTP(w, r)
	} else {
		h.unauthorized(w)
	}
}

func (h Handler) correctCredentials(username string, password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(h.HashedPassword), []byte(password))
	return h.Username == username && err == nil
}

func (h Handler) unauthorized(w http.ResponseWriter) {
	w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
	w.WriteHeader(http.StatusUnauthorized)
}

var ErrUnparsableHeader = errors.New("unparseable Authorization header")

func ExtractUsernameAndPassword(authorizationHeader string) (string, string, error) {
	if !strings.HasPrefix(authorizationHeader, "Basic ") {
		return "", "", ErrUnparsableHeader
	}

	substring := authorizationHeader[6:]
	decodedSubstring, err := base64.StdEncoding.DecodeString(substring)
	if err != nil {
		return "", "", ErrUnparsableHeader
	}

	parts := strings.Split(string(decodedSubstring), ":")
	if len(parts) != 2 {
		return "", "", ErrUnparsableHeader
	}

	return parts[0], parts[1], nil
}
<commit_msg>tidy up english<commit_after>package auth

import (
	"encoding/base64"
	"errors"
	"net/http"
	"strings"

	"code.google.com/p/go.crypto/bcrypt"
)

type Handler struct {
	Handler        http.Handler
	Username       string
	HashedPassword string
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	header := r.Header.Get("Authorization")
	username, password, err := ExtractUsernameAndPassword(header)
	if err != nil {
		h.unauthorized(w)
		return
	}

	if h.correctCredentials(username, password) {
		h.Handler.ServeHTTP(w, r)
	} else {
		h.unauthorized(w)
	}
}

func (h Handler) correctCredentials(username string, password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(h.HashedPassword), []byte(password))
	return h.Username == username && err == nil
}

func (h Handler) unauthorized(w http.ResponseWriter) {
	w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
	w.WriteHeader(http.StatusUnauthorized)
}

var ErrUnparsableHeader = errors.New("cannot parse 'Authorization' header")

func ExtractUsernameAndPassword(authorizationHeader string) (string, string, error) {
	if !strings.HasPrefix(authorizationHeader, "Basic ") {
		return "", "", ErrUnparsableHeader
	}

	substring := authorizationHeader[6:]
	decodedSubstring, err := base64.StdEncoding.DecodeString(substring)
	if err != nil {
		return "", "", ErrUnparsableHeader
	}

	parts := strings.Split(string(decodedSubstring), ":")
	if len(parts) != 2 {
		return "", "", ErrUnparsableHeader
	}

	return parts[0], parts[1], nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"net/url"

	html "code.google.com/p/go.net/html"
	atom "code.google.com/p/go.net/html/atom"
	"github.com/PuerkitoBio/goquery"
	log "github.com/cihub/seelog"
)

var (
	InvalidNode                 = errors.New("Node is not an anchor")
	InvalidNodeAttributeMissing = errors.New("Node does not contain the specified attribute")
)

type Fetcher interface {
	// Fetch returns the body of URL and
	// a slice of URLs found on that page.
	Fetch(url string) (urls []*url.URL, assets []*url.URL, err error)
}

type HttpFetcher struct{}

// Fetch retrieves the page at the specified URL and extracts URLs
func (h *HttpFetcher) Fetch(url string) ([]*url.URL, []*url.URL, error) {

	doc, err := goquery.NewDocument(url)
	if err != nil {
		return nil, nil, err
	}

	urls, err := h.extractLinks(doc)
	if err != nil {
		return nil, nil, err
	}

	assets, err := h.extractAssets(doc)
	if err != nil {
		return nil, nil, err
	}

	log.Debugf("URLs: %+v", urls)
	log.Debugf("Assets: %+v", assets)

	return urls, assets, nil
}

// extractLinks from a document
func (h *HttpFetcher) extractLinks(doc *goquery.Document) ([]*url.URL, error) {

	// Blank slice to hold the links on this page
	urls := make([]*url.URL, 0)

	// Extract all 'a' elements from the document
	sel := doc.Find("a")
	if sel == nil {
		// Assume zero links on failure
		return nil, nil
	}

	// Range over links, and add them to the list if valid
	for i, n := range sel.Nodes {

		// Validate the node is a link, and extract the target URL
		href, err := h.extractValidHref(n)
		if err != nil || href == "" {
			continue
		}

		// Normalise the URL and add if valid
		if uri := h.normaliseUrl(doc.Url, href); uri != nil {
			urls = append(urls, uri)
		}
	}

	return urls, nil
}

// extractAssets from a document
// @todo break this up and add tests
func (h *HttpFetcher) extractAssets(doc *goquery.Document) ([]*url.URL, error) {

	var sel *goquery.Selection
	assets := make([]*url.URL, 0)

	// First grab all the images
	sel = doc.Find("img")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}
		for _, a := range n.Attr {
			if a.Key == "src" && a.Val != "" {
				if uri := h.normaliseUrl(doc.Url, a.Val); uri != nil {
					assets = append(assets, uri)
					break
				}

			}
		}
	}

	// Next scripts
	sel = doc.Find("script")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}
		for _, a := range n.Attr {
			if a.Key == "src" && a.Val != "" {
				if uri := h.normaliseUrl(doc.Url, a.Val); uri != nil {
					assets = append(assets, uri)
					break
				}

			}
		}
	}

	// Links, eg styles, shortcut icons etc
	sel = doc.Find("link")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}

		// Pull out various fields
		var rel, linktype string
		var uri *url.URL
		for _, a := range n.Attr {
			switch a.Key {
			case "rel":
				rel = a.Val
			case "type":
				linktype = a.Val
			case "href":
				uri = h.normaliseUrl(doc.Url, a.Val)
			}
		}

		// Continue if there is no link target
		if uri == nil {
			continue
		}

		// Otherwise select specific combinations
		switch {
		case rel == "stylesheet" && linktype == "text/css":
			assets = append(assets, uri)
		case rel == "shortcut icon":
			assets = append(assets, uri)
		}
	}

	return assets, nil
}

// validateLink is an anchor with a href, and extract normalised url
func (h *HttpFetcher) extractValidHref(n *html.Node) (string, error) {
	var href string

	// Confirm this node is an anchor element
	if n == nil || n.Type != html.ElementNode || n.DataAtom != atom.A {
		return href, InvalidNode
	}

	// Return the value of the href attr if it exists
	for _, a := range n.Attr {
		if a.Key == "href" && a.Val != "" {
			return a.Val, nil
		}
	}

	return "", InvalidNodeAttributeMissing
}

// normaliseUrl converts relative URLs to absolute URLs
func (h *HttpFetcher) normaliseUrl(parent *url.URL, urlString string) *url.URL {

	// Parse the string into a url.URL
	uri, err := url.Parse(urlString)
	if err != nil {
		log.Debugf("Failed to parse URL: %s", urlString)
		return nil
	}

	// Resolve references to get an absolute URL
	abs := parent.ResolveReference(uri)

	return abs
}
<commit_msg>Fix unused var<commit_after>package main

import (
	"errors"
	"net/url"

	html "code.google.com/p/go.net/html"
	atom "code.google.com/p/go.net/html/atom"
	"github.com/PuerkitoBio/goquery"
	log "github.com/cihub/seelog"
)

var (
	InvalidNode                 = errors.New("Node is not an anchor")
	InvalidNodeAttributeMissing = errors.New("Node does not contain the specified attribute")
)

type Fetcher interface {
	// Fetch returns the body of URL and
	// a slice of URLs found on that page.
	Fetch(url string) (urls []*url.URL, assets []*url.URL, err error)
}

type HttpFetcher struct{}

// Fetch retrieves the page at the specified URL and extracts URLs
func (h *HttpFetcher) Fetch(url string) ([]*url.URL, []*url.URL, error) {

	doc, err := goquery.NewDocument(url)
	if err != nil {
		return nil, nil, err
	}

	urls, err := h.extractLinks(doc)
	if err != nil {
		return nil, nil, err
	}

	assets, err := h.extractAssets(doc)
	if err != nil {
		return nil, nil, err
	}

	log.Debugf("URLs: %+v", urls)
	log.Debugf("Assets: %+v", assets)

	return urls, assets, nil
}

// extractLinks from a document
func (h *HttpFetcher) extractLinks(doc *goquery.Document) ([]*url.URL, error) {

	// Blank slice to hold the links on this page
	urls := make([]*url.URL, 0)

	// Extract all 'a' elements from the document
	sel := doc.Find("a")
	if sel == nil {
		// Assume zero links on failure
		return nil, nil
	}

	// Range over links, and add them to the list if valid
	for _, n := range sel.Nodes {

		// Validate the node is a link, and extract the target URL
		href, err := h.extractValidHref(n)
		if err != nil || href == "" {
			continue
		}

		// Normalise the URL and add if valid
		if uri := h.normaliseUrl(doc.Url, href); uri != nil {
			urls = append(urls, uri)
		}
	}

	return urls, nil
}

// extractAssets from a document
// @todo break this up and add tests
func (h *HttpFetcher) extractAssets(doc *goquery.Document) ([]*url.URL, error) {

	var sel *goquery.Selection
	assets := make([]*url.URL, 0)

	// First grab all the images
	sel = doc.Find("img")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}
		for _, a := range n.Attr {
			if a.Key == "src" && a.Val != "" {
				if uri := h.normaliseUrl(doc.Url, a.Val); uri != nil {
					assets = append(assets, uri)
					break
				}

			}
		}
	}

	// Next scripts
	sel = doc.Find("script")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}
		for _, a := range n.Attr {
			if a.Key == "src" && a.Val != "" {
				if uri := h.normaliseUrl(doc.Url, a.Val); uri != nil {
					assets = append(assets, uri)
					break
				}

			}
		}
	}

	// Links, eg styles, shortcut icons etc
	sel = doc.Find("link")
	for _, n := range sel.Nodes {
		if n == nil {
			continue
		}

		// Pull out various fields
		var rel, linktype string
		var uri *url.URL
		for _, a := range n.Attr {
			switch a.Key {
			case "rel":
				rel = a.Val
			case "type":
				linktype = a.Val
			case "href":
				uri = h.normaliseUrl(doc.Url, a.Val)
			}
		}

		// Continue if there is no link target
		if uri == nil {
			continue
		}

		// Otherwise select specific combinations
		switch {
		case rel == "stylesheet" && linktype == "text/css":
			assets = append(assets, uri)
		case rel == "shortcut icon":
			assets = append(assets, uri)
		}
	}

	return assets, nil
}

// validateLink is an anchor with a href, and extract normalised url
func (h *HttpFetcher) extractValidHref(n *html.Node) (string, error) {
	var href string

	// Confirm this node is an anchor element
	if n == nil || n.Type != html.ElementNode || n.DataAtom != atom.A {
		return href, InvalidNode
	}

	// Return the value of the href attr if it exists
	for _, a := range n.Attr {
		if a.Key == "href" && a.Val != "" {
			return a.Val, nil
		}
	}

	return "", InvalidNodeAttributeMissing
}

// normaliseUrl converts relative URLs to absolute URLs
func (h *HttpFetcher) normaliseUrl(parent *url.URL, urlString string) *url.URL {

	// Parse the string into a url.URL
	uri, err := url.Parse(urlString)
	if err != nil {
		log.Debugf("Failed to parse URL: %s", urlString)
		return nil
	}

	// Resolve references to get an absolute URL
	abs := parent.ResolveReference(uri)

	return abs
}
<|endoftext|>


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

// Package textpb marshals and unmarshals protocol buffer messages as the
// textproto format.

package textpb
<commit_msg>encoding/textpb: remove blank line<commit_after>// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package textpb marshals and unmarshals protocol buffer messages as the
// textproto format.
package textpb
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/micro/internal/handler"
	"github.com/micro/micro/internal/helper"
	"github.com/micro/micro/internal/server"
	"github.com/micro/micro/internal/stats"
)

var (
	Address      = ":8080"
	RPCPath      = "/rpc"
	APIPath      = "/"
	ProxyPath    = "/{service:[a-zA-Z0-9]+}"
	Namespace    = "go.micro.api"
	HeaderPrefix = "X-Micro-"
	CORS         = map[string]bool{"*": true}
)

type srv struct {
	*mux.Router
}

func (s *srv) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if origin := r.Header.Get("Origin"); CORS[origin] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	} else if len(origin) > 0 && CORS["*"] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}

	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		return
	}

	s.Router.ServeHTTP(w, r)
}

func run(ctx *cli.Context) {
	// Init API
	var opts []server.Option

	if ctx.GlobalBool("enable_tls") {
		config, err := helper.TLSConfig(ctx)
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		opts = append(opts, server.EnableTLS(true))
		opts = append(opts, server.TLSConfig(config))
	}

	// create the router
	r := mux.NewRouter()
	s := &srv{r}
	var h http.Handler = s

	if ctx.GlobalBool("enable_stats") {
		st := stats.New()
		r.HandleFunc("/stats", st.StatsHandler)
		h = st.ServeHTTP(s)
		st.Start()
		defer st.Stop()
	}

	log.Printf("Registering RPC Handler at %s", RPCPath)
	r.HandleFunc(RPCPath, handler.RPC)

	switch ctx.GlobalString("api_handler") {
	case "proxy":
		log.Printf("Registering API Proxy Handler at %s", ProxyPath)
		r.PathPrefix(ProxyPath).Handler(handler.Proxy(Namespace, false))
	default:
		log.Printf("Registering API Handler at %s", APIPath)
		r.PathPrefix(APIPath).HandlerFunc(apiHandler)
	}

	// create the server
	api := server.NewServer(Address)
	api.Init(opts...)
	api.Handle("/", h)

	// Initialise Server
	service := micro.NewService(
		micro.Name("go.micro.api"),
		micro.RegisterTTL(
			time.Duration(ctx.GlobalInt("register_ttl"))*time.Second,
		),
		micro.RegisterInterval(
			time.Duration(ctx.GlobalInt("register_interval"))*time.Second,
		),
	)

	// Start API
	if err := api.Start(); err != nil {
		log.Fatal(err)
	}

	// Run server
	if err := service.Run(); err != nil {
		log.Fatal(err)
	}

	// Stop API
	if err := api.Stop(); err != nil {
		log.Fatal(err)
	}
}

func New(address string) server.Server {
	return server.NewServer(address)
}

func Commands() []cli.Command {
	return []cli.Command{
		{
			Name:   "api",
			Usage:  "Run the micro API",
			Action: run,
		},
	}
}
<commit_msg>Allow Authorization header<commit_after>package api

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/micro/cli"
	"github.com/micro/go-micro"
	"github.com/micro/micro/internal/handler"
	"github.com/micro/micro/internal/helper"
	"github.com/micro/micro/internal/server"
	"github.com/micro/micro/internal/stats"
)

var (
	Address      = ":8080"
	RPCPath      = "/rpc"
	APIPath      = "/"
	ProxyPath    = "/{service:[a-zA-Z0-9]+}"
	Namespace    = "go.micro.api"
	HeaderPrefix = "X-Micro-"
	CORS         = map[string]bool{"*": true}
)

type srv struct {
	*mux.Router
}

func (s *srv) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if origin := r.Header.Get("Origin"); CORS[origin] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	} else if len(origin) > 0 && CORS["*"] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}

	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		return
	}

	s.Router.ServeHTTP(w, r)
}

func run(ctx *cli.Context) {
	// Init API
	var opts []server.Option

	if ctx.GlobalBool("enable_tls") {
		config, err := helper.TLSConfig(ctx)
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		opts = append(opts, server.EnableTLS(true))
		opts = append(opts, server.TLSConfig(config))
	}

	// create the router
	r := mux.NewRouter()
	s := &srv{r}
	var h http.Handler = s

	if ctx.GlobalBool("enable_stats") {
		st := stats.New()
		r.HandleFunc("/stats", st.StatsHandler)
		h = st.ServeHTTP(s)
		st.Start()
		defer st.Stop()
	}

	log.Printf("Registering RPC Handler at %s", RPCPath)
	r.HandleFunc(RPCPath, handler.RPC)

	switch ctx.GlobalString("api_handler") {
	case "proxy":
		log.Printf("Registering API Proxy Handler at %s", ProxyPath)
		r.PathPrefix(ProxyPath).Handler(handler.Proxy(Namespace, false))
	default:
		log.Printf("Registering API Handler at %s", APIPath)
		r.PathPrefix(APIPath).HandlerFunc(apiHandler)
	}

	// create the server
	api := server.NewServer(Address)
	api.Init(opts...)
	api.Handle("/", h)

	// Initialise Server
	service := micro.NewService(
		micro.Name("go.micro.api"),
		micro.RegisterTTL(
			time.Duration(ctx.GlobalInt("register_ttl"))*time.Second,
		),
		micro.RegisterInterval(
			time.Duration(ctx.GlobalInt("register_interval"))*time.Second,
		),
	)

	// Start API
	if err := api.Start(); err != nil {
		log.Fatal(err)
	}

	// Run server
	if err := service.Run(); err != nil {
		log.Fatal(err)
	}

	// Stop API
	if err := api.Stop(); err != nil {
		log.Fatal(err)
	}
}

func New(address string) server.Server {
	return server.NewServer(address)
}

func Commands() []cli.Command {
	return []cli.Command{
		{
			Name:   "api",
			Usage:  "Run the micro API",
			Action: run,
		},
	}
}
<|endoftext|>


<commit_before>package json

import (
	"bytes"
	"encoding/json"
	"io"
	"io/ioutil"
	"testing"

	"github.com/yarpc/yarpc-go"
	"github.com/yarpc/yarpc-go/transport"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"golang.org/x/net/context"
)

type simpleRequest struct {
	Name       string
	Attributes map[string]int32
}

type simpleResponse struct {
	Success bool
}

func TestHandleStructSuccess(t *testing.T) {
	h := wrapHandler(
		"foo",
		func(_ context.Context, _ yarpc.Meta, r *simpleRequest) (*simpleResponse, yarpc.Meta, error) {
			assert.Equal(t, "foo", r.Name)
			assert.Equal(t, map[string]int32{"bar": 42}, r.Attributes)

			return &simpleResponse{Success: true}, nil, nil
		},
	)

	res, err := h.Handle(context.Background(), &transport.Request{
		Procedure: "foo",
		Body:      jsonBody(`{"name": "foo", "attributes": {"bar": 42}}`),
	})
	require.NoError(t, err)

	body, err := ioutil.ReadAll(res.Body)
	require.NoError(t, err)

	var response simpleResponse
	require.NoError(t, json.Unmarshal(body, &response))

	assert.Equal(t, simpleResponse{Success: true}, response)
}

func TestHandleMapSuccess(t *testing.T) {
	h := wrapHandler(
		"foo",
		func(_ context.Context, _ yarpc.Meta, r map[string]interface{}) (map[string]string, yarpc.Meta, error) {
			// 42.0 instead of 42 because json.Decode defaults to float64 for
			// numbers.
			assert.Equal(t, 42.0, r["foo"])
			assert.Equal(t, []interface{}{"a", "b", "c"}, r["bar"])

			return map[string]string{"success": "true"}, nil, nil
		},
	)

	res, err := h.Handle(context.Background(), &transport.Request{
		Procedure: "foo",
		Body:      jsonBody(`{"foo": 42, "bar": ["a", "b", "c"]}`),
	})
	require.NoError(t, err)

	body, err := ioutil.ReadAll(res.Body)
	require.NoError(t, err)

	var response struct{ Success string }
	require.NoError(t, json.Unmarshal(body, &response))
	assert.Equal(t, "true", response.Success)
}

func jsonBody(s string) io.Reader {
	return bytes.NewReader([]byte(s))
}
<commit_msg>Don't test wrapHandler when testing jsonHandler.<commit_after>package json

import (
	"bytes"
	"encoding/json"
	"io"
	"io/ioutil"
	"reflect"
	"testing"

	"github.com/yarpc/yarpc-go"
	"github.com/yarpc/yarpc-go/transport"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"golang.org/x/net/context"
)

type simpleRequest struct {
	Name       string
	Attributes map[string]int32
}

type simpleResponse struct {
	Success bool
}

func TestHandleStructSuccess(t *testing.T) {
	h := func(_ context.Context, _ yarpc.Meta, r *simpleRequest) (*simpleResponse, yarpc.Meta, error) {
		assert.Equal(t, "foo", r.Name)
		assert.Equal(t, map[string]int32{"bar": 42}, r.Attributes)

		return &simpleResponse{Success: true}, nil, nil
	}

	handler := jsonHandler{
		reader:  structReader{reflect.TypeOf(simpleRequest{})},
		handler: reflect.ValueOf(h),
	}

	res, err := handler.Handle(context.Background(), &transport.Request{
		Procedure: "foo",
		Body:      jsonBody(`{"name": "foo", "attributes": {"bar": 42}}`),
	})
	require.NoError(t, err)

	body, err := ioutil.ReadAll(res.Body)
	require.NoError(t, err)

	var response simpleResponse
	require.NoError(t, json.Unmarshal(body, &response))

	assert.Equal(t, simpleResponse{Success: true}, response)
}

func TestHandleMapSuccess(t *testing.T) {
	h := func(_ context.Context, _ yarpc.Meta, r map[string]interface{}) (map[string]string, yarpc.Meta, error) {
		assert.Equal(t, 42.0, r["foo"])
		assert.Equal(t, []interface{}{"a", "b", "c"}, r["bar"])

		return map[string]string{"success": "true"}, nil, nil
	}

	handler := jsonHandler{
		reader:  mapReader{reflect.TypeOf(make(map[string]interface{}))},
		handler: reflect.ValueOf(h),
	}

	res, err := handler.Handle(context.Background(), &transport.Request{
		Procedure: "foo",
		Body:      jsonBody(`{"foo": 42, "bar": ["a", "b", "c"]}`),
	})
	require.NoError(t, err)

	body, err := ioutil.ReadAll(res.Body)
	require.NoError(t, err)

	var response struct{ Success string }
	require.NoError(t, json.Unmarshal(body, &response))
	assert.Equal(t, "true", response.Success)
}

func jsonBody(s string) io.Reader {
	return bytes.NewReader([]byte(s))
}
<|endoftext|>


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

package rpc

import (
	"encoding/hex"
	"fmt"
	"strconv"

	ptypes "github.com/hyperledger/burrow/permission/types"

	"github.com/hyperledger/burrow/client"
	"github.com/hyperledger/burrow/keys"
	"github.com/hyperledger/burrow/txs"
)

//------------------------------------------------------------------------------------
// core functions with string args.
// validates strings and forms transaction

func Send(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, toAddr, amtS, nonceS string) (*txs.SendTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	if toAddr == "" {
		return nil, fmt.Errorf("destination address must be given with --to flag")
	}

	toAddrBytes, err := hex.DecodeString(toAddr)
	if err != nil {
		return nil, fmt.Errorf("toAddr is bad hex: %v", err)
	}

	tx := txs.NewSendTx()
	tx.AddInputWithNonce(pub, amt, int(nonce))
	tx.AddOutput(toAddrBytes, amt)

	return tx, nil
}

func Call(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, toAddr, amtS, nonceS, gasS, feeS, data string) (*txs.CallTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	toAddrBytes, err := hex.DecodeString(toAddr)
	if err != nil {
		return nil, fmt.Errorf("toAddr is bad hex: %v", err)
	}

	fee, err := strconv.ParseInt(feeS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("fee is misformatted: %v", err)
	}

	gas, err := strconv.ParseInt(gasS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("gas is misformatted: %v", err)
	}

	dataBytes, err := hex.DecodeString(data)
	if err != nil {
		return nil, fmt.Errorf("data is bad hex: %v", err)
	}

	tx := txs.NewCallTxWithNonce(pub, toAddrBytes, dataBytes, amt, gas, fee, int(nonce))
	return tx, nil
}

func Name(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, amtS, nonceS, feeS, name, data string) (*txs.NameTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	fee, err := strconv.ParseInt(feeS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("fee is misformatted: %v", err)
	}

	tx := txs.NewNameTxWithNonce(pub, name, data, amt, fee, int(nonce))
	return tx, nil
}

func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addrS, nonceS, permFunc string, argsS []string) (*txs.PermissionsTx, error) {
	pub, _, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addrS, "0", nonceS)
	if err != nil {
		return nil, err
	}
	var args ptypes.PermArgs
	switch permFunc {
	case "setBase":
		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
		if err != nil {
			return nil, err
		}
		if len(argsS) != 3 {
			return nil, fmt.Errorf("setBase also takes a value (true or false)")
		}
		var value bool
		if argsS[2] == "true" {
			value = true
		} else if argsS[2] == "false" {
			value = false
		} else {
			return nil, fmt.Errorf("Unknown value %s", argsS[2])
		}
		args = &ptypes.SetBaseArgs{addr, pF, value}
	case "unsetBase":
		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
		if err != nil {
			return nil, err
		}
		args = &ptypes.UnsetBaseArgs{addr, pF}
	case "setGlobal":
		pF, err := ptypes.PermStringToFlag(argsS[0])
		if err != nil {
			return nil, err
		}
		var value bool
		if argsS[1] == "true" {
			value = true
		} else if argsS[1] == "false" {
			value = false
		} else {
			return nil, fmt.Errorf("Unknown value %s", argsS[1])
		}
		args = &ptypes.SetGlobalArgs{pF, value}
	case "addRole":
		addr, err := hex.DecodeString(argsS[0])
		if err != nil {
			return nil, err
		}
		args = &ptypes.AddRoleArgs{addr, argsS[1]}
	case "removeRole":
		addr, err := hex.DecodeString(argsS[0])
		if err != nil {
			return nil, err
		}
		args = &ptypes.RmRoleArgs{addr, argsS[1]}
	default:
		return nil, fmt.Errorf("Invalid permission function for use in PermissionsTx: %s", permFunc)
	}
	// args := snativeArgs(
	tx := txs.NewPermissionsTxWithNonce(pub, args, int(nonce))
	return tx, nil
}

func Bond(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, unbondAddr, amtS, nonceS string) (*txs.BondTx, error) {
	return nil, fmt.Errorf("Bond Transaction formation to be implemented on 0.12.0")
	// pub, amt, nonce, err := checkCommon(nodeAddr, signAddr, pubkey, "", amtS, nonceS)
	// if err != nil {
	// 	return nil, err
	// }
	// var pubKey crypto.PubKeyEd25519
	// var unbondAddrBytes []byte

	// if unbondAddr == "" {
	// 	pkb, _ := hex.DecodeString(pubkey)
	// 	copy(pubKey[:], pkb)
	// 	unbondAddrBytes = pubKey.Address()
	// } else {
	// 	unbondAddrBytes, err = hex.DecodeString(unbondAddr)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("unbondAddr is bad hex: %v", err)
	// 	}

	// }

	// tx, err := types.NewBondTx(pub)
	// if err != nil {
	// 	return nil, err
	// }
	// tx.AddInputWithNonce(pub, amt, int(nonce))
	// tx.AddOutput(unbondAddrBytes, amt)

	// return tx, nil
}

func Unbond(addrS, heightS string) (*txs.UnbondTx, error) {
	return nil, fmt.Errorf("Unbond Transaction formation to be implemented on 0.12.0")
	// if addrS == "" {
	// 	return nil, fmt.Errorf("Validator address must be given with --addr flag")
	// }

	// addrBytes, err := hex.DecodeString(addrS)
	// if err != nil {
	// 	return nil, fmt.Errorf("addr is bad hex: %v", err)
	// }

	// height, err := strconv.ParseInt(heightS, 10, 32)
	// if err != nil {
	// 	return nil, fmt.Errorf("height is misformatted: %v", err)
	// }

	// return &types.UnbondTx{
	// 	Address: addrBytes,
	// 	Height:  int(height),
	// }, nil
}

func Rebond(addrS, heightS string) (*txs.RebondTx, error) {
	return nil, fmt.Errorf("Rebond Transaction formation to be implemented on 0.12.0")
	// 	if addrS == "" {
	// 		return nil, fmt.Errorf("Validator address must be given with --addr flag")
	// 	}

	// 	addrBytes, err := hex.DecodeString(addrS)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("addr is bad hex: %v", err)
	// 	}

	// 	height, err := strconv.ParseInt(heightS, 10, 32)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("height is misformatted: %v", err)
	// 	}

	// 	return &types.RebondTx{
	// 		Address: addrBytes,
	// 		Height:  int(height),
	// 	}, nil
}

type TxResult struct {
	BlockHash []byte // all txs get in a block
	Hash      []byte // all txs get a hash

	// only CallTx
	Address   []byte // only for new contracts
	Return    []byte
	Exception string

	//TODO: make Broadcast() errors more responsive so we
	// can differentiate mempool errors from other
}

// Preserve
func SignAndBroadcast(chainID string, nodeClient client.NodeClient, keyClient keys.KeyClient, tx txs.Tx, sign,
	broadcast, wait bool) (txResult *TxResult, err error) {
	var inputAddr []byte
	if sign {
		inputAddr, tx, err = signTx(keyClient, chainID, tx)
		if err != nil {
			return nil, err
		}
	}

	if broadcast {
		if wait {
			wsClient, err := nodeClient.DeriveWebsocketClient()
			if err != nil {
				return nil, err
			}
			var confirmationChannel chan client.Confirmation
			confirmationChannel, err = wsClient.WaitForConfirmation(tx, chainID, inputAddr)
			if err != nil {
				return nil, err
			} else {
				defer func() {
					if err != nil {
						// if broadcast threw an error, just return
						return
					}
					confirmation := <-confirmationChannel
					if confirmation.Error != nil {
						err = fmt.Errorf("Encountered error waiting for event: %s", confirmation.Error)
						return
					}
					if confirmation.Exception != nil {
						err = fmt.Errorf("Encountered Exception from chain: %s", confirmation.Exception)
						return
					}
					txResult.BlockHash = confirmation.BlockHash
					txResult.Exception = ""
					eventDataTx, ok := confirmation.Event.(*txs.EventDataTx)
					if !ok {
						err = fmt.Errorf("Received wrong event type.")
						return
					}
					txResult.Return = eventDataTx.Return
				}()
			}
		}

		var receipt *txs.Receipt
		receipt, err = nodeClient.Broadcast(tx)
		if err != nil {
			return nil, err
		}
		txResult = &TxResult{
			Hash: receipt.TxHash,
		}
		// NOTE: [ben] is this consistent with the Ethereum protocol?  It should seem
		// reasonable to get this returned from the chain directly.  Alternatively,
		// the benefit is that the we don't need to trust the chain node
		if tx_, ok := tx.(*txs.CallTx); ok {
			if len(tx_.Address) == 0 {
				txResult.Address = txs.NewContractAddress(tx_.Input.Address, tx_.Input.Sequence)
			}
		}
	}
	return
}
<commit_msg>Client: fix shadowed error value in SignAndBroadcast<commit_after>// Copyright 2017 Monax Industries Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rpc

import (
	"encoding/hex"
	"fmt"
	"strconv"

	ptypes "github.com/hyperledger/burrow/permission/types"

	"github.com/hyperledger/burrow/client"
	"github.com/hyperledger/burrow/keys"
	"github.com/hyperledger/burrow/txs"
)

//------------------------------------------------------------------------------------
// core functions with string args.
// validates strings and forms transaction

func Send(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, toAddr, amtS, nonceS string) (*txs.SendTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	if toAddr == "" {
		return nil, fmt.Errorf("destination address must be given with --to flag")
	}

	toAddrBytes, err := hex.DecodeString(toAddr)
	if err != nil {
		return nil, fmt.Errorf("toAddr is bad hex: %v", err)
	}

	tx := txs.NewSendTx()
	tx.AddInputWithNonce(pub, amt, int(nonce))
	tx.AddOutput(toAddrBytes, amt)

	return tx, nil
}

func Call(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, toAddr, amtS, nonceS, gasS, feeS, data string) (*txs.CallTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	toAddrBytes, err := hex.DecodeString(toAddr)
	if err != nil {
		return nil, fmt.Errorf("toAddr is bad hex: %v", err)
	}

	fee, err := strconv.ParseInt(feeS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("fee is misformatted: %v", err)
	}

	gas, err := strconv.ParseInt(gasS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("gas is misformatted: %v", err)
	}

	dataBytes, err := hex.DecodeString(data)
	if err != nil {
		return nil, fmt.Errorf("data is bad hex: %v", err)
	}

	tx := txs.NewCallTxWithNonce(pub, toAddrBytes, dataBytes, amt, gas, fee, int(nonce))
	return tx, nil
}

func Name(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addr, amtS, nonceS, feeS, name, data string) (*txs.NameTx, error) {
	pub, amt, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addr, amtS, nonceS)
	if err != nil {
		return nil, err
	}

	fee, err := strconv.ParseInt(feeS, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("fee is misformatted: %v", err)
	}

	tx := txs.NewNameTxWithNonce(pub, name, data, amt, fee, int(nonce))
	return tx, nil
}

func Permissions(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, addrS, nonceS, permFunc string, argsS []string) (*txs.PermissionsTx, error) {
	pub, _, nonce, err := checkCommon(nodeClient, keyClient, pubkey, addrS, "0", nonceS)
	if err != nil {
		return nil, err
	}
	var args ptypes.PermArgs
	switch permFunc {
	case "setBase":
		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
		if err != nil {
			return nil, err
		}
		if len(argsS) != 3 {
			return nil, fmt.Errorf("setBase also takes a value (true or false)")
		}
		var value bool
		if argsS[2] == "true" {
			value = true
		} else if argsS[2] == "false" {
			value = false
		} else {
			return nil, fmt.Errorf("Unknown value %s", argsS[2])
		}
		args = &ptypes.SetBaseArgs{addr, pF, value}
	case "unsetBase":
		addr, pF, err := decodeAddressPermFlag(argsS[0], argsS[1])
		if err != nil {
			return nil, err
		}
		args = &ptypes.UnsetBaseArgs{addr, pF}
	case "setGlobal":
		pF, err := ptypes.PermStringToFlag(argsS[0])
		if err != nil {
			return nil, err
		}
		var value bool
		if argsS[1] == "true" {
			value = true
		} else if argsS[1] == "false" {
			value = false
		} else {
			return nil, fmt.Errorf("Unknown value %s", argsS[1])
		}
		args = &ptypes.SetGlobalArgs{pF, value}
	case "addRole":
		addr, err := hex.DecodeString(argsS[0])
		if err != nil {
			return nil, err
		}
		args = &ptypes.AddRoleArgs{addr, argsS[1]}
	case "removeRole":
		addr, err := hex.DecodeString(argsS[0])
		if err != nil {
			return nil, err
		}
		args = &ptypes.RmRoleArgs{addr, argsS[1]}
	default:
		return nil, fmt.Errorf("Invalid permission function for use in PermissionsTx: %s", permFunc)
	}
	// args := snativeArgs(
	tx := txs.NewPermissionsTxWithNonce(pub, args, int(nonce))
	return tx, nil
}

func Bond(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, unbondAddr, amtS, nonceS string) (*txs.BondTx, error) {
	return nil, fmt.Errorf("Bond Transaction formation to be implemented on 0.12.0")
	// pub, amt, nonce, err := checkCommon(nodeAddr, signAddr, pubkey, "", amtS, nonceS)
	// if err != nil {
	// 	return nil, err
	// }
	// var pubKey crypto.PubKeyEd25519
	// var unbondAddrBytes []byte

	// if unbondAddr == "" {
	// 	pkb, _ := hex.DecodeString(pubkey)
	// 	copy(pubKey[:], pkb)
	// 	unbondAddrBytes = pubKey.Address()
	// } else {
	// 	unbondAddrBytes, err = hex.DecodeString(unbondAddr)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("unbondAddr is bad hex: %v", err)
	// 	}

	// }

	// tx, err := types.NewBondTx(pub)
	// if err != nil {
	// 	return nil, err
	// }
	// tx.AddInputWithNonce(pub, amt, int(nonce))
	// tx.AddOutput(unbondAddrBytes, amt)

	// return tx, nil
}

func Unbond(addrS, heightS string) (*txs.UnbondTx, error) {
	return nil, fmt.Errorf("Unbond Transaction formation to be implemented on 0.12.0")
	// if addrS == "" {
	// 	return nil, fmt.Errorf("Validator address must be given with --addr flag")
	// }

	// addrBytes, err := hex.DecodeString(addrS)
	// if err != nil {
	// 	return nil, fmt.Errorf("addr is bad hex: %v", err)
	// }

	// height, err := strconv.ParseInt(heightS, 10, 32)
	// if err != nil {
	// 	return nil, fmt.Errorf("height is misformatted: %v", err)
	// }

	// return &types.UnbondTx{
	// 	Address: addrBytes,
	// 	Height:  int(height),
	// }, nil
}

func Rebond(addrS, heightS string) (*txs.RebondTx, error) {
	return nil, fmt.Errorf("Rebond Transaction formation to be implemented on 0.12.0")
	// 	if addrS == "" {
	// 		return nil, fmt.Errorf("Validator address must be given with --addr flag")
	// 	}

	// 	addrBytes, err := hex.DecodeString(addrS)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("addr is bad hex: %v", err)
	// 	}

	// 	height, err := strconv.ParseInt(heightS, 10, 32)
	// 	if err != nil {
	// 		return nil, fmt.Errorf("height is misformatted: %v", err)
	// 	}

	// 	return &types.RebondTx{
	// 		Address: addrBytes,
	// 		Height:  int(height),
	// 	}, nil
}

type TxResult struct {
	BlockHash []byte // all txs get in a block
	Hash      []byte // all txs get a hash

	// only CallTx
	Address   []byte // only for new contracts
	Return    []byte
	Exception string

	//TODO: make Broadcast() errors more responsive so we
	// can differentiate mempool errors from other
}

// Preserve
func SignAndBroadcast(chainID string, nodeClient client.NodeClient, keyClient keys.KeyClient, tx txs.Tx, sign,
	broadcast, wait bool) (txResult *TxResult, err error) {
	var inputAddr []byte
	if sign {
		inputAddr, tx, err = signTx(keyClient, chainID, tx)
		if err != nil {
			return nil, err
		}
	}

	if broadcast {
		if wait {
			var wsClient client.NodeWebsocketClient
			wsClient, err = nodeClient.DeriveWebsocketClient()
			if err != nil {
				return nil, err
			}
			var confirmationChannel chan client.Confirmation
			confirmationChannel, err = wsClient.WaitForConfirmation(tx, chainID, inputAddr)
			if err != nil {
				return nil, err
			} else {
				defer func() {
					if err != nil {
						// if broadcast threw an error, just return
						return
					}
					confirmation := <-confirmationChannel
					if confirmation.Error != nil {
						err = fmt.Errorf("Encountered error waiting for event: %s", confirmation.Error)
						return
					}
					if confirmation.Exception != nil {
						err = fmt.Errorf("Encountered Exception from chain: %s", confirmation.Exception)
						return
					}
					txResult.BlockHash = confirmation.BlockHash
					txResult.Exception = ""
					eventDataTx, ok := confirmation.Event.(*txs.EventDataTx)
					if !ok {
						err = fmt.Errorf("Received wrong event type.")
						return
					}
					txResult.Return = eventDataTx.Return
				}()
			}
		}

		var receipt *txs.Receipt
		receipt, err = nodeClient.Broadcast(tx)
		if err != nil {
			return nil, err
		}
		txResult = &TxResult{
			Hash: receipt.TxHash,
		}
		// NOTE: [ben] is this consistent with the Ethereum protocol?  It should seem
		// reasonable to get this returned from the chain directly.  Alternatively,
		// the benefit is that the we don't need to trust the chain node
		if tx_, ok := tx.(*txs.CallTx); ok {
			if len(tx_.Address) == 0 {
				txResult.Address = txs.NewContractAddress(tx_.Input.Address, tx_.Input.Sequence)
			}
		}
	}
	return
}
<|endoftext|>