<commit_before>package avcompat

import "errors"

// ISC Errors
var (
	ErrIndexRange        = errors.New("Transition index exceeds encoding range")
	ErrSerialLength      = errors.New("Serial transition length cannot exceed 252 bytes")
	ErrSerialInvalidByte = errors.New("Serial transition cannot contain \\xFF byte")
	ErrDecodeLength      = errors.New("Cannot decode due to short buffer")
	ErrDecodeIllegal     = errors.New("Cannot decode due to invalid bitstream")
)

type ISCDigitalTransition struct {
	index uint
	value bool
}

type ISCAnalogTransition struct {
	index uint
	value uint16
}

type ISCSerialTransition struct {
	index uint
	value []byte
}

type ISCClearOperation struct{}
type ISCRefreshOperation struct{}

func (t *ISCDigitalTransition) MarshalBinary() ([]byte, error) {
	var buf [2]byte
	if t.index > 4095 {
		return nil, ErrIndexRange
	}
	buf[0] = byte(0x80) | byte(0x1f&(t.index>>7))
	if !t.value {
		buf[0] |= 0x20 // contains the complement of the value
	}
	buf[1] = byte(0x7f & t.index)
	return buf[:], nil
}

func (t *ISCDigitalTransition) UnmarshalBinary(buf []byte) error {
	if len(buf) < 2 {
		return ErrDecodeLength
	}
	if (buf[0]&byte(0xC0) != byte(0x80)) || (buf[1]&byte(0x80) != byte(0x00)) {
		return ErrDecodeIllegal
	}

	t.index = uint(buf[1]) | uint(0x1f&(buf[0])<<7)
	t.value = (buf[0]&byte(0x20) == byte(0x00))
	return nil
}

func (t *ISCAnalogTransition) MarshalBinary() ([]byte, error) {
	var buf [4]byte
	if t.index > 1023 {
		return nil, ErrIndexRange
	}
	buf[0] = byte(0xc0) | byte((t.value>>14)<<4) | byte(t.index>>7)
	buf[1] = byte(0x7f & t.index)
	buf[2] = byte(0x7f & (t.value >> 7))
	buf[3] = byte(0x7f & t.value)
	return buf[0:4], nil
}

func (t *ISCAnalogTransition) UnmarshalBinary(buf []byte) error {
	if len(buf) < 4 {
		return ErrDecodeLength
	}
	if (buf[0]&byte(0xC8) != byte(0xC0)) ||
		(buf[1]&byte(0x80) != byte(0x00)) ||
		(buf[2]&byte(0x80) != byte(0x00)) ||
		(buf[3]&byte(0x80) != byte(0x00)) {
		return ErrDecodeIllegal
	}

	t.index = uint(buf[1]) | uint(0x07&(buf[0])<<7)
	t.value = uint16(0x30&buf[0]<<14) | uint16(buf[2]<<7) | uint16(buf[3])
	return nil
}

func (t *ISCSerialTransition) MarshalBinary() ([]byte, error) {
	if t.index > 1023 {
		return nil, ErrIndexRange
	}
	if len(t.value) > 252 {
		return nil, ErrSerialLength
	}
	for j := range t.value {
		if t.value[j] == byte(0xFF) {
			return nil, ErrSerialInvalidByte
		}
	}
	buf := make([]byte, len(t.value)+3, len(t.value)+3)
	buf[0] = byte(0xc8) | byte(t.index>>7)
	buf[1] = byte(0x7f & t.index)
	copy(buf[2:], t.value)
	buf[len(buf)-1] = 0xff
	return buf, nil
}

func (o *ISCClearOperation) MarshalBinary() ([]byte, error) {
	return []byte{0xFC}, nil
}

func (o *ISCRefreshOperation) MarshalBinary() ([]byte, error) {
	return []byte{0xFD}, nil
}
<commit_msg>Unmarshal operations for completeness<commit_after>package avcompat

import "errors"

// ISC Errors
var (
	ErrIndexRange        = errors.New("Transition index exceeds encoding range")
	ErrSerialLength      = errors.New("Serial transition length cannot exceed 252 bytes")
	ErrSerialInvalidByte = errors.New("Serial transition cannot contain \\xFF byte")
	ErrDecodeLength      = errors.New("Cannot decode due to short buffer")
	ErrDecodeIllegal     = errors.New("Cannot decode due to invalid bitstream")
)

type ISCDigitalTransition struct {
	index uint
	value bool
}

type ISCAnalogTransition struct {
	index uint
	value uint16
}

type ISCSerialTransition struct {
	index uint
	value []byte
}

type ISCClearOperation struct{}
type ISCRefreshOperation struct{}

func (t *ISCDigitalTransition) MarshalBinary() ([]byte, error) {
	var buf [2]byte
	if t.index > 4095 {
		return nil, ErrIndexRange
	}
	buf[0] = byte(0x80) | byte(0x1f&(t.index>>7))
	if !t.value {
		buf[0] |= 0x20 // contains the complement of the value
	}
	buf[1] = byte(0x7f & t.index)
	return buf[:], nil
}

func (t *ISCDigitalTransition) UnmarshalBinary(buf []byte) error {
	if len(buf) < 2 {
		return ErrDecodeLength
	}
	if (buf[0]&byte(0xC0) != byte(0x80)) || (buf[1]&byte(0x80) != byte(0x00)) {
		return ErrDecodeIllegal
	}

	t.index = uint(buf[1]) | uint(0x1f&(buf[0])<<7)
	t.value = (buf[0]&byte(0x20) == byte(0x00))
	return nil
}

func (t *ISCAnalogTransition) MarshalBinary() ([]byte, error) {
	var buf [4]byte
	if t.index > 1023 {
		return nil, ErrIndexRange
	}
	buf[0] = byte(0xc0) | byte((t.value>>14)<<4) | byte(t.index>>7)
	buf[1] = byte(0x7f & t.index)
	buf[2] = byte(0x7f & (t.value >> 7))
	buf[3] = byte(0x7f & t.value)
	return buf[0:4], nil
}

func (t *ISCAnalogTransition) UnmarshalBinary(buf []byte) error {
	if len(buf) < 4 {
		return ErrDecodeLength
	}
	if (buf[0]&byte(0xC8) != byte(0xC0)) ||
		(buf[1]&byte(0x80) != byte(0x00)) ||
		(buf[2]&byte(0x80) != byte(0x00)) ||
		(buf[3]&byte(0x80) != byte(0x00)) {
		return ErrDecodeIllegal
	}

	t.index = uint(buf[1]) | uint(0x07&(buf[0])<<7)
	t.value = uint16(0x30&buf[0]<<14) | uint16(buf[2]<<7) | uint16(buf[3])
	return nil
}

func (t *ISCSerialTransition) MarshalBinary() ([]byte, error) {
	if t.index > 1023 {
		return nil, ErrIndexRange
	}
	if len(t.value) > 252 {
		return nil, ErrSerialLength
	}
	for j := range t.value {
		if t.value[j] == byte(0xFF) {
			return nil, ErrSerialInvalidByte
		}
	}
	buf := make([]byte, len(t.value)+3, len(t.value)+3)
	buf[0] = byte(0xc8) | byte(t.index>>7)
	buf[1] = byte(0x7f & t.index)
	copy(buf[2:], t.value)
	buf[len(buf)-1] = 0xff
	return buf, nil
}

func (o *ISCClearOperation) MarshalBinary() ([]byte, error) {
	return []byte{0xFC}, nil
}

func (o *ISCClearOperation) UnmarshalBinary(buf []byte) error {
	if len(buf) < 1 {
		return ErrDecodeLength
	}
	if buf[0] != 0xFC {
		return ErrDecodeIllegal
	}
	return nil
}

func (o *ISCRefreshOperation) MarshalBinary() ([]byte, error) {
	return []byte{0xFD}, nil
}

func (o *ISCRefreshOperation) UnmarshalBinary(buf []byte) error {
	if len(buf) < 1 {
		return ErrDecodeLength
	}
	if buf[0] != 0xFD {
		return ErrDecodeIllegal
	}
	return nil
}<|endoftext|>


<commit_before>package exchange

import (
	"github.com/anacrolix/sync"
	"time"
	"encoding/json"
	"net/http"
	"errors"
	"github.com/op/go-logging"
	"strconv"
)

var log = logging.MustGetLogger("ipfs")

type BitcoinPriceFetcher struct {
	sync.Mutex
	cache map[string]float64
}

func NewBitcoinPriceFetcher() *BitcoinPriceFetcher {
	b := BitcoinPriceFetcher{
		cache: make(map[string]float64),
	}
	go b.run()
	return &b
}

func (b *BitcoinPriceFetcher) GetExchangeRate(currencyCode string) (float64, error) {
	price, ok := b.cache[currencyCode]
	if !ok {
		return 0, errors.New("Currency not tracked")
	}
	return price, nil
}

func (b *BitcoinPriceFetcher) GetLatestRate(currencyCode string) (float64, error) {
	b.fetchCurrentRates()
	price, ok := b.cache[currencyCode]
	if !ok {
		return 0, errors.New("Currency not tracked")
	}
	return price, nil
}

func (b *BitcoinPriceFetcher) run() {
	b.fetchCurrentRates()
	ticker := time.NewTicker(time.Minute * 15)
	for {
		select {
		case <- ticker.C:
			b.fetchCurrentRates()
		}
	}
}

func (b *BitcoinPriceFetcher) fetchCurrentRates() {
	log.Infof("Fetching bitcoin exchange rates...")
	err := b.fetchBitcoinAverage()
	if err == nil {
		return
	}
	err = b.fetchBitpay()
	if err == nil {
		return
	}
	err = b.fetchBlockchainDotInfo()
	if err == nil {
		return
	}
	err = b.fetchBitcoinCharts()
	if err != nil {
		log.Error("Failed to fetch bitcoin exchange rates")
	}

}

