<commit_before>package models

import (
	"errors"
	"fmt"
	"testing"

	"github.com/taironas/gonawin/helpers"

	"appengine/aetest"
)

type testUser struct {
	email    string
	username string
	name     string
	alias    string
	isAdmin  bool
	auth     string
}

// TestCreateUser tests that you can create a user.
//
func TestCreateUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		user  testUser
	}{
		{"can create user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""}},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *User
		if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUser(got, test.user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUserInvertedIndex(t, c, got); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyUser tests that you can destroy a user.
//
func TestDestroyUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can destroy user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	if err = got.Destroy(c); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User
	if u, err = UserById(c, got.Id); u != nil {
		t.Errorf("Error: user found, not properly destroyed")
	}
	if err = checkUserInvertedIndex(t, c, got); err == nil {
		t.Errorf("Error: user found in database")
	}
}

// TestFindUser tests that you can find a user.
//
func TestFindUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can find user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)

	if _, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var got *User
	if got = FindUser(c, "Username", "john.snow"); got == nil {
		t.Errorf("Error: user not found by Username")
	}

	if got = FindUser(c, "Name", "john snow"); got == nil {
		t.Errorf("Error: user not found by Name")
	}

	if got = FindUser(c, "Alias", "crow"); got == nil {
		t.Errorf("Error: user not found by Alias")
	}
}

