<commit_before>package meritop

/*
The dummy task is designed for regresion test of meritop framework.
This works with tree topology.
The main idea behind the regression test is following:
There will be two kinds of dummyTasks: master and slaves. We will have one master
sits at the top with taskID = 0, and then rest 6 (2^n - 2) tasks forms a tree under
the master. There will be 10 epochs, from 1 to 10, at each epoch, we send out a
vector with all values equal to epochID, and each slave is supposedly return a vector
with all values equals epochID*taskID, the values are reduced back to master, and
master will print out the epochID and aggregated vector. After all 10 epoch, it kills
job.
*/

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"testing"

	"github.com/coreos/go-etcd/etcd"
)

const (
	numOfIterations uint64 = uint64(10)
)

// dummyData is used to carry parameter and gradient;
type dummyData struct {
	value int32
	data  [10]int32
}

// dummyMaster is prototype of parameter server, for now it does not
// carry out optimization yet. But it should be easy to add support when
// this full tests out.
// Note: in theory, since there should be no parent of this, so we should
// add error checing in the right places. We will skip these test for now.
type dummyMaster struct {
	dataChan      chan int32
	framework     Framework
	epoch, taskID uint64
	logger        *log.Logger

	param, gradient *dummyData
	fromChildren    map[uint64]*dummyData
}

// This is useful to bring the task up to speed from scratch or if it recovers.
func (t *dummyMaster) Init(taskID uint64, framework Framework, config Config) {
	t.taskID = taskID
	t.framework = framework
	t.logger = log.New(os.Stdout, "dummyMaster:", log.Ldate|log.Ltime|log.Lshortfile)

	// Jump start the taskgraph
	t.framework.IncEpoch()
}

// Task need to finish up for exit, last chance to save work?
func (t *dummyMaster) Exit() {}

// Ideally, we should also have the following:
func (t *dummyMaster) ParentMetaReady(parentID uint64, meta string) {}
func (t *dummyMaster) ChildMetaReady(childID uint64, meta string) {
	// Get data from child. When all the data is back, starts the next epoch.
	t.framework.DataRequest(childID, meta)
}

// This give the task an opportunity to cleanup and regroup.
func (t *dummyMaster) SetEpoch(epoch uint64) {
	t.epoch = epoch
	for i := 0; i < 10; i++ {
		t.param.data[i] = int32(t.epoch)
	}

	// Make sure we have a clean slate.
	t.fromChildren = make(map[uint64]*dummyData)
	t.framework.FlagChildMetaReady("ParamReady")
}