func (b *BitcoinPriceFetcher) fetchBitcoinAverage() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://api.bitcoinaverage.com/ticker/global/all")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		if k != "timestamp" {
			price := v.(map[string]interface{})["last"].(float64)
			b.cache[k] = price
		}
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBitpay() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://bitpay.com/api/rates")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data []map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for _, obj := range data {
		k := obj["code"].(string)
		price := obj["rate"].(float64)
		b.cache[k] = price
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBlockchainDotInfo() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://blockchain.info/ticker")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		price := v.(map[string]interface{})["last"].(float64)
		b.cache[k] = price
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBitcoinCharts() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://api.bitcoincharts.com/v1/weighted_prices.json")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		if k != "timestamp" {
			p, ok := v.(map[string]interface{})["24h"]
			if !ok {
				continue
			}
			price, err := strconv.ParseFloat(p.(string), 64)
			if err != nil {
				return err
			}
			b.cache[k] = price
		}
	}
	return nil
}<commit_msg>Add cache locking<commit_after>package exchange

import (
	"github.com/anacrolix/sync"
	"time"
	"encoding/json"
	"net/http"
	"errors"
	"github.com/op/go-logging"
	"strconv"
)

var log = logging.MustGetLogger("ipfs")

type BitcoinPriceFetcher struct {
	sync.Mutex
	cache map[string]float64
}

func NewBitcoinPriceFetcher() *BitcoinPriceFetcher {
	b := BitcoinPriceFetcher{
		cache: make(map[string]float64),
	}
	go b.run()
	return &b
}

func (b *BitcoinPriceFetcher) GetExchangeRate(currencyCode string) (float64, error) {
	b.Lock()
	defer b.Unlock()
	price, ok := b.cache[currencyCode]
	if !ok {
		return 0, errors.New("Currency not tracked")
	}
	return price, nil
}

func (b *BitcoinPriceFetcher) GetLatestRate(currencyCode string) (float64, error) {
	b.fetchCurrentRates()
	b.Lock()
	defer b.Unlock()
	price, ok := b.cache[currencyCode]
	if !ok {
		return 0, errors.New("Currency not tracked")
	}
	return price, nil
}

func (b *BitcoinPriceFetcher) run() {
	b.fetchCurrentRates()
	ticker := time.NewTicker(time.Minute * 15)
	for {
		select {
		case <- ticker.C:
			b.fetchCurrentRates()
		}
	}
}

func (b *BitcoinPriceFetcher) fetchCurrentRates() {
	b.Lock()
	defer b.Unlock()
	log.Infof("Fetching bitcoin exchange rates...")
	err := b.fetchBitcoinAverage()
	if err == nil {
		return
	}
	err = b.fetchBitpay()
	if err == nil {
		return
	}
	err = b.fetchBlockchainDotInfo()
	if err == nil {
		return
	}
	err = b.fetchBitcoinCharts()
	if err != nil {
		log.Error("Failed to fetch bitcoin exchange rates")
	}

}

func (b *BitcoinPriceFetcher) fetchBitcoinAverage() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://api.bitcoinaverage.com/ticker/global/all")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		if k != "timestamp" {
			price := v.(map[string]interface{})["last"].(float64)
			b.cache[k] = price
		}
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBitpay() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://bitpay.com/api/rates")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data []map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for _, obj := range data {
		k := obj["code"].(string)
		price := obj["rate"].(float64)
		b.cache[k] = price
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBlockchainDotInfo() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://blockchain.info/ticker")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		price := v.(map[string]interface{})["last"].(float64)
		b.cache[k] = price
	}
	return nil
}

func (b *BitcoinPriceFetcher) fetchBitcoinCharts() (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = errors.New("Panic fetching exchange rates")
		}
	}()
	resp, err := http.Get("https://api.bitcoincharts.com/v1/weighted_prices.json")
	if err != nil {
		return err
	}
	decoder := json.NewDecoder(resp.Body)
	var data map[string]interface{}
	err = decoder.Decode(&data)
	if err != nil {
		return err
	}
	for k, v := range data {
		if k != "timestamp" {
			p, ok := v.(map[string]interface{})["24h"]
			if !ok {
				continue
			}
			price, err := strconv.ParseFloat(p.(string), 64)
			if err != nil {
				return err
			}
			b.cache[k] = price
		}
	}
	return nil
}<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 v3

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"testing"

	"cloud.google.com/go/storage"
	"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
	"github.com/google/uuid"
)

func TestBatchTranslateText(t *testing.T) {
	t.Skip("https://github.com/GoogleCloudPlatform/golang-samples/issues/1572")
	tc := testutil.SystemTest(t)

	bucketName := fmt.Sprintf("%s-batch_translate_text-%v", tc.ProjectID, uuid.New().ID())
	location := "us-central1"
	inputURI := "gs://cloud-samples-data/translation/text.txt"
	outputURI := fmt.Sprintf("gs://%s/translation/output/", bucketName)
	sourceLang := "en"
	targetLang := "es"

	// Create a temporary bucket to store annotation output.
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		t.Fatalf("storage.NewClient: %v", err)
	}
	defer client.Close()

	bucket := client.Bucket(bucketName)
	if err := bucket.Create(ctx, tc.ProjectID, nil); err != nil {
		t.Fatalf("bucket.Create: %v", err)
	}
	defer deleteBucket(ctx, t, bucket)

	// Translate a sample text and check the number of translated characters.
	var buf bytes.Buffer
	if err := batchTranslateText(&buf, tc.ProjectID, location, inputURI, outputURI, sourceLang, targetLang); err != nil {
		t.Fatalf("batchTranslateText: %v", err)
	}
	if got, want := buf.String(), "Total characters"; !strings.Contains(got, want) {
		t.Errorf("batchTranslateText got:\n----\n%s----\nWant to contain:\n----\n%s\n----", got, want)
	}
}
<commit_msg>chore: added retry for flaky ttranslate test (#1860)<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 v3

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"testing"
	"time"

	"cloud.google.com/go/storage"
	"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
	"github.com/google/uuid"
)

func TestBatchTranslateText(t *testing.T) {
	t.Skip("https://github.com/GoogleCloudPlatform/golang-samples/issues/1572")
	tc := testutil.SystemTest(t)

	bucketName := fmt.Sprintf("%s-batch_translate_text-%v", tc.ProjectID, uuid.New().ID())
	location := "us-central1"
	inputURI := "gs://cloud-samples-data/translation/text.txt"
	outputURI := fmt.Sprintf("gs://%s/translation/output/", bucketName)
	sourceLang := "en"
	targetLang := "es"

	// Create a temporary bucket to store annotation output.
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		t.Fatalf("storage.NewClient: %v", err)
	}
	defer client.Close()

	bucket := client.Bucket(bucketName)
	if err := bucket.Create(ctx, tc.ProjectID, nil); err != nil {
		t.Fatalf("bucket.Create: %v", err)
	}
	defer deleteBucket(ctx, t, bucket)

	// Translate a sample text and check the number of translated characters.
	testutil.Retry(t, 3, 10*time.Second, func(r *testutil.R) {
		var buf bytes.Buffer
		if err := batchTranslateText(&buf, tc.ProjectID, location, inputURI, outputURI, sourceLang, targetLang); err != nil {
			r.Errorf("batchTranslateText: %v", err)
			return
		}
		if got, want := buf.String(), "Total characters"; !strings.Contains(got, want) {
			r.Errorf("batchTranslateText got:\n----\n%s----\nWant to contain:\n----\n%s\n----", got, want)
		}
	})
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"go/build"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

type mPlay struct {
	Args      []string          `json:"args"`
	Dir       string            `json:"dir"`
	Src       string            `json:"src"`
	Env       map[string]string `json:"env"`
	Cid       string            `json:"cid"`
	BuildOnly bool              `json:"build_only"`
	b         *Broker
}

// todo: send the client output as it comes
func (m *mPlay) Call() (interface{}, string) {
	env := envSlice(m.Env)

	tmpDir := m.Env["TMP"]
	if tmpDir == "" {
		tmpDir = os.TempDir()
	}
	tmpDir = filepath.Join(tmpDir, "GoSublime", "play")
	// if this fails then the next operation fails as well so no point in checking this
	os.MkdirAll(tmpDir, 0755)

	dir, err := ioutil.TempDir(tmpDir, "play-")
	if err != nil {
		return nil, err.Error()
	}
	defer os.RemoveAll(dir)

	if m.Src != "" {
		err = ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(m.Src), 0755)
		if err != nil {
			return nil, err.Error()
		}
		m.Dir = dir
	}

	if m.Args == nil {
		m.Args = []string{}
	}

	if m.Dir == "" {
		return nil, "missing directory"
	}

	if m.Cid == "" {
		m.Cid = "play.auto." + numbers.nextString()
	} else {
		killCmd(m.Cid)
	}

	res := M{}
	stdErr := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	runCmd := func(name string, args ...string) (M, error) {
		start := time.Now()
		stdOut.Reset()
		stdErr.Reset()
		c := exec.Command(name, args...)
		c.Stdout = stdOut
		c.Stderr = stdErr
		c.Dir = m.Dir
		c.Env = env

		watchCmd(m.Cid, c)
		defer unwatchCmd(m.Cid)

		err := c.Run()
		res := M{
			"out": jData(stdOut.Bytes()),
			"err": jData(stdErr.Bytes()),
			"dur": time.Now().Sub(start).String(),
		}

		return res, err
	}

	if !m.BuildOnly {
		pkg, err := build.ImportDir(m.Dir, 0)
		if err != nil {
			return res, err.Error()
		}

		if !pkg.IsCommand() {
			res, err = runCmd("go", "test")
			return res, errStr(err)
		}
	}

	fn := filepath.Join(dir, "gosublime.a.exe")
	res, err = runCmd("go", "build", "-o", fn)
	if m.BuildOnly || err != nil {
		return res, errStr(err)
	}

	res, err = runCmd(fn, m.Args...)
	return res, errStr(err)
}

func init() {
	registry.Register("play", func(b *Broker) Caller {
		return &mPlay{
			b:   b,
			Env: map[string]string{},
		}
	})
}
<commit_msg>* pass the temp fn and src fn back to the client<commit_after>package main