// TestFindAllUsers tests that you can find all the users.
//
func TestFindAllUsers(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can find users",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)

	for _, user := range test.users {
		if _, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}
	}

	var got []*User
	if got = FindAllUsers(c); got == nil {
		t.Errorf("Error: users not found")
	}

	if len(got) != len(test.users) {
		t.Errorf("Error: want users count == %s, got %s", len(test.users), len(got))
	}

	for i, user := range test.users {
		if err = checkUser(got[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

func checkUser(got *User, want testUser) error {
	var s string
	if got.Email != want.email {
		s = fmt.Sprintf("want Email == %s, got %s", want.email, got.Email)
	} else if got.Username != want.username {
		s = fmt.Sprintf("want Username == %s, got %s", want.username, got.Username)
	} else if got.Name != want.name {
		s = fmt.Sprintf("want Name == %s, got %s", want.name, got.Name)
	} else if got.Alias != want.alias {
		s = fmt.Sprintf("want Name == %s, got %s", want.alias, got.Alias)
	} else if got.IsAdmin != want.isAdmin {
		s = fmt.Sprintf("want isAdmin == %t, got %t", want.isAdmin, got.IsAdmin)
	} else if got.Auth != want.auth {
		s = fmt.Sprintf("want auth == %s, got %s", want.auth, got.Auth)
	} else {
		return nil
	}
	return errors.New(s)
}

func checkUserInvertedIndex(t *testing.T, c aetest.Context, got *User) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings("john")
	if ids, err = GetUserInvertedIndexes(c, words); err != nil {
		s := fmt.Sprintf("failed calling GetUserInvertedIndexes %v", err)
		return errors.New(s)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("user not found")

}
<commit_msg>add test User.UsersByIds<commit_after>package models

import (
	"errors"
	"fmt"
	"testing"

	"github.com/taironas/gonawin/helpers"

	"appengine/aetest"
)

type testUser struct {
	email    string
	username string
	name     string
	alias    string
	isAdmin  bool
	auth     string
}

// TestCreateUser tests that you can create a user.
//
func TestCreateUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		user  testUser
	}{
		{"can create user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""}},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *User
		if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUser(got, test.user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUserInvertedIndex(t, c, got); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestUserById tests that you can get a user by its ID.
//
func TestUserById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can get user by ID", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User

	// Test non existing user
	if u, err = UserById(c, got.Id+50); u != nil {
		t.Errorf("Error: no user should have been found")
	}

	if err == nil {
		t.Errorf("Error: an error should have been returned in case of non existing user")
	}

	// Test existing user
	if u, err = UserById(c, got.Id); u == nil {
		t.Errorf("Error: user not found")
	}

	if err = checkUser(got, test.user); err != nil {
		t.Errorf("Error: want user == %v, got %v", test.user, got)
	}
}

// TestUsersByIds tests that you can get a list of users by their IDs.
//
func TestUsersByIds(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can get users by IDs",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)
	var gotIDs []int64
	var got *User
	for _, user := range test.users {
		if got, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}

		gotIDs = append(gotIDs, got.Id)
	}

	var users []*User

	// Test non existing users
	var nonExistingIDs []int64
	for _, ID := range gotIDs {
		nonExistingIDs = append(nonExistingIDs, ID+50)
	}

	if users, err = UsersByIds(c, nonExistingIDs); users != nil {
		t.Errorf("Error: no users should have been found")
	}

	// Test existing users
	if users, err = UsersByIds(c, gotIDs); users == nil {
		t.Errorf("Error: users not found")
	}

	for i, user := range test.users {
		if err = checkUser(users[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyUser tests that you can destroy a user.
//
func TestDestroyUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can destroy user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	if err = got.Destroy(c); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User
	if u, err = UserById(c, got.Id); u != nil {
		t.Errorf("Error: user found, not properly destroyed")
	}
	if err = checkUserInvertedIndex(t, c, got); err == nil {
		t.Errorf("Error: user found in database")
	}
}

// TestFindUser tests that you can find a user.
//
func TestFindUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can find user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)

	if _, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var got *User
	if got = FindUser(c, "Username", "john.snow"); got == nil {
		t.Errorf("Error: user not found by Username")
	}

	if got = FindUser(c, "Name", "john snow"); got == nil {
		t.Errorf("Error: user not found by Name")
	}

	if got = FindUser(c, "Alias", "crow"); got == nil {
		t.Errorf("Error: user not found by Alias")
	}
}

// TestFindAllUsers tests that you can find all the users.
//
func TestFindAllUsers(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can find users",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)

	for _, user := range test.users {
		if _, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}
	}

	var got []*User
	if got = FindAllUsers(c); got == nil {
		t.Errorf("Error: users not found")
	}

	if len(got) != len(test.users) {
		t.Errorf("Error: want users count == %s, got %s", len(test.users), len(got))
	}

	for i, user := range test.users {
		if err = checkUser(got[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

func checkUser(got *User, want testUser) error {
	var s string
	if got.Email != want.email {
		s = fmt.Sprintf("want Email == %s, got %s", want.email, got.Email)
	} else if got.Username != want.username {
		s = fmt.Sprintf("want Username == %s, got %s", want.username, got.Username)
	} else if got.Name != want.name {
		s = fmt.Sprintf("want Name == %s, got %s", want.name, got.Name)
	} else if got.Alias != want.alias {
		s = fmt.Sprintf("want Name == %s, got %s", want.alias, got.Alias)
	} else if got.IsAdmin != want.isAdmin {
		s = fmt.Sprintf("want isAdmin == %t, got %t", want.isAdmin, got.IsAdmin)
	} else if got.Auth != want.auth {
		s = fmt.Sprintf("want auth == %s, got %s", want.auth, got.Auth)
	} else {
		return nil
	}
	return errors.New(s)
}

func checkUserInvertedIndex(t *testing.T, c aetest.Context, got *User) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings("john")
	if ids, err = GetUserInvertedIndexes(c, words); err != nil {
		s := fmt.Sprintf("failed calling GetUserInvertedIndexes %v", err)
		return errors.New(s)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("user not found")

}
<|endoftext|>


<commit_before>package s3

import (
	"context"
	"errors"
	"log"
	"io/ioutil"
	"os"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/aws/smithy-go"
	"github.com/buildkite/elastic-ci-stack-s3-secrets-hooks/s3secrets-helper/v2/sentinel"
)

type Client struct {
	s3 *s3.Client
	bucket string
}

func New(log *log.Logger, bucket string) (*Client, error) {
	ctx := context.Background()

	// Using the current region (or a guess) find where the bucket lives
	managerCfg, err := config.LoadDefaultConfig(ctx,
		config.WithRegion(os.Getenv("AWS_DEFAULT_REGION")),
		config.WithEC2IMDSRegion(),
		config.WithDefaultRegion("us-east-1"),
	)
	if err != nil {
		return nil, err
	}

	log.Printf("Discovered current region as %q\n", managerCfg.Region)

	managerClient := s3.NewFromConfig(managerCfg)
	bucketRegion, err := manager.GetBucketRegion(ctx, managerClient, bucket)
	if err != nil {
		return nil, err
	}

	log.Printf("Discovered bucket region as %q\n", bucketRegion)

	s3Cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(bucketRegion))
	if err != nil {
		return nil, err
	}

	return &Client{
		s3: s3.NewFromConfig(s3Cfg),
		bucket: bucket,
	}, nil
}

func (c *Client) Bucket() (string) {
	return c.bucket
}

// Get downloads an object from S3.
// Intended for small files; object is fully read into memory.
// sentinel.ErrNotFound and sentinel.ErrForbidden are returned for those cases.
// Other errors are returned verbatim.
func (c *Client) Get(key string) ([]byte, error) {
	out, err := c.s3.GetObject(context.Background(), &s3.GetObjectInput{
		Bucket: &c.bucket,
		Key:    &key,
	})
	if err != nil {
		var noSuchKey *types.NoSuchKey
		if errors.As(err, &noSuchKey) {
			return nil, sentinel.ErrNotFound
		}

		var apiErr smithy.APIError
		if errors.As(err, &apiErr) {
			code := apiErr.ErrorCode()
			// TODO confirm "Forbidden" is a member of the set of values this can return
			if code == "Forbidden" {
				return nil, sentinel.ErrForbidden
			}
		}

		return nil, err
	}
	defer out.Body.Close()
	// we probably should return io.Reader or io.ReadCloser rather than []byte,
	// maybe somebody should refactor that (and all the tests etc) one day.
	return ioutil.ReadAll(out.Body)
}

// BucketExists returns whether the bucket exists.
// 200 OK returns true without error.
// 404 Not Found and 403 Forbidden return false without error.
// Other errors result in false with an error.
func (c *Client) BucketExists() (bool, error) {
	if _, err := c.s3.HeadBucket(context.Background(), &s3.HeadBucketInput{Bucket: &c.bucket}); err != nil {
		return false, err
	}
	return true, nil
}
<commit_msg>Reuse the config once discovered<commit_after>package s3

import (
	"context"
	"errors"
	"log"
	"io/ioutil"
	"os"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/aws/smithy-go"
	"github.com/buildkite/elastic-ci-stack-s3-secrets-hooks/s3secrets-helper/v2/sentinel"
)

type Client struct {
	s3 *s3.Client
	bucket string
}

func New(log *log.Logger, bucket string) (*Client, error) {
	ctx := context.Background()

	// Using the current region (or a guess) find where the bucket lives
	config, err := config.LoadDefaultConfig(ctx,
		config.WithRegion(os.Getenv("AWS_DEFAULT_REGION")),
		config.WithEC2IMDSRegion(),
		config.WithDefaultRegion("us-east-1"),
	)
	if err != nil {
		return nil, err
	}

	log.Printf("Discovered current region as %q\n", config.Region)

	bucketRegion, err := manager.GetBucketRegion(ctx, s3.NewFromConfig(config), bucket)
	if err != nil {
		return nil, err
	}

	log.Printf("Discovered bucket region as %q\n", bucketRegion)

	config.Region = bucketRegion

	return &Client{
		s3: s3.NewFromConfig(config),
		bucket: bucket,
	}, nil
}

func (c *Client) Bucket() (string) {
	return c.bucket
}

// Get downloads an object from S3.
// Intended for small files; object is fully read into memory.
// sentinel.ErrNotFound and sentinel.ErrForbidden are returned for those cases.
// Other errors are returned verbatim.
func (c *Client) Get(key string) ([]byte, error) {
	out, err := c.s3.GetObject(context.Background(), &s3.GetObjectInput{
		Bucket: &c.bucket,
		Key:    &key,
	})
	if err != nil {
		var noSuchKey *types.NoSuchKey
		if errors.As(err, &noSuchKey) {
			return nil, sentinel.ErrNotFound
		}

		var apiErr smithy.APIError
		if errors.As(err, &apiErr) {
			code := apiErr.ErrorCode()
			// TODO confirm "Forbidden" is a member of the set of values this can return
			if code == "Forbidden" {
				return nil, sentinel.ErrForbidden
			}
		}

		return nil, err
	}
	defer out.Body.Close()
	// we probably should return io.Reader or io.ReadCloser rather than []byte,
	// maybe somebody should refactor that (and all the tests etc) one day.
	return ioutil.ReadAll(out.Body)
}

// BucketExists returns whether the bucket exists.
// 200 OK returns true without error.
// 404 Not Found and 403 Forbidden return false without error.
// Other errors result in false with an error.
func (c *Client) BucketExists() (bool, error) {
	if _, err := c.s3.HeadBucket(context.Background(), &s3.HeadBucketInput{Bucket: &c.bucket}); err != nil {
		return false, err
	}
	return true, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"fmt"
	etcdErr "github.com/coreos/etcd/error"
	"github.com/coreos/go-raft"
	"net/http"
	"net/url"
	"time"
)

type raftServer struct {
	*raft.Server
	version string
	name    string
	url     string
	tlsConf *TLSConfig
	tlsInfo *TLSInfo
}

var r *raftServer

func newRaftServer(name string, url string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *raftServer {

	// Create transporter for raft
	raftTransporter := newTransporter(tlsConf.Scheme, tlsConf.Client)

	// Create raft server
	server, err := raft.NewServer(name, dirPath, raftTransporter, etcdStore, nil)

	check(err)

	return &raftServer{
		Server:  server,
		version: raftVersion,
		name:    name,
		url:     url,
		tlsConf: tlsConf,
		tlsInfo: tlsInfo,
	}
}

// Start the raft server
func (r *raftServer) ListenAndServe() {

	// Setup commands.
	registerCommands()

	// LoadSnapshot
	if snapshot {
		err := r.LoadSnapshot()

		if err == nil {
			debugf("%s finished load snapshot", r.name)
		} else {
			debug(err)
		}
	}

	r.SetElectionTimeout(ElectionTimeout)
	r.SetHeartbeatTimeout(HeartbeatTimeout)

	r.Start()

	if r.IsLogEmpty() {

		// start as a leader in a new cluster
		if len(cluster) == 0 {
			startAsLeader()

		} else {
			startAsFollower()
		}

	} else {
		// rejoin the previous cluster
		debugf("%s restart as a follower", r.name)
	}

	// open the snapshot
	if snapshot {
		go monitorSnapshot()
	}

	// start to response to raft requests
	go r.startTransport(r.tlsConf.Scheme, r.tlsConf.Server)

}

func startAsLeader() {
	// leader need to join self as a peer
	for {
		_, err := r.Do(newJoinCommand())
		if err == nil {
			break
		}
	}
	debugf("%s start as a leader", r.name)
}

func startAsFollower() {
	// start as a follower in a existing cluster
	for i := 0; i < retryTimes; i++ {

		for _, machine := range cluster {

			if len(machine) == 0 {
				continue
			}

			err := joinCluster(r.Server, machine, r.tlsConf.Scheme)
			if err == nil {
				debugf("%s success join to the cluster via machine %s", r.name, machine)
				return

			} else {
				if _, ok := err.(etcdErr.Error); ok {
					fatal(err)
				}
				debugf("cannot join to cluster via machine %s %s", machine, err)
			}
		}

		warnf("cannot join to cluster via given machines, retry in %d seconds", RetryInterval)
		time.Sleep(time.Second * RetryInterval)
	}

	fatalf("Cannot join the cluster via given machines after %x retries", retryTimes)
}

// Start to listen and response raft command
func (r *raftServer) startTransport(scheme string, tlsConf tls.Config) {
	u, _ := url.Parse(r.url)
	infof("raft server [%s:%s]", r.name, u)

	raftMux := http.NewServeMux()

	server := &http.Server{
		Handler:   raftMux,
		TLSConfig: &tlsConf,
		Addr:      u.Host,
	}

	// internal commands
	raftMux.HandleFunc("/name", NameHttpHandler)
	raftMux.HandleFunc("/version", RaftVersionHttpHandler)
	raftMux.Handle("/join", errorHandler(JoinHttpHandler))
	raftMux.HandleFunc("/vote", VoteHttpHandler)
	raftMux.HandleFunc("/log", GetLogHttpHandler)
	raftMux.HandleFunc("/log/append", AppendEntriesHttpHandler)
	raftMux.HandleFunc("/snapshot", SnapshotHttpHandler)
	raftMux.HandleFunc("/snapshotRecovery", SnapshotRecoveryHttpHandler)
	raftMux.HandleFunc("/etcdURL", EtcdURLHttpHandler)

	if scheme == "http" {
		fatal(server.ListenAndServe())
	} else {
		fatal(server.ListenAndServeTLS(r.tlsInfo.CertFile, r.tlsInfo.KeyFile))
	}

}

func getLeaderVersion(t transporter, versionURL url.URL) (string, error) {
	resp, err := t.Get(versionURL.String())

	if err != nil {
		return "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	return string(body), nil
}

// Send join requests to the leader.
func joinCluster(s *raft.Server, raftURL string, scheme string) error {
	var b bytes.Buffer

	// t must be ok
	t, _ := r.Transporter().(transporter)

	// Our version must match the leaders version
	versionURL := url.URL{Host: raftURL, Scheme: scheme, Path: "/version"}
	version, err := getLeaderVersion(t, versionURL)
	if err != nil {
		return fmt.Errorf("Unable to join: %v", err)
	}

	// TODO: versioning of the internal protocol. See:
	// Documentation/internatl-protocol-versioning.md
	if version != r.version {
		return fmt.Errorf("Unable to join: internal version mismatch, entire cluster must be running identical versions of etcd")
	}

	json.NewEncoder(&b).Encode(newJoinCommand())

	joinURL := url.URL{Host: raftURL, Scheme: scheme, Path: "/join"}

	debugf("Send Join Request to %s", raftURL)

	resp, err := t.Post(joinURL.String(), &b)

	for {
		if err != nil {
			return fmt.Errorf("Unable to join: %v", err)
		}
		if resp != nil {
			defer resp.Body.Close()
			if resp.StatusCode == http.StatusOK {
				return nil
			}
			if resp.StatusCode == http.StatusTemporaryRedirect {

				address := resp.Header.Get("Location")
				debugf("Send Join Request to %s", address)

				json.NewEncoder(&b).Encode(newJoinCommand())

				resp, err = t.Post(address, &b)

			} else if resp.StatusCode == http.StatusBadRequest {
				debug("Reach max number machines in the cluster")
				decoder := json.NewDecoder(resp.Body)
				err := &etcdErr.Error{}
				decoder.Decode(err)
				return *err
			} else {
				return fmt.Errorf("Unable to join")
			}
		}

	}
	return fmt.Errorf("Unable to join: %v", err)
}

// Register commands to raft server
func registerCommands() {
	raft.RegisterCommand(&JoinCommand{})
	raft.RegisterCommand(&SetCommand{})
	raft.RegisterCommand(&GetCommand{})
	raft.RegisterCommand(&DeleteCommand{})
	raft.RegisterCommand(&WatchCommand{})
	raft.RegisterCommand(&TestAndSetCommand{})
}
<commit_msg>fix(raft_server): rename getLeaderVersion to getVersion<commit_after>package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"fmt"
	etcdErr "github.com/coreos/etcd/error"
	"github.com/coreos/go-raft"
	"net/http"
	"net/url"
	"time"
)

type raftServer struct {
	*raft.Server
	version string
	name    string
	url     string
	tlsConf *TLSConfig
	tlsInfo *TLSInfo
}

var r *raftServer

func newRaftServer(name string, url string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *raftServer {

	// Create transporter for raft
	raftTransporter := newTransporter(tlsConf.Scheme, tlsConf.Client)

	// Create raft server
	server, err := raft.NewServer(name, dirPath, raftTransporter, etcdStore, nil)

	check(err)

	return &raftServer{
		Server:  server,
		version: raftVersion,
		name:    name,
		url:     url,
		tlsConf: tlsConf,
		tlsInfo: tlsInfo,
	}
}

// Start the raft server
func (r *raftServer) ListenAndServe() {

	// Setup commands.
	registerCommands()

	// LoadSnapshot
	if snapshot {
		err := r.LoadSnapshot()

		if err == nil {
			debugf("%s finished load snapshot", r.name)
		} else {
			debug(err)
		}
	}

	r.SetElectionTimeout(ElectionTimeout)
	r.SetHeartbeatTimeout(HeartbeatTimeout)

	r.Start()

	if r.IsLogEmpty() {

		// start as a leader in a new cluster
		if len(cluster) == 0 {
			startAsLeader()

		} else {
			startAsFollower()
		}

	} else {
		// rejoin the previous cluster
		debugf("%s restart as a follower", r.name)
	}

	// open the snapshot
	if snapshot {
		go monitorSnapshot()
	}

	// start to response to raft requests
	go r.startTransport(r.tlsConf.Scheme, r.tlsConf.Server)

}

func startAsLeader() {
	// leader need to join self as a peer
	for {
		_, err := r.Do(newJoinCommand())
		if err == nil {
			break
		}
	}
	debugf("%s start as a leader", r.name)
}

func startAsFollower() {
	// start as a follower in a existing cluster
	for i := 0; i < retryTimes; i++ {

		for _, machine := range cluster {

			if len(machine) == 0 {
				continue
			}

			err := joinCluster(r.Server, machine, r.tlsConf.Scheme)
			if err == nil {
				debugf("%s success join to the cluster via machine %s", r.name, machine)
				return

			} else {
				if _, ok := err.(etcdErr.Error); ok {
					fatal(err)
				}
				debugf("cannot join to cluster via machine %s %s", machine, err)
			}
		}

		warnf("cannot join to cluster via given machines, retry in %d seconds", RetryInterval)
		time.Sleep(time.Second * RetryInterval)
	}

	fatalf("Cannot join the cluster via given machines after %x retries", retryTimes)
}

// Start to listen and response raft command
func (r *raftServer) startTransport(scheme string, tlsConf tls.Config) {
	u, _ := url.Parse(r.url)
	infof("raft server [%s:%s]", r.name, u)

	raftMux := http.NewServeMux()

	server := &http.Server{
		Handler:   raftMux,
		TLSConfig: &tlsConf,
		Addr:      u.Host,
	}

	// internal commands
	raftMux.HandleFunc("/name", NameHttpHandler)
	raftMux.HandleFunc("/version", RaftVersionHttpHandler)
	raftMux.Handle("/join", errorHandler(JoinHttpHandler))
	raftMux.HandleFunc("/vote", VoteHttpHandler)
	raftMux.HandleFunc("/log", GetLogHttpHandler)
	raftMux.HandleFunc("/log/append", AppendEntriesHttpHandler)
	raftMux.HandleFunc("/snapshot", SnapshotHttpHandler)
	raftMux.HandleFunc("/snapshotRecovery", SnapshotRecoveryHttpHandler)
	raftMux.HandleFunc("/etcdURL", EtcdURLHttpHandler)

	if scheme == "http" {
		fatal(server.ListenAndServe())
	} else {
		fatal(server.ListenAndServeTLS(r.tlsInfo.CertFile, r.tlsInfo.KeyFile))
	}

}

// getVersion fetches the raft version of a peer. This works for now but we
// will need to do something more sophisticated later when we allow mixed
// version clusters.
func getVersion(t transporter, versionURL url.URL) (string, error) {
	resp, err := t.Get(versionURL.String())

	if err != nil {
		return "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	return string(body), nil
}

// Send join requests to the leader.
func joinCluster(s *raft.Server, raftURL string, scheme string) error {
	var b bytes.Buffer

	// t must be ok
	t, _ := r.Transporter().(transporter)

	// Our version must match the leaders version
	versionURL := url.URL{Host: raftURL, Scheme: scheme, Path: "/version"}
	version, err := getVersion(t, versionURL)
	if err != nil {
		return fmt.Errorf("Unable to join: %v", err)
	}

	// TODO: versioning of the internal protocol. See:
	// Documentation/internatl-protocol-versioning.md
	if version != r.version {
		return fmt.Errorf("Unable to join: internal version mismatch, entire cluster must be running identical versions of etcd")
	}

	json.NewEncoder(&b).Encode(newJoinCommand())

	joinURL := url.URL{Host: raftURL, Scheme: scheme, Path: "/join"}

	debugf("Send Join Request to %s", raftURL)

	resp, err := t.Post(joinURL.String(), &b)

	for {
		if err != nil {
			return fmt.Errorf("Unable to join: %v", err)
		}
		if resp != nil {
			defer resp.Body.Close()
			if resp.StatusCode == http.StatusOK {
				return nil
			}
			if resp.StatusCode == http.StatusTemporaryRedirect {

				address := resp.Header.Get("Location")
				debugf("Send Join Request to %s", address)

				json.NewEncoder(&b).Encode(newJoinCommand())

				resp, err = t.Post(address, &b)

			} else if resp.StatusCode == http.StatusBadRequest {
				debug("Reach max number machines in the cluster")
				decoder := json.NewDecoder(resp.Body)
				err := &etcdErr.Error{}
				decoder.Decode(err)
				return *err
			} else {
				return fmt.Errorf("Unable to join")
			}
		}

	}
	return fmt.Errorf("Unable to join: %v", err)
}

// Register commands to raft server
func registerCommands() {
	raft.RegisterCommand(&JoinCommand{})
	raft.RegisterCommand(&SetCommand{})
	raft.RegisterCommand(&GetCommand{})
	raft.RegisterCommand(&DeleteCommand{})
	raft.RegisterCommand(&WatchCommand{})
	raft.RegisterCommand(&TestAndSetCommand{})
}
<|endoftext|>


<commit_before>// Copyright 2015 Daniel Pupius

package rcache_test

import (
	"fmt"
	"github.com/dpup/rcache"
)

type CarKey struct {
	Manufacturer string
	Model        string
}

func (key CarKey) Dependencies() []rcache.CacheKey {
	return rcache.NoDeps
}

type ThumbnailKey struct {
	Manufacturer string
	Model        string
	Size         int
}

func (key ThumbnailKey) Dependencies() []rcache.CacheKey {
	return []rcache.CacheKey{CarKey{key.Manufacturer, key.Model}}
}

// The following example (pretends to) request images for a car, then has a
// dependent cache for thumbnails. If the original image is invalidated, so are
// the thumbnails.
func ExampleCache() {
	c := rcache.New("mycache")
	c.RegisterFetcher(func(key CarKey) ([]byte, error) {
		return getCarImage(key.Manufacturer, key.Model), nil
	})
	c.RegisterFetcher(func(key ThumbnailKey) ([]byte, error) {
		fullImage, _ := c.Get(CarKey{key.Manufacturer, key.Model})
		return resize(fullImage, key.Size), nil
	})

	// Original image is only fetched once.
	t200, _ := c.Get(ThumbnailKey{"BMW", "M5", 200})
	t400, _ := c.Get(ThumbnailKey{"BMW", "M5", 400})

	fmt.Printf("%s + %s", t200, t400)

	// Output: image: BMW.M5.200.jpg + image: BMW.M5.400.jpg
}

func getCarImage(manufacturer, model string) []byte {
	// In the real world this would go off and fetch an actual image.
	return []byte(fmt.Sprintf("image: %s.%s", manufacturer, model))
}

func resize(image []byte, size int) []byte {
	// In the real world this would resize the image.
	return []byte(fmt.Sprintf("%s.%d.jpg", image, size))
}
<commit_msg>Update example<commit_after>// Copyright 2015 Daniel Pupius

package rcache_test

import (
	"fmt"
	"github.com/dpup/rcache"
)

type CarKey struct {
	Manufacturer string
	Model        string
}

func (key CarKey) Dependencies() []rcache.CacheKey {
	return rcache.NoDeps
}

type ThumbnailKey struct {
	Manufacturer string
	Model        string
	Size         int
}

func (key ThumbnailKey) Dependencies() []rcache.CacheKey {
	return []rcache.CacheKey{CarKey{key.Manufacturer, key.Model}}
}

// The following example (pretends to) request images for a car, then has a
// dependent cache for thumbnails. If the original image is invalidated, so are
// the thumbnails.
func ExampleCache() {
	c := rcache.New("mycache")
	c.RegisterFetcher(func(key CarKey) ([]byte, error) {
		return getCarImage(key.Manufacturer, key.Model), nil
	})
	c.RegisterFetcher(func(key ThumbnailKey) ([]byte, error) {
		fullImage, _ := c.Get(CarKey{key.Manufacturer, key.Model})
		return resize(fullImage, key.Size), nil
	})

	// Original image is only fetched once.
	tx, _ := c.Get(CarKey{"BMW", "M5"})
	t200, _ := c.Get(ThumbnailKey{"BMW", "M5", 200})
	t400, _ := c.Get(ThumbnailKey{"BMW", "M5", 400})

	fmt.Printf("%s + %s + %s", tx, t200, t400)

	// Output: image:BMW.M5 + image:BMW.M5@200 + image:BMW.M5@400
}

func getCarImage(manufacturer, model string) []byte {
	// In the real world this would go off and fetch an actual image.
	return []byte(fmt.Sprintf("image:%s.%s", manufacturer, model))
}

func resize(image []byte, size int) []byte {
	// In the real world this would resize the image.
	return []byte(fmt.Sprintf("%s@%d", image, size))
}
<|endoftext|>


<commit_before>package geoip2

import (
	"math/rand"
	"net"
	"testing"

	. "gopkg.in/check.v1"
)

func TestGeoIP2(t *testing.T) { TestingT(t) }

type MySuite struct{}

var _ = Suite(&MySuite{})

func (s *MySuite) TestReader(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.City(net.ParseIP("81.2.69.160"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	m := reader.Metadata()
	c.Assert(m.BinaryFormatMajorVersion, Equals, uint(2))
	c.Assert(m.BinaryFormatMinorVersion, Equals, uint(0))
	c.Assert(m.BuildEpoch, Equals, uint(1436981935))
	c.Assert(m.DatabaseType, Equals, "GeoIP2-City")
	c.Assert(m.Description, DeepEquals, map[string]string{
		"en": "GeoIP2 City Test Database (a small sample of real GeoIP2 data)",
		"zh": "小型数据库",
	})
	c.Assert(m.IPVersion, Equals, uint(6))
	c.Assert(m.Languages, DeepEquals, []string{"en", "zh"})
	c.Assert(m.NodeCount, Equals, uint(1240))
	c.Assert(m.RecordSize, Equals, uint(28))

	c.Assert(record.City.GeoNameID, Equals, uint(2643743))
	c.Assert(record.City.Names, DeepEquals, map[string]string{
		"de":    "London",
		"en":    "London",
		"es":    "Londres",
		"fr":    "Londres",
		"ja":    "ロンドン",
		"pt-BR": "Londres",
		"ru":    "Лондон",
	})
	c.Assert(record.Continent.GeoNameID, Equals, uint(6255148))
	c.Assert(record.Continent.Code, Equals, "EU")
	c.Assert(record.Continent.Names, DeepEquals, map[string]string{
		"de":    "Europa",
		"en":    "Europe",
		"es":    "Europa",
		"fr":    "Europe",
		"ja":    "ヨーロッパ",
		"pt-BR": "Europa",
		"ru":    "Европа",
		"zh-CN": "欧洲",
	})

	c.Assert(record.Country.GeoNameID, Equals, uint(2635167))
	c.Assert(record.Country.IsoCode, Equals, "GB")
	c.Assert(record.Country.Names, DeepEquals, map[string]string{
		"de":    "Vereinigtes Königreich",
		"en":    "United Kingdom",
		"es":    "Reino Unido",
		"fr":    "Royaume-Uni",
		"ja":    "イギリス",
		"pt-BR": "Reino Unido",
		"ru":    "Великобритания",
		"zh-CN": "英国",
	})

	c.Assert(record.Location.Latitude, Equals, 51.5142)
	c.Assert(record.Location.Longitude, Equals, -0.0931)
	c.Assert(record.Location.TimeZone, Equals, "Europe/London")

	c.Assert(record.Subdivisions[0].GeoNameID, Equals, uint(6269131))
	c.Assert(record.Subdivisions[0].IsoCode, Equals, "ENG")
	c.Assert(record.Subdivisions[0].Names, DeepEquals, map[string]string{
		"en":    "England",
		"pt-BR": "Inglaterra",
		"fr":    "Angleterre",
		"es":    "Inglaterra",
	})

	c.Assert(record.RegisteredCountry.GeoNameID, Equals, uint(6252001))
	c.Assert(record.RegisteredCountry.IsoCode, Equals, "US")
	c.Assert(record.RegisteredCountry.Names, DeepEquals, map[string]string{
		"de":    "USA",
		"en":    "United States",
		"es":    "Estados Unidos",
		"fr":    "États-Unis",
		"ja":    "アメリカ合衆国",
		"pt-BR": "Estados Unidos",
		"ru":    "США",
		"zh-CN": "美国",
	})
}

func (s *MySuite) TestMetroCode(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.City(net.ParseIP("216.160.83.56"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.Location.MetroCode, Equals, uint(819))
}

func (s *MySuite) TestConnectionType(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Connection-Type-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.ConnectionType(net.ParseIP("1.0.1.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	c.Assert(record.ConnectionType, Equals, "Cable/DSL")

}

func (s *MySuite) TestDomain(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Domain-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.Domain(net.ParseIP("1.2.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	c.Assert(record.Domain, Equals, "maxmind.com")

}

func (s *MySuite) TestISP(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-ISP-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.ISP(net.ParseIP("1.128.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.AutonomousSystemNumber, Equals, uint(1221))

	c.Assert(record.AutonomousSystemOrganization, Equals, "Telstra Pty Ltd")
	c.Assert(record.ISP, Equals, "Telstra Internet")
	c.Assert(record.Organization, Equals, "Telstra Internet")

}

func (s *MySuite) TestAnonymousIP(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Anonymous-IP-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.AnonymousIP(net.ParseIP("1.2.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.IsAnonymous, Equals, true)

	c.Assert(record.IsAnonymousVPN, Equals, true)
	c.Assert(record.IsHostingProvider, Equals, false)
	c.Assert(record.IsPublicProxy, Equals, false)
	c.Assert(record.IsTorExitNode, Equals, false)

}

// This ensures the compiler does not optimize away the function call
var cityResult *City

func BenchmarkMaxMindDB(b *testing.B) {
	db, err := Open("GeoLite2-City.mmdb")
	if err != nil {
		b.Fatal(err)
	}
	defer db.Close()

	r := rand.New(rand.NewSource(0))

	var city *City

	for i := 0; i < b.N; i++ {
		ip := randomIPv4Address(b, r)
		city, err = db.City(ip)
		if err != nil {
			b.Fatal(err)
		}
	}
	cityResult = city
}

func randomIPv4Address(b *testing.B, r *rand.Rand) net.IP {
	num := r.Uint32()
	ip := []byte{byte(num >> 24), byte(num >> 16), byte(num >> 8),
		byte(num)}
	if _, err := rand.Read(ip); err != nil {
		b.Fatalf("Error generating IP: %v", err)
	}

	return ip
}
<commit_msg>Remove extra line<commit_after>package geoip2

import (
	"math/rand"
	"net"
	"testing"

	. "gopkg.in/check.v1"
)

func TestGeoIP2(t *testing.T) { TestingT(t) }

type MySuite struct{}

var _ = Suite(&MySuite{})

func (s *MySuite) TestReader(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.City(net.ParseIP("81.2.69.160"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	m := reader.Metadata()
	c.Assert(m.BinaryFormatMajorVersion, Equals, uint(2))
	c.Assert(m.BinaryFormatMinorVersion, Equals, uint(0))
	c.Assert(m.BuildEpoch, Equals, uint(1436981935))
	c.Assert(m.DatabaseType, Equals, "GeoIP2-City")
	c.Assert(m.Description, DeepEquals, map[string]string{
		"en": "GeoIP2 City Test Database (a small sample of real GeoIP2 data)",
		"zh": "小型数据库",
	})
	c.Assert(m.IPVersion, Equals, uint(6))
	c.Assert(m.Languages, DeepEquals, []string{"en", "zh"})
	c.Assert(m.NodeCount, Equals, uint(1240))
	c.Assert(m.RecordSize, Equals, uint(28))

	c.Assert(record.City.GeoNameID, Equals, uint(2643743))
	c.Assert(record.City.Names, DeepEquals, map[string]string{
		"de":    "London",
		"en":    "London",
		"es":    "Londres",
		"fr":    "Londres",
		"ja":    "ロンドン",
		"pt-BR": "Londres",
		"ru":    "Лондон",
	})
	c.Assert(record.Continent.GeoNameID, Equals, uint(6255148))
	c.Assert(record.Continent.Code, Equals, "EU")
	c.Assert(record.Continent.Names, DeepEquals, map[string]string{
		"de":    "Europa",
		"en":    "Europe",
		"es":    "Europa",
		"fr":    "Europe",
		"ja":    "ヨーロッパ",
		"pt-BR": "Europa",
		"ru":    "Европа",
		"zh-CN": "欧洲",
	})

	c.Assert(record.Country.GeoNameID, Equals, uint(2635167))
	c.Assert(record.Country.IsoCode, Equals, "GB")
	c.Assert(record.Country.Names, DeepEquals, map[string]string{
		"de":    "Vereinigtes Königreich",
		"en":    "United Kingdom",
		"es":    "Reino Unido",
		"fr":    "Royaume-Uni",
		"ja":    "イギリス",
		"pt-BR": "Reino Unido",
		"ru":    "Великобритания",
		"zh-CN": "英国",
	})

	c.Assert(record.Location.Latitude, Equals, 51.5142)
	c.Assert(record.Location.Longitude, Equals, -0.0931)
	c.Assert(record.Location.TimeZone, Equals, "Europe/London")

	c.Assert(record.Subdivisions[0].GeoNameID, Equals, uint(6269131))
	c.Assert(record.Subdivisions[0].IsoCode, Equals, "ENG")
	c.Assert(record.Subdivisions[0].Names, DeepEquals, map[string]string{
		"en":    "England",
		"pt-BR": "Inglaterra",
		"fr":    "Angleterre",
		"es":    "Inglaterra",
	})

	c.Assert(record.RegisteredCountry.GeoNameID, Equals, uint(6252001))
	c.Assert(record.RegisteredCountry.IsoCode, Equals, "US")
	c.Assert(record.RegisteredCountry.Names, DeepEquals, map[string]string{
		"de":    "USA",
		"en":    "United States",
		"es":    "Estados Unidos",
		"fr":    "États-Unis",
		"ja":    "アメリカ合衆国",
		"pt-BR": "Estados Unidos",
		"ru":    "США",
		"zh-CN": "美国",
	})
}

func (s *MySuite) TestMetroCode(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.City(net.ParseIP("216.160.83.56"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.Location.MetroCode, Equals, uint(819))
}

func (s *MySuite) TestConnectionType(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Connection-Type-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.ConnectionType(net.ParseIP("1.0.1.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	c.Assert(record.ConnectionType, Equals, "Cable/DSL")

}

func (s *MySuite) TestDomain(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Domain-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.Domain(net.ParseIP("1.2.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	c.Assert(record.Domain, Equals, "maxmind.com")

}

func (s *MySuite) TestISP(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-ISP-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.ISP(net.ParseIP("1.128.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.AutonomousSystemNumber, Equals, uint(1221))

	c.Assert(record.AutonomousSystemOrganization, Equals, "Telstra Pty Ltd")
	c.Assert(record.ISP, Equals, "Telstra Internet")
	c.Assert(record.Organization, Equals, "Telstra Internet")

}

func (s *MySuite) TestAnonymousIP(c *C) {
	reader, err := Open("test-data/test-data/GeoIP2-Anonymous-IP-Test.mmdb")
	if err != nil {
		c.Log(err)
		c.Fail()
	}
	defer reader.Close()

	record, err := reader.AnonymousIP(net.ParseIP("1.2.0.0"))
	if err != nil {
		c.Log(err)
		c.Fail()
	}

	c.Assert(record.IsAnonymous, Equals, true)

	c.Assert(record.IsAnonymousVPN, Equals, true)
	c.Assert(record.IsHostingProvider, Equals, false)
	c.Assert(record.IsPublicProxy, Equals, false)
	c.Assert(record.IsTorExitNode, Equals, false)

}

// This ensures the compiler does not optimize away the function call
var cityResult *City

func BenchmarkMaxMindDB(b *testing.B) {
	db, err := Open("GeoLite2-City.mmdb")
	if err != nil {
		b.Fatal(err)
	}
	defer db.Close()

	r := rand.New(rand.NewSource(0))

	var city *City

	for i := 0; i < b.N; i++ {
		ip := randomIPv4Address(b, r)
		city, err = db.City(ip)
		if err != nil {
			b.Fatal(err)
		}
	}
	cityResult = city
}

func randomIPv4Address(b *testing.B, r *rand.Rand) net.IP {
	num := r.Uint32()
	ip := []byte{byte(num >> 24), byte(num >> 16), byte(num >> 8),
		byte(num)}

	return ip
}
<|endoftext|>


<commit_before>package asyncpi

import (
	"strings"
	"testing"
)

// Tests reduction of (send | recv)
func TestReduceSendRecv(t *testing.T) {
	const proc = `(new a)(a<b> | a(x).x().0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Recv)
	if !ok {
		t.Fatalf("expects *Recv but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Chan.Name(); want != got {
		t.Fatalf("expects receive on %s but got %s", want, got)
	}
	_, ok = p2.Cont.(*NilProcess)
	if !ok {
		t.Fatalf("expects *NilProcess but got %s (type %T)", p2.Cont.Calculi(), p2.Cont)
	}
}

// Test reduction of (recv | send)
func TestReduceRecvSend(t *testing.T) {
	const proc = `(new a)(a(x).x<> | a<b>)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Send)
	if !ok {
		t.Fatalf("expects *Send but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Chan.Name(); want != got {
		t.Fatalf("expects send on %s but got %s", want, got)
	}
}

// Test reduction (and simplify) where all names are bound.
func TestReduceBoundRecvSend(t *testing.T) {
	const proc = `(new a)(new b)(a(x).x<> | a<b>)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Restrict)
	if !ok {
		t.Fatalf("expects a *Restrict but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Name.Name(); want != got {
		t.Fatalf("expects restrict on %s but got %s", want, got)
	}
	p3, ok := p2.Proc.(*Send)
	if !ok {
		t.Fatalf("expects *Send but got %s (type %T)", p2.Calculi(), p2)
	}
	if want, got := "b", p3.Chan.Name(); want != got {
		t.Fatalf("expects send on %s but got %s", want, got)
	}
}

func TestReduceFreeSendRecv(t *testing.T) {
	const proc = `a<b> | a(x).0`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
}

func TestReduceNone(t *testing.T) {
	const proc = `(new a)(a<b> | b(x).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

func TestReduceBoundRecvRecv(t *testing.T) {
	const proc = `(new a)(a(z).0 | a(x).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

// Non-shared name cannot reduce.
func TestReduceFreeRecvRecv(t *testing.T) {
	const proc = `a(z).0 | a(x).0`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to note reduce but it changed to", proc, p.Calculi())
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

func TestReduceMultiple(t *testing.T) {
	const proc = `(new a)(a<b,c>|a(x,y).x(z).z<y> | b<d> | d(z).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	procPrev := p.Calculi()
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", procPrev, p.Calculi())
	procPrev = p.Calculi()
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", procPrev, p.Calculi())
	if _, ok := p.(*NilProcess); !ok {
		t.Fatalf("expects *NilProcess but got %s (type %T)", p.Calculi(), p)
	}
}
<commit_msg>OOPS: fix wrong argument to Fatalf.<commit_after>package asyncpi

import (
	"strings"
	"testing"
)

// Tests reduction of (send | recv)
func TestReduceSendRecv(t *testing.T) {
	const proc = `(new a)(a<b> | a(x).x().0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Recv)
	if !ok {
		t.Fatalf("expects *Recv but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Chan.Name(); want != got {
		t.Fatalf("expects receive on %s but got %s", want, got)
	}
	_, ok = p2.Cont.(*NilProcess)
	if !ok {
		t.Fatalf("expects *NilProcess but got %s (type %T)", p2.Cont.Calculi(), p2.Cont)
	}
}

// Test reduction of (recv | send)
func TestReduceRecvSend(t *testing.T) {
	const proc = `(new a)(a(x).x<> | a<b>)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Send)
	if !ok {
		t.Fatalf("expects *Send but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Chan.Name(); want != got {
		t.Fatalf("expects send on %s but got %s", want, got)
	}
}

// Test reduction (and simplify) where all names are bound.
func TestReduceBoundRecvSend(t *testing.T) {
	const proc = `(new a)(new b)(a(x).x<> | a<b>)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	p2, ok := p.(*Restrict)
	if !ok {
		t.Fatalf("expects a *Restrict but got %s (type %T)", p.Calculi(), p)
	}
	if want, got := "b", p2.Name.Name(); want != got {
		t.Fatalf("expects restrict on %s but got %s", want, got)
	}
	p3, ok := p2.Proc.(*Send)
	if !ok {
		t.Fatalf("expects *Send but got %s (type %T)", p2.Calculi(), p2)
	}
	if want, got := "b", p3.Chan.Name(); want != got {
		t.Fatalf("expects send on %s but got %s", want, got)
	}
}

func TestReduceFreeSendRecv(t *testing.T) {
	const proc = `a<b> | a(x).0`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
}

func TestReduceNone(t *testing.T) {
	const proc = `(new a)(a<b> | b(x).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

func TestReduceBoundRecvRecv(t *testing.T) {
	const proc = `(new a)(a(z).0 | a(x).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

// Non-shared name cannot reduce.
func TestReduceFreeRecvRecv(t *testing.T) {
	const proc = `a(z).0 | a(x).0`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to note reduce but it changed to %s", proc, p.Calculi())
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if changed {
		t.Fatalf("expects %s to not reduce but reduced to %s", proc, p.Calculi())
	}
	t.Logf("%s reduces to %s (no change)", proc, p.Calculi())
}

func TestReduceMultiple(t *testing.T) {
	const proc = `(new a)(a<b,c>|a(x,y).x(z).z<y> | b<d> | d(z).0)`
	p, err := Parse(strings.NewReader(proc))
	if err != nil {
		t.Fatal(err)
	}
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", proc, p.Calculi())
	procPrev := p.Calculi()
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", procPrev, p.Calculi())
	procPrev = p.Calculi()
	if changed, err := reduceOnce(p); err != nil {
		t.Fatalf("cannot reduce: %v", err)
	} else if !changed {
		t.Fatalf("expects %s to reduce but unchanged", p.Calculi())
	}
	p, err = SimplifyBySC(p)
	if err != nil {
		t.Fatalf("cannot simplify process: %v", err)
	}
	t.Logf("%s reduces to %s", procPrev, p.Calculi())
	if _, ok := p.(*NilProcess); !ok {
		t.Fatalf("expects *NilProcess but got %s (type %T)", p.Calculi(), p)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/gestic-tools/go-gestic-sdk"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go-uber"
	"github.com/ninjasphere/sphere-go-led-controller/fonts/O4b03b"
	"github.com/ninjasphere/sphere-go-led-controller/util"
)

var latitude = config.Float(0.0, "latitude")
var longitude = config.Float(0.0, "longitude")

var tapInterval = time.Duration(time.Second / 2)
var introDuration = time.Duration(time.Second * 2)

var visibleTimeout = time.Duration(time.Second * 2) // Time between frames rendered before we reset the ui.
var staleDataTimeout = time.Duration(time.Second * 90)

var timezone *time.Location

var imageSurge = util.LoadImage(util.ResolveImagePath("surge.gif"))
var imageNoSurge = util.LoadImage(util.ResolveImagePath("no_surge.gif"))
var imageLogo = util.LoadImage(util.ResolveImagePath("logo.png"))

type UberPane struct {
	siteModel *ninja.ServiceClient
	site      *model.Site

	times  []*uber.Time
	prices []*uber.Price

	lastTap       time.Time
	lastDoubleTap time.Time

	intro        bool
	introTimeout *time.Timer

	visible        bool
	visibleTimeout *time.Timer

	staleDataTimeout *time.Timer
	updateTimer      *time.Timer

	uberProduct string

	keepAwake        bool
	keepAwakeTimeout *time.Timer
}

func NewUberPane(conn *ninja.Connection) *UberPane {

	pane := &UberPane{
		siteModel:   conn.GetServiceClient("$home/services/SiteModel"),
		lastTap:     time.Now(),
		uberProduct: config.String("uberX", "uber.product"),
	}

	pane.visibleTimeout = time.AfterFunc(0, func() {
		pane.keepAwake = false
		pane.visible = false
	})

	pane.introTimeout = time.AfterFunc(0, func() {
		pane.intro = false
	})

	pane.staleDataTimeout = time.AfterFunc(0, func() {
		pane.times, pane.prices = nil, nil
	})

	pane.updateTimer = time.AfterFunc(0, func() {
		if !pane.visible {
			return
		}

		err := pane.UpdateData()
		if err != nil {
			log.Errorf("Failed to get uber data: %s", err)
			pane.updateTimer.Reset(time.Second * 5)
		}
	})

	pane.keepAwakeTimeout = time.AfterFunc(0, func() {
		pane.keepAwake = false
	})

	go pane.Start()

	return pane
}

func (p *UberPane) Start() {

	if longitude == 0 || latitude == 0 {

		log.Infof("No --latitude and/or --longitude provided, using site location.")

		for {
			site := &model.Site{}
			err := p.siteModel.Call("fetch", config.MustString("siteId"), site, time.Second*5)

			if err == nil && (site.Longitude != nil || site.Latitude != nil) {
				longitude, latitude = *site.Longitude, *site.Latitude
				break
			}

			log.Infof("Failed to get site, or site has no location.")

			time.Sleep(time.Second * 2)
		}

	}

}

func (p *UberPane) UpdateData() error {
	times, err := client.GetTimes(latitude, longitude, user.UUID, "")
	if err != nil {
		return err
	}

	prices, err := client.GetPrices(latitude, longitude, latitude, longitude)
	if err != nil {
		return err
	}

	p.times = times
	p.prices = prices

	spew.Dump("Updated data", times, prices)

	p.staleDataTimeout.Reset(staleDataTimeout)

	if p.visible {
		p.updateTimer.Reset(time.Second * 30)
	}

	return nil
}

func (p *UberPane) Gesture(gesture *gestic.GestureMessage) {

	if gesture.Tap.Active() && time.Since(p.lastTap) > tapInterval {
		p.lastTap = time.Now()

		log.Infof("Tap!")
	}

	if gesture.DoubleTap.Active() && time.Since(p.lastDoubleTap) > tapInterval {
		p.lastDoubleTap = time.Now()

		log.Infof("Double Tap!")
	}

}

func (p *UberPane) KeepAwake() bool {
	return true
}

func (p *UberPane) Render() (*image.RGBA, error) {

	if !p.visible {
		p.visible = true
		p.intro = true

		p.introTimeout.Reset(introDuration)

		go p.UpdateData()
	}

	p.visibleTimeout.Reset(visibleTimeout)

	if p.intro || p.times == nil {
		return imageLogo.GetNextFrame(), nil
	}

	var time *uber.Time
	var price *uber.Price
	var border util.Image

	for _, t := range p.times {
		if t.DisplayName == p.uberProduct {
			time = t
		}
	}

	for _, t := range p.prices {
		if t.DisplayName == p.uberProduct {
			price = t
		}
	}

	if price == nil || time == nil {
		spew.Dump(p.prices, p.times)
		log.Fatalf("Could not find price/time for product %s", p.uberProduct)
	}

	if price.SurgeMultiplier > 1 {
		border = imageSurge
	} else {
		border = imageNoSurge
	}

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))
	/*draw.Draw(frame, frame.Bounds(), &image.Uniform{color.RGBA{
		R: 0,
		G: 0,
		B: 0,
		A: 255,
	}}, image.ZP, draw.Src)*/

	waitInMinutes := int(time.Estimate / 60)

	drawText := func(text string, col color.RGBA, top int) {
		width := O4b03b.Font.DrawString(img, 0, 8, text, color.Black)
		start := int(16 - width - 2)

		O4b03b.Font.DrawString(img, start, top, text, col)
	}

	drawText(fmt.Sprintf("%dm", waitInMinutes), color.RGBA{253, 151, 32, 255}, 2)
	drawText(fmt.Sprintf("%.1fx", price.SurgeMultiplier), color.RGBA{69, 175, 249, 255}, 9)

	draw.Draw(img, img.Bounds(), border.GetNextFrame(), image.Point{0, 0}, draw.Over)

	return img, nil
}

func (p *UberPane) IsEnabled() bool {
	return true
}

func (p *UberPane) IsDirty() bool {
	return true
}
<commit_msg>Fix text alignment<commit_after>package main

import (
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/gestic-tools/go-gestic-sdk"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/go-uber"
	"github.com/ninjasphere/sphere-go-led-controller/fonts/O4b03b"
	"github.com/ninjasphere/sphere-go-led-controller/util"
)

var latitude = config.Float(0.0, "latitude")
var longitude = config.Float(0.0, "longitude")

var tapInterval = time.Duration(time.Second / 2)
var introDuration = time.Duration(time.Second * 2)

var visibleTimeout = time.Duration(time.Second * 2) // Time between frames rendered before we reset the ui.
var staleDataTimeout = time.Duration(time.Second * 90)

var timezone *time.Location

var imageSurge = util.LoadImage(util.ResolveImagePath("surge.gif"))
var imageNoSurge = util.LoadImage(util.ResolveImagePath("no_surge.gif"))
var imageLogo = util.LoadImage(util.ResolveImagePath("logo.png"))

type UberPane struct {
	siteModel *ninja.ServiceClient
	site      *model.Site

	times  []*uber.Time
	prices []*uber.Price

	lastTap       time.Time
	lastDoubleTap time.Time

	intro        bool
	introTimeout *time.Timer

	visible        bool
	visibleTimeout *time.Timer

	staleDataTimeout *time.Timer
	updateTimer      *time.Timer

	uberProduct string

	keepAwake        bool
	keepAwakeTimeout *time.Timer
}

func NewUberPane(conn *ninja.Connection) *UberPane {

	pane := &UberPane{
		siteModel:   conn.GetServiceClient("$home/services/SiteModel"),
		lastTap:     time.Now(),
		uberProduct: config.String("uberX", "uber.product"),
	}

	pane.visibleTimeout = time.AfterFunc(0, func() {
		pane.keepAwake = false
		pane.visible = false
	})

	pane.introTimeout = time.AfterFunc(0, func() {
		pane.intro = false
	})

	pane.staleDataTimeout = time.AfterFunc(0, func() {
		pane.times, pane.prices = nil, nil
	})

	pane.updateTimer = time.AfterFunc(0, func() {
		if !pane.visible {
			return
		}

		err := pane.UpdateData()
		if err != nil {
			log.Errorf("Failed to get uber data: %s", err)
			pane.updateTimer.Reset(time.Second * 5)
		}
	})

	pane.keepAwakeTimeout = time.AfterFunc(0, func() {
		pane.keepAwake = false
	})

	go pane.Start()

	return pane
}

func (p *UberPane) Start() {

	if longitude == 0 || latitude == 0 {

		log.Infof("No --latitude and/or --longitude provided, using site location.")

		for {
			site := &model.Site{}
			err := p.siteModel.Call("fetch", config.MustString("siteId"), site, time.Second*5)

			if err == nil && (site.Longitude != nil || site.Latitude != nil) {
				longitude, latitude = *site.Longitude, *site.Latitude
				break
			}

			log.Infof("Failed to get site, or site has no location.")

			time.Sleep(time.Second * 2)
		}

	}

}

func (p *UberPane) UpdateData() error {
	times, err := client.GetTimes(latitude, longitude, user.UUID, "")
	if err != nil {
		return err
	}

	prices, err := client.GetPrices(latitude, longitude, latitude, longitude)
	if err != nil {
		return err
	}

	p.times = times
	p.prices = prices

	spew.Dump("Updated data", times, prices)

	p.staleDataTimeout.Reset(staleDataTimeout)

	if p.visible {
		p.updateTimer.Reset(time.Second * 30)
	}

	return nil
}

func (p *UberPane) Gesture(gesture *gestic.GestureMessage) {

	if gesture.Tap.Active() && time.Since(p.lastTap) > tapInterval {
		p.lastTap = time.Now()

		log.Infof("Tap!")
	}

	if gesture.DoubleTap.Active() && time.Since(p.lastDoubleTap) > tapInterval {
		p.lastDoubleTap = time.Now()

		log.Infof("Double Tap!")
	}

}

func (p *UberPane) KeepAwake() bool {
	return true
}

func (p *UberPane) Render() (*image.RGBA, error) {

	if !p.visible {
		p.visible = true
		p.intro = true

		p.introTimeout.Reset(introDuration)

		go p.UpdateData()
	}

	p.visibleTimeout.Reset(visibleTimeout)

	if p.intro || p.times == nil {
		return imageLogo.GetNextFrame(), nil
	}

	var time *uber.Time
	var price *uber.Price
	var border util.Image

	for _, t := range p.times {
		if t.DisplayName == p.uberProduct {
			time = t
		}
	}

	for _, t := range p.prices {
		if t.DisplayName == p.uberProduct {
			price = t
		}
	}

	if price == nil || time == nil {
		spew.Dump(p.prices, p.times)
		log.Fatalf("Could not find price/time for product %s", p.uberProduct)
	}

	if price.SurgeMultiplier > 1 {
		border = imageSurge
	} else {
		border = imageNoSurge
	}

	img := image.NewRGBA(image.Rect(0, 0, 16, 16))
	/*draw.Draw(frame, frame.Bounds(), &image.Uniform{color.RGBA{
		R: 0,
		G: 0,
		B: 0,
		A: 255,
	}}, image.ZP, draw.Src)*/

	waitInMinutes := int(time.Estimate / 60)

	drawText := func(text string, col color.RGBA, top int) {
		width := O4b03b.Font.DrawString(img, 0, 8, text, color.Black)
		start := int(16 - width - 1)

		O4b03b.Font.DrawString(img, start, top, text, col)
	}

	drawText(fmt.Sprintf("%dm", waitInMinutes), color.RGBA{253, 151, 32, 255}, 2)
	drawText(fmt.Sprintf("%.1fx", price.SurgeMultiplier), color.RGBA{69, 175, 249, 255}, 9)

	draw.Draw(img, img.Bounds(), border.GetNextFrame(), image.Point{0, 0}, draw.Over)

	return img, nil
}

func (p *UberPane) IsEnabled() bool {
	return true
}

func (p *UberPane) IsDirty() bool {
	return true
}
<|endoftext|>


<commit_before>package gouda

import (
        "container/vector"
	"fmt"
	)

type Relation struct {
	conditions vector.StringVector
	table string
}

func (r *Relation) Where(s string) *Relation {

	r.conditions.Push(s)

	return r

}

func (r *Relation) Table(t string) *Relation{
	r.table=t
return r
}

func (r *Relation) String() string {

	s := " Conditions : ("

	for _, ss := range r.conditions {
		s += ss
		if ss != r.conditions.Last() {
			s += ", "
		}
	}
	s += ")"

	return "Une relation" + s
}

func (r *Relation) Sql() (sql string) {
	sql = "Select * from "+r.table+" where ( "
	for _, ss := range r.conditions {
		sql += ss
		if ss != r.conditions.Last() {
			sql += " ) AND ( "
		}
	}

	sql += " );"

	return
}

func  NewRelation(t interface{}) (r *Relation){
	r=new(Relation)
	r.Table(fmt.Sprintf("%T",t))
	return
}
<commit_msg>using reflect to get table<commit_after>package gouda

import (
        "container/vector"
//	"fmt"
	"reflect"
	"strings"
	)

type Relation struct {
	conditions vector.StringVector
	table string
}

func (r *Relation) Where(s string) *Relation {

	r.conditions.Push(s)

	return r

}

func (r *Relation) Table(t string) *Relation{
	r.table=t
return r
}

func (r *Relation) String() string {

	s := " Conditions : ("

	for _, ss := range r.conditions {
		s += ss
		if ss != r.conditions.Last() {
			s += ", "
		}
	}
	s += ")"

	return "Une relation" + s
}

func (r *Relation) Sql() (sql string) {
	sql = "Select * from "+r.table+" where ( "
	for _, ss := range r.conditions {
		sql += ss
		if ss != r.conditions.Last() {
			sql += " ) AND ( "
		}
	}

	sql += " );"

	return
}

func  NewRelation(t interface{}) (r *Relation){
	r=new(Relation)
	tab:=strings.Split(reflect.Typeof(t).String(),".",0)
	tablename:=strings.ToLower(tab[len(tab)-1])
	r.Table(tablename)
	return
}
<|endoftext|>


<commit_before>// 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/opennota/morph"

	"github.com/PuerkitoBio/goquery"
	"github.com/microcosm-cc/bluemonday"
)

const (
	synonymsBaseURL = "https://dic.academic.ru/dic.nsf/dic_synonims/"
	synSeekBaseURL  = "https://dic.academic.ru/seek4term.php?json=true&limit=20&did=dic_synonims&q="
)

var (
	rSynonymsURL = regexp.MustCompile(`^https?://dic\.academic\.ru/dic\.nsf/dic_synonims/(\d+)/`)

	yoReplacer = strings.NewReplacer("ё", "е")

	useMorph = morph.Init() == nil
)

type seekResult struct {
	ID    int    `json:"id"`
	Value string `json:"value"`
}

func fitKey(key string) string {
	if len(key) <= 127 {
		return key
	}
	cksum := crc32.ChecksumIEEE([]byte(key))
	key = key[:127-10]
	r, size := utf8.DecodeLastRuneInString(key)
	if r == utf8.RuneError {
		key = key[:len(key)-size]
	}
	return key + fmt.Sprintf("..%08x", cksum)
}

func seekSynonym(query string) ([]seekResult, error) {
	key := "a:s:0:" + query
	key = fitKey(key)
	data, _ := cache.Get(key)
	if data == nil {
		url := synSeekBaseURL + url.QueryEscape(query)
		resp, err := httpClient.Get(url)
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			return nil, httpStatus{resp.StatusCode, url}
		}

		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}

		cache.Put(key, data)
	}

	rd := bytes.NewReader(data)
	var results []seekResult
	if err := json.NewDecoder(rd).Decode(&struct {
		Results *[]seekResult
	}{
		&results,
	}); err != nil {
		return nil, err
	}

	return results, nil
}

func (a *App) Academic(w http.ResponseWriter, r *http.Request) {
	query := strings.ToLower(r.FormValue("query"))
	if useMorph && r.FormValue("exact") == "" {
		_, norms, _ := morph.Parse(query)
		if len(norms) > 0 {
			norms = append(norms, yoReplacer.Replace(query))
			sort.Strings(norms)
			words := norms[:0]
			for i, w := range norms {
				w = yoReplacer.Replace(w)
				if i == 0 || words[len(words)-1] != w {
					words = append(words, w)
				}
			}

			if len(words) == 1 {
				query = yoReplacer.Replace(words[0])
			} else {
				w.Header().Add("Content-Type", "encoding/json")
				pre, post := `<a data-id="" morph="1">`, `</a>`
				json.NewEncoder(w).Encode(struct {
					ID      int          `json:"id"`
					Value   string       `json:"value"`
					HTML    string       `json:"html"`
					SeeAlso []seekResult `json:"see_also"`
				}{
					-1,
					query,
					`<div>Select one of: ` + pre + strings.Join(words, post+", "+pre) + post + "
",
					[]seekResult{},
				})
				return
			}
		}
	}

	query = yoReplacer.Replace(query)
	results, err := seekSynonym(query)
	key := "a:s:1:" + query
	key = fitKey(key)
	data, _ := cache.Get(key)

	if err != nil {
		if data == nil {
			internalError(w, err)
			return
		}
		logError(err)
	}
	if len(results) == 0 {
		if data == nil {
			http.NotFound(w, r)
			return
		}
		results = []seekResult{{0, query}}
	}

	if data == nil {
		url := synonymsBaseURL + fmt.Sprint(results[0].ID)
		resp, err := httpClient.Get(url)
		if err != nil {
			internalError(w, err)
			return
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			internalError(w, httpStatus{resp.StatusCode, url})
			return
		}

		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			internalError(w, err)
			return
		}

		cache.Put(key, data)
	}

	d, err := goquery.NewDocumentFromReader(bytes.NewReader(data))
	if err != nil {
		internalError(w, err)
		return
	}

	policy := bluemonday.NewPolicy()
	policy.AllowElements("div", "em", "span", "strong", "u")
	policy.AllowAttrs("data-id").OnElements("a")
	policy.AllowAttrs("class").OnElements("div", "span")

	var entries []string
	d.Find(`div[itemtype$="/term-def.xml"]`).Each(func(_ int, sel *goquery.Selection) {
		sel.Find("[href]").Each(func(_ int, sel *goquery.Selection) {
			href, _ := sel.Attr("href")
			m := rSynonymsURL.FindStringSubmatch(href)
			if m != nil {
				sel.SetAttr("data-id", m[1])
			}
		})
		sel.Find("[style]").Each(func(_ int, sel *goquery.Selection) {
			style, _ := sel.Attr("style")
			switch style {
			case "color: darkgray;", "color: tomato;":
				sel.SetAttr("class", "text-muted")
			case "margin-left:5px", "color: saddlebrown;":
			}
		})
		html, _ := sel.Find("dd").First().Html()
		entries = append(entries, policy.Sanitize(html))
	})

	w.Header().Add("Content-Type", "encoding/json")
	json.NewEncoder(w).Encode(struct {
		ID      int          `json:"id"`
		Value   string       `json:"value"`
		HTML    string       `json:"html"`
		SeeAlso []seekResult `json:"see_also"`
	}{
		results[0].ID,
		results[0].Value,
		strings.Join(entries, ""),
		results[1:],
	})
}
<commit_msg>Reduce key size further for use with ecryptfs<commit_after>// 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 main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"hash/crc32"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/opennota/morph"

	"github.com/PuerkitoBio/goquery"
	"github.com/microcosm-cc/bluemonday"
)

const (
	synonymsBaseURL = "https://dic.academic.ru/dic.nsf/dic_synonims/"
	synSeekBaseURL  = "https://dic.academic.ru/seek4term.php?json=true&limit=20&did=dic_synonims&q="
)

var (
	rSynonymsURL = regexp.MustCompile(`^https?://dic\.academic\.ru/dic\.nsf/dic_synonims/(\d+)/`)

	yoReplacer = strings.NewReplacer("ё", "е")

	useMorph = morph.Init() == nil
)

type seekResult struct {
	ID    int    `json:"id"`
	Value string `json:"value"`
}

func fitKey(key string) string {
	if len(key) <= 71 {
		return key
	}
	cksum := crc32.ChecksumIEEE([]byte(key))
	key = key[:71-10]
	r, size := utf8.DecodeLastRuneInString(key)
	if r == utf8.RuneError {
		key = key[:len(key)-size]
	}
	return key + fmt.Sprintf("..%08x", cksum)
}

func seekSynonym(query string) ([]seekResult, error) {
	key := "a:s:0:" + query
	key = fitKey(key)
	data, _ := cache.Get(key)
	if data == nil {
		url := synSeekBaseURL + url.QueryEscape(query)
		resp, err := httpClient.Get(url)
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			return nil, httpStatus{resp.StatusCode, url}
		}

		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}

		cache.Put(key, data)
	}

	rd := bytes.NewReader(data)
	var results []seekResult
	if err := json.NewDecoder(rd).Decode(&struct {
		Results *[]seekResult
	}{
		&results,
	}); err != nil {
		return nil, err
	}

	return results, nil
}

func (a *App) Academic(w http.ResponseWriter, r *http.Request) {
	query := strings.ToLower(r.FormValue("query"))
	if useMorph && r.FormValue("exact") == "" {
		_, norms, _ := morph.Parse(query)
		if len(norms) > 0 {
			norms = append(norms, yoReplacer.Replace(query))
			sort.Strings(norms)
			words := norms[:0]
			for i, w := range norms {
				w = yoReplacer.Replace(w)
				if i == 0 || words[len(words)-1] != w {
					words = append(words, w)
				}
			}

			if len(words) == 1 {
				query = yoReplacer.Replace(words[0])
			} else {
				w.Header().Add("Content-Type", "encoding/json")
				pre, post := `<a data-id="" morph="1">`, `</a>`
				json.NewEncoder(w).Encode(struct {
					ID      int          `json:"id"`
					Value   string       `json:"value"`
					HTML    string       `json:"html"`
					SeeAlso []seekResult `json:"see_also"`
				}{
					-1,
					query,
					`<div>Select one of: ` + pre + strings.Join(words, post+", "+pre) + post + "
",
					[]seekResult{},
				})
				return
			}
		}
	}

	query = yoReplacer.Replace(query)
	results, err := seekSynonym(query)
	key := "a:s:1:" + query
	key = fitKey(key)
	data, _ := cache.Get(key)

	if err != nil {
		if data == nil {
			internalError(w, err)
			return
		}
		logError(err)
	}
	if len(results) == 0 {
		if data == nil {
			http.NotFound(w, r)
			return
		}
		results = []seekResult{{0, query}}
	}

	if data == nil {
		url := synonymsBaseURL + fmt.Sprint(results[0].ID)
		resp, err := httpClient.Get(url)
		if err != nil {
			internalError(w, err)
			return
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			internalError(w, httpStatus{resp.StatusCode, url})
			return
		}

		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			internalError(w, err)
			return
		}

		cache.Put(key, data)
	}

	d, err := goquery.NewDocumentFromReader(bytes.NewReader(data))
	if err != nil {
		internalError(w, err)
		return
	}

	policy := bluemonday.NewPolicy()
	policy.AllowElements("div", "em", "span", "strong", "u")
	policy.AllowAttrs("data-id").OnElements("a")
	policy.AllowAttrs("class").OnElements("div", "span")

	var entries []string
	d.Find(`div[itemtype$="/term-def.xml"]`).Each(func(_ int, sel *goquery.Selection) {
		sel.Find("[href]").Each(func(_ int, sel *goquery.Selection) {
			href, _ := sel.Attr("href")
			m := rSynonymsURL.FindStringSubmatch(href)
			if m != nil {
				sel.SetAttr("data-id", m[1])
			}
		})
		sel.Find("[style]").Each(func(_ int, sel *goquery.Selection) {
			style, _ := sel.Attr("style")
			switch style {
			case "color: darkgray;", "color: tomato;":
				sel.SetAttr("class", "text-muted")
			case "margin-left:5px", "color: saddlebrown;":
			}
		})
		html, _ := sel.Find("dd").First().Html()
		entries = append(entries, policy.Sanitize(html))
	})

	w.Header().Add("Content-Type", "encoding/json")
	json.NewEncoder(w).Encode(struct {
		ID      int          `json:"id"`
		Value   string       `json:"value"`
		HTML    string       `json:"html"`
		SeeAlso []seekResult `json:"see_also"`
	}{
		results[0].ID,
		results[0].Value,
		strings.Join(entries, ""),
		results[1:],
	})
}
<|endoftext|>


<commit_before>package main

import (
  "os"
  "fmt"
  "strconv"
  "net/http"
  "path/filepath"
  "github.com/jawher/mow.cli"
  "github.com/skratchdot/open-golang/open"
)

func NoCache(h http.Handler) http.Handler {
  return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Cache-Control", "private, max-age=0, no-cache")
    r.Header.Set("Cache-Control", "no-cache")
    r.Header.Del("If-Modified-Since")
    r.Header.Del("If-None-Match")
    h.ServeHTTP(w, r)
  })
}

func main() {
  app := cli.App("sfs", "Static file server - https://github.com/schmich/sfs")
  app.Version("v version", "sfs " + Version)

  port := app.IntOpt("p port", 8080, "Listening port")
  iface := app.StringOpt("i iface interface", "127.0.0.1", "Listening interface")
  allIface := app.BoolOpt("g global", false, "Listen on all interfaces (overrides -i)")
  dir := app.StringOpt("d dir directory", ".", "Directory to serve")
  noBrowser := app.BoolOpt("B no-browser", false, "Do not launch browser")
  cache := app.BoolOpt("c cache", false, "Allow cached responses")

  app.Action = func () {
    var err error

    *dir, err = filepath.Abs(*dir)
    if err != nil {
      panic(err)
    }

    if *allIface {
      *iface = "0.0.0.0"
    }

    portPart := ":" + strconv.Itoa(*port)
    listen := *iface + portPart

    server := http.FileServer(http.Dir(*dir))
    if !*cache {
      server = NoCache(server)
    }

    fmt.Printf(">> Serving %s\n", *dir)
    fmt.Printf(">> Listening on %s\n", listen)
    fmt.Println(">> Ctrl+C to stop")

    if !*noBrowser {
      url := "http://127.0.0.1" + portPart
      open.Start(url)
    }

    panic(http.ListenAndServe(listen, server))
  }

  app.Run(os.Args)
}
<commit_msg>Fix #4: Add option to log requests.<commit_after>package main

import (
  "os"
  "fmt"
  "time"
  "strconv"
  "strings"
  "regexp"
  "net/http"
  "path/filepath"
  "github.com/jawher/mow.cli"
  "github.com/skratchdot/open-golang/open"
)

type TraceResponseWriter struct {
  impl http.ResponseWriter
  bytesWritten int
  statusCode int
}

func NewTraceResponseWriter(writer http.ResponseWriter) *TraceResponseWriter {
  return &TraceResponseWriter{
    impl: writer,
    bytesWritten: 0,
    statusCode: 200,
  }
}

func (writer *TraceResponseWriter) Header() http.Header {
  return writer.impl.Header()
}

func (writer *TraceResponseWriter) Write(bytes []byte) (int, error) {
  writer.bytesWritten += len(bytes)
  return writer.impl.Write(bytes)
}

func (writer *TraceResponseWriter) WriteHeader(statusCode int) {
  writer.statusCode = statusCode
  writer.impl.WriteHeader(statusCode)
}

func formatSize(bytes int) string {
  if bytes < 1000 {
    return strconv.Itoa(bytes)
  } else if bytes < 1000000 {
    return fmt.Sprintf("%.2fK", float32(bytes) / 1000)
  } else {
    return fmt.Sprintf("%.2fM", float32(bytes) / 1000000)
  }
}

func TraceServer(h http.Handler, log string) http.Handler {
  formatter, _ := regexp.Compile("%.")

  return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
    traceWriter := NewTraceResponseWriter(w)
    h.ServeHTTP(traceWriter, r)

    ip := r.RemoteAddr
    if i := strings.Index(ip, ":"); i >= 0 {
      ip = ip[:i]
    }

    line := string(formatter.ReplaceAllFunc([]byte(log), func(match []byte) []byte {
      switch string(match[1]) {
      case "i":
        return []byte(ip)
      case "t":
        return []byte(time.Now().Format("2/Jan/2006:15:04:05 -0700"))
      case "m":
        return []byte(r.Method)
      case "u":
        return []byte(r.URL.String())
      case "s":
        return []byte(strconv.Itoa(traceWriter.statusCode))
      case "b":
        return []byte(formatSize(traceWriter.bytesWritten))
      case "a":
        return []byte(r.Header.Get("User-Agent"))
      case "%":
        return []byte("%")
      default:
        return match
      }
    }))

    fmt.Println(line)
  })
}

func NoCacheServer(h http.Handler) http.Handler {
  return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Cache-Control", "private, max-age=0, no-cache")
    r.Header.Set("Cache-Control", "no-cache")
    r.Header.Del("If-Modified-Since")
    r.Header.Del("If-None-Match")
    h.ServeHTTP(w, r)
  })
}

func main() {
  app := cli.App("sfs", "Static file server - https://github.com/schmich/sfs")
  app.Version("v version", "sfs " + Version)

  port := app.IntOpt("p port", 8080, "Listening port")
  iface := app.StringOpt("i iface interface", "127.0.0.1", "Listening interface")
  allIface := app.BoolOpt("g global", false, "Listen on all interfaces (overrides -i)")
  dir := app.StringOpt("d dir directory", ".", "Directory to serve")
  noBrowser := app.BoolOpt("B no-browser", false, "Do not launch browser")
  trace := app.StringOpt("t trace", "", "Trace requests")
  cache := app.BoolOpt("c cache", false, "Allow cached responses")

  app.Action = func () {
    var err error

    *dir, err = filepath.Abs(*dir)
    if err != nil {
      panic(err)
    }

    if *allIface {
      *iface = "0.0.0.0"
    }

    portPart := ":" + strconv.Itoa(*port)
    listen := *iface + portPart

    server := http.FileServer(http.Dir(*dir))
    if !*cache {
      server = NoCacheServer(server)
    }

    if strings.TrimSpace(*trace) != "" {
      server = TraceServer(server, *trace)
    }

    fmt.Printf(">> Serving %s\n", *dir)
    fmt.Printf(">> Listening on %s\n", listen)
    fmt.Println(">> Ctrl+C to stop")

    if !*noBrowser {
      url := "http://127.0.0.1" + portPart
      open.Start(url)
    }

    panic(http.ListenAndServe(listen, server))
  }

  app.Run(os.Args)
}
<|endoftext|>


<commit_before>package goSSEClient

import (
	"bufio"
	"bytes"
	"fmt"
	"net/http"
	"os"

	"github.com/visionmedia/go-debug"
)

var dbg = debug.Debug("goSSEClient")

type SSEvent struct {
	Id   string
	Data []byte
}

func OpenSSEUrl(url string) (events chan SSEvent, err error) {
	tr := &http.Transport{
		DisableCompression: true,
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("Error: resp.StatusCode == %d\n", resp.StatusCode)
	}

	if resp.Header.Get("Content-Type") != "text/event-stream" {
		return nil, fmt.Errorf("Error: invalid Content-Type == %s\n", resp.Header.Get("Content-Type"))
	}

	dbg("Response: %+v", resp)

	events = make(chan SSEvent)
	var buf bytes.Buffer

	go func() {
		ev := SSEvent{}

		buffed := bufio.NewReader(resp.Body)
		for {
			line, err := buffed.ReadBytes('\n')
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error during resp.Body read:%s\n", err)
				close(events)
			}
			// dbg("NewLine: %s", string(line))

			switch {

			// start of event
			case bytes.HasPrefix(line, []byte("id:")):
				ev.Id = string(line[3:])
				dbg("eventID:", ev.Id)

			// event data
			case bytes.HasPrefix(line, []byte("data:")):
				buf.Write(line[6:])
				dbg("data: %s", string(line[5:]))

			// end of event
			case len(line) == 1:
				ev.Data = buf.Bytes()
				buf.Reset()
				events <- ev
				dbg("Event send.")
				ev = SSEvent{}

			default:
				fmt.Fprintf(os.Stderr, "Error during EventReadLoop - Default triggerd! len:%d\n%s", len(line), line)
				close(events)

			}
		}
	}()

	return events, nil
}
<commit_msg>using bufio.Scanner<commit_after>package goSSEClient

import (
	"bufio"
	"bytes"
	"fmt"
	"net/http"
	"os"

	"github.com/visionmedia/go-debug"
)

var dbg = debug.Debug("goSSEClient")

type SSEvent struct {
	Id   string
	Data []byte
}

func OpenSSEUrl(url string) (<-chan SSEvent, error) {
	tr := &http.Transport{
		DisableCompression: true,
	}
	client := &http.Client{Transport: tr}
	resp, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	dbg("OpenURL resp: %+v", resp)

	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("Error: resp.StatusCode == %d\n", resp.StatusCode)
	}

	if resp.Header.Get("Content-Type") != "text/event-stream" {
		return nil, fmt.Errorf("Error: invalid Content-Type == %s\n", resp.Header.Get("Content-Type"))
	}

	events := make(chan SSEvent)

	var buf bytes.Buffer

	go func() {
		ev := SSEvent{}
		scanner := bufio.NewScanner(resp.Body)

		for scanner.Scan() {
			line := scanner.Bytes()
			dbg("newLine: %s", string(line))

			switch {

			// start of event
			case bytes.HasPrefix(line, []byte("id:")):
				ev.Id = string(line[3:])
				dbg("id: %s", ev.Id)

			// event data
			case bytes.HasPrefix(line, []byte("data:")):
				buf.Write(line[6:])
				dbg("data: %s", string(line[5:]))

			// end of event
			case len(line) == 0:
				ev.Data = buf.Bytes()
				buf.Reset()
				events <- ev
				dbg("Event send.")
				ev = SSEvent{}

			default:
				fmt.Fprintf(os.Stderr, "Error during EventReadLoop - Default triggerd! len:%d\n%s", len(line), line)
				close(events)

			}
		}

		if err = scanner.Err(); err != nil {
			fmt.Fprintf(os.Stderr, "Error during resp.Body read:%s\n", err)
			close(events)

		}
	}()

	return events, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io/ioutil"
	"net"
	"os"
	"os/user"
	"path/filepath"

	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/go.crypto/ssh/agent"
)

// sshClientConfig stores the configuration
// and the ssh agent to forward authentication requests
type sshClientConfig struct {
	// agent is the connection to the ssh agent
	agent agent.Agent

	*ssh.ClientConfig
}

// newSshClientConfig initializes the ssh configuration.
// It connects with the ssh agent when agent forwarding is enabled.
func newSshClientConfig(userName, identity string, agentForwarding bool) (*sshClientConfig, error) {
	if agentForwarding {
		return newSshAgentConfig(userName)
	}

	return newSshDefaultConfig(userName, identity)
}

func newSshAgentConfig(userName string) (*sshClientConfig, error) {
	agent, err := newAgent()
	if err != nil {
		return nil, err
	}

	config, err := sshAgentConfig(userName, agent)
	if err != nil {
		return nil, err
	}

	return &sshClientConfig{
		agent:        agent,
		ClientConfig: config,
	}, nil
}

func newSshDefaultConfig(userName, identity string) (*sshClientConfig, error) {
	config, err := sshDefaultConfig(userName, identity)
	if err != nil {
		return nil, err
	}

	return &sshClientConfig{ClientConfig: config}, nil
}

// NewSession creates a new ssh session with the host.
// It forwards authentication to the agent when it's configured.
func (s *sshClientConfig) NewSession(host string) (*ssh.Session, error) {
	conn, err := ssh.Dial("tcp", host, s.ClientConfig)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	if s.agent != nil {
		if err := agent.ForwardToAgent(conn, s.agent); err != nil {
			return nil, err
		}
	}

	session, err := conn.NewSession()
	if s.agent != nil {
		err = agent.RequestAgentForwarding(session)
	}

	return session, err
}

// newAgent connects with the SSH agent in the to forward authentication requests.
func newAgent() (agent.Agent, error) {
	sock := os.Getenv("SSH_AUTH_SOCK")
	if sock == "" {
		return nil, errors.New("Unable to connect to the ssh agent. Please, check that SSH_AUTH_SOCK is set and the ssh agent is running")
	}

	conn, err := net.Dial("unix", sock)
	if err != nil {
		return nil, err
	}

	return agent.NewClient(conn), nil
}

func sshAgentConfig(userName string, a agent.Agent) (*ssh.ClientConfig, error) {
	signers, err := a.Signers()
	if err != nil {
		return nil, err
	}

	return &ssh.ClientConfig{
		User: userName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signers...),
		},
	}, nil
}

// sshDefaultConfig returns the SSH client config for the connection
func sshDefaultConfig(userName, identity string) (*ssh.ClientConfig, error) {
	contents, err := loadDefaultIdentity(userName, identity)
	if err != nil {
		return nil, err
	}
	signer, err := ssh.ParsePrivateKey(contents)
	if err != nil {
		return nil, err
	}

	return &ssh.ClientConfig{
		User: userName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
	}, nil
}

// loadDefaultIdentity returns the private key file's contents
func loadDefaultIdentity(userName, identity string) ([]byte, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}

	return ioutil.ReadFile(filepath.Join(u.HomeDir, ".ssh", identity))
}
<commit_msg>Make sure the ssh connection is properly closed after the session.<commit_after>package main

import (
	"errors"
	"io/ioutil"
	"net"
	"os"
	"os/user"
	"path/filepath"

	"code.google.com/p/go.crypto/ssh"
	"code.google.com/p/go.crypto/ssh/agent"
)

// sshSession stores the open session and connection to execute a command.
type sshSession struct {
	// conn is the ssh client that started the session.
	conn *ssh.Client

	*ssh.Session
}

// Close closses the open ssh session and connection.
func (s *sshSession) Close() {
	s.Session.Close()
	s.conn.Close()
}

// sshClientConfig stores the configuration
// and the ssh agent to forward authentication requests
type sshClientConfig struct {
	// agent is the connection to the ssh agent
	agent agent.Agent

	*ssh.ClientConfig
}

// newSshClientConfig initializes the ssh configuration.
// It connects with the ssh agent when agent forwarding is enabled.
func newSshClientConfig(userName, identity string, agentForwarding bool) (*sshClientConfig, error) {
	if agentForwarding {
		return newSshAgentConfig(userName)
	}

	return newSshDefaultConfig(userName, identity)
}

// newSshAgentConfig initializes the configuration to talk with an ssh agent.
func newSshAgentConfig(userName string) (*sshClientConfig, error) {
	agent, err := newAgent()
	if err != nil {
		return nil, err
	}

	config, err := sshAgentConfig(userName, agent)
	if err != nil {
		return nil, err
	}

	return &sshClientConfig{
		agent:        agent,
		ClientConfig: config,
	}, nil
}

// newSshDefaultConfig initializes the configuration to use an ideitity file.
func newSshDefaultConfig(userName, identity string) (*sshClientConfig, error) {
	config, err := sshDefaultConfig(userName, identity)
	if err != nil {
		return nil, err
	}

	return &sshClientConfig{ClientConfig: config}, nil
}

// NewSession creates a new ssh session with the host.
// It forwards authentication to the agent when it's configured.
func (s *sshClientConfig) NewSession(host string) (*sshSession, error) {
	conn, err := ssh.Dial("tcp", host, s.ClientConfig)
	if err != nil {
		return nil, err
	}

	if s.agent != nil {
		if err := agent.ForwardToAgent(conn, s.agent); err != nil {
			return nil, err
		}
	}

	session, err := conn.NewSession()
	if s.agent != nil {
		err = agent.RequestAgentForwarding(session)
	}

	return &sshSession{
		conn:    conn,
		Session: session,
	}, err
}

// newAgent connects with the SSH agent in the to forward authentication requests.
func newAgent() (agent.Agent, error) {
	sock := os.Getenv("SSH_AUTH_SOCK")
	if sock == "" {
		return nil, errors.New("Unable to connect to the ssh agent. Please, check that SSH_AUTH_SOCK is set and the ssh agent is running")
	}

	conn, err := net.Dial("unix", sock)
	if err != nil {
		return nil, err
	}

	return agent.NewClient(conn), nil
}

// sshAgentConfig creates a new configuration for the ssh client
// with the signatures from the ssh agent.
func sshAgentConfig(userName string, a agent.Agent) (*ssh.ClientConfig, error) {
	signers, err := a.Signers()
	if err != nil {
		return nil, err
	}

	return &ssh.ClientConfig{
		User: userName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signers...),
		},
	}, nil
}

// sshDefaultConfig returns the SSH client config for the connection
func sshDefaultConfig(userName, identity string) (*ssh.ClientConfig, error) {
	contents, err := loadDefaultIdentity(userName, identity)
	if err != nil {
		return nil, err
	}
	signer, err := ssh.ParsePrivateKey(contents)
	if err != nil {
		return nil, err
	}

	return &ssh.ClientConfig{
		User: userName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
	}, nil
}

// loadDefaultIdentity returns the private key file's contents
func loadDefaultIdentity(userName, identity string) ([]byte, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}

	return ioutil.ReadFile(filepath.Join(u.HomeDir, ".ssh", identity))
}
<|endoftext|>