// These are payload rpc for application purpose.
func (t *dummyMaster) ServeAsParent(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.param)
	if err != nil {
		t.logger.Printf("Master can't encode parameter: %v, error: %v\n", t.param, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummyMaster) ServeAsChild(fromID uint64, req string) []byte {
	return nil
}

func (t *dummyMaster) ParentDataReady(parentID uint64, req string, resp []byte) {}
func (t *dummyMaster) ChildDataReady(childID uint64, req string, resp []byte) {

	d := new(dummyData)
	json.Unmarshal(resp, d)
	t.fromChildren[childID] = d

	// This is a weak form of checking. We can also check the task ids.
	// But this really means that we get all the events from children, we
	// should go into the next epoch now.
	if len(t.fromChildren) == len(t.framework.GetTopology().GetChildren(t.epoch)) {
		for _, g := range t.fromChildren {
			for i := 0; i < 10; i++ {
				t.gradient.data[i] += g.data[i]
			}
		}

		// TODO(xiaoyunwu) We need to do some test here.

		// In real ML, we modify the gradient first. But here it is noop.
		// Notice that we only
		if t.epoch == numOfIterations {
			t.framework.Exit()
		} else {
			t.framework.IncEpoch()
		}
	}
}

// dummySlave is an prototype for data shard in machine learning applications.
// It mainly does to things, pass on parameters to its children, and collect
// gradient back then add them together before make it available to its parent.
type dummySlave struct {
	framework     Framework
	epoch, taskID uint64
	logger        *log.Logger

	param, gradient *dummyData
	fromChildren    map[uint64]*dummyData
}

// This is useful to bring the task up to speed from scratch or if it recovers.
func (t *dummySlave) Init(taskID uint64, framework Framework, config Config) {
	t.taskID = taskID
	t.framework = framework
	t.logger = log.New(os.Stdout, "dummySlave:", log.Ldate|log.Ltime|log.Lshortfile)
}

// Task need to finish up for exit, last chance to save work?
func (t *dummySlave) Exit() {}

// Ideally, we should also have the following:
func (t *dummySlave) ParentMetaReady(parentID uint64, meta string) {
	t.framework.DataRequest(parentID, meta)
}

func (t *dummySlave) ChildMetaReady(childID uint64, meta string) {
	t.framework.DataRequest(childID, meta)
}

// This give the task an opportunity to cleanup and regroup.
func (t *dummySlave) SetEpoch(epoch uint64) {
	t.epoch = epoch

	// Make sure we have a clean slate.
	t.fromChildren = make(map[uint64]*dummyData)
}

// These are payload rpc for application purpose.
func (t *dummySlave) ServeAsParent(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.param)
	if err != nil {
		t.logger.Printf("Slave can't encode parameter: %v, error: %v\n", t.param, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummySlave) ServeAsChild(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.gradient)
	if err != nil {
		t.logger.Printf("Slave can't encode gradient: %v, error: %v\n", t.gradient, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummySlave) ParentDataReady(parentID uint64, req string, resp []byte) {
	t.param = new(dummyData)
	json.Unmarshal(resp, t.param)

	// We need to carry out local compuation.
	for i := 0; i < 10; i++ {
		t.gradient.data[i] = int32(t.framework.GetTaskID())
	}

	// If this task has children, flag meta so that children can start pull
	// parameter.
	children := t.framework.GetTopology().GetChildren(t.epoch)
	if len(children) != 0 {
		t.framework.FlagChildMetaReady("ParamReady")
	} else {
		// On leaf node, we can immediately return by and flag parent
		// that this node is ready.
		t.framework.FlagParentMetaReady("GradientReady")
	}
}

func (t *dummySlave) ChildDataReady(childID uint64, req string, resp []byte) {
	t.fromChildren[childID] = new(dummyData)
	json.Unmarshal(resp, t.fromChildren[childID])

	// This is a weak form of checking. We can also check the task ids.
	// But this really means that we get all the events from children, we
	// should go into the next epoch now.
	if len(t.fromChildren) == len(t.framework.GetTopology().GetChildren(t.epoch)) {
		// In real ML, we add the gradient first.
		for _, g := range t.fromChildren {
			for i := 0; i < 10; i++ {
				t.gradient.data[i] += g.data[i]
			}
		}

		t.framework.FlagParentMetaReady("GradientReady")
	}
}

type simpleTaskBuilder struct{}

var gDataChan = make(chan int32, 1)

// Leave it at global level so that we use this to terminate and test.
// cDataChan := make(chan *tDataBundle, 1)

// This method is called once by framework implementation to get the
// right task implementation for the node/task. It requires the taskID
// for current node, and also a global array of tasks.
func (tc simpleTaskBuilder) GetTask(taskID uint64) Task {
	if taskID == 0 {
		return &dummyMaster{dataChan: gDataChan}
	} else {
		return &dummySlave{}
	}
}

// This is used to show how to drive the network.
func drive(jobName string, etcds []string, config Config, ntask uint64) {
	var bootstrap Bootstrap = NewBootStrap(jobName, etcds, config)
	var taskBuilder simpleTaskBuilder
	bootstrap.SetTaskBuilder(taskBuilder)
	bootstrap.SetTopology(NewTreeTopology(2, ntask))
	bootstrap.Start()
}

func tTestFramework(t *testing.T) {

	m := mustNewMember(t, "framework_regression_test")
	m.Launch()
	defer m.Terminate(t)
	url := fmt.Sprintf("http://%s", m.ClientListeners[0].Addr().String())

	job := "framework_regression_test"
	etcds := []string{url}
	config := map[string]string{}
	numOfTasks := uint64(15)

	controller := &controller{
		name:       job,
		etcdclient: etcd.NewClient([]string{url}),
		numOfTasks: numOfTasks,
	}

	controller.initEtcdLayout()
	go controller.destroyEtcdLayout()

	// We need to set etcd so that nodes know what to do.
	for i := uint64(0); i < numOfTasks; i++ {
		go drive(job, etcds, config, numOfTasks)
	}

	// wait for last number to comeback.
	data := <-gDataChan
	fmt.Println("Exiting with data = %d", data)
}
<commit_msg>respond to Hongchao's comments<commit_after>package meritop

/*
The dummy task is designed for regresion test of meritop framework.
This works with tree topology.
The main idea behind the regression test is following:
There will be two kinds of dummyTasks: master and slaves. We will have one master
sits at the top with taskID = 0, and then rest 6 (2^n - 2) tasks forms a tree under
the master. There will be 10 epochs, from 1 to 10, at each epoch, we send out a
vector with all values equal to epochID, and each slave is supposedly return a vector
with all values equals epochID*taskID, the values are reduced back to master, and
master will print out the epochID and aggregated vector. After all 10 epoch, it kills
job.
*/

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"testing"

	"github.com/coreos/go-etcd/etcd"
)

const (
	numOfIterations uint64 = uint64(10)
)

// dummyData is used to carry parameter and gradient;
type dummyData struct {
	value int32
	data  [10]int32
}

// dummyMaster is prototype of parameter server, for now it does not
// carry out optimization yet. But it should be easy to add support when
// this full tests out.
// Note: in theory, since there should be no parent of this, so we should
// add error checing in the right places. We will skip these test for now.
type dummyMaster struct {
	dataChan      chan int32
	framework     Framework
	epoch, taskID uint64
	logger        *log.Logger

	param, gradient *dummyData
	fromChildren    map[uint64]*dummyData
}

// This is useful to bring the task up to speed from scratch or if it recovers.
func (t *dummyMaster) Init(taskID uint64, framework Framework, config Config) {
	t.taskID = taskID
	t.framework = framework
	t.logger = log.New(os.Stdout, "dummyMaster:", log.Ldate|log.Ltime|log.Lshortfile)

	// Jump start the taskgraph
	t.framework.IncEpoch()
}

// Task need to finish up for exit, last chance to save work?
func (t *dummyMaster) Exit() {}

// Ideally, we should also have the following:
func (t *dummyMaster) ParentMetaReady(parentID uint64, meta string) {}
func (t *dummyMaster) ChildMetaReady(childID uint64, meta string) {
	// Get data from child. When all the data is back, starts the next epoch.
	t.framework.DataRequest(childID, meta)
}

// This give the task an opportunity to cleanup and regroup.
func (t *dummyMaster) SetEpoch(epoch uint64) {
	t.epoch = epoch
	for i := 0; i < 10; i++ {
		t.param.data[i] = int32(t.epoch)
	}

	// Make sure we have a clean slate.
	t.fromChildren = make(map[uint64]*dummyData)
	t.framework.FlagChildMetaReady("ParamReady")
}

// These are payload rpc for application purpose.
func (t *dummyMaster) ServeAsParent(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.param)
	if err != nil {
		t.logger.Printf("Master can't encode parameter: %v, error: %v\n", t.param, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummyMaster) ServeAsChild(fromID uint64, req string) []byte {
	return nil
}

func (t *dummyMaster) ParentDataReady(parentID uint64, req string, resp []byte) {}
func (t *dummyMaster) ChildDataReady(childID uint64, req string, resp []byte) {

	d := new(dummyData)
	json.Unmarshal(resp, d)
	t.fromChildren[childID] = d

	// This is a weak form of checking. We can also check the task ids.
	// But this really means that we get all the events from children, we
	// should go into the next epoch now.
	if len(t.fromChildren) == len(t.framework.GetTopology().GetChildren(t.epoch)) {
		for _, g := range t.fromChildren {
			for i := 0; i < 10; i++ {
				t.gradient.data[i] += g.data[i]
			}
		}

		// TODO(xiaoyunwu) We need to do some test here.

		// In real ML, we modify the gradient first. But here it is noop.
		// Notice that we only
		if t.epoch == numOfIterations {
			t.framework.Exit()
		} else {
			t.framework.IncEpoch()
		}
	}
}

// dummySlave is an prototype for data shard in machine learning applications.
// It mainly does to things, pass on parameters to its children, and collect
// gradient back then add them together before make it available to its parent.
type dummySlave struct {
	framework     Framework
	epoch, taskID uint64
	logger        *log.Logger

	param, gradient *dummyData
	fromChildren    map[uint64]*dummyData
}

// This is useful to bring the task up to speed from scratch or if it recovers.
func (t *dummySlave) Init(taskID uint64, framework Framework, config Config) {
	t.taskID = taskID
	t.framework = framework
	t.logger = log.New(os.Stdout, "dummySlave:", log.Ldate|log.Ltime|log.Lshortfile)
}

// Task need to finish up for exit, last chance to save work?
func (t *dummySlave) Exit() {}

// Ideally, we should also have the following:
func (t *dummySlave) ParentMetaReady(parentID uint64, meta string) {
	t.framework.DataRequest(parentID, meta)
}

func (t *dummySlave) ChildMetaReady(childID uint64, meta string) {
	t.framework.DataRequest(childID, meta)
}

// This give the task an opportunity to cleanup and regroup.
func (t *dummySlave) SetEpoch(epoch uint64) {
	t.epoch = epoch

	// Make sure we have a clean slate.
	t.fromChildren = make(map[uint64]*dummyData)
}

// These are payload rpc for application purpose.
func (t *dummySlave) ServeAsParent(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.param)
	if err != nil {
		t.logger.Printf("Slave can't encode parameter: %v, error: %v\n", t.param, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummySlave) ServeAsChild(fromID uint64, req string) []byte {
	b, err := json.Marshal(t.gradient)
	if err != nil {
		t.logger.Printf("Slave can't encode gradient: %v, error: %v\n", t.gradient, err)
		t.framework.Exit()
		return nil
	}
	return b
}

func (t *dummySlave) ParentDataReady(parentID uint64, req string, resp []byte) {
	t.param = new(dummyData)
	json.Unmarshal(resp, t.param)

	// We need to carry out local compuation.
	for i := 0; i < 10; i++ {
		t.gradient.data[i] = int32(t.framework.GetTaskID())
	}

	// If this task has children, flag meta so that children can start pull
	// parameter.
	children := t.framework.GetTopology().GetChildren(t.epoch)
	if len(children) != 0 {
		t.framework.FlagChildMetaReady("ParamReady")
	} else {
		// On leaf node, we can immediately return by and flag parent
		// that this node is ready.
		t.framework.FlagParentMetaReady("GradientReady")
	}
}

func (t *dummySlave) ChildDataReady(childID uint64, req string, resp []byte) {
	t.fromChildren[childID] = new(dummyData)
	json.Unmarshal(resp, t.fromChildren[childID])

	// This is a weak form of checking. We can also check the task ids.
	// But this really means that we get all the events from children, we
	// should go into the next epoch now.
	if len(t.fromChildren) == len(t.framework.GetTopology().GetChildren(t.epoch)) {
		// In real ML, we add the gradient first.
		for _, g := range t.fromChildren {
			for i := 0; i < 10; i++ {
				t.gradient.data[i] += g.data[i]
			}
		}

		t.framework.FlagParentMetaReady("GradientReady")
	}
}

type simpleTaskBuilder struct{}

var gDataChan = make(chan int32, 1)

// Leave it at global level so that we use this to terminate and test.
// cDataChan := make(chan *tDataBundle, 1)

// This method is called once by framework implementation to get the
// right task implementation for the node/task. It requires the taskID
// for current node, and also a global array of tasks.
func (tc simpleTaskBuilder) GetTask(taskID uint64) Task {
	if taskID == 0 {
		return &dummyMaster{dataChan: gDataChan}
	} else {
		return &dummySlave{}
	}
}

// This is used to show how to drive the network.
func drive(jobName string, etcds []string, config Config, ntask uint64) {
	var bootstrap Bootstrap = NewBootStrap(jobName, etcds, config)
	var taskBuilder simpleTaskBuilder
	bootstrap.SetTaskBuilder(taskBuilder)
	bootstrap.SetTopology(NewTreeTopology(2, ntask))
	bootstrap.Start()
}

func tTestFramework(t *testing.T) {

	m := mustNewMember(t, "framework_regression_test")
	m.Launch()
	defer m.Terminate(t)
	url := fmt.Sprintf("http://%s", m.ClientListeners[0].Addr().String())

	job := "framework_regression_test"
	etcds := []string{url}
	config := map[string]string{}
	numOfTasks := uint64(15)

	controller := &controller{
		name:       job,
		etcdclient: etcd.NewClient([]string{url}),
		numOfTasks: numOfTasks,
	}

	controller.initEtcdLayout()
	defer controller.destroyEtcdLayout()

	// We need to set etcd so that nodes know what to do.
	for i := uint64(0); i < numOfTasks; i++ {
		go drive(job, etcds, config, numOfTasks)
	}

	// wait for last number to comeback.
	data := <-gDataChan
	fmt.Println("Exiting with data = %d", data)
}
<|endoftext|>


<commit_before>package api

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

	"github.com/bosssauce/ponzu/content"
	"github.com/bosssauce/ponzu/system/admin/upload"
	"github.com/bosssauce/ponzu/system/db"
)

// Externalable accepts or rejects external POST requests to endpoints such as:
// /external/posts?type=Review
type Externalable interface {
	// Accepts determines whether a type will allow external submissions
	Accepts() bool
}

// Mergeable allows external post content to be approved and published through
// the public-facing API
type Mergeable interface {
	// Approve copies an external post to the internal collection and triggers
	// a re-sort of its content type posts
	Approve() error
}

func externalPostsHandler(res http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		res.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
	if err != nil {
		log.Println("[External] error:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	t := req.URL.Query().Get("type")
	if t == "" {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	p, found := content.Types[t]
	if !found {
		log.Println("[External] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusNotFound)
		return
	}

	post := p()

	ext, ok := post.(Externalable)
	if !ok {
		log.Println("[External] rejected non-externalable type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	if ext.Accepts() {
		ts := fmt.Sprintf("%d", time.Now().Unix()*1000)
		req.PostForm.Set("timestamp", ts)
		req.PostForm.Set("updated", ts)

		urlPaths, err := upload.StoreFiles(req)
		if err != nil {
			log.Println(err)
			res.WriteHeader(http.StatusInternalServerError)
			return
		}

		for name, urlPath := range urlPaths {
			req.PostForm.Add(name, urlPath)
		}

		// check for any multi-value fields (ex. checkbox fields)
		// and correctly format for db storage. Essentially, we need
		// fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
		var discardKeys []string
		for k, v := range req.PostForm {
			if strings.Contains(k, ".") {
				key := strings.Split(k, ".")[0]

				if req.PostForm.Get(key) == "" {
					req.PostForm.Set(key, v[0])
					discardKeys = append(discardKeys, k)
				} else {
					req.PostForm.Add(key, v[0])
				}
			}
		}

		for _, discardKey := range discardKeys {
			req.PostForm.Del(discardKey)
		}

		_, err = db.SetContent(t+":-1", req.PostForm)
		if err != nil {
			log.Println("[External] error:", err)
			res.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
}
<commit_msg>fixing previously removed specifier for pending in refactored db set content<commit_after>package api

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

	"github.com/bosssauce/ponzu/content"
	"github.com/bosssauce/ponzu/system/admin/upload"
	"github.com/bosssauce/ponzu/system/db"
)

// Externalable accepts or rejects external POST requests to endpoints such as:
// /external/posts?type=Review
type Externalable interface {
	// Accepts determines whether a type will allow external submissions
	Accepts() bool
}

// Mergeable allows external post content to be approved and published through
// the public-facing API
type Mergeable interface {
	// Approve copies an external post to the internal collection and triggers
	// a re-sort of its content type posts
	Approve() error
}

func externalPostsHandler(res http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		res.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
	if err != nil {
		log.Println("[External] error:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	t := req.URL.Query().Get("type")
	if t == "" {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	p, found := content.Types[t]
	if !found {
		log.Println("[External] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusNotFound)
		return
	}

	post := p()

	ext, ok := post.(Externalable)
	if !ok {
		log.Println("[External] rejected non-externalable type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	if ext.Accepts() {
		ts := fmt.Sprintf("%d", time.Now().Unix()*1000)
		req.PostForm.Set("timestamp", ts)
		req.PostForm.Set("updated", ts)

		urlPaths, err := upload.StoreFiles(req)
		if err != nil {
			log.Println(err)
			res.WriteHeader(http.StatusInternalServerError)
			return
		}

		for name, urlPath := range urlPaths {
			req.PostForm.Add(name, urlPath)
		}

		// check for any multi-value fields (ex. checkbox fields)
		// and correctly format for db storage. Essentially, we need
		// fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
		var discardKeys []string
		for k, v := range req.PostForm {
			if strings.Contains(k, ".") {
				key := strings.Split(k, ".")[0]

				if req.PostForm.Get(key) == "" {
					req.PostForm.Set(key, v[0])
					discardKeys = append(discardKeys, k)
				} else {
					req.PostForm.Add(key, v[0])
				}
			}
		}

		for _, discardKey := range discardKeys {
			req.PostForm.Del(discardKey)
		}

		_, err = db.SetContent(t+"_pending:-1", req.PostForm)
		if err != nil {
			log.Println("[External] error:", err)
			res.WriteHeader(http.StatusInternalServerError)
			return
		}
	}
}
<|endoftext|>


<commit_before>package system

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	httpd "github.com/rqlite/rqlite/http"
	"github.com/rqlite/rqlite/store"
)

// Node represents a node under test.
type Node struct {
	APIAddr  string
	RaftAddr string
	Dir      string
	Store    *store.Store
	Service  *httpd.Service
}

// SameAs returns true if this node is the same as node o.
func (n *Node) SameAs(o *Node) bool {
	return n.RaftAddr == o.RaftAddr
}

// Deprovision shuts down and removes all resources associated with the node.
func (n *Node) Deprovision() {
	n.Store.Close(false)
	n.Service.Close()
	os.RemoveAll(n.Dir)
}

// WaitForLeader blocks for up to 10 seconds until the node detects a leader.
func (n *Node) WaitForLeader() (string, error) {
	return n.Store.WaitForLeader(10 * time.Second)
}

// Execute executes a single statement against the node.
func (n *Node) Execute(stmt string) (string, error) {
	return n.ExecuteMulti([]string{stmt})
}

// ExecuteMulti executes multiple statements against the node.
func (n *Node) ExecuteMulti(stmts []string) (string, error) {
	j, err := json.Marshal(stmts)
	if err != nil {
		return "", err
	}
	return n.postExecute(string(j))
}

// Query runs a single query against the node.
func (n *Node) Query(stmt string) (string, error) {
	v, _ := url.Parse("http://" + n.APIAddr + "/db/query")
	v.RawQuery = url.Values{"q": []string{stmt}}.Encode()

	resp, err := http.Get(v.String())
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// Join instructs this node to join the leader.
func (n *Node) Join(leader *Node) error {
	b, err := json.Marshal(map[string]string{"addr": n.RaftAddr})
	if err != nil {
		return err
	}

	// Attempt to join leader
	resp, err := http.Post("http://"+leader.APIAddr+"/join", "application-type/json", bytes.NewReader(b))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to join, leader returned: %s", resp.Status)
	}
	defer resp.Body.Close()
	return nil
}

// ConfirmRedirect confirms that the node responds with a redirect to the given host.
func (n *Node) ConfirmRedirect(host string) bool {
	v, _ := url.Parse("http://" + n.APIAddr + "/db/query")
	v.RawQuery = url.Values{"q": []string{`SELECT * FROM foo`}}.Encode()

	resp, err := http.Get(v.String())
	if err != nil {
		return false
	}
	defer resp.Body.Close()
	fmt.Println(resp.StatusCode)
	if resp.StatusCode != http.StatusMovedPermanently {
		return false
	}
	if resp.Header.Get("location") != host {
		return false
	}
	return true
}

func (n *Node) postExecute(stmt string) (string, error) {
	resp, err := http.Post("http://"+n.APIAddr+"/db/execute", "application/json", strings.NewReader(stmt))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// Cluster represents a cluster of nodes.
type Cluster []*Node

// Leader returns the leader node of a cluster.
func (c Cluster) Leader() (*Node, error) {
	l, err := c[0].WaitForLeader()
	if err != nil {
		return nil, err
	}
	return c.FindNodeByRaftAddr(l)
}

// WaitForNewLeader waits for the leader to change from the node passed in.
func (c Cluster) WaitForNewLeader(old *Node) (*Node, error) {
	timer := time.NewTimer(30 * time.Second)
	defer timer.Stop()
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-timer.C:
			return nil, fmt.Errorf("timed out waiting for new leader")
		case <-ticker.C:
			l, err := c.Leader()
			if err != nil {
				continue
			}
			if !l.SameAs(old) {
				return l, nil
			}
		}
	}
}

// Followers returns the slice of nodes in the cluster that are followers.
func (c Cluster) Followers() ([]*Node, error) {
	n, err := c[0].WaitForLeader()
	if err != nil {
		return nil, err
	}
	leader, err := c.FindNodeByRaftAddr(n)
	if err != nil {
		return nil, err
	}

	var followers []*Node
	for _, n := range c {
		if n != leader {
			followers = append(followers, n)
		}
	}
	return followers, nil
}

// RemoveNode removes the given node from the list of nodes representing
// a cluster.
func (c Cluster) RemoveNode(node *Node) {
	for i, n := range c {
		if n.RaftAddr == node.RaftAddr {
			c = append(c[:i], c[i+1:]...)
			return
		}
	}
}

// FindNodeByRaftAddr returns the node with the given Raft address.
func (c Cluster) FindNodeByRaftAddr(addr string) (*Node, error) {
	for _, n := range c {
		if n.RaftAddr == addr {
			return n, nil
		}
	}
	return nil, fmt.Errorf("node not found")
}

// Deprovision deprovisions every node in the cluster.
func (c Cluster) Deprovision() {
	for _, n := range c {
		n.Deprovision()
	}
}

// Remove tells the cluster at n to remove the node at addr. Assumes n is the leader.
func Remove(n *Node, addr string) error {
	b, err := json.Marshal(map[string]string{"addr": addr})
	if err != nil {
		return err
	}

	// Attempt to remove node from leader.
	resp, err := http.Post("http://"+n.APIAddr+"/remove", "application-type/json", bytes.NewReader(b))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to remove node, leader returned: %s", resp.Status)
	}
	defer resp.Body.Close()
	return nil
}

func mustNewNode(enableSingle bool) *Node {
	node := &Node{
		Dir: mustTempDir(),
	}

	dbConf := store.NewDBConfig("", false)
	node.Store = store.New(dbConf, node.Dir, mustMockTransport("localhost:0"))
	if err := node.Store.Open(enableSingle); err != nil {
		node.Deprovision()
		panic(fmt.Sprintf("failed to open store: %s", err.Error()))
	}
	node.RaftAddr = node.Store.Addr().String()

	node.Service = httpd.New("localhost:0", node.Store, nil)
	if err := node.Service.Start(); err != nil {
		node.Deprovision()
		panic(fmt.Sprintf("failed to start HTTP server: %s", err.Error()))
	}
	node.APIAddr = node.Service.Addr().String()

	return node
}

func mustNewLeaderNode() *Node {
	node := mustNewNode(true)
	if _, err := node.WaitForLeader(); err != nil {
		node.Deprovision()
		panic("node never became leader")
	}
	return node
}

type mockTransport struct {
	ln net.Listener
}

func mustMockTransport(addr string) *mockTransport {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		panic("failed to create new transport")
	}
	return &mockTransport{ln}
}

func (m *mockTransport) Dial(addr string, timeout time.Duration) (net.Conn, error) {
	return net.DialTimeout("tcp", addr, timeout)
}

func (m *mockTransport) Accept() (net.Conn, error) { return m.ln.Accept() }

func (m *mockTransport) Close() error { return m.ln.Close() }

func (m *mockTransport) Addr() net.Addr { return m.ln.Addr() }

func mustTempDir() string {
	var err error
	path, err := ioutil.TempDir("", "rqlilte-system-test-")
	if err != nil {
		panic("failed to create temp dir")
	}
	return path
}
<commit_msg>Minor refactor of system test utilities<commit_after>package system

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	httpd "github.com/rqlite/rqlite/http"
	"github.com/rqlite/rqlite/store"
)

// Node represents a node under test.
type Node struct {
	APIAddr  string
	RaftAddr string
	Dir      string
	Store    *store.Store
	Service  *httpd.Service
}

// SameAs returns true if this node is the same as node o.
func (n *Node) SameAs(o *Node) bool {
	return n.RaftAddr == o.RaftAddr
}

// Deprovision shuts down and removes all resources associated with the node.
func (n *Node) Deprovision() {
	n.Store.Close(false)
	n.Service.Close()
	os.RemoveAll(n.Dir)
}

// WaitForLeader blocks for up to 10 seconds until the node detects a leader.
func (n *Node) WaitForLeader() (string, error) {
	return n.Store.WaitForLeader(10 * time.Second)
}

// Execute executes a single statement against the node.
func (n *Node) Execute(stmt string) (string, error) {
	return n.ExecuteMulti([]string{stmt})
}

// ExecuteMulti executes multiple statements against the node.
func (n *Node) ExecuteMulti(stmts []string) (string, error) {
	j, err := json.Marshal(stmts)
	if err != nil {
		return "", err
	}
	return n.postExecute(string(j))
}

// Query runs a single query against the node.
func (n *Node) Query(stmt string) (string, error) {
	v, _ := url.Parse("http://" + n.APIAddr + "/db/query")
	v.RawQuery = url.Values{"q": []string{stmt}}.Encode()

	resp, err := http.Get(v.String())
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// Join instructs this node to join the leader.
func (n *Node) Join(leader *Node) error {
	resp, err := DoJoinRequest(leader.APIAddr, n.RaftAddr)
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to join, leader returned: %s", resp.Status)
	}
	defer resp.Body.Close()
	return nil
}

// ConfirmRedirect confirms that the node responds with a redirect to the given host.
func (n *Node) ConfirmRedirect(host string) bool {
	v, _ := url.Parse("http://" + n.APIAddr + "/db/query")
	v.RawQuery = url.Values{"q": []string{`SELECT * FROM foo`}}.Encode()

	resp, err := http.Get(v.String())
	if err != nil {
		return false
	}
	defer resp.Body.Close()
	fmt.Println(resp.StatusCode)
	if resp.StatusCode != http.StatusMovedPermanently {
		return false
	}
	if resp.Header.Get("location") != host {
		return false
	}
	return true
}

func (n *Node) postExecute(stmt string) (string, error) {
	resp, err := http.Post("http://"+n.APIAddr+"/db/execute", "application/json", strings.NewReader(stmt))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(body), nil
}

// Cluster represents a cluster of nodes.
type Cluster []*Node

// Leader returns the leader node of a cluster.
func (c Cluster) Leader() (*Node, error) {
	l, err := c[0].WaitForLeader()
	if err != nil {
		return nil, err
	}
	return c.FindNodeByRaftAddr(l)
}

// WaitForNewLeader waits for the leader to change from the node passed in.
func (c Cluster) WaitForNewLeader(old *Node) (*Node, error) {
	timer := time.NewTimer(30 * time.Second)
	defer timer.Stop()
	ticker := time.NewTicker(100 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-timer.C:
			return nil, fmt.Errorf("timed out waiting for new leader")
		case <-ticker.C:
			l, err := c.Leader()
			if err != nil {
				continue
			}
			if !l.SameAs(old) {
				return l, nil
			}
		}
	}
}

// Followers returns the slice of nodes in the cluster that are followers.
func (c Cluster) Followers() ([]*Node, error) {
	n, err := c[0].WaitForLeader()
	if err != nil {
		return nil, err
	}
	leader, err := c.FindNodeByRaftAddr(n)
	if err != nil {
		return nil, err
	}

	var followers []*Node
	for _, n := range c {
		if n != leader {
			followers = append(followers, n)
		}
	}
	return followers, nil
}

// RemoveNode removes the given node from the list of nodes representing
// a cluster.
func (c Cluster) RemoveNode(node *Node) {
	for i, n := range c {
		if n.RaftAddr == node.RaftAddr {
			c = append(c[:i], c[i+1:]...)
			return
		}
	}
}

// FindNodeByRaftAddr returns the node with the given Raft address.
func (c Cluster) FindNodeByRaftAddr(addr string) (*Node, error) {
	for _, n := range c {
		if n.RaftAddr == addr {
			return n, nil
		}
	}
	return nil, fmt.Errorf("node not found")
}

// Deprovision deprovisions every node in the cluster.
func (c Cluster) Deprovision() {
	for _, n := range c {
		n.Deprovision()
	}
}

// Remove tells the cluster at n to remove the node at addr. Assumes n is the leader.
func Remove(n *Node, addr string) error {
	b, err := json.Marshal(map[string]string{"addr": addr})
	if err != nil {
		return err
	}

	// Attempt to remove node from leader.
	resp, err := http.Post("http://"+n.APIAddr+"/remove", "application-type/json", bytes.NewReader(b))
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("failed to remove node, leader returned: %s", resp.Status)
	}
	defer resp.Body.Close()
	return nil
}

// DoJoinRequest sends a join request to nodeAddr, for raftAddr.
func DoJoinRequest(nodeAddr, raftAddr string) (*http.Response, error) {
	b, err := json.Marshal(map[string]string{"addr": raftAddr})
	if err != nil {
		return nil, err
	}

	resp, err := http.Post("http://"+nodeAddr+"/join", "application-type/json", bytes.NewReader(b))
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func mustNewNode(enableSingle bool) *Node {
	node := &Node{
		Dir: mustTempDir(),
	}

	dbConf := store.NewDBConfig("", false)
	node.Store = store.New(dbConf, node.Dir, mustMockTransport("localhost:0"))
	if err := node.Store.Open(enableSingle); err != nil {
		node.Deprovision()
		panic(fmt.Sprintf("failed to open store: %s", err.Error()))
	}
	node.RaftAddr = node.Store.Addr().String()

	node.Service = httpd.New("localhost:0", node.Store, nil)
	if err := node.Service.Start(); err != nil {
		node.Deprovision()
		panic(fmt.Sprintf("failed to start HTTP server: %s", err.Error()))
	}
	node.APIAddr = node.Service.Addr().String()

	return node
}

func mustNewLeaderNode() *Node {
	node := mustNewNode(true)
	if _, err := node.WaitForLeader(); err != nil {
		node.Deprovision()
		panic("node never became leader")
	}
	return node
}

type mockTransport struct {
	ln net.Listener
}

func mustMockTransport(addr string) *mockTransport {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		panic("failed to create new transport")
	}
	return &mockTransport{ln}
}

func (m *mockTransport) Dial(addr string, timeout time.Duration) (net.Conn, error) {
	return net.DialTimeout("tcp", addr, timeout)
}

func (m *mockTransport) Accept() (net.Conn, error) { return m.ln.Accept() }

func (m *mockTransport) Close() error { return m.ln.Close() }

func (m *mockTransport) Addr() net.Addr { return m.ln.Addr() }

func mustTempDir() string {
	var err error
	path, err := ioutil.TempDir("", "rqlilte-system-test-")
	if err != nil {
		panic("failed to create temp dir")
	}
	return path
}
<|endoftext|>


<commit_before>package shell

import (
	"context"
	"fmt"
	"io"
	"os"

	"github.com/chrislusf/seaweedfs/weed/filer2"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/golang/protobuf/proto"
)

func init() {
	commands = append(commands, &commandFsMetaLoad{})
}

type commandFsMetaLoad struct {
}

func (c *commandFsMetaLoad) Name() string {
	return "fs.meta.load"
}

func (c *commandFsMetaLoad) Help() string {
	return `load saved filer meta data to restore the directory and file structure

	fs.meta.load <filer_host>-<port>-<time>.meta

`
}

func (c *commandFsMetaLoad) Do(args []string, commandEnv *commandEnv, writer io.Writer) (err error) {

	filerServer, filerPort, path, err := commandEnv.parseUrl(findInputDirectory(nil))
	if err != nil {
		return err
	}

	fileName := args[len(args)-1]

	dst, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
	if err != nil {
		return nil
	}
	defer dst.Close()

	var dirCount, fileCount uint64

	ctx := context.Background()

	err = commandEnv.withFilerClient(ctx, filerServer, filerPort, func(client filer_pb.SeaweedFilerClient) error {

		sizeBuf := make([]byte, 4)

		for {
			if n, err := dst.Read(sizeBuf); n != 4 {
				if err == io.EOF {
					return nil
				}
				return err
			}

			size := util.BytesToUint32(sizeBuf)

			data := make([]byte, int(size))

			if n, err := dst.Read(data); n != len(data) {
				return err
			}

			fullEntry := &filer_pb.FullEntry{}
			if err = proto.Unmarshal(data, fullEntry); err != nil {
				return err
			}

			if _, err = client.CreateEntry(ctx, &filer_pb.CreateEntryRequest{
				Directory: fullEntry.Dir,
				Entry:     fullEntry.Entry,
			}); err != nil {
				return err
			}

			fmt.Fprintf(writer, "load %s\n", filer2.FullPath(fullEntry.Dir).Child(fullEntry.Entry.Name))

			if fullEntry.Entry.IsDirectory {
				dirCount++
			} else {
				fileCount++
			}

		}

	})

	if err == nil {
		fmt.Fprintf(writer, "\ntotal %d directories, %d files", dirCount, fileCount)
		fmt.Fprintf(writer, "\n%s is loaded to http://%s:%d%s\n", fileName, filerServer, filerPort, path)
	}

	return err
}
<commit_msg>minor<commit_after>package shell

import (
	"context"
	"fmt"
	"io"
	"os"

	"github.com/chrislusf/seaweedfs/weed/filer2"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/golang/protobuf/proto"
)

func init() {
	commands = append(commands, &commandFsMetaLoad{})
}

type commandFsMetaLoad struct {
}

func (c *commandFsMetaLoad) Name() string {
	return "fs.meta.load"
}

func (c *commandFsMetaLoad) Help() string {
	return `load saved filer meta data to restore the directory and file structure

	fs.meta.load <filer_host>-<port>-<time>.meta

`
}

func (c *commandFsMetaLoad) Do(args []string, commandEnv *commandEnv, writer io.Writer) (err error) {

	if len(args) == 0 {
		fmt.Fprintf(writer, "missing a metadata file\n")
		return nil
	}

	filerServer, filerPort, path, err := commandEnv.parseUrl(findInputDirectory(nil))
	if err != nil {
		return err
	}

	fileName := args[len(args)-1]

	dst, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
	if err != nil {
		return nil
	}
	defer dst.Close()

	var dirCount, fileCount uint64

	ctx := context.Background()

	err = commandEnv.withFilerClient(ctx, filerServer, filerPort, func(client filer_pb.SeaweedFilerClient) error {

		sizeBuf := make([]byte, 4)

		for {
			if n, err := dst.Read(sizeBuf); n != 4 {
				if err == io.EOF {
					return nil
				}
				return err
			}

			size := util.BytesToUint32(sizeBuf)

			data := make([]byte, int(size))

			if n, err := dst.Read(data); n != len(data) {
				return err
			}

			fullEntry := &filer_pb.FullEntry{}
			if err = proto.Unmarshal(data, fullEntry); err != nil {
				return err
			}

			if _, err = client.CreateEntry(ctx, &filer_pb.CreateEntryRequest{
				Directory: fullEntry.Dir,
				Entry:     fullEntry.Entry,
			}); err != nil {
				return err
			}

			fmt.Fprintf(writer, "load %s\n", filer2.FullPath(fullEntry.Dir).Child(fullEntry.Entry.Name))

			if fullEntry.Entry.IsDirectory {
				dirCount++
			} else {
				fileCount++
			}

		}

	})

	if err == nil {
		fmt.Fprintf(writer, "\ntotal %d directories, %d files", dirCount, fileCount)
		fmt.Fprintf(writer, "\n%s is loaded to http://%s:%d%s\n", fileName, filerServer, filerPort, path)
	}

	return err
}
<|endoftext|>


<commit_before>package roblox_challenge

import (
	"errors"
	"fmt"
	"math"
)

func Merger(slice1 []int32, slice2 []int32) ([]int32) {
	i1 := 0
	i2 := 0

	acc := make([]int32, 0, len(slice1) + len(slice2))
	for i1 < len(slice1) || i2 < len(slice2) {
		if i1 >= len(slice1) {
			acc = append(acc, slice2[i2])
			i2++
			continue
		}

		if i2 >= len(slice2) {
			acc = append(acc, slice1[i1])
			i1++
			continue
		}

		if slice1[i1] > slice2[i2] {
			acc = append(acc, slice2[i2])
			i2++
		}else {
			acc = append(acc, slice1[i1])
			i1++
		}

	}
	return acc
}

func overflowDetectingMulti(nums ...int32) (prod int32, err error) {

	fmt.Printf("Multiplying #%v\n", nums)
	prod = nums[0]
	for i := 1; i < len(nums); i++ {
		x := nums[i]

		fmt.Printf("x:%d * prod:%d = %d\n", x, prod, x * prod)
		if (x == -1 && prod == math.MinInt32) || (x == math.MinInt32 && prod == -1) {
			err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
			return
		}

		/*
		Assuming our arguments are currently already valid int32s:
		1) multiplying by a 0 will always yield 0
		2) multiplying by -1 will always yield a valid number expect for above case
		3) multiplying by 1 will never change the product
		*/
		if (prod > 1 || prod < -1) &&  (x > 1 || x < -1) {
			if prod > 0 {
				fmt.Println("prod is greater than 0 ")
				if x > (math.MaxInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
					return
				}
				fmt.Printf("(math.MinInt32 / prod ) = %d \n", (math.MinInt32 / prod ))
				if x < (math.MinInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Underflow detected x: %d, prod: %d\n", x, prod))
					return
				}
			}else {
				fmt.Println("prod is less than 0 ")
				if x < (math.MaxInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
					return
				}
				if x > (math.MinInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Underflow detected x: %d, prod: %d div: %d\n", x, prod, math.MinInt32 / prod))
					return
				}
			}
		}
		prod *= x
	}
	return
}

func FindLargestProduct(slice1 []int32) (prod int32, err error) {

	if len(slice1) == 0 {
		return
	}else if len(slice1) == 1 {
		prod = slice1[0]
		return
	}else if len(slice1) == 2 {
		prod = slice1[0] * slice1[1]
		return
	}

	var pos1 int32 = math.MinInt32
	var pos2 int32 = math.MinInt32
	var pos3 int32 = math.MinInt32

	var neg1 int32 = math.MaxInt32
	var neg2 int32 = math.MaxInt32

	for _, v := range slice1 {
		if v > pos1 {
			pos3 = pos2
			pos2 = pos1
			pos1 = v
		}else if (v > pos2) {
			pos3 = pos2
			pos2 = v
		}else if (v > pos3) {
			pos3 = v
		}

		if v < neg1 {
			neg2 = neg1
			neg1 = v
		}else if (v < neg2) {
			neg2 = v
		}

	}

	p1, err := overflowDetectingMulti(pos1, pos2, pos3)
	if err != nil {
		return
	}

	//Multiplying negative numbers first should prevent underflow
	p2, err := overflowDetectingMulti(neg1, neg2, pos1)
	if err != nil {
		return
	}

	if p1 > p2 {
		prod = p1
	}else {
		prod = p2
	}

	return
}

<commit_msg>updating variable names and comment<commit_after>package roblox_challenge

import (
	"errors"
	"fmt"
	"math"
)

func Merger(slice1 []int32, slice2 []int32) ([]int32) {
	i1 := 0
	i2 := 0

	acc := make([]int32, 0, len(slice1) + len(slice2))
	for i1 < len(slice1) || i2 < len(slice2) {
		if i1 >= len(slice1) {
			acc = append(acc, slice2[i2])
			i2++
			continue
		}

		if i2 >= len(slice2) {
			acc = append(acc, slice1[i1])
			i1++
			continue
		}

		if slice1[i1] > slice2[i2] {
			acc = append(acc, slice2[i2])
			i2++
		}else {
			acc = append(acc, slice1[i1])
			i1++
		}

	}
	return acc
}

func overflowDetectingMulti(nums ...int32) (prod int32, err error) {

	fmt.Printf("Multiplying #%v\n", nums)
	prod = nums[0]
	for i := 1; i < len(nums); i++ {
		x := nums[i]

		fmt.Printf("x:%d * prod:%d = %d\n", x, prod, x * prod)
		if (x == -1 && prod == math.MinInt32) || (x == math.MinInt32 && prod == -1) {
			err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
			return
		}

		/*
		Assuming our arguments are currently already valid int32s:
		1) multiplying by a 0 will always yield 0
		2) multiplying by -1 will always yield a valid number expect for above case
		3) multiplying by 1 will never change the product
		*/
		if (prod > 1 || prod < -1) &&  (x > 1 || x < -1) {
			if prod > 0 {
				fmt.Println("prod is greater than 0 ")
				if x > (math.MaxInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
					return
				}
				fmt.Printf("(math.MinInt32 / prod ) = %d \n", (math.MinInt32 / prod ))
				if x < (math.MinInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Underflow detected x: %d, prod: %d\n", x, prod))
					return
				}
			}else {
				fmt.Println("prod is less than 0 ")
				if x < (math.MaxInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Overflow detected x: %d, prod: %d\n", x, prod))
					return
				}
				if x > (math.MinInt32 / prod ) {
					err = errors.New(fmt.Sprintf("Underflow detected x: %d, prod: %d div: %d\n", x, prod, math.MinInt32 / prod))
					return
				}
			}
		}
		prod *= x
	}
	return
}

func FindLargestProduct(slice1 []int32) (prod int32, err error) {

	if len(slice1) == 0 {
		return
	}else if len(slice1) == 1 {
		prod = slice1[0]
		return
	}else if len(slice1) == 2 {
		prod = slice1[0] * slice1[1]
		return
	}

	var biggest int32 = math.MinInt32
	var bigger int32 = math.MinInt32
	var big int32 = math.MinInt32

	var smaller int32 = math.MaxInt32
	var small int32 = math.MaxInt32

	for _, v := range slice1 {
		if v > biggest {
			big = bigger
			bigger = biggest
			biggest = v
		}else if (v > bigger) {
			big = bigger
			bigger = v
		}else if (v > big) {
			big = v
		}

		if v < smaller {
			small = smaller
			smaller = v
		}else if (v < small) {
			small = v
		}

	}

	p1, err := overflowDetectingMulti(biggest, bigger, big)
	if err != nil {
		return
	}

	//if the 2 smallest numbers are negative, they maybe be part of the solution
	p2, err := overflowDetectingMulti(smaller, small, biggest)
	if err != nil {
		return
	}

	if p1 > p2 {
		prod = p1
	}else {
		prod = p2
	}

	return
}

<|endoftext|>


<commit_before>package sql

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type Schema []Column

func (s Schema) CheckRow(row Row) error {
	expected := len(s)
	got := len(row)
	if expected != got {
		return fmt.Errorf("expected %d values, got %d", expected, got)
	}

	for idx, f := range s {
		v := row[idx]
		if f.Type.Check(v) {
			continue
		}

		typ := reflect.TypeOf(v).String()
		return fmt.Errorf("value at %d has unexpected type: %s",
			idx, typ)

	}

	return nil
}

type Column struct {
	Name string
	Type Type
}

type Type interface {
	Name() string
	InternalType() reflect.Kind
	Check(interface{}) bool
	Convert(interface{}) (interface{}, error)
	Compare(interface{}, interface{}) int
}

var Null = nullType{}

type nullType struct{}

func (t nullType) Name() string {
	return "null"
}

func (t nullType) InternalType() reflect.Kind {
	return reflect.Interface
}

func (t nullType) Check(v interface{}) bool {
	return v == nil
}

func (t nullType) Convert(v interface{}) (interface{}, error) {
	if v != nil {
		return nil, fmt.Errorf("value not nil: %#v", v)
	}

	return nil, nil
}

func (t nullType) Compare(a interface{}, b interface{}) int {
	//XXX: Note that while this returns 0 (equals) for ordering purposes, in
	//     SQL NULL != NULL.
	return 0
}

var Integer = integerType{}

type integerType struct{}

func (t integerType) Name() string {
	return "integer"
}

func (t integerType) InternalType() reflect.Kind {
	return reflect.Int32
}

func (t integerType) Check(v interface{}) bool {
	return checkInt32(v)
}

func (t integerType) Convert(v interface{}) (interface{}, error) {
	return convertToInt32(v)
}

func (t integerType) Compare(a interface{}, b interface{}) int {
	return compareInt32(a, b)
}

var BigInteger = bigIntegerType{}

type bigIntegerType struct{}

func (t bigIntegerType) Name() string {
	return "biginteger"
}

func (t bigIntegerType) InternalType() reflect.Kind {
	return reflect.Int64
}

func (t bigIntegerType) Check(v interface{}) bool {
	return checkInt64(v)
}

func (t bigIntegerType) Convert(v interface{}) (interface{}, error) {
	return convertToInt64(v)
}

func (t bigIntegerType) Compare(a interface{}, b interface{}) int {
	return compareInt64(a, b)
}

// TimestampWithTimezone is a timestamp with timezone.
var TimestampWithTimezone = timestampWithTimeZoneType{}

type timestampWithTimeZoneType struct{}

func (t timestampWithTimeZoneType) Name() string {
	return "timestamp with timezone"
}

func (t timestampWithTimeZoneType) InternalType() reflect.Kind {
	return reflect.Struct
}

func (t timestampWithTimeZoneType) Check(v interface{}) bool {
	return checkTimestamp(v)
}

func (t timestampWithTimeZoneType) Convert(v interface{}) (interface{}, error) {
	return convertToTimestamp(v)
}

func (t timestampWithTimeZoneType) Compare(a interface{}, b interface{}) int {
	return compareTimestamp(a, b)
}

var String = stringType{}

type stringType struct{}

func (t stringType) Name() string {
	return "string"
}

func (t stringType) InternalType() reflect.Kind {
	return reflect.String
}

func (t stringType) Check(v interface{}) bool {
	return checkString(v)
}

func (t stringType) Convert(v interface{}) (interface{}, error) {
	return convertToString(v)
}

func (t stringType) Compare(a interface{}, b interface{}) int {
	return compareString(a, b)
}

var Boolean Type = booleanType{}

type booleanType struct{}

func (t booleanType) Name() string {
	return "boolean"
}

func (t booleanType) InternalType() reflect.Kind {
	return reflect.Bool
}

func (t booleanType) Check(v interface{}) bool {
	return checkBoolean(v)
}

func (t booleanType) Convert(v interface{}) (interface{}, error) {
	return convertToBool(v)
}

func (t booleanType) Compare(a interface{}, b interface{}) int {
	return compareBool(a, b)
}

var Float Type = floatType{}

type floatType struct{}

func (t floatType) Name() string {
	return "float"
}

func (t floatType) InternalType() reflect.Kind {
	return reflect.Float64
}

func (t floatType) Check(v interface{}) bool {
	return checkFloat64(v)
}

func (t floatType) Convert(v interface{}) (interface{}, error) {
	return convertToFloat64(v)
}

func (t floatType) Compare(a interface{}, b interface{}) int {
	return compareFloat64(a, b)
}

func checkString(v interface{}) bool {
	_, ok := v.(string)
	return ok
}

func convertToString(v interface{}) (interface{}, error) {
	switch v.(type) {
	case string:
		return v.(string), nil
	case fmt.Stringer:
		return v.(fmt.Stringer).String(), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareString(a interface{}, b interface{}) int {
	av := a.(string)
	bv := b.(string)
	return strings.Compare(av, bv)
}

func checkInt32(v interface{}) bool {
	_, ok := v.(int32)
	return ok
}

func convertToInt32(v interface{}) (interface{}, error) {
	switch v.(type) {
	case int:
		return int32(v.(int)), nil
	case int8:
		return int32(v.(int8)), nil
	case int16:
		return int32(v.(int16)), nil
	case int32:
		return v.(int32), nil
	case int64:
		i64 := v.(int64)
		if i64 > (1<<31)-1 || i64 < -(1<<31) {
			return nil, fmt.Errorf("value %d overflows int32", i64)
		}
		return int32(i64), nil
	case uint8:
		return int32(v.(uint8)), nil
	case uint16:
		return int32(v.(uint16)), nil
	case uint:
		u := v.(uint)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case uint32:
		u := v.(uint32)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case uint64:
		u := v.(uint64)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case string:
		s := v.(string)
		i, err := strconv.Atoi(s)
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int32", v)
		}
		return int32(i), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareInt32(a interface{}, b interface{}) int {
	av := a.(int32)
	bv := b.(int32)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkInt64(v interface{}) bool {
	_, ok := v.(int64)
	return ok
}

func convertToInt64(v interface{}) (interface{}, error) {
	switch v.(type) {
	case int:
		return int64(v.(int)), nil
	case int8:
		return int64(v.(int8)), nil
	case int16:
		return int64(v.(int16)), nil
	case int32:
		return int64(v.(int32)), nil
	case int64:
		return v.(int64), nil
	case uint:
		return int64(v.(uint)), nil
	case uint8:
		return int64(v.(uint8)), nil
	case uint16:
		return int64(v.(uint16)), nil
	case uint32:
		return int64(v.(uint32)), nil
	case uint64:
		u := v.(uint64)
		if u >= 1<<63 {
			return nil, fmt.Errorf("value %d overflows int64", v)
		}
		return int64(u), nil
	case string:
		s := v.(string)
		i, err := strconv.Atoi(s)
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int64", v)
		}
		return int64(i), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareInt64(a interface{}, b interface{}) int {
	av := a.(int64)
	bv := b.(int64)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkBoolean(v interface{}) bool {
	_, ok := v.(bool)
	return ok
}

func convertToBool(v interface{}) (interface{}, error) {
	switch v.(type) {
	case bool:
		return v.(bool), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareBool(a interface{}, b interface{}) int {
	av := a.(bool)
	bv := b.(bool)
	if av == bv {
		return 0
	} else if av == false {
		return -1
	} else {
		return 1
	}
}

func checkFloat64(v interface{}) bool {
	_, ok := v.(float32)
	return ok
}

func convertToFloat64(v interface{}) (interface{}, error) {
	switch v.(type) {
	case float32:
		return v.(float32), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareFloat64(a interface{}, b interface{}) int {
	av := a.(float32)
	bv := b.(float32)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkTimestamp(v interface{}) bool {
	_, ok := v.(time.Time)
	return ok
}

const timestampLayout = "2006-01-02 15:04:05.000000"

func convertToTimestamp(v interface{}) (interface{}, error) {
	switch v.(type) {
	case string:
		t, err := time.Parse(timestampLayout, v.(string))
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int64", v)
		}
		return t, nil
	default:
		if !BigInteger.Check(v) {
			return nil, ErrInvalidType
		}

		bi, err := BigInteger.Convert(v)
		if err != nil {
			return nil, ErrInvalidType
		}

		return time.Unix(bi.(int64), 0), nil
	}
}

func compareTimestamp(a interface{}, b interface{}) int {
	av := a.(time.Time)
	bv := b.(time.Time)
	if av.Before(bv) {
		return -1
	} else if av.After(bv) {
		return 1
	}
	return 0
}
<commit_msg>sql: add Native method to Type (#104)<commit_after>package sql

import (
	"database/sql/driver"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

type Schema []Column

func (s Schema) CheckRow(row Row) error {
	expected := len(s)
	got := len(row)
	if expected != got {
		return fmt.Errorf("expected %d values, got %d", expected, got)
	}

	for idx, f := range s {
		v := row[idx]
		if f.Type.Check(v) {
			continue
		}

		typ := reflect.TypeOf(v).String()
		return fmt.Errorf("value at %d has unexpected type: %s",
			idx, typ)

	}

	return nil
}

type Column struct {
	Name string
	Type Type
}

type Type interface {
	Name() string
	InternalType() reflect.Kind
	Check(interface{}) bool
	Convert(interface{}) (interface{}, error)
	Compare(interface{}, interface{}) int
	Native(interface{}) driver.Value
}

var Null = nullType{}

type nullType struct{}

func (t nullType) Name() string {
	return "null"
}

func (t nullType) InternalType() reflect.Kind {
	return reflect.Interface
}

func (t nullType) Check(v interface{}) bool {
	return v == nil
}

func (t nullType) Convert(v interface{}) (interface{}, error) {
	if v != nil {
		return nil, fmt.Errorf("value not nil: %#v", v)
	}

	return nil, nil
}

func (t nullType) Compare(a interface{}, b interface{}) int {
	//XXX: Note that while this returns 0 (equals) for ordering purposes, in
	//     SQL NULL != NULL.
	return 0
}

func (t nullType) Native(v interface{}) driver.Value {
	return driver.Value(nil)
}

var Integer = integerType{}

type integerType struct{}

func (t integerType) Name() string {
	return "integer"
}

func (t integerType) InternalType() reflect.Kind {
	return reflect.Int32
}

func (t integerType) Check(v interface{}) bool {
	return checkInt32(v)
}

func (t integerType) Convert(v interface{}) (interface{}, error) {
	return convertToInt32(v)
}

func (t integerType) Compare(a interface{}, b interface{}) int {
	return compareInt32(a, b)
}

func (t integerType) Native(v interface{}) driver.Value {
	return driver.Value(int64(v.(int32)))
}

var BigInteger = bigIntegerType{}

type bigIntegerType struct{}

func (t bigIntegerType) Name() string {
	return "biginteger"
}

func (t bigIntegerType) InternalType() reflect.Kind {
	return reflect.Int64
}

func (t bigIntegerType) Check(v interface{}) bool {
	return checkInt64(v)
}

func (t bigIntegerType) Convert(v interface{}) (interface{}, error) {
	return convertToInt64(v)
}

func (t bigIntegerType) Compare(a interface{}, b interface{}) int {
	return compareInt64(a, b)
}

func (t bigIntegerType) Native(v interface{}) driver.Value {
	return driver.Value(v.(int64))
}

// TimestampWithTimezone is a timestamp with timezone.
var TimestampWithTimezone = timestampWithTimeZoneType{}

type timestampWithTimeZoneType struct{}

func (t timestampWithTimeZoneType) Name() string {
	return "timestamp with timezone"
}

func (t timestampWithTimeZoneType) InternalType() reflect.Kind {
	return reflect.Struct
}

func (t timestampWithTimeZoneType) Check(v interface{}) bool {
	return checkTimestamp(v)
}

func (t timestampWithTimeZoneType) Convert(v interface{}) (interface{}, error) {
	return convertToTimestamp(v)
}

func (t timestampWithTimeZoneType) Compare(a interface{}, b interface{}) int {
	return compareTimestamp(a, b)
}

func (t timestampWithTimeZoneType) Native(v interface{}) driver.Value {
	return driver.Value(v.(time.Time))
}

var String = stringType{}

type stringType struct{}

func (t stringType) Name() string {
	return "string"
}

func (t stringType) InternalType() reflect.Kind {
	return reflect.String
}

func (t stringType) Check(v interface{}) bool {
	return checkString(v)
}

func (t stringType) Convert(v interface{}) (interface{}, error) {
	return convertToString(v)
}

func (t stringType) Compare(a interface{}, b interface{}) int {
	return compareString(a, b)
}

func (t stringType) Native(v interface{}) driver.Value {
	return driver.Value(v.(string))
}

var Boolean Type = booleanType{}

type booleanType struct{}

func (t booleanType) Name() string {
	return "boolean"
}

func (t booleanType) InternalType() reflect.Kind {
	return reflect.Bool
}

func (t booleanType) Check(v interface{}) bool {
	return checkBoolean(v)
}

func (t booleanType) Convert(v interface{}) (interface{}, error) {
	return convertToBool(v)
}

func (t booleanType) Compare(a interface{}, b interface{}) int {
	return compareBool(a, b)
}

func (t booleanType) Native(v interface{}) driver.Value {
	return driver.Value(v.(bool))
}

var Float Type = floatType{}

type floatType struct{}

func (t floatType) Name() string {
	return "float"
}

func (t floatType) InternalType() reflect.Kind {
	return reflect.Float64
}

func (t floatType) Check(v interface{}) bool {
	return checkFloat64(v)
}

func (t floatType) Convert(v interface{}) (interface{}, error) {
	return convertToFloat64(v)
}

func (t floatType) Compare(a interface{}, b interface{}) int {
	return compareFloat64(a, b)
}

func (t floatType) Native(v interface{}) driver.Value {
	return driver.Value(v.(float64))
}

func checkString(v interface{}) bool {
	_, ok := v.(string)
	return ok
}

func convertToString(v interface{}) (interface{}, error) {
	switch v.(type) {
	case string:
		return v.(string), nil
	case fmt.Stringer:
		return v.(fmt.Stringer).String(), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareString(a interface{}, b interface{}) int {
	av := a.(string)
	bv := b.(string)
	return strings.Compare(av, bv)
}

func checkInt32(v interface{}) bool {
	_, ok := v.(int32)
	return ok
}

func convertToInt32(v interface{}) (interface{}, error) {
	switch v.(type) {
	case int:
		return int32(v.(int)), nil
	case int8:
		return int32(v.(int8)), nil
	case int16:
		return int32(v.(int16)), nil
	case int32:
		return v.(int32), nil
	case int64:
		i64 := v.(int64)
		if i64 > (1<<31)-1 || i64 < -(1<<31) {
			return nil, fmt.Errorf("value %d overflows int32", i64)
		}
		return int32(i64), nil
	case uint8:
		return int32(v.(uint8)), nil
	case uint16:
		return int32(v.(uint16)), nil
	case uint:
		u := v.(uint)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case uint32:
		u := v.(uint32)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case uint64:
		u := v.(uint64)
		if u > (1<<31)-1 {
			return nil, fmt.Errorf("value %d overflows int32", v)
		}
		return int32(u), nil
	case string:
		s := v.(string)
		i, err := strconv.Atoi(s)
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int32", v)
		}
		return int32(i), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareInt32(a interface{}, b interface{}) int {
	av := a.(int32)
	bv := b.(int32)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkInt64(v interface{}) bool {
	_, ok := v.(int64)
	return ok
}

func convertToInt64(v interface{}) (interface{}, error) {
	switch v.(type) {
	case int:
		return int64(v.(int)), nil
	case int8:
		return int64(v.(int8)), nil
	case int16:
		return int64(v.(int16)), nil
	case int32:
		return int64(v.(int32)), nil
	case int64:
		return v.(int64), nil
	case uint:
		return int64(v.(uint)), nil
	case uint8:
		return int64(v.(uint8)), nil
	case uint16:
		return int64(v.(uint16)), nil
	case uint32:
		return int64(v.(uint32)), nil
	case uint64:
		u := v.(uint64)
		if u >= 1<<63 {
			return nil, fmt.Errorf("value %d overflows int64", v)
		}
		return int64(u), nil
	case string:
		s := v.(string)
		i, err := strconv.Atoi(s)
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int64", v)
		}
		return int64(i), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareInt64(a interface{}, b interface{}) int {
	av := a.(int64)
	bv := b.(int64)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkBoolean(v interface{}) bool {
	_, ok := v.(bool)
	return ok
}

func convertToBool(v interface{}) (interface{}, error) {
	switch v.(type) {
	case bool:
		return v.(bool), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareBool(a interface{}, b interface{}) int {
	av := a.(bool)
	bv := b.(bool)
	if av == bv {
		return 0
	} else if av == false {
		return -1
	} else {
		return 1
	}
}

func checkFloat64(v interface{}) bool {
	_, ok := v.(float32)
	return ok
}

func convertToFloat64(v interface{}) (interface{}, error) {
	switch v.(type) {
	case float32:
		return v.(float32), nil
	default:
		return nil, ErrInvalidType
	}
}

func compareFloat64(a interface{}, b interface{}) int {
	av := a.(float32)
	bv := b.(float32)
	if av < bv {
		return -1
	} else if av > bv {
		return 1
	}
	return 0
}

func checkTimestamp(v interface{}) bool {
	_, ok := v.(time.Time)
	return ok
}

const timestampLayout = "2006-01-02 15:04:05.000000"

func convertToTimestamp(v interface{}) (interface{}, error) {
	switch v.(type) {
	case string:
		t, err := time.Parse(timestampLayout, v.(string))
		if err != nil {
			return nil, fmt.Errorf("value %q can't be converted to int64", v)
		}
		return t, nil
	default:
		if !BigInteger.Check(v) {
			return nil, ErrInvalidType
		}

		bi, err := BigInteger.Convert(v)
		if err != nil {
			return nil, ErrInvalidType
		}

		return time.Unix(bi.(int64), 0), nil
	}
}

func compareTimestamp(a interface{}, b interface{}) int {
	av := a.(time.Time)
	bv := b.(time.Time)
	if av.Before(bv) {
		return -1
	} else if av.After(bv) {
		return 1
	}
	return 0
}
<|endoftext|>


<commit_before>package argon2

import (
	"github.com/martinlindhe/base36"
	argon2lib "golang.org/x/crypto/argon2"
)

// HashSimple returns an argon2id hashed password encoded in Base36.
func HashSimpleBase36(input, salt []byte) string {
	return base36.EncodeBytes(argon2lib.IDKey(input, salt, 1, 64*1024, 4, 32))
}
<commit_msg>update comments<commit_after>package argon2

import (
	"github.com/martinlindhe/base36"
	argon2lib "golang.org/x/crypto/argon2"
)

// HashSimple returns an argon2id hashed password encoded in Base36.
// The base36 library always returns upper case.
func HashSimpleBase36(input, salt []byte) string {
	return base36.EncodeBytes(argon2lib.IDKey(input, salt, 1, 64*1024, 4, 32))
}
<|endoftext|>


<commit_before>// Package rfc4757 provides encryption and checksum methods as specified in RFC 4757
package rfc4757

import (
	"bytes"
	"crypto/rand"
	"crypto/rc4"
	"errors"
	"fmt"
	"github.com/jcmturner/gokrb5/crypto/etype"
)

// EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 4757.
func EncryptData(key, data []byte, e etype.EType) ([]byte, error) {
	if len(key) != e.GetKeyByteSize() {
		return []byte{}, fmt.Errorf("Incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
	}
	rc4Cipher, err := rc4.NewCipher(key)
	if err != nil {
		return []byte{}, fmt.Errorf("Error creating RC4 cipher: %v", err)
	}
	ed := make([]byte, len(data))
	copy(ed, data)
	rc4Cipher.XORKeyStream(ed, ed)
	rc4Cipher.Reset()
	return ed, nil
}

// DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 4757.
func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
	return EncryptData(key, data, e)
}

// EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
// The encrypted data is concatenated with its RC4 header containing integrity checksum and confounder to create an encrypted message.
func EncryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
	confounder := make([]byte, e.GetConfounderByteSize()) // size = 8
	_, err := rand.Read(confounder)
	if err != nil {
		return []byte{}, fmt.Errorf("Error generating confounder: %v", err)
	}
	k1 := key
	k2 := HMAC(k1, UsageToMSMsgType(usage))
	toenc := append(confounder, data...)
	chksum := HMAC(k2, toenc)
	k3 := HMAC(k2, chksum)

	ed, err := EncryptData(k3, toenc, e)
	if err != nil {
		return []byte{}, fmt.Errorf("Error encrypting data: %v", err)
	}

	msg := append(chksum, ed...)
	return msg, nil
}

// DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
// The integrity of the message is also verified.
func DecryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
	checksum := data[:e.GetHMACBitLength()/8]
	ct := data[e.GetHMACBitLength()/8:]
	_, k2, k3 := deriveKeys(key, checksum, usage, export)

	pt, err := DecryptData(k3, ct, e)
	if err != nil {
		return []byte{}, fmt.Errorf("Error decrypting data: %v", err)
	}

	if !VerifyIntegrity(k2, pt, data, e) {
		return []byte{}, errors.New("Integrity checksum incorrect")
	}
	return pt[e.GetConfounderByteSize():], nil
}

func VerifyIntegrity(key, pt, data []byte, e etype.EType) bool {
	chksum := HMAC(key, pt)
	if bytes.Equal(chksum, data[:e.GetHMACBitLength()/8]) {
		return true
	}
	return false
}
<commit_msg>comment update<commit_after>// Package rfc4757 provides encryption and checksum methods as specified in RFC 4757
package rfc4757

import (
	"bytes"
	"crypto/rand"
	"crypto/rc4"
	"errors"
	"fmt"
	"github.com/jcmturner/gokrb5/crypto/etype"
)

// EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 4757.
func EncryptData(key, data []byte, e etype.EType) ([]byte, error) {
	if len(key) != e.GetKeyByteSize() {
		return []byte{}, fmt.Errorf("Incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
	}
	rc4Cipher, err := rc4.NewCipher(key)
	if err != nil {
		return []byte{}, fmt.Errorf("Error creating RC4 cipher: %v", err)
	}
	ed := make([]byte, len(data))
	copy(ed, data)
	rc4Cipher.XORKeyStream(ed, ed)
	rc4Cipher.Reset()
	return ed, nil
}

// DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 4757.
func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
	return EncryptData(key, data, e)
}

// EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
// The encrypted data is concatenated with its RC4 header containing integrity checksum and confounder to create an encrypted message.
func EncryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
	confounder := make([]byte, e.GetConfounderByteSize()) // size = 8
	_, err := rand.Read(confounder)
	if err != nil {
		return []byte{}, fmt.Errorf("Error generating confounder: %v", err)
	}
	k1 := key
	k2 := HMAC(k1, UsageToMSMsgType(usage))
	toenc := append(confounder, data...)
	chksum := HMAC(k2, toenc)
	k3 := HMAC(k2, chksum)

	ed, err := EncryptData(k3, toenc, e)
	if err != nil {
		return []byte{}, fmt.Errorf("Error encrypting data: %v", err)
	}

	msg := append(chksum, ed...)
	return msg, nil
}

// DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
// The integrity of the message is also verified.
func DecryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
	checksum := data[:e.GetHMACBitLength()/8]
	ct := data[e.GetHMACBitLength()/8:]
	_, k2, k3 := deriveKeys(key, checksum, usage, export)

	pt, err := DecryptData(k3, ct, e)
	if err != nil {
		return []byte{}, fmt.Errorf("Error decrypting data: %v", err)
	}

	if !VerifyIntegrity(k2, pt, data, e) {
		return []byte{}, errors.New("Integrity checksum incorrect")
	}
	return pt[e.GetConfounderByteSize():], nil
}

// VerifyIntegrity checks the integrity checksum of the data matches that calculated from the decrypted data.
func VerifyIntegrity(key, pt, data []byte, e etype.EType) bool {
	chksum := HMAC(key, pt)
	if bytes.Equal(chksum, data[:e.GetHMACBitLength()/8]) {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

func init() {
	addTestCases(errgoMaskTests, errgoMask)
	addTestCases(errgoCauseTests, errgoCause)
}

var errgoMaskTests = []testCase{{
	Name: "errgo-mask.0",
	In: `package main

import (
	"errors"
	"fmt"
	"github.com/errgo/errgo"
	gc "launchpad.net/gocheck"
)

var errSomething = errors.New("foo")

func f() error {
	if err := foo(); err != nil {
		return fmt.Errorf("failure: %v", err)
	}
	errgo.New("foo: %s, %s", arg1, arg2)
	errgo.Annotate(err, "blah")
	errgo.Annotatef(err, "blah: %s, %s", arg1, arg2)
	return fmt.Errorf("cannot something: %s, %s", x, y)
}

func wrapper() (int, error) {
	if x, err := foo(); err != nil {
		return 0, err
	}
	if err := foo(); err != nil {
		return 0, err // A comment
	}
	return 24, nil
}
`,
	Out: `package main

import (
	"fmt"
	"launchpad.net/errgo/v2/errors"
	gc "launchpad.net/gocheck"
)

var errSomething = errors.New("foo")

func f() error {
	if err := foo(); err != nil {
		return errors.Notef(err, "failure")
	}
	errors.Newf("foo: %s, %s", arg1, arg2)
	errors.NoteMask(err, "blah")
	errors.Notef(err, "blah: %s, %s", arg1, arg2)
	return errors.Newf("cannot something: %s, %s", x, y)
}

func wrapper() (int, error) {
	if x, err := foo(); err != nil {
		return 0, errors.Mask(err)
	}
	if err := foo(); err != nil {
		return 0, errors. // A comment
					Mask(err)
	}
	return 24, nil
}
`,
}}

var errgoCauseTests = []testCase{{
	Name: "errgo-cause.0",
	In: `package main

import (
	"errors"
	"fmt"
	gc "launchpad.net/gocheck"
)

func (*suite) TestSomething(c *gc.C) {
	err := foo()
	c.Check(err, gc.Equals, errSomething)
	c.Check(err, gc.Not(gc.Equals), errSomething)
	c.Check(err, gc.Equals, nil)
	c.Check(err, gc.Not(gc.Equals), nil)
}

func tester() error {
	if err := foo(); err == errSomething {
		return nil
	}
	if err := foo(); err == nil {
		return nil
	}
	return nil
}
`,
	Out: `package main

import (
	"fmt"
	"launchpad.net/errgo/v2/errors"
	gc "launchpad.net/gocheck"
)

func (*suite) TestSomething(c *gc.C) {
	err := foo()
	c.Check(errors.Cause(err), gc.Equals, errSomething)
	c.Check(errors.Cause(err), gc.Not(gc.Equals), errSomething)
	c.Check(err, gc.Equals, nil)
	c.Check(err, gc.Not(gc.Equals), nil)
}

func tester() error {
	if err := foo(); errors.Cause(err) == errSomething {
		return nil
	}
	if err := foo(); err == nil {
		return nil
	}
	return nil
}
`,
}}
<commit_msg>exp/cmd/errfix: illustrate comment problem more realistically<commit_after>package main

func init() {
	addTestCases(errgoMaskTests, errgoMask)
	addTestCases(errgoCauseTests, errgoCause)
}

var errgoMaskTests = []testCase{{
	Name: "errgo-mask.0",
	In: `package main

import (
	"errors"
	"fmt"
	"github.com/errgo/errgo"
	gc "launchpad.net/gocheck"
)

var errSomething = errors.New("foo")

func f() error {
	if err := foo(); err != nil {
		return fmt.Errorf("failure: %v", err)
	}
	errgo.New("foo: %s, %s", arg1, arg2)
	errgo.Annotate(err, "blah")
	errgo.Annotatef(err, "blah: %s, %s", arg1, arg2)
	return fmt.Errorf("cannot something: %s, %s", x, y)
}

func wrapper() (int, error) {
	if x, err := foo(); err != nil {
		return 0, err
	}
	if err := foo(); err != nil {
		return 0, err
	}
	// A comment
	return 24, nil
}
`,
	Out: `package main

import (
	"fmt"
	"launchpad.net/errgo/v2/errors"
	gc "launchpad.net/gocheck"
)

var errSomething = errors.New("foo")

func f() error {
	if err := foo(); err != nil {
		return errors.Notef(err, "failure")
	}
	errors.Newf("foo: %s, %s", arg1, arg2)
	errors.NoteMask(err, "blah")
	errors.Notef(err, "blah: %s, %s", arg1, arg2)
	return errors.Newf("cannot something: %s, %s", x, y)
}

func wrapper() (int, error) {
	if x, err := foo(); err != nil {
		return 0, errors.Mask(err)
	}
	if err := foo(); err != nil {
		return 0, errors.Mask(

			// A comment
			err)
	}

	return 24, nil
}
`,
}}

var errgoCauseTests = []testCase{{
	Name: "errgo-cause.0",
	In: `package main

import (
	"errors"
	"fmt"
	gc "launchpad.net/gocheck"
)

func (*suite) TestSomething(c *gc.C) {
	err := foo()
	c.Check(err, gc.Equals, errSomething)
	c.Check(err, gc.Not(gc.Equals), errSomething)
	c.Check(err, gc.Equals, nil)
	c.Check(err, gc.Not(gc.Equals), nil)
}

func tester() error {
	if err := foo(); err == errSomething {
		return nil
	}
	if err := foo(); err == nil {
		return nil
	}
	return nil
}
`,
	Out: `package main

import (
	"fmt"
	"launchpad.net/errgo/v2/errors"
	gc "launchpad.net/gocheck"
)

func (*suite) TestSomething(c *gc.C) {
	err := foo()
	c.Check(errors.Cause(err), gc.Equals, errSomething)
	c.Check(errors.Cause(err), gc.Not(gc.Equals), errSomething)
	c.Check(err, gc.Equals, nil)
	c.Check(err, gc.Not(gc.Equals), nil)
}

func tester() error {
	if err := foo(); errors.Cause(err) == errSomething {
		return nil
	}
	if err := foo(); err == nil {
		return nil
	}
	return nil
}
`,
}}
<|endoftext|>


<commit_before>/*
Authentication code.

Author:		Alastair Hughes
Contact:	<hobbitalastair at yandex dot com>
*/

package backend

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"log"
	"net/http"

	"database/sql"
	"golang.org/x/crypto/scrypt"
)

const passwordSize = 256

// internalError ends the request and logs an internal error.
func internalError(fail func(int), err error) {
	fail(http.StatusInternalServerError)
	log.Printf("%q\n", err)
}

// SetPassword sets the given user's password.
func SetPassword(user, password string, db *sql.DB) error {
	salt := make([]byte, passwordSize)
	err := db.QueryRow("SELECT salt FROM users WHERE name=$1", user).Scan(&salt)
	if err != nil {
		return fmt.Errorf("Failed to find existing salt: %q\n", err)
	}
	key, err := encryptPassword(password, salt)
	if err != nil {
		return fmt.Errorf("Failed to encrypt the user password: %q\n", err)
	}
	_, err = db.Exec("UPDATE users SET password=$1 WHERE name=$2", key, user)
	if err != nil {
		return fmt.Errorf("Failed to update the user password: %q\n", err)
	}
	return nil
}

// encryptPassword salts and encrypts the given password.
func encryptPassword(password string, salt []byte) ([]byte, error) {
	// We salt and encrypt the password to avoid potential security issues if
	// the db is stolen.
	// This appears to be reasonably close to "best practice", but the 1<<16
	// value probably should be checked for sanity.
	// FIXME: We don't store the 1<<16 value in the db, but it should be
	// increased as compute power grows. Doing so is complicated since some way
	// of migrating users from the old value would also need to be implemented.
	return scrypt.Key([]byte(password), salt, 1<<16, 8, 1, passwordSize)
}

// authenticateUser checks that the user and password in the given HTTP request.
func authenticateUser(writer http.ResponseWriter, fail func(int), request *http.Request, db *sql.DB) (user string, ok bool) {
	// get the user name and password.
	user, password, ok := request.BasicAuth()
	if !ok {
		writer.Header().Add("WWW-Authenticate", "basic realm=\"\"")
		fail(http.StatusUnauthorized)
		return user, false
	}

	// Retrieve the salt and database password.
	salt := make([]byte, passwordSize)
	dbpassword := []byte("")
	err := db.QueryRow("SELECT salt, password FROM users WHERE name=$1", user).Scan(&salt, &dbpassword)
	if err == sql.ErrNoRows && request.URL.Path == "/login" && request.Method == http.MethodPost {
		// FIXME: Special case creating a new user.
		log.Printf("Creating a new user %s\n", user)
		_, err = rand.Read(salt)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		key, err := encryptPassword(password, salt)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		_, err = db.Exec("INSERT INTO users VALUES ($1, $2, $3, $4)", user, salt, key, false)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		return user, true
	} else if err == sql.ErrNoRows {
		log.Printf("No such user %s\n", user)
		fail(http.StatusForbidden)
		return user, false
	} else if err != nil {
		internalError(fail, err)
		return user, false
	}

	// Check the password.
	if string(dbpassword) == "" {
		// Special case an empty password in the database.
		// This lets us create "public" demonstration accounts.
		return user, true
	}
	key, err := encryptPassword(password, salt)
	if err != nil {
		internalError(fail, err)
		return user, false
	}
	if !bytes.Equal(key, dbpassword) {
		log.Printf("Invalid password for user %s\n", user)
		fail(http.StatusForbidden)
		return user, false
	}
	return user, true
}

// authenticateRequest checks that the given user has permission to complete
// the request.
func authenticateRequest(request *http.Request, defaultResource resource) (ok bool) {
	return ((request.Method == http.MethodGet) && (defaultResource.Permissions()&get != 0)) ||
		((request.Method == http.MethodPut) && (defaultResource.Permissions()&set != 0)) ||
		((request.Method == http.MethodPost) && (defaultResource.Permissions()&create != 0)) ||
		((request.Method == http.MethodDelete) && (defaultResource.Permissions()&delete != 0))
}

// vim: sw=4 ts=4 noexpandtab
<commit_msg>Add a TODO - we shouldn't export SetPassword<commit_after>/*
Authentication code.

Author:		Alastair Hughes
Contact:	<hobbitalastair at yandex dot com>
*/

package backend

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"log"
	"net/http"

	"database/sql"
	"golang.org/x/crypto/scrypt"
)

const passwordSize = 256

// internalError ends the request and logs an internal error.
func internalError(fail func(int), err error) {
	fail(http.StatusInternalServerError)
	log.Printf("%q\n", err)
}

// SetPassword sets the given user's password.
// TODO: We should not need to export this.
func SetPassword(user, password string, db *sql.DB) error {
	salt := make([]byte, passwordSize)
	err := db.QueryRow("SELECT salt FROM users WHERE name=$1", user).Scan(&salt)
	if err != nil {
		return fmt.Errorf("Failed to find existing salt: %q\n", err)
	}
	key, err := encryptPassword(password, salt)
	if err != nil {
		return fmt.Errorf("Failed to encrypt the user password: %q\n", err)
	}
	_, err = db.Exec("UPDATE users SET password=$1 WHERE name=$2", key, user)
	if err != nil {
		return fmt.Errorf("Failed to update the user password: %q\n", err)
	}
	return nil
}

// encryptPassword salts and encrypts the given password.
func encryptPassword(password string, salt []byte) ([]byte, error) {
	// We salt and encrypt the password to avoid potential security issues if
	// the db is stolen.
	// This appears to be reasonably close to "best practice", but the 1<<16
	// value probably should be checked for sanity.
	// FIXME: We don't store the 1<<16 value in the db, but it should be
	// increased as compute power grows. Doing so is complicated since some way
	// of migrating users from the old value would also need to be implemented.
	return scrypt.Key([]byte(password), salt, 1<<16, 8, 1, passwordSize)
}

// authenticateUser checks that the user and password in the given HTTP request.
func authenticateUser(writer http.ResponseWriter, fail func(int), request *http.Request, db *sql.DB) (user string, ok bool) {
	// get the user name and password.
	user, password, ok := request.BasicAuth()
	if !ok {
		writer.Header().Add("WWW-Authenticate", "basic realm=\"\"")
		fail(http.StatusUnauthorized)
		return user, false
	}

	// Retrieve the salt and database password.
	salt := make([]byte, passwordSize)
	dbpassword := []byte("")
	err := db.QueryRow("SELECT salt, password FROM users WHERE name=$1", user).Scan(&salt, &dbpassword)
	if err == sql.ErrNoRows && request.URL.Path == "/login" && request.Method == http.MethodPost {
		// FIXME: Special case creating a new user.
		log.Printf("Creating a new user %s\n", user)
		_, err = rand.Read(salt)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		key, err := encryptPassword(password, salt)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		_, err = db.Exec("INSERT INTO users VALUES ($1, $2, $3, $4)", user, salt, key, false)
		if err != nil {
			internalError(fail, err)
			return user, false
		}
		return user, true
	} else if err == sql.ErrNoRows {
		log.Printf("No such user %s\n", user)
		fail(http.StatusForbidden)
		return user, false
	} else if err != nil {
		internalError(fail, err)
		return user, false
	}

	// Check the password.
	if string(dbpassword) == "" {
		// Special case an empty password in the database.
		// This lets us create "public" demonstration accounts.
		return user, true
	}
	key, err := encryptPassword(password, salt)
	if err != nil {
		internalError(fail, err)
		return user, false
	}
	if !bytes.Equal(key, dbpassword) {
		log.Printf("Invalid password for user %s\n", user)
		fail(http.StatusForbidden)
		return user, false
	}
	return user, true
}

// authenticateRequest checks that the given user has permission to complete
// the request.
func authenticateRequest(request *http.Request, defaultResource resource) (ok bool) {
	return ((request.Method == http.MethodGet) && (defaultResource.Permissions()&get != 0)) ||
		((request.Method == http.MethodPut) && (defaultResource.Permissions()&set != 0)) ||
		((request.Method == http.MethodPost) && (defaultResource.Permissions()&create != 0)) ||
		((request.Method == http.MethodDelete) && (defaultResource.Permissions()&delete != 0))
}

// vim: sw=4 ts=4 noexpandtab
<|endoftext|>


<commit_before>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"path/filepath"
	"strings"
	"testing"
)

func TestNoPackages(t *testing.T) {
	pi, err := buildPackageIndex(packageDefinitionList{})

	if err != nil {
		t.Error("Building index for an empty list returned an error")
	}

	if pi.packageByName == nil || pi.orderedPackages == nil ||
		len(pi.packageByName) != 0 || len(pi.orderedPackages) != 0 {
		t.Error("Index structures are not properly initialized")
	}
}

func dummyPackageDefinition(pkgName string, dep ...string) *packageDefinition {
	var pd packageDefinition
	pd.packageName = pkgName
	pd.pathname = filepath.Join(pkgName, packageDefinitionFilename)
	pd.requires = dep
	return &pd
}

func TestDuplicateDefinition(t *testing.T) {
	pkgList := packageDefinitionList{
		dummyPackageDefinition("base"),
		dummyPackageDefinition("client"),
		dummyPackageDefinition("base"),
	}

	pi, err := buildPackageIndex(pkgList)

	if pi != nil || err == nil || !strings.Contains(err.Error(),
		"duplicate package name: base") {
		t.Error("Package duplicate was not detected")
	}
}

func TestCircularDependency(t *testing.T) {
	pkgList := packageDefinitionList{
		dummyPackageDefinition("a", "b"),
		dummyPackageDefinition("b", "c"),
		dummyPackageDefinition("c", "a"),
	}

	_, err := buildPackageIndex(pkgList)

	if err == nil {
		t.Error("Circular dependency was not detected")
	} else if !strings.Contains(err.Error(),
		"circular dependency detected: a -> b -> c -> a") {
		t.Error("Unexpected circular dependency error: " +
			err.Error())
	}
}
<commit_msg>Add more circular dependency test cases<commit_after>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

import (
	"path/filepath"
	"strings"
	"testing"
)

func TestNoPackages(t *testing.T) {
	pi, err := buildPackageIndex(packageDefinitionList{})

	if err != nil {
		t.Error("Building index for an empty list returned an error")
	}

	if pi.packageByName == nil || pi.orderedPackages == nil ||
		len(pi.packageByName) != 0 || len(pi.orderedPackages) != 0 {
		t.Error("Index structures are not properly initialized")
	}
}

func dummyPackageDefinition(pkgName string, dep ...string) *packageDefinition {
	var pd packageDefinition
	pd.packageName = pkgName
	pd.pathname = filepath.Join(pkgName, packageDefinitionFilename)
	pd.requires = dep
	return &pd
}

func TestDuplicateDefinition(t *testing.T) {
	pkgList := packageDefinitionList{
		dummyPackageDefinition("base"),
		dummyPackageDefinition("client"),
		dummyPackageDefinition("base"),
	}

	pi, err := buildPackageIndex(pkgList)

	if pi != nil || err == nil || !strings.Contains(err.Error(),
		"duplicate package name: base") {
		t.Error("Package duplicate was not detected")
	}
}

func testCircularDependency(t *testing.T,
	pkgList packageDefinitionList, cycle string) {
	_, err := buildPackageIndex(pkgList)

	if err == nil {
		t.Error("Circular dependency was not detected")
	} else if !strings.Contains(err.Error(),
		"circular dependency detected: "+cycle) {
		t.Error("Unexpected circular dependency error: " +
			err.Error())
	}
}

func TestCircularDependency(t *testing.T) {
	testCircularDependency(t, packageDefinitionList{
		dummyPackageDefinition("a", "b"),
		dummyPackageDefinition("b", "c"),
		dummyPackageDefinition("c", "a"),
	}, "a -> b -> c -> a")

	testCircularDependency(t, packageDefinitionList{
		dummyPackageDefinition("a", "b"),
		dummyPackageDefinition("b", "c"),
		dummyPackageDefinition("c", "b", "d"),
		dummyPackageDefinition("d"),
	}, "b -> c -> b")

	testCircularDependency(t, packageDefinitionList{
		dummyPackageDefinition("a", "b", "a"),
		dummyPackageDefinition("b"),
	}, "a -> a")
}
<|endoftext|>


<commit_before>// Package packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

// Packet holds all layers information
type Packet struct {
	Eth     *layers.Ethernet
	IPv4    *layers.IPv4
	IPv6    *layers.IPv6
	TCP     *layers.TCP
	UDP     *layers.UDP
	SrcHost []string
	DstHost []string
	Payload string
}

var (
	device            = "en0"
	snapLen     int32 = 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
)

// NewPacket creates an empty packet info
func NewPacket() *Packet {
	return &Packet{}
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	go func() {
		handle, err = pcap.OpenLive(device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Fatal(err)
		}
		if err := handle.SetBPFFilter(""); err != nil {
			log.Fatal(err)
		}

		defer handle.Close()
		defer close(s)
		defer close(c)

		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			packet, err := packetSource.NextPacket()
			if err != nil {
				continue
			}
			select {
			case <-s:
				loop = false
				signal.Stop(s)
			case c <- GetPacketInfo(packet):
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.Eth.EthernetType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		println("IPV6")
	case layers.EthernetTypeARP:
		println("ARP")
	default:
		println("unknown")

	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {
	var src, dst string

	if len(p.SrcHost) > 0 {
		src = p.SrcHost[0]
	} else {
		src = p.IPv4.SrcIP.String()
	}
	if len(p.DstHost) > 0 {
		dst = p.DstHost[0]
	} else {
		dst = p.IPv4.DstIP.String()
	}

	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("IP/%s %s:%s > %s:%s , len: %d\n",
			p.IPv4.Protocol, src, p.TCP.SrcPort, dst, p.TCP.DstPort, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("IP/%s %s:%s > %s:%s , len: %d\n",
			p.IPv4.Protocol, src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	}
}

// GetPacketInfo decodes layers
func GetPacketInfo(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		p.Eth, _ = ethernetLayer.(*layers.Ethernet)
	}

	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
		p.SrcHost = lookup(p.IPv4.SrcIP)
		p.DstHost = lookup(p.IPv4.DstIP)
	} else {
		// IP Address V6
		ipLayer := packet.Layer(layers.LayerTypeIPv6)
		if ipLayer != nil {
			p.IPv6, _ = ipLayer.(*layers.IPv6)
			p.SrcHost = lookup(p.IPv6.SrcIP)
			p.DstHost = lookup(p.IPv6.DstIP)
		}
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		fmt.Println("Error decoding some part of the packet:", err)
	}
	return &p
}

func lookup(ip net.IP) []string {
	host, _ := net.LookupAddr(ip.String())
	return host
}

func getIFAddrs() map[string]struct{} {
	var r = make(map[string]struct{}, 20)

	ifs, _ := net.Interfaces()
	for _, i := range ifs {
		addrs, _ := i.Addrs()
		for _, addr := range addrs {
			r[addr.String()] = struct{}{}
		}
	}
	return r
}
<commit_msg>init PrintIPv6<commit_after>// Package packet is a wrapper for GoPacket and sub packages
package packet

import (
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
)

// Packet holds all layers information
type Packet struct {
	Eth     *layers.Ethernet
	IPv4    *layers.IPv4
	IPv6    *layers.IPv6
	TCP     *layers.TCP
	UDP     *layers.UDP
	SrcHost []string
	DstHost []string
	Payload string
}

var (
	device            = "en0"
	snapLen     int32 = 1024
	promiscuous       = false
	err         error
	timeout     = 100 * time.Nanosecond
	handle      *pcap.Handle
)

// NewPacket creates an empty packet info
func NewPacket() *Packet {
	return &Packet{}
}

// Open is a loop over packets
func (p *Packet) Open() chan *Packet {
	var (
		c    = make(chan *Packet, 1)
		s    = make(chan os.Signal, 1)
		loop = true
	)
	// capture interrupt w/ s channel
	signal.Notify(s, os.Interrupt)

	go func() {
		handle, err = pcap.OpenLive(device, snapLen, promiscuous, timeout)
		if err != nil {
			log.Fatal(err)
		}
		if err := handle.SetBPFFilter(""); err != nil {
			log.Fatal(err)
		}

		defer handle.Close()
		defer close(s)
		defer close(c)

		packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
		for loop {
			packet, err := packetSource.NextPacket()
			if err != nil {
				continue
			}
			select {
			case <-s:
				loop = false
				signal.Stop(s)
			case c <- ParsePacketLayers(packet):
			}
		}
	}()
	return c
}

// PrintPretty prints out the captured data
// to the stdout
func (p *Packet) PrintPretty() {
	switch p.Eth.EthernetType {
	case layers.EthernetTypeIPv4:
		p.PrintIPv4()
	case layers.EthernetTypeIPv6:
		println("IPV6")
		p.PrintIPv6()
	case layers.EthernetTypeARP:
		println("ARP")
	default:
		println("unknown")

	}
}

// PrintIPv4 prints IPv4 packets
func (p *Packet) PrintIPv4() {
	var src, dst string

	if len(p.SrcHost) > 0 {
		src = p.SrcHost[0]
	} else {
		src = p.IPv4.SrcIP.String()
	}
	if len(p.DstHost) > 0 {
		dst = p.DstHost[0]
	} else {
		dst = p.IPv4.DstIP.String()
	}

	switch {
	case p.IPv4.Protocol == layers.IPProtocolTCP:
		log.Printf("IP4/%s %s:%s > %s:%s , len: %d\n",
			p.IPv4.Protocol, src, p.TCP.SrcPort, dst, p.TCP.DstPort, len(p.Payload))
	case p.IPv4.Protocol == layers.IPProtocolUDP:
		log.Printf("IP4/%s %s:%s > %s:%s , len: %d\n",
			p.IPv4.Protocol, src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	}
}

// PrintIPv6 prints IPv6 packets
func (p *Packet) PrintIPv6() {
	var src, dst string

	if len(p.SrcHost) > 0 {
		src = p.SrcHost[0]
	} else {
		src = p.IPv6.SrcIP.String()
	}
	if len(p.DstHost) > 0 {
		dst = p.DstHost[0]
	} else {
		dst = p.IPv6.DstIP.String()
	}

	switch {
	case p.IPv6.NextHeader == layers.IPProtocolTCP:
		log.Printf("IP6/%s %s:%s > %s:%s , len: %d\n",
			p.IPv6.NextHeader, src, p.TCP.SrcPort, dst, p.TCP.DstPort, len(p.Payload))
	case p.IPv6.NextHeader == layers.IPProtocolUDP:
		log.Printf("IP6/%s %s:%s > %s:%s , len: %d\n",
			p.IPv6.NextHeader, src, p.UDP.SrcPort, dst, p.UDP.DstPort, len(p.Payload))
	}
}

// ParsePacketLayers decodes layers
func ParsePacketLayers(packet gopacket.Packet) *Packet {
	var p Packet
	// Ethernet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		p.Eth, _ = ethernetLayer.(*layers.Ethernet)
	}

	// IP Address V4
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		p.IPv4, _ = ipLayer.(*layers.IPv4)
		p.SrcHost = lookup(p.IPv4.SrcIP)
		p.DstHost = lookup(p.IPv4.DstIP)
	} else {
		// IP Address V6
		ipLayer := packet.Layer(layers.LayerTypeIPv6)
		if ipLayer != nil {
			p.IPv6, _ = ipLayer.(*layers.IPv6)
			p.SrcHost = lookup(p.IPv6.SrcIP)
			p.DstHost = lookup(p.IPv6.DstIP)
		}
	}

	// TCP
	tcpLayer := packet.Layer(layers.LayerTypeTCP)
	if tcpLayer != nil {
		p.TCP, _ = tcpLayer.(*layers.TCP)
	} else {
		// UDP
		udpLayer := packet.Layer(layers.LayerTypeUDP)
		if udpLayer != nil {
			p.UDP, _ = udpLayer.(*layers.UDP)
		}
	}

	// Application
	applicationLayer := packet.ApplicationLayer()
	if applicationLayer != nil {
		p.Payload = string(applicationLayer.Payload())
	}

	// Check for errors
	if err := packet.ErrorLayer(); err != nil {
		fmt.Println("Error decoding some part of the packet:", err)
	}
	return &p
}

func lookup(ip net.IP) []string {
	host, _ := net.LookupAddr(ip.String())
	return host
}

func getIFAddrs() map[string]struct{} {
	var r = make(map[string]struct{}, 20)

	ifs, _ := net.Interfaces()
	for _, i := range ifs {
		addrs, _ := i.Addrs()
		for _, addr := range addrs {
			r[addr.String()] = struct{}{}
		}
	}
	return r
}
<|endoftext|>