import (
	"bytes"
	"go/build"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

type mPlay struct {
	Args      []string          `json:"args"`
	Dir       string            `json:"dir"`
	Fn        string            `json:"fn"`
	Src       string            `json:"src"`
	Env       map[string]string `json:"env"`
	Cid       string            `json:"cid"`
	BuildOnly bool              `json:"build_only"`
	b         *Broker
}

// todo: send the client output as it comes
func (m *mPlay) Call() (interface{}, string) {
	env := envSlice(m.Env)

	tmpDir := m.Env["TMP"]
	if tmpDir == "" {
		tmpDir = os.TempDir()
	}
	tmpDir = filepath.Join(tmpDir, "GoSublime", "play")
	// if this fails then the next operation fails as well so no point in checking this
	os.MkdirAll(tmpDir, 0755)

	dir, err := ioutil.TempDir(tmpDir, "play-")
	if err != nil {
		return nil, err.Error()
	}
	defer os.RemoveAll(dir)

	tmpFn := ""
	if m.Src != "" {
		tmpFn = filepath.Join(dir, "a.go")
		err = ioutil.WriteFile(tmpFn, []byte(m.Src), 0644)
		if err != nil {
			return nil, err.Error()
		}
		m.Dir = dir
	}

	if m.Args == nil {
		m.Args = []string{}
	}

	if m.Dir == "" {
		return nil, "missing directory"
	}

	if m.Cid == "" {
		m.Cid = "play.auto." + numbers.nextString()
	} else {
		killCmd(m.Cid)
	}

	res := M{}
	stdErr := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	runCmd := func(name string, args ...string) (M, error) {
		start := time.Now()
		stdOut.Reset()
		stdErr.Reset()
		c := exec.Command(name, args...)
		c.Stdout = stdOut
		c.Stderr = stdErr
		c.Dir = m.Dir
		c.Env = env

		watchCmd(m.Cid, c)
		defer unwatchCmd(m.Cid)

		err := c.Run()
		res := M{
			"tmpFn": tmpFn,
			"fn":    m.Fn,
			"out":   jData(stdOut.Bytes()),
			"err":   jData(stdErr.Bytes()),
			"dur":   time.Now().Sub(start).String(),
		}

		return res, err
	}

	if !m.BuildOnly {
		pkg, err := build.ImportDir(m.Dir, 0)
		if err != nil {
			return res, err.Error()
		}

		if !pkg.IsCommand() {
			res, err = runCmd("go", "test")
			return res, errStr(err)
		}
	}

	fn := filepath.Join(dir, "gosublime.a.exe")
	res, err = runCmd("go", "build", "-o", fn)
	if m.BuildOnly || err != nil {
		return res, errStr(err)
	}

	res, err = runCmd(fn, m.Args...)
	return res, errStr(err)
}

func init() {
	registry.Register("play", func(b *Broker) Caller {
		return &mPlay{
			b:   b,
			Env: map[string]string{},
		}
	})
}
<|endoftext|>


<commit_before>/*
 Copyright 2017 Crunchy Data Solutions, Inc.
 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.
*/

// Crunchy Container Test
package cct

import (
	"bytes"
	"fmt"
	"os/exec"
	"path"
	"testing"

	"github.com/docker/docker/client"
)

// executes a named docker example, and traps output
func startDockerExample(
    basePath string,
    exampleName string,
    arg ...string) (pathToCleanup string, cmdout string, err error) {

    pathToExample := path.Join(
        basePath, "examples", "docker", exampleName, "run.sh")
    pathToCleanup = path.Join(
        basePath, "examples", "docker", exampleName, "cleanup.sh")

    out, err := exec.Command(pathToExample, arg...).CombinedOutput()

    cmdout = bytes.NewBuffer(out).String()
    if err != nil {
        return
    }
    return
}

// executes an example cleanup script, and traps output
func cleanupExample(pathToCleanup string) (cmdout string, err error) {
    out, err := exec.Command(pathToCleanup).CombinedOutput()
    if err != nil {
        return
    }
    cmdout = bytes.NewBuffer(out).String()
    return
}

// Starts a named example for a golang test, logs output or fails test. The returned cleanup function, which wraps the example cleanup function, will have no effect if skip=true
func startDockerExampleForTest(
    t *testing.T,
    basePath string,
    exampleName string,
    arg ...string) (cleanup func(skip bool)) {

    t.Log("Starting Example: docker/" + exampleName)
    pathToCleanup, cmdout, err := startDockerExample(basePath, exampleName, arg...)
    if err != nil {
        t.Fatal(err, cmdout)
    }
    t.Log(cmdout)

    cleanup = func (skip bool) {
        cleanupTest(t, skip, exampleName, pathToCleanup)
    }

    return
}

// wraps example cleanup script for a golang unit test, or has no effect if skip=true
func cleanupTest(t *testing.T, skip bool, name string, pathToCleanup string) {

    if skip {
        t.Logf("SKIPPING %s cleanup: %s\n", name, pathToCleanup)
    } else {
        t.Logf("Cleaning %s: %s\n", name, pathToCleanup)
        cmdout, err := cleanupExample(pathToCleanup)
        if err != nil {
            t.Error(err, cmdout)
        }
        t.Log(cmdout)
    }
}

// Starts basic example for test. It is caller's responsibility to cleanup
func startBasic(
    t *testing.T,
    docker *client.Client,
    basePath string,
    timeout int64) (id string, cleanup func(skip bool)) {

    fmt.Printf("\nWaiting maximum %d seconds to start basic example", timeout)
    cleanup = startDockerExampleForTest(t, basePath, "basic")

    var err error
    id, err = waitForPostgresContainer(docker, "basic", timeout)
    if err != nil {
        t.Fatal(err)
    }
    t.Log("Started basic container: " + id)

    return
}

// Starts the master-replica example, and wait for both servers to start
func startMasterReplica(
    t *testing.T,
    docker *client.Client,
    basePath string,
    timeoutSeconds int64) (masterId, replicaId string, cleanup func(skip bool)) {

    fmt.Println("Starting master-replica example, and pausing while example sleeps for 20 seconds")
    cleanup = startDockerExampleForTest(t, basePath, "master-replica")

    var err error

    fmt.Printf("\nWaiting maximum of %d seconds for master container", timeoutSeconds)
    masterId, err = waitForPostgresContainer(docker, "master", timeoutSeconds)
    if err != nil {
        t.Fatal("master container did not start")
    }
    t.Log("Started master container: " + masterId)

    fmt.Printf("\nWaiting maximum of %d seconds for replica container", timeoutSeconds)
    replicaId, err = waitForPostgresContainer(docker, "replica", timeoutSeconds)
    if err != nil {
        t.Fatal("replica container did not start")
    }
    t.Log("Started replica container: " + replicaId)

    return
}
<commit_msg>cmdout to logfile<commit_after>/*
 Copyright 2017 Crunchy Data Solutions, Inc.
 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.
*/

// Crunchy Container Test
package cct

import (
	"bytes"
	"fmt"
    "io/ioutil"
    "os"
	"os/exec"
	"path"
	"testing"

	"github.com/docker/docker/client"
)

// executes a named docker example, and traps output
func startDockerExample(
    basePath string,
    exampleName string,
    arg ...string) (pathToCleanup string, cmdout string, err error) {

    pathToExample := path.Join(
        basePath, "examples", "docker", exampleName, "run.sh")
    pathToCleanup = path.Join(
        basePath, "examples", "docker", exampleName, "cleanup.sh")

    out, err := exec.Command(pathToExample, arg...).CombinedOutput()

    cmdout = bytes.NewBuffer(out).String()
    if err != nil {
        return
    }
    return
}

// executes an example cleanup script, and traps output
func cleanupExample(pathToCleanup string) (cmdout string, err error) {
    out, err := exec.Command(pathToCleanup).CombinedOutput()
    if err != nil {
        return
    }
    cmdout = bytes.NewBuffer(out).String()
    return
}

func writeCmdout(cmdout, path string, append bool) error {
    if _, err := os.Stat(path); err == nil && append {
        f, err := os.OpenFile(path, os.O_APPEND | os.O_WRONLY, 0644)
        if err != nil {
            return err
        }
        defer f.Close()
        if _, err = f.WriteString(cmdout); err != nil {
            return err
        }
    }

    out := []byte(cmdout)

    return ioutil.WriteFile(path, out, 0644)
}

// Starts a named example for a golang test, logs output or fails test. The returned cleanup function, which wraps the example cleanup function, will have no effect if skip=true
func startDockerExampleForTest(
    t *testing.T,
    basePath string,
    exampleName string,
    arg ...string) (cleanup func(skip bool)) {

    var logname string = path.Join("/tmp", "cmdout." + exampleName + ".log")
    t.Log("Starting Example: docker/" + exampleName)
    pathToCleanup, cmdout, err := startDockerExample(basePath, exampleName, arg...)
    if err != nil {
        if e := writeCmdout(cmdout, logname, false); e != nil {
            t.Errorf("Error logging cmdout to %s:\n%s\ncmdout:\n%s\n", logname, e, cmdout)
        }
        t.Fatal(err)
    }
    if e := writeCmdout(cmdout, logname, false); e != nil {
        t.Errorf("Error logging cmdout to %s:\n%s\ncmdout:\n%s\n", logname, e, cmdout)
    }

    cleanup = func (skip bool) {
        cleanupTest(t, skip, exampleName, pathToCleanup)
    }

    return
}

// wraps example cleanup script for a golang unit test, or has no effect if skip=true
func cleanupTest(t *testing.T, skip bool, name string, pathToCleanup string) {

    if skip {
        t.Logf("SKIPPING %s cleanup: %s\n", name, pathToCleanup)
    } else {
        t.Logf("Cleaning %s: %s\n", name, pathToCleanup)

        var logname string = path.Join("/tmp", "cmdout." + name + ".log")

        cmdout, err := cleanupExample(pathToCleanup)
        if err != nil {
            if e := writeCmdout(cmdout, logname, true); e != nil {
                t.Errorf("Error logging cmdout to %s:\n%s\ncmdout:\n%s\n", logname, e, cmdout)
            }
            t.Error(err)
        }
        if e := writeCmdout(cmdout, logname, true); e != nil {
            t.Errorf("Error logging cmdout to %s:\n%s\ncmdout:\n%s\n", logname, e, cmdout)
        }
    }
}

// Starts basic example for test. It is caller's responsibility to cleanup
func startBasic(
    t *testing.T,
    docker *client.Client,
    basePath string,
    timeout int64) (id string, cleanup func(skip bool)) {

    fmt.Printf("\nWaiting maximum %d seconds to start basic example", timeout)
    cleanup = startDockerExampleForTest(t, basePath, "basic")

    var err error
    id, err = waitForPostgresContainer(docker, "basic", timeout)
    if err != nil {
        t.Fatal(err)
    }
    t.Log("Started basic container: " + id)

    return
}

// Starts the master-replica example, and wait for both servers to start
func startMasterReplica(
    t *testing.T,
    docker *client.Client,
    basePath string,
    timeoutSeconds int64) (masterId, replicaId string, cleanup func(skip bool)) {

    fmt.Println("Starting master-replica example, and pausing while example sleeps for 20 seconds")
    cleanup = startDockerExampleForTest(t, basePath, "master-replica")

    var err error

    fmt.Printf("\nWaiting maximum of %d seconds for master container", timeoutSeconds)
    masterId, err = waitForPostgresContainer(docker, "master", timeoutSeconds)
    if err != nil {
        t.Fatal("master container did not start")
    }
    t.Log("Started master container: " + masterId)

    fmt.Printf("\nWaiting maximum of %d seconds for replica container", timeoutSeconds)
    replicaId, err = waitForPostgresContainer(docker, "replica", timeoutSeconds)
    if err != nil {
        t.Fatal("replica container did not start")
    }
    t.Log("Started replica container: " + replicaId)

    return
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 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 indexpack

// This file adds a VFS implementation that enables an index pack to be read
// from a ZIP file of its root directory.  It is not possible to write to the
// pack in this format, and the methods that support writing will return
// errors.

import (
	"archive/zip"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/net/context"
)

// The operations that support writing all return errNotSupported for all calls.
var errNotSupported = errors.New("operation not supported")

type readerAt struct{ io.ReadSeeker }

func (r readerAt) ReadAt(buf []byte, pos int64) (int, error) {
	const fromStart = 0
	if _, err := r.Seek(pos, fromStart); err != nil {
		return 0, err
	}
	return r.Read(buf)
}

// OpenZip returns a read-only *Archive tied to the ZIP file at r, which is
// expected to contain the recursive contents of an indexpack directory named
// root and its subdirectories.  Operations that write to the pack will return
// errors.
func OpenZip(ctx context.Context, r io.ReadSeeker, root string, opts ...Option) (*Archive, error) {
	const fromEnd = 2
	size, err := r.Seek(0, fromEnd)
	if err != nil {
		return nil, err
	}

	rc, err := zip.NewReader(readerAt{r}, size)
	if err != nil {
		return nil, err
	}
	opts = append(opts, FS(zipFS{rc, "./"}))
	pack, err := Open(ctx, "./"+root, opts...)
	if err != nil {
		return nil, err
	}
	return pack, nil
}

type zipFS struct {
	pack   *zip.Reader
	prefix string
}

func (z zipFS) find(path string) *zip.File {
	dirNeedle := strings.TrimPrefix(path, z.prefix) + string(filepath.Separator)
	needle := dirNeedle[:len(dirNeedle)-1]
	for _, f := range z.pack.File {
		switch f.Name {
		case needle, dirNeedle:
			return f
		}
	}
	return nil
}

// Stat implements part of indexpack.VFS using the file metadata stored in the
// zip archive.  The path must match one of the archive paths, modulo the
// prefix associated with z.
func (z zipFS) Stat(_ context.Context, path string) (os.FileInfo, error) {
	f := z.find(path)
	if f == nil {
		return nil, fmt.Errorf("path %q does not exist", path)
	}
	return f.FileInfo(), nil
}

// Open implements part of indexpack.VFS, returning a io.ReadCloser owned by
// the underlying zip archive. It is safe to open multiple files concurrently,
// as documented by the zip package.
func (z zipFS) Open(_ context.Context, path string) (io.ReadCloser, error) {
	f := z.find(path)
	if f == nil {
		return nil, os.ErrNotExist
	}
	return f.Open()
}

// Glob implements part of indexpack.VFS using filepath.Match to compare the
// glob pattern to each archive path as trimmed by the prefix.
func (z zipFS) Glob(_ context.Context, glob string) ([]string, error) {
	needle := strings.TrimPrefix(glob, z.prefix)
	var names []string
	for _, f := range z.pack.File {
		name := strings.TrimPrefix(f.Name, z.prefix)
		if ok, err := filepath.Match(needle, name); err != nil {
			log.Panicf("Invalid glob pattern %q: %v", needle, err)
		} else if ok {
			names = append(names, name)
		}
	}
	return names, nil
}

func (zipFS) Create(_ context.Context, _ string) (io.WriteCloser, error) { return nil, errNotSupported }
func (zipFS) MkdirAll(_ context.Context, _ string, _ os.FileMode) error  { return errNotSupported }
func (zipFS) Rename(_ context.Context, _, _ string) error                { return errNotSupported }
func (zipFS) Remove(_ context.Context, _ string) error                   { return errNotSupported }
<commit_msg>Drop unwarranted premature optimization. :)<commit_after>/*
 * Copyright 2015 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 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 indexpack

// This file adds a VFS implementation that enables an index pack to be read
// from a ZIP file of its root directory.  It is not possible to write to the
// pack in this format, and the methods that support writing will return
// errors.

import (
	"archive/zip"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/net/context"
)

// The operations that support writing all return errNotSupported for all calls.
var errNotSupported = errors.New("operation not supported")

type readerAt struct{ io.ReadSeeker }

func (r readerAt) ReadAt(buf []byte, pos int64) (int, error) {
	const fromStart = 0
	if _, err := r.Seek(pos, fromStart); err != nil {
		return 0, err
	}
	return r.Read(buf)
}

// OpenZip returns a read-only *Archive tied to the ZIP file at r, which is
// expected to contain the recursive contents of an indexpack directory named
// root and its subdirectories.  Operations that write to the pack will return
// errors.
func OpenZip(ctx context.Context, r io.ReadSeeker, root string, opts ...Option) (*Archive, error) {
	const fromEnd = 2
	size, err := r.Seek(0, fromEnd)
	if err != nil {
		return nil, err
	}

	rc, err := zip.NewReader(readerAt{r}, size)
	if err != nil {
		return nil, err
	}
	opts = append(opts, FS(zipFS{rc, "./"}))
	pack, err := Open(ctx, "./"+root, opts...)
	if err != nil {
		return nil, err
	}
	return pack, nil
}

type zipFS struct {
	pack   *zip.Reader
	prefix string
}

func (z zipFS) find(path string) *zip.File {
	needle := strings.TrimPrefix(path, z.prefix)
	dirNeedle := needle + string(filepath.Separator)
	for _, f := range z.pack.File {
		switch f.Name {
		case needle, dirNeedle:
			return f
		}
	}
	return nil
}

// Stat implements part of indexpack.VFS using the file metadata stored in the
// zip archive.  The path must match one of the archive paths, modulo the
// prefix associated with z.
func (z zipFS) Stat(_ context.Context, path string) (os.FileInfo, error) {
	f := z.find(path)
	if f == nil {
		return nil, fmt.Errorf("path %q does not exist", path)
	}
	return f.FileInfo(), nil
}

// Open implements part of indexpack.VFS, returning a io.ReadCloser owned by
// the underlying zip archive. It is safe to open multiple files concurrently,
// as documented by the zip package.
func (z zipFS) Open(_ context.Context, path string) (io.ReadCloser, error) {
	f := z.find(path)
	if f == nil {
		return nil, os.ErrNotExist
	}
	return f.Open()
}

// Glob implements part of indexpack.VFS using filepath.Match to compare the
// glob pattern to each archive path as trimmed by the prefix.
func (z zipFS) Glob(_ context.Context, glob string) ([]string, error) {
	needle := strings.TrimPrefix(glob, z.prefix)
	var names []string
	for _, f := range z.pack.File {
		name := strings.TrimPrefix(f.Name, z.prefix)
		if ok, err := filepath.Match(needle, name); err != nil {
			log.Panicf("Invalid glob pattern %q: %v", needle, err)
		} else if ok {
			names = append(names, name)
		}
	}
	return names, nil
}

func (zipFS) Create(_ context.Context, _ string) (io.WriteCloser, error) { return nil, errNotSupported }
func (zipFS) MkdirAll(_ context.Context, _ string, _ os.FileMode) error  { return errNotSupported }
func (zipFS) Rename(_ context.Context, _, _ string) error                { return errNotSupported }
func (zipFS) Remove(_ context.Context, _ string) error                   { return errNotSupported }
<|endoftext|>


<commit_before>/*
 *  Charon: A game authentication server
 *  Copyright (C) 2014-2016  Alex Mayfield <alexmax2742@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package charon

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"github.com/go-ini/ini"
	"log"
	"net"
)

// AuthApp contains all state for a single instance of the
// authentication server.
type AuthApp struct {
	config   *ini.File
	database Database
}

type request struct {
	address *net.UDPAddr
	message []byte
}

type response struct {
	address *net.UDPAddr
	message []byte
}

type routeFunc func(*request) (response, error)

// NewAuthApp creates a new instance of the auth server app.
func NewAuthApp(config *ini.File) (authApp *AuthApp, err error) {
	authApp = new(AuthApp)

	// Attach configuration
	authApp.config = config

	// Initialize database connection
	database, err := NewDatabase(config)
	if err != nil {
		return
	}
	authApp.database = *database
	return
}

// ListenAndServe starts the auth server app.
func (self *AuthApp) ListenAndServe(addr string) (err error) {
	listenaddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return
	}

	conn, err := net.ListenUDP("udp", listenaddr)
	if err != nil {
		return
	}

	for {
		message := make([]byte, 1024)

		msglen, msgaddr, msgerr := conn.ReadFromUDP(message)
		if msgerr != nil {
			log.Printf("[ERROR] %s", err.Error())
			continue
		}

		req := request{msgaddr, message[:msglen]}
		go self.requestHandler(&req)
	}
}

func (self *AuthApp) requestHandler(req *request) {
	// Select callback function to route to.
	route, err := self.router(req)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}

	// Route message to callback function.
	res, err := route(req)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}

	// Respond to sender.
	conn, err := net.ListenUDP("udp", req.address)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}
	conn.WriteToUDP(res.message, res.address)
}

func (self *AuthApp) router(req *request) (route routeFunc, err error) {
	if len(req.message) < 4 {
		err = errors.New("Message is too small")
		return
	}

	// Route the message to the appropriate handler.
	header := binary.LittleEndian.Uint32(req.message[:4])
	switch header {
	case CharonServerNegotiate:
		route = self.handleNegotiate
	case CharonServerEphemeral:
		route = self.handleEphemeral
	case CharonServerProof:
		route = self.handleProof
	default:
		err = errors.New("Invalid packet type")
	}

	return
}

// Handle initial negotiation
func (self *AuthApp) handleNegotiate(req *request) (res response, err error) {
	var packet ServerNegotiate
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	// Ensure that the user exists.
	user, err := self.database.FindUser(packet.username)
	if err != nil {
		return
	}

	// Create new session
	sessionBytes := make([]byte, 4)
	_, err = rand.Read(sessionBytes)
	if err != nil {
		return
	}
	var sessionID uint32
	sessionBuffer := bytes.NewBuffer(sessionBytes)
	err = binary.Read(sessionBuffer, binary.LittleEndian, &sessionID)
	if err != nil {
		return
	}

	// Assemble response
	var resPacket AuthNegotiate
	resPacket.clientSession = packet.clientSession
	resPacket.session = sessionID
	resPacket.salt = user.Salt
	resPacket.username = user.Username
	resPacket.version = 2
	message, err := resPacket.MarshalBinary()
	if err != nil {
		return
	}

	res.address = req.address
	res.message = message

	return
}

// Handle SRP ephemeral exchange
func (self *AuthApp) handleEphemeral(req *request) (res response, err error) {
	var packet ServerEphemeral
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	return
}

// Handle SRP proof exchange
func (self *AuthApp) handleProof(req *request) (res response, err error) {
	var packet ServerProof
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	return
}
<commit_msg>Pass connection into goroutine to write response.<commit_after>/*
 *  Charon: A game authentication server
 *  Copyright (C) 2014-2016  Alex Mayfield <alexmax2742@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package charon

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"github.com/go-ini/ini"
	"log"
	"net"
)

// AuthApp contains all state for a single instance of the
// authentication server.
type AuthApp struct {
	config   *ini.File
	database Database
}

type request struct {
	address *net.UDPAddr
	message []byte
}

type response struct {
	address *net.UDPAddr
	message []byte
}

type routeFunc func(*request) (response, error)

// NewAuthApp creates a new instance of the auth server app.
func NewAuthApp(config *ini.File) (authApp *AuthApp, err error) {
	authApp = new(AuthApp)

	// Attach configuration
	authApp.config = config

	// Initialize database connection
	database, err := NewDatabase(config)
	if err != nil {
		return
	}
	authApp.database = *database
	return
}

// ListenAndServe starts the auth server app.
func (self *AuthApp) ListenAndServe(addr string) (err error) {
	listenaddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return
	}

	conn, err := net.ListenUDP("udp", listenaddr)
	if err != nil {
		return
	}

	for {
		message := make([]byte, 1024)

		msglen, msgaddr, msgerr := conn.ReadFromUDP(message)
		if msgerr != nil {
			log.Printf("[ERROR] %s", err.Error())
			continue
		}

		req := request{msgaddr, message[:msglen]}
		go self.requestHandler(conn, &req)
	}
}

func (self *AuthApp) requestHandler(conn *net.UDPConn, req *request) {
	// Select callback function to route to.
	route, err := self.router(req)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}

	// Route message to callback function.
	res, err := route(req)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}

	// Respond to sender.
	_, err = conn.WriteToUDP(res.message, res.address)
	if err != nil {
		log.Printf("[DEBUG] %s", err.Error())
		return
	}
}

func (self *AuthApp) router(req *request) (route routeFunc, err error) {
	if len(req.message) < 4 {
		err = errors.New("Message is too small")
		return
	}

	// Route the message to the appropriate handler.
	header := binary.LittleEndian.Uint32(req.message[:4])
	switch header {
	case CharonServerNegotiate:
		route = self.handleNegotiate
	case CharonServerEphemeral:
		route = self.handleEphemeral
	case CharonServerProof:
		route = self.handleProof
	default:
		err = errors.New("Invalid packet type")
	}

	return
}

// Handle initial negotiation
func (self *AuthApp) handleNegotiate(req *request) (res response, err error) {
	var packet ServerNegotiate
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	// Ensure that the user exists.
	user, err := self.database.FindUser(packet.username)
	if err != nil {
		return
	}

	// Create new session
	sessionBytes := make([]byte, 4)
	_, err = rand.Read(sessionBytes)
	if err != nil {
		return
	}
	var sessionID uint32
	sessionBuffer := bytes.NewBuffer(sessionBytes)
	err = binary.Read(sessionBuffer, binary.LittleEndian, &sessionID)
	if err != nil {
		return
	}

	// Assemble response
	var resPacket AuthNegotiate
	resPacket.clientSession = packet.clientSession
	resPacket.session = sessionID
	resPacket.salt = user.Salt
	resPacket.username = user.Username
	resPacket.version = 2
	message, err := resPacket.MarshalBinary()
	if err != nil {
		return
	}

	res.address = req.address
	res.message = message

	return
}

// Handle SRP ephemeral exchange
func (self *AuthApp) handleEphemeral(req *request) (res response, err error) {
	var packet ServerEphemeral
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	return
}

// Handle SRP proof exchange
func (self *AuthApp) handleProof(req *request) (res response, err error) {
	var packet ServerProof
	err = packet.UnmarshalBinary(req.message)
	if err != nil {
		return
	}

	return
}
<|endoftext|>


<commit_before>package asock

// Copyright (c) 2014,2015 Shawn Boyette <shawn@firepear.net>. All
// rights reserved.  Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Socket code for asock

import (
	"fmt"
	"net"
	"time"

	"firepear.net/qsplit"
)

// sockAccept monitors the listener socket and spawns connections for
// clients.
func (a *Asock) sockAccept() {
	defer a.w.Done()
	var n uint
	for n = 1; true; n++ {
		c, err := a.l.Accept()
		if err != nil {
			select {
			case <-a.q:
				// a.Quit() was invoked; close up shop
				a.genMsg(0, 0, 199, 1, "closing listener socket", nil)
				return
			default:
				// we've had a networking error
				a.Msgr <- &Msg{0, 0, 599, "read from listener socket failed", err}
				return
			}
		}
		// we have a new client
		a.w.Add(1)
		go a.connHandler(c, n)
	}
}

// connHandler dispatches commands from, and sends reponses to, a client. It
// is launched, per-connection, from sockAccept().
func (a *Asock) connHandler(c net.Conn, n uint) {
	defer a.w.Done()
	defer c.Close()
	b1 := make([]byte, 64) // buffer 1:  network reads go here, 64B at a time
	var b2 []byte          // buffer 2:  then are accumulated here
	var bs [][]byte        // b2, sliced by word
	var reqnum uint        // request counter for this connection
	var cmdhelp string     // list of commands for the auto-help msg
	var cmd string         // builds cmdhelp, then holds command for dispatch
	for cmd := range a.d {
		cmdhelp = cmdhelp + "    " + cmd + "\n"
	}
	a.genMsg(n, reqnum, 100, 1, "client connected", nil)
	for {
		// check if we're a one-shot connection, and if we're done
		if a.t < 0 && reqnum > 0 {
			a.genMsg(n, reqnum, 197, 1, "ending session", nil)
			return
		}
		// set conn timeout deadline if needed
		if a.t != 0 {
			err := a.setConnTimeout(c)
			if err != nil {
				a.genMsg(n, reqnum, 501, 2, "deadline set failed; disconnecting client", err)
				c.Write([]byte("Sorry, an error occurred. Terminating connection."))
				return
			}
		}
		// get request from the client
		for {
			b, err := c.Read(b1)
			if err != nil {
				if err.Error() == "EOF" {
					a.genMsg(n, reqnum, 198, 1, "client disconnected", err)
				} else {
					a.genMsg(n, reqnum, 197, 1, "ending session", err)
				}
				return
			}
			if b > 0 {
				// then copy those bytes into the b2 slice
				b2 = append(b2, b1[:b]...)
				// if we read 64 bytes, loop back to get anything that
				// might be left on the wire
				if b == 64 {
					continue
				}
				// break inner loop; drop to dispatch
				break
			}
		}
		reqnum++
		// extract the command
		cl := qsplit.Locations(b2)
		cmd = string(b2[cl[0][0]:cl[0][1]])
		// send error and list of known commands if cmd isn't known
		dfunc, ok := a.d[cmd]
		if !ok {
			c.Write([]byte(fmt.Sprintf("Unknown command '%v'\nAvailable commands:\n%v",
				cmd, cmdhelp)))
			a.genMsg(n, reqnum, 400, 0, fmt.Sprintf("bad command '%v'", cmd), nil)
			continue
		}
		// dispatch command and send response
		a.genMsg(n, reqnum, 101, 0, fmt.Sprintf("dispatching [%v]", cmd), nil)
		switch dfunc.Argmode {
		case "split":
			bs = qsplit.ToBytes(b2[cl[1][0]:])
		case "nosplit":
			bs = bs[:0]
			bs = append(bs, b2[cl[1][0]:])
		}
		reply, err := dfunc.Func(bs)
		if err != nil {
			c.Write([]byte("Sorry, an error occurred and your request could not be completed."))
			a.genMsg(n, reqnum, 500, 2, "request failed", err)
			continue
		}
		c.Write(reply)
		a.genMsg(n, reqnum, 200, 0, "reply sent", nil)
		// reslice b2 so that it will be "empty" on the next read
		b2 = b2[:0]
	}
}

func (a *Asock) setConnTimeout(c net.Conn) error {
	var t time.Duration
	if a.t > 0 {
		t = time.Duration(a.t)
	} else {
		t = time.Duration(a.t - (a.t * 2))
	}
	err := c.SetReadDeadline(time.Now().Add(t * time.Second))
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>initial buffer size changed to 128<commit_after>package asock

// Copyright (c) 2014,2015 Shawn Boyette <shawn@firepear.net>. All
// rights reserved.  Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Socket code for asock

import (
	"fmt"
	"net"
	"time"

	"firepear.net/qsplit"
)

// sockAccept monitors the listener socket and spawns connections for
// clients.
func (a *Asock) sockAccept() {
	defer a.w.Done()
	var n uint
	for n = 1; true; n++ {
		c, err := a.l.Accept()
		if err != nil {
			select {
			case <-a.q:
				// a.Quit() was invoked; close up shop
				a.genMsg(0, 0, 199, 1, "closing listener socket", nil)
				return
			default:
				// we've had a networking error
				a.Msgr <- &Msg{0, 0, 599, "read from listener socket failed", err}
				return
			}
		}
		// we have a new client
		a.w.Add(1)
		go a.connHandler(c, n)
	}
}

// connHandler dispatches commands from, and sends reponses to, a client. It
// is launched, per-connection, from sockAccept().
func (a *Asock) connHandler(c net.Conn, n uint) {
	defer a.w.Done()
	defer c.Close()
	b1 := make([]byte, 128) // buffer 1:  network reads go here, 128B at a time
	var b2 []byte           // buffer 2:  then are accumulated here
	var bs [][]byte         // b2, sliced by word
	var reqnum uint         // request counter for this connection
	var cmdhelp string      // list of commands for the auto-help msg
	var cmd string          // builds cmdhelp, then holds command for dispatch
	for cmd := range a.d {
		cmdhelp = cmdhelp + "    " + cmd + "\n"
	}
	a.genMsg(n, reqnum, 100, 1, "client connected", nil)
	for {
		// check if we're a one-shot connection, and if we're done
		if a.t < 0 && reqnum > 0 {
			a.genMsg(n, reqnum, 197, 1, "ending session", nil)
			return
		}
		// set conn timeout deadline if needed
		if a.t != 0 {
			err := a.setConnTimeout(c)
			if err != nil {
				a.genMsg(n, reqnum, 501, 2, "deadline set failed; disconnecting client", err)
				c.Write([]byte("Sorry, an error occurred. Terminating connection."))
				return
			}
		}
		// get request from the client
		for {
			b, err := c.Read(b1)
			if err != nil {
				if err.Error() == "EOF" {
					a.genMsg(n, reqnum, 198, 1, "client disconnected", err)
				} else {
					a.genMsg(n, reqnum, 197, 1, "ending session", err)
				}
				return
			}
			if b > 0 {
				// then copy those bytes into the b2 slice
				b2 = append(b2, b1[:b]...)
				// if we read 128 bytes, loop back to get anything that
				// might be left on the wire
				if b == 128 {
					continue
				}
				// break inner loop; drop to dispatch
				break
			}
		}
		reqnum++
		// extract the command
		cl := qsplit.Locations(b2)
		cmd = string(b2[cl[0][0]:cl[0][1]])
		// send error and list of known commands if cmd isn't known
		dfunc, ok := a.d[cmd]
		if !ok {
			c.Write([]byte(fmt.Sprintf("Unknown command '%v'\nAvailable commands:\n%v",
				cmd, cmdhelp)))
			a.genMsg(n, reqnum, 400, 0, fmt.Sprintf("bad command '%v'", cmd), nil)
			continue
		}
		// dispatch command and send response
		a.genMsg(n, reqnum, 101, 0, fmt.Sprintf("dispatching [%v]", cmd), nil)
		switch dfunc.Argmode {
		case "split":
			bs = qsplit.ToBytes(b2[cl[1][0]:])
		case "nosplit":
			bs = bs[:0]
			bs = append(bs, b2[cl[1][0]:])
		}
		reply, err := dfunc.Func(bs)
		if err != nil {
			c.Write([]byte("Sorry, an error occurred and your request could not be completed."))
			a.genMsg(n, reqnum, 500, 2, "request failed", err)
			continue
		}
		c.Write(reply)
		a.genMsg(n, reqnum, 200, 0, "reply sent", nil)
		// reslice b2 so that it will be "empty" on the next read
		b2 = b2[:0]
	}
}

func (a *Asock) setConnTimeout(c net.Conn) error {
	var t time.Duration
	if a.t > 0 {
		t = time.Duration(a.t)
	} else {
		t = time.Duration(a.t - (a.t * 2))
	}
	err := c.SetReadDeadline(time.Now().Add(t * time.Second))
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package leds

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"
)

var Colors = map[string][]int{
	"black":   {0, 0, 0},
	"red":     {1, 0, 0},
	"green":   {0, 1, 0},
	"blue":    {0, 0, 1},
	"cyan":    {0, 1, 1},
	"magenta": {1, 0, 1},
	"yellow":  {1, 1, 0},
	"white":   {1, 1, 1},
}

var LedNames = []string{
	"power",
	"wired_internet",
	"wireless",
	"pairing",
	"radio",
}

var LedPositions = [][]int{
	{15, 13, 14},
	{12, 10, 11},
	{9, 1, 8},
	{2, 4, 3},
	{5, 7, 6},
}

// holds the state for an array of leds on our board.
type LedArray struct {
	Leds      []int
	LedStates []LedState
	ticker    *time.Ticker
	lock      *sync.Mutex
}

type LedState struct {
	Flash bool
	Color string
	On    bool
}

func CreateLedArray() *LedArray {
	ledArr := &LedArray{
		Leds:      []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		LedStates: make([]LedState, 5),
		lock:      &sync.Mutex{},
	}
	initLEDs()
	go ledArr.setupBackgroundJob()

	return ledArr
}

func (l *LedArray) setupBackgroundJob() {
	l.ticker = time.NewTicker(1 * time.Second)

	for {
		select {
		case <-l.ticker.C:

			l.lock.Lock()

			//log.Println("[DEBUG] flash")
			for n := range l.LedStates {
				if l.LedStates[n].Flash {

					if l.LedStates[n].On {
						l.setColorInt(n, Colors["black"])
						l.LedStates[n].On = false
					} else {
						l.setColorInt(n, Colors[l.LedStates[n].Color])
						l.LedStates[n].On = true
					}
				}
			}
			// we should use a cached copy of the array then do a diff and conditionally
			// set leds.
			l.SetLEDs()

			l.lock.Unlock()

		}
	}
}

func (l *LedArray) setColorInt(position int, color []int) {
	var indexes = LedPositions[position]
	for i := 0; i < 3; i++ {
		l.Leds[indexes[i]] = color[i]
	}
}

func (l *LedArray) SetPwmBrightness(brightness int) {
	writetofile("/sys/class/backlight/pwm-backlight/brightness", fmt.Sprintf("%d", brightness))
}

func (l *LedArray) SetColor(position int, color string, flash bool) {
	defer l.lock.Unlock()
	l.lock.Lock()
	// update the state
	l.LedStates[position].Flash = flash
	l.LedStates[position].Color = color
	l.LedStates[position].On = true
	l.setColorInt(position, Colors[color])
	// apply it
	l.SetLEDs()
}

func (l *LedArray) Reset() {
	defer l.lock.Unlock()
	l.lock.Lock()
	for pos := range LedNames {
		// update the states
		l.LedStates[pos].Flash = false
		l.LedStates[pos].Color = "black"
		l.LedStates[pos].On = true
		l.setColorInt(pos, Colors["black"])
	}
	// apply it
	l.SetLEDs()
}

func ValidBrightness(brightness int) bool {
	return brightness >= 0 && brightness <= 100
}

func ValidColor(color string) bool {
	return Colors[color] != nil
}

func ValidLedName(name string) bool {
	for n := range LedNames {
		if LedNames[n] == name {
			return true
		}
	}
	return false
}

func LedNameIndex(name string) int {
	for n := range LedNames {
		if LedNames[n] == name {
			return n
		}
	}
	panic("LedName didn't exist.")
}

func initLEDs() {
	log.Printf("Initializing LEDs")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data15", "27")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data14", "27")
	writetofile("/sys/kernel/debug/omap_mux/uart0_ctsn", "27")
	writetofile("/sys/kernel/debug/omap_mux/mii1_col", "27")

	if _, err := os.Stat("/sys/class/gpio/gpio11/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "11")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio10/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "10")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio40/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "40")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio96/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "96")
	}

	writetofile("/sys/class/gpio/gpio11/direction", "low")
	writetofile("/sys/class/gpio/gpio10/direction", "low")
	writetofile("/sys/class/gpio/gpio40/direction", "low")
	writetofile("/sys/class/gpio/gpio96/direction", "low")

}

func (l *LedArray) SetLEDs() {
	//	log.Printf("[DEBUG] Updating leds: %v", l.Leds)
	//	log.Printf("[DEBUG] Updating flashstate: %v", l.LedStates)

	for i := range l.Leds {
		writetofile("/sys/class/gpio/gpio40/value", fmt.Sprintf("%d", l.Leds[i]))
		writetofile("/sys/class/gpio/gpio96/value", "1")
		writetofile("/sys/class/gpio/gpio96/value", "0")
	}

	writetofile("/sys/class/gpio/gpio11/value", "1")
	writetofile("/sys/class/gpio/gpio11/value", "0")
}

func writetofile(fn string, val string) error {

	df, err := os.OpenFile(fn, os.O_WRONLY|os.O_SYNC, 0666)

	if err != nil {
		log.Printf("[ERROR] failed to open file %s - %s", fn, err)
		return err
	}

	defer df.Close()

	if _, err = fmt.Fprintln(df, val); err != nil {
		log.Printf("[ERROR] failed write to %s - %s", fn, err)
		return err
	}

	return nil
}
<commit_msg>Sync blinking leds as it was annoying me.<commit_after>package leds

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"
)

var Colors = map[string][]int{
	"black":   {0, 0, 0},
	"red":     {1, 0, 0},
	"green":   {0, 1, 0},
	"blue":    {0, 0, 1},
	"cyan":    {0, 1, 1},
	"magenta": {1, 0, 1},
	"yellow":  {1, 1, 0},
	"white":   {1, 1, 1},
}

var LedNames = []string{
	"power",
	"wired_internet",
	"wireless",
	"pairing",
	"radio",
}

var LedPositions = [][]int{
	{15, 13, 14},
	{12, 10, 11},
	{9, 1, 8},
	{2, 4, 3},
	{5, 7, 6},
}

// holds the state for an array of leds on our board.
type LedArray struct {
	Leds         []int
	LedStates    []LedState
	BlinkOnState bool
	ticker       *time.Ticker
	lock         *sync.Mutex
}

type LedState struct {
	Flash bool
	Color string
	On    bool
}

func CreateLedArray() *LedArray {
	ledArr := &LedArray{
		Leds:      []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		LedStates: make([]LedState, 5),
		lock:      &sync.Mutex{},
	}
	initLEDs()
	go ledArr.setupBackgroundJob()

	return ledArr
}

func (l *LedArray) setupBackgroundJob() {
	l.ticker = time.NewTicker(1 * time.Second)

	for {
		select {
		case <-l.ticker.C:

			l.lock.Lock()

			//log.Println("[DEBUG] flash")
			for n := range l.LedStates {
				if l.LedStates[n].Flash {

					if l.LedStates[n].On {
						l.setColorInt(n, Colors["black"])
						l.LedStates[n].On = false
						l.BlinkOnState = false
					} else {
						l.setColorInt(n, Colors[l.LedStates[n].Color])
						l.LedStates[n].On = true
						l.BlinkOnState = true
					}
				}
			}
			// we should use a cached copy of the array then do a diff and conditionally
			// set leds.
			l.SetLEDs()

			l.lock.Unlock()

		}
	}
}

func (l *LedArray) setColorInt(position int, color []int) {
	var indexes = LedPositions[position]
	for i := 0; i < 3; i++ {
		l.Leds[indexes[i]] = color[i]
	}
}

func (l *LedArray) SetPwmBrightness(brightness int) {
	writetofile("/sys/class/backlight/pwm-backlight/brightness", fmt.Sprintf("%d", brightness))
}

func (l *LedArray) SetColor(position int, color string, flash bool) {
	defer l.lock.Unlock()
	l.lock.Lock()
	// update the state
	l.LedStates[position].Flash = flash
	l.LedStates[position].Color = color
	if flash {
		l.LedStates[position].On = l.BlinkOnState
	} else {
		l.LedStates[position].On = true
	}
	l.setColorInt(position, Colors[color])
	// apply it
	l.SetLEDs()
}

func (l *LedArray) Reset() {
	defer l.lock.Unlock()
	l.lock.Lock()
	for pos := range LedNames {
		// update the states
		l.LedStates[pos].Flash = false
		l.LedStates[pos].Color = "black"
		l.LedStates[pos].On = true
		l.setColorInt(pos, Colors["black"])
	}
	// apply it
	l.SetLEDs()
}

func ValidBrightness(brightness int) bool {
	return brightness >= 0 && brightness <= 100
}

func ValidColor(color string) bool {
	return Colors[color] != nil
}

func ValidLedName(name string) bool {
	for n := range LedNames {
		if LedNames[n] == name {
			return true
		}
	}
	return false
}

func LedNameIndex(name string) int {
	for n := range LedNames {
		if LedNames[n] == name {
			return n
		}
	}
	panic("LedName didn't exist.")
}

func initLEDs() {
	log.Printf("Initializing LEDs")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data15", "27")
	writetofile("/sys/kernel/debug/omap_mux/lcd_data14", "27")
	writetofile("/sys/kernel/debug/omap_mux/uart0_ctsn", "27")
	writetofile("/sys/kernel/debug/omap_mux/mii1_col", "27")

	if _, err := os.Stat("/sys/class/gpio/gpio11/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "11")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio10/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "10")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio40/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "40")
	}

	if _, err := os.Stat("/sys/class/gpio/gpio96/direction"); os.IsNotExist(err) {
		writetofile("/sys/class/gpio/export", "96")
	}

	writetofile("/sys/class/gpio/gpio11/direction", "low")
	writetofile("/sys/class/gpio/gpio10/direction", "low")
	writetofile("/sys/class/gpio/gpio40/direction", "low")
	writetofile("/sys/class/gpio/gpio96/direction", "low")

}

func (l *LedArray) SetLEDs() {
	//	log.Printf("[DEBUG] Updating leds: %v", l.Leds)
	//	log.Printf("[DEBUG] Updating flashstate: %v", l.LedStates)

	for i := range l.Leds {
		writetofile("/sys/class/gpio/gpio40/value", fmt.Sprintf("%d", l.Leds[i]))
		writetofile("/sys/class/gpio/gpio96/value", "1")
		writetofile("/sys/class/gpio/gpio96/value", "0")
	}

	writetofile("/sys/class/gpio/gpio11/value", "1")
	writetofile("/sys/class/gpio/gpio11/value", "0")
}

func writetofile(fn string, val string) error {

	df, err := os.OpenFile(fn, os.O_WRONLY|os.O_SYNC, 0666)

	if err != nil {
		log.Printf("[ERROR] failed to open file %s - %s", fn, err)
		return err
	}

	defer df.Close()

	if _, err = fmt.Fprintln(df, val); err != nil {
		log.Printf("[ERROR] failed write to %s - %s", fn, err)
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
)

func GetAllRelationships(selector Selector) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Sort("timestamp").All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetSomeRelationships(selector Selector, limit int) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Limit(limit).All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetRelationship(selector Selector) (models.Relationship, error) {
	relationship := models.Relationship{}

	query := func(c *mgo.Collection) error {
		return c.Find(selector).One(&relationship)
	}

	err := mongodb.Run("relationships", query)

	return relationship, err
}

func DeleteRelationship(selector Selector) error {
	query := func(c *mgo.Collection) error {
		_, err := c.RemoveAll(selector)
		return err
	}

	return mongodb.Run("relationships", query)
}

func AddRelationship(r *models.Relationship) error {
	query := insertQuery(r)

	return mongodb.Run("relationships", query)
}
<commit_msg>Migration: UpdateRelationship is added to helper<commit_after>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
)

func GetAllRelationships(selector Selector) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Sort("timestamp").All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetSomeRelationships(selector Selector, limit int) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Limit(limit).All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetRelationship(selector Selector) (models.Relationship, error) {
	relationship := models.Relationship{}

	query := func(c *mgo.Collection) error {
		return c.Find(selector).One(&relationship)
	}

	err := mongodb.Run("relationships", query)

	return relationship, err
}

func DeleteRelationship(selector Selector) error {
	query := func(c *mgo.Collection) error {
		_, err := c.RemoveAll(selector)
		return err
	}

	return mongodb.Run("relationships", query)
}

func AddRelationship(r *models.Relationship) error {
	query := insertQuery(r)

	return mongodb.Run("relationships", query)
}

func UpdateRelationship(r *models.Relationship) error {
	query := updateByIdQuery(r.Id.Hex(), r)
	return mongodb.Run("relationships", query)
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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 main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	_ "github.com/go-sql-driver/mysql"
	"google.golang.org/appengine"
)

var (
	db          *sql.DB
	queryString = "SELECT probability_of_answer, probability_of_downvote, minutes FROM questions WHERE tag = ? AND first_word = ? AND ends_question = ? AND weekday_utc = ? AND account_creation_year = ? AND question_length = ? AND hour_utc = ?"
	port        = ""
)

func main() {
	var err error
	db, err = getDatabase()
	if err != nil {
		log.Printf("Failed to establish connection to Database. Server terminated")
		return
	}

	port = os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	http.HandleFunc("/experiment/bqml-stackoverflow/api/", func(w http.ResponseWriter, r *http.Request) {
		rows, err := attemptQuery(5, r)
		if err != nil {
			log.Printf("db.Query: %v", err)

			w.Write(getEmptyAnswer())
			return
		}
		defer rows.Close()

		if rows.Next() {
			var probabilityOfAnswer float32
			var probablityOfDownvote float32
			var minutes float32

			if err := rows.Scan(&probabilityOfAnswer, &probablityOfDownvote, &minutes); err != nil {
				log.Printf("rows.Scan: %v", err)
			}

			var answer = &Answer{
				Minutes:   minutes,
				PDownvote: probablityOfDownvote,
				PAnswer:   probabilityOfAnswer,
			}

			json, _ := json.Marshal(answer)

			w.Write(json)
		} else {
			w.Write(getEmptyAnswer())
		}

	})

	fs := wrapHandler(http.FileServer(http.Dir("./dist")))
	http.HandleFunc("/", fs)

	fmt.Printf("Starting server on port %s\n", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}

}

func getEmptyAnswer() []byte {
	json, _ := json.Marshal(&Answer{
		Minutes:   0,
		PAnswer:   0,
		PDownvote: 0,
	})

	return json
}

func getDatabase() (*sql.DB, error) {
	user := os.Getenv("DB_USER")
	password := os.Getenv("DB_PASSWORD")
	database := os.Getenv("DB_DATABASE")
	instance := os.Getenv("DB_INSTANCE")

	if appengine.IsDevAppServer() {
		return sql.Open("mysql", fmt.Sprintf("%s:%s@tcp([localhost]:3306)/%s", user, password, database))
	}
	log.Printf("Database call to (%s)/%s", instance, database)
	return sql.Open("mysql", fmt.Sprintf("%s:%s@unix(/cloudsql/%s)/%s", user, password, instance, database))
}

func attemptQuery(attempts int, r *http.Request) (*sql.Rows, error) {
	var rows *sql.Rows
	var err error

	query := r.URL.Query()

	for i := 0; i < attempts; i++ {
		rows, err = db.Query(
			queryString,
			query.Get("tag"),
			query.Get("first_word"),
			query.Get("ends_question"),
			query.Get("weekday_utc"),
			query.Get("account_creation_year"),
			query.Get("question_length"),
			query.Get("hour_utc"),
		)

		if err == nil {
			break
		} else {
			fmt.Printf("error getting using the database %v\n", err)
			db, err = getDatabase()
			if err != nil {
				fmt.Printf("error getting database %v\n", err)
			}
		}
	}

	return rows, err
}

// Answer respresents the api query response json.
type Answer struct {
	Minutes   float32 `json:"minutes"`
	PAnswer   float32 `json:"probability_of_answer"`
	PDownvote float32 `json:"probabiliy_of_downvote"`
}

type NotFoundRedirectRespWr struct {
	http.ResponseWriter // We embed http.ResponseWriter
	status              int
}

func (w *NotFoundRedirectRespWr) WriteHeader(status int) {
	w.status = status // Store the status for our own use
	if status != http.StatusNotFound {
		w.ResponseWriter.WriteHeader(status)
	}
}

func (w *NotFoundRedirectRespWr) Write(p []byte) (int, error) {
	if w.status != http.StatusNotFound {
		return w.ResponseWriter.Write(p)
	}
	return len(p), nil // Lie that we successfully written it
}

func wrapHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		nfrw := &NotFoundRedirectRespWr{ResponseWriter: w}
		h.ServeHTTP(nfrw, r)
		if nfrw.status == 404 {
			http.Redirect(w, r, "/experiment/bqml-stackoverflow/index.html", http.StatusFound)
		}
	}
}
<commit_msg>Update main.go<commit_after>// Copyright 2019 Google LLC
//
// 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 main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"

	_ "github.com/go-sql-driver/mysql"
	"google.golang.org/appengine"
)

var (
	db          *sql.DB
	queryString = "SELECT probability_of_answer, probability_of_downvote, minutes FROM questions WHERE tag = ? AND first_word = ? AND ends_question = ? AND weekday_utc = ? AND account_creation_year = ? AND question_length = ? AND hour_utc = ?"
	port        = ""
)

func main() {
	var err error
	db, err = getDatabase()
	if err != nil {
		log.Printf("Failed to establish connection to Database. Server terminated")
		return
	}

	port = os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	http.HandleFunc("/experiment/bqml-stackoverflow/api/", func(w http.ResponseWriter, r *http.Request) {
		rows, err := attemptQuery(5, r)
		if err != nil {
			log.Printf("db.Query: %v", err)

			w.Write(getEmptyAnswer())
			return
		}
		defer rows.Close()

		if rows.Next() {
			var probabilityOfAnswer float32
			var probablityOfDownvote float32
			var minutes float32

			if err := rows.Scan(&probabilityOfAnswer, &probablityOfDownvote, &minutes); err != nil {
				log.Printf("rows.Scan: %v", err)
			}

			var answer = &Answer{
				Minutes:   minutes,
				PDownvote: probablityOfDownvote,
				PAnswer:   probabilityOfAnswer,
			}

			json, _ := json.Marshal(answer)

			w.Write(json)
		} else {
			w.Write(getEmptyAnswer())
		}

	})

	fs := wrapHandler(http.FileServer(http.Dir("./dist")))
	http.HandleFunc("/experiment/bqml-stackoverflow/", fs)

	fmt.Printf("Starting server on port %s\n", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}

}

func getEmptyAnswer() []byte {
	json, _ := json.Marshal(&Answer{
		Minutes:   0,
		PAnswer:   0,
		PDownvote: 0,
	})

	return json
}

func getDatabase() (*sql.DB, error) {
	user := os.Getenv("DB_USER")
	password := os.Getenv("DB_PASSWORD")
	database := os.Getenv("DB_DATABASE")
	instance := os.Getenv("DB_INSTANCE")

	if appengine.IsDevAppServer() {
		return sql.Open("mysql", fmt.Sprintf("%s:%s@tcp([localhost]:3306)/%s", user, password, database))
	}
	log.Printf("Database call to (%s)/%s", instance, database)
	return sql.Open("mysql", fmt.Sprintf("%s:%s@unix(/cloudsql/%s)/%s", user, password, instance, database))
}

func attemptQuery(attempts int, r *http.Request) (*sql.Rows, error) {
	var rows *sql.Rows
	var err error

	query := r.URL.Query()

	for i := 0; i < attempts; i++ {
		rows, err = db.Query(
			queryString,
			query.Get("tag"),
			query.Get("first_word"),
			query.Get("ends_question"),
			query.Get("weekday_utc"),
			query.Get("account_creation_year"),
			query.Get("question_length"),
			query.Get("hour_utc"),
		)

		if err == nil {
			break
		} else {
			fmt.Printf("error getting using the database %v\n", err)
			db, err = getDatabase()
			if err != nil {
				fmt.Printf("error getting database %v\n", err)
			}
		}
	}

	return rows, err
}

// Answer respresents the api query response json.
type Answer struct {
	Minutes   float32 `json:"minutes"`
	PAnswer   float32 `json:"probability_of_answer"`
	PDownvote float32 `json:"probabiliy_of_downvote"`
}

type NotFoundRedirectRespWr struct {
	http.ResponseWriter // We embed http.ResponseWriter
	status              int
}

func (w *NotFoundRedirectRespWr) WriteHeader(status int) {
	w.status = status // Store the status for our own use
	if status != http.StatusNotFound {
		w.ResponseWriter.WriteHeader(status)
	}
}

func (w *NotFoundRedirectRespWr) Write(p []byte) (int, error) {
	if w.status != http.StatusNotFound {
		return w.ResponseWriter.Write(p)
	}
	return len(p), nil // Lie that we successfully written it
}

func wrapHandler(h http.Handler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		nfrw := &NotFoundRedirectRespWr{ResponseWriter: w}
		h.ServeHTTP(nfrw, r)
		if nfrw.status == 404 {
			http.Redirect(w, r, "/experiment/bqml-stackoverflow/index.html", http.StatusFound)
		}
	}
}
<|endoftext|>


<commit_before>//  Copyright (c) 2013 Couchbase, Inc.
//  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 main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/couchbaselabs/clog"
	"github.com/sbinet/liner"
)

func HandleInteractiveMode(tiServer, prompt string) {

	// try to find a HOME environment variable
	homeDir := os.Getenv("HOME")
	if homeDir == "" {
		// then try USERPROFILE for Windows
		homeDir = os.Getenv("USERPROFILE")
		if homeDir == "" {
			fmt.Printf("Unable to determine home directory, history file disabled\n")
		}
	}

	var liner = liner.NewLiner()
	defer liner.Close()

	LoadHistory(liner, homeDir)

	go signalCatcher(liner)

	for {
		line, err := liner.Prompt(prompt + "> ")
		if err != nil {
			break
		}

		if line == "" {
			continue
		}

		UpdateHistory(liner, homeDir, line)
		err = execute_internal(tiServer, line, os.Stdout)
		if err != nil {
			clog.Error(err)
		}
	}

}

/**
 *  Attempt to clean up after ctrl-C otherwise
 *  terminal is left in bad shape
 */
func signalCatcher(liner *liner.State) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT)
	<-ch
	liner.Close()
	os.Exit(0)
}
<commit_msg>Multi line query support (MB-10880)<commit_after>//  Copyright (c) 2013 Couchbase, Inc.
//  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 main

import (
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/couchbaselabs/clog"
	"github.com/sbinet/liner"
)

const (
	QRY_EOL     = ";"
	QRY_PROMPT1 = "> "
	QRY_PROMPT2 = "   > "
)

func HandleInteractiveMode(tiServer, prompt string) {

	// try to find a HOME environment variable
	homeDir := os.Getenv("HOME")
	if homeDir == "" {
		// then try USERPROFILE for Windows
		homeDir = os.Getenv("USERPROFILE")
		if homeDir == "" {
			fmt.Printf("Unable to determine home directory, history file disabled\n")
		}
	}

	var liner = liner.NewLiner()
	defer liner.Close()

	LoadHistory(liner, homeDir)

	go signalCatcher(liner)

	// state for reading a multi-line query
	queryLines := []string{}
	fullPrompt := prompt + QRY_PROMPT1
	for {
		line, err := liner.Prompt(fullPrompt)
		if err != nil {
			break
		}

		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}

		// Building query string mode: set prompt, gather current line
		fullPrompt = QRY_PROMPT2
		queryLines = append(queryLines, line)

		// If the current line ends with a QRY_EOL, join all query lines,
		// trim off trailing QRY_EOL characters, and submit the query string:
		if strings.HasSuffix(line, QRY_EOL) {
			queryString := strings.Join(queryLines, " ")
			for strings.HasSuffix(queryString, QRY_EOL) {
				queryString = strings.TrimSuffix(queryString, QRY_EOL)
			}
			if queryString != "" {
				UpdateHistory(liner, homeDir, queryString+QRY_EOL)
				err = execute_internal(tiServer, queryString, os.Stdout)
				if err != nil {
					clog.Error(err)
				}
			}
			// reset state for multi-line query
			queryLines = []string{}
			fullPrompt = prompt + QRY_PROMPT1
		}
	}

}

/**
 *  Attempt to clean up after ctrl-C otherwise
 *  terminal is left in bad shape
 */
func signalCatcher(liner *liner.State) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT)
	<-ch
	liner.Close()
	os.Exit(0)
}
<|endoftext|>