<commit_before>package sudoku

// Sudoku has one rule - no value can be repeated horizontally, vertically,
// or in the same section. This gives rise to a few simple rules - and those
// rules are applied across each cluster - without even knowning the orientation
// of the cluster.
//
// In order to make solving possible however, that one rule is enforced with
// the following rules:
//
// 1) If all cells are solved, that cluster is solved.
// 2) If any cell is solved, it has no possibles.
// 3) If any cell is solved, that value is not possible in other cells.
// 4) If any cell only has one possible value, that is that cell's value.
// 5) If any x cells only have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
// 6) If any value only has one possible cell, that is that cell's value.
// 7) If any x values only have x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
//
// Additional Helper functions are included and explained later.

// indexedCLuster is a datatype for an index for the values of the cluster.
// Each possible value is a key in the map. THe value of each key is an array of
// possible locations for that value - the index and order are not defined,
// instead the values of the array are the indexes of possible cells in for that
// value.
type intArray []int
type indexedCluster map[int]intArray

func indexCluster(in []cell) (out indexedCluster) {
	for id, each := range in {
		for _, onePossible_ := range each.possible {
			out[onePossible] = append(out[onePossible], id)
		}
	}
	return out
}

// This covers rule 1 from above:
// 1) If all cells are solved, that cluster is solved.
func clusterSolved(cluster []cell, u chan cell) (solved bool) {
	solved = true
	for _, each := range cluster {
		if each.actual == 0 {
			solved = false
		} else if len(each.possible) > 0 {
			solved = false
		}
	}
	return solved
}

// This covers rule 2 from above:
// 2) If any cell is solved, it has no possibles.
func solvedNoPossible(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		if each.actual == 0 {
			continue
		}
		if len(each.possible) > 0 {
			changed = true
			u <- cell{
				location: each.location,
				possible: each.possible,
			}
		}
	}
	return changed
}

// Removes known values from other possibles in the same cluster
// Covers rule 3 from above:
// 3) If any cell is solved, that value is not possible in other cells.
func eliminateKnowns(workingCluster []cell, u chan cell) (changed bool) {
	var knownValues []int

	// Loop thru and find all solved values.
	for _, each := range workingCluster {
		if each.actual != 0 {
			knownValues = append(knownValues, each.actual)
		}
	}

	for _, each := range workingCluster {
		if anyInArr(each, knownValues) {
			u <- cell{
				location: each.location,
				possible: subArr(each, knownValues)
			}
			changed = true
		}
	}
	return changed
}

// This covers the 4th rule from above:
// 4) If any cell only has one possible value, that is that cell's value.
func singleValueSolver(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		// if the cell is already solved, skip this.
		if each.actual != 0 {
			continue
		}

		// if there is more than one possible value for this cell, you should be good
		if len(each.possible) > 1 {
			continue
		}

		// should never happen - probably #TODO# to catch this
		if len(each.possible) < 1 {
			panic("Found an unsolved cell with no possible values")
		}

		changed = true

		// send back an update for this cell
		u <- cell{
			location: each.location,
			actual:   each.possible[0],
			possible: []int{}
		}
	}
	return changed
}

// A helper function to determine the number of valus hit given a specific set
// of cells.
func cellsCost(markedCells map[int]bool, cluster []cell) int {
	var neededValues map[int]bool
	for cellPos, _ := range markedCells {
		for possibleValue, _ := range cluster[cellPos].possible {
			neededValues[possibleValue] = true
		}
	}
	return len(neededValues)
}

func cellLimiterChild(limit int, markedCells map[int]bool, cluster []cell, u chan cell) (changed bool) {
	valueCount := cellsCost(markedCells, cluster)
	// you have overspent - it's a no-go
	if len(markedCells) > limit {
		return false
	}

	// you have room to add more cells (depth first?)
	if len(markedCells) < limit {
		if valueCount < len(markedCells) {
			// #TODO# probably fix this? rework into error?
			panic("less possible values than squares to fill")
		}
		if valueCount > len(markedCells) {
			// you need to try adding each other cell
			for idCell, oneCell := range cluster {
				if oneCell.actual != 0 {
					continue
				}
				if markedCells[idCell] {
					// this cell is already in the map, skip
					continue
				}

				// decend down into looking at that cell
				childMarkedCells := markedCells // #TODO# map copy
				childMarkedCells[idCell] = true
				if cellLimiterChild(limit, childMarkedCells, cluster, u) {
					// if you got true from the child, pass it on
					return true
				}
			}
		}
	}

	// did you fill the cells? if so, mark it
	if valueCount == len(markedCells) {
		// it's a match - so remove values
		for idCell, oneCell := range cluster {
			if oneCell.actual != 0 {
				// already solved
				continue
			}
			if markedCells[idCell] {
				// this cell is a part of the list - no exclusions needed
				continue
			}
			remove := map[int]bool{}
			for potential, _ := range oneCell.possible {
				if markedCells[idCell] {
					// this possibility exists in the map - need to remove it
					remove[potential] = true
				}
			}
			if len(remove) > 0 {
				changed = true
				u <- cell{
					location: oneCell.location,
					possible: remove,
				}
			}
		}
	}
	return changed
}

// This covers rule 5:
// 5) If any x cells have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
func cellLimiter(cluster []cell, u chan cell) (changed bool) {
	upperBound := len(cluster)
	for _, eachCell := range cluster {
		if eachCell.actual != 0 {
			upperBound--
		}
	}
	for i := 2; i <= upperBound; i++ {
		if cellLimiterChild(i, map[int]bool{}, cluster, u) {
			changed = true
		}
	}
	return changed
}

// This covers rule 6 from above:
// 6) If any value only has one possible cell, that is that cell's value.
func singleCellSolver(index indexedCluster, workingCluster []cell, u chan cell) (changed bool) {
	for val, section := range index {
		if len(section) < 1 {
			// something went terribly wrong here - #TODO# add panic catch?
			panic("Found an unsolved cell with no possible values")
		} else if len(section) == 1 {
			u <- cell{
				location: workingCluster[section[0]].location,
				actual:   val,
			}
			changed = true
		}
	}
	return changed
}

// A helper function to determine the number of cells hit by working across a map
// of values.
func valuesCost(markedVals map[int]bool, index indexedCluster, cluseter []cell) int {
	var neededCells map[int]bool
	for value, _ := range markedVals {
		for oneCell, _ := range index[value] {
			neededCells[oneCell] = true
		}
	}
	return len(neededCells)
}

func valueLimiterChild(limit int, markedValues map[int]bool, index indexedCluster,
	cluster []cell, u chan cell) (changed bool) {
	if len(markedValues) > limit {
		// we have marked more values
		return false
	}
	currentCost := valuesCost(markedValues, index, cluster)
	if currentCost > limit {
		// you're over the budget to spend
		return false
	}
	return changed
}

// THis covers rule 7 from above:
// 7) If any x values have only x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
/*
func valueLimiter(index indexedCluster, cluster []cell, u chan cell) (changed bool) {

}
*/
<commit_msg>changed `singleCellSolver` slightly in line wiht other changes<commit_after>package sudoku

// Sudoku has one rule - no value can be repeated horizontally, vertically,
// or in the same section. This gives rise to a few simple rules - and those
// rules are applied across each cluster - without even knowning the orientation
// of the cluster.
//
// In order to make solving possible however, that one rule is enforced with
// the following rules:
//
// 1) If all cells are solved, that cluster is solved.
// 2) If any cell is solved, it has no possibles.
// 3) If any cell is solved, that value is not possible in other cells.
// 4) If any cell only has one possible value, that is that cell's value.
// 5) If any x cells only have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
// 6) If any value only has one possible cell, that is that cell's value.
// 7) If any x values only have x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
//
// Additional Helper functions are included and explained later.

// indexedCLuster is a datatype for an index for the values of the cluster.
// Each possible value is a key in the map. THe value of each key is an array of
// possible locations for that value - the index and order are not defined,
// instead the values of the array are the indexes of possible cells in for that
// value.
type intArray []int
type indexedCluster map[int]intArray

func indexCluster(in []cell) (out indexedCluster) {
	for id, each := range in {
		for _, onePossible_ := range each.possible {
			out[onePossible] = append(out[onePossible], id)
		}
	}
	return out
}

// This covers rule 1 from above:
// 1) If all cells are solved, that cluster is solved.
func clusterSolved(cluster []cell, u chan cell) (solved bool) {
	solved = true
	for _, each := range cluster {
		if each.actual == 0 {
			solved = false
		} else if len(each.possible) > 0 {
			solved = false
		}
	}
	return solved
}

// This covers rule 2 from above:
// 2) If any cell is solved, it has no possibles.
func solvedNoPossible(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		if each.actual == 0 {
			continue
		}
		if len(each.possible) > 0 {
			changed = true
			u <- cell{
				location: each.location,
				possible: each.possible,
			}
		}
	}
	return changed
}

// Removes known values from other possibles in the same cluster
// Covers rule 3 from above:
// 3) If any cell is solved, that value is not possible in other cells.
func eliminateKnowns(workingCluster []cell, u chan cell) (changed bool) {
	var knownValues []int

	// Loop thru and find all solved values.
	for _, each := range workingCluster {
		if each.actual != 0 {
			knownValues = append(knownValues, each.actual)
		}
	}

	for _, each := range workingCluster {
		if anyInArr(each, knownValues) {
			u <- cell{
				location: each.location,
				possible: subArr(each, knownValues)
			}
			changed = true
		}
	}
	return changed
}

// This covers the 4th rule from above:
// 4) If any cell only has one possible value, that is that cell's value.
func singleValueSolver(cluster []cell, u chan cell) (changed bool) {
	for _, each := range cluster {
		// if the cell is already solved, skip this.
		if each.actual != 0 {
			continue
		}

		// if there is more than one possible value for this cell, you should be good
		if len(each.possible) > 1 {
			continue
		}

		// should never happen - probably #TODO# to catch this
		if len(each.possible) < 1 {
			panic("Found an unsolved cell with no possible values")
		}

		changed = true

		// send back an update for this cell
		u <- cell{
			location: each.location,
			actual:   each.possible[0],
			possible: []int{}
		}
	}
	return changed
}

// A helper function to determine the number of valus hit given a specific set
// of cells.
func cellsCost(markedCells map[int]bool, cluster []cell) int {
	var neededValues map[int]bool
	for cellPos, _ := range markedCells {
		for possibleValue, _ := range cluster[cellPos].possible {
			neededValues[possibleValue] = true
		}
	}
	return len(neededValues)
}

func cellLimiterChild(limit int, markedCells map[int]bool, cluster []cell, u chan cell) (changed bool) {
	valueCount := cellsCost(markedCells, cluster)
	// you have overspent - it's a no-go
	if len(markedCells) > limit {
		return false
	}

	// you have room to add more cells (depth first?)
	if len(markedCells) < limit {
		if valueCount < len(markedCells) {
			// #TODO# probably fix this? rework into error?
			panic("less possible values than squares to fill")
		}
		if valueCount > len(markedCells) {
			// you need to try adding each other cell
			for idCell, oneCell := range cluster {
				if oneCell.actual != 0 {
					continue
				}
				if markedCells[idCell] {
					// this cell is already in the map, skip
					continue
				}

				// decend down into looking at that cell
				childMarkedCells := markedCells // #TODO# map copy
				childMarkedCells[idCell] = true
				if cellLimiterChild(limit, childMarkedCells, cluster, u) {
					// if you got true from the child, pass it on
					return true
				}
			}
		}
	}

	// did you fill the cells? if so, mark it
	if valueCount == len(markedCells) {
		// it's a match - so remove values
		for idCell, oneCell := range cluster {
			if oneCell.actual != 0 {
				// already solved
				continue
			}
			if markedCells[idCell] {
				// this cell is a part of the list - no exclusions needed
				continue
			}
			remove := map[int]bool{}
			for potential, _ := range oneCell.possible {
				if markedCells[idCell] {
					// this possibility exists in the map - need to remove it
					remove[potential] = true
				}
			}
			if len(remove) > 0 {
				changed = true
				u <- cell{
					location: oneCell.location,
					possible: remove,
				}
			}
		}
	}
	return changed
}

// This covers rule 5:
// 5) If any x cells have x possible values, those values are not possible
//  outside of those cells - those values are constrained to those cells.
func cellLimiter(cluster []cell, u chan cell) (changed bool) {
	upperBound := len(cluster)
	for _, eachCell := range cluster {
		if eachCell.actual != 0 {
			upperBound--
		}
	}
	for i := 2; i <= upperBound; i++ {
		if cellLimiterChild(i, map[int]bool{}, cluster, u) {
			changed = true
		}
	}
	return changed
}

// This covers rule 6 from above:
// 6) If any value only has one possible cell, that is that cell's value.
func singleCellSolver(index indexedCluster, cluster []cell, u chan cell) (changed bool) {
	for val, section := range index {
		if len(section) < 1 {
			// something went terribly wrong here - #TODO# add panic catch?
			panic("Found an unsolved cell with no possible values")
		} else if len(section) == 1 {
			u <- cell{
				location: cluster[section[0]].location,
				actual:   val,
				possible: []int{},
			}
			changed = true
		}
	}
	return changed
}

// A helper function to determine the number of cells hit by working across a map
// of values.
func valuesCost(markedVals map[int]bool, index indexedCluster, cluseter []cell) int {
	var neededCells map[int]bool
	for value, _ := range markedVals {
		for oneCell, _ := range index[value] {
			neededCells[oneCell] = true
		}
	}
	return len(neededCells)
}

func valueLimiterChild(limit int, markedValues map[int]bool, index indexedCluster,
	cluster []cell, u chan cell) (changed bool) {
	if len(markedValues) > limit {
		// we have marked more values
		return false
	}
	currentCost := valuesCost(markedValues, index, cluster)
	if currentCost > limit {
		// you're over the budget to spend
		return false
	}
	return changed
}

// THis covers rule 7 from above:
// 7) If any x values have only x possible cells, those cells only have those
//  possible values - those cells are constrained to those values.
/*
func valueLimiter(index indexedCluster, cluster []cell, u chan cell) (changed bool) {

}
*/
<|endoftext|>


<commit_before>// IronMQ (elastic message queue) client library
package mq

import (
	"errors"
	"time"

	"github.com/iron-io/iron_go/api"
	"github.com/iron-io/iron_go/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueSubscriber struct {
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers,omitempty"`
}

type QueueInfo struct {
	Id            string            `json:"id,omitempty"`
	Name          string            `json:"name,omitempty"`
	PushType      string            `json:"push_type,omitempty"`
	Reserved      int               `json:"reserved,omitempty"`
	RetriesDelay  int               `json:"retries_delay,omitempty"`
	Retries       int               `json:"retries,omitempty"`
	Size          int               `json:"size,omitempty"`
	Subscribers   []QueueSubscriber `json:"subscribers,omitempty"`
	Alerts        []Alert           `json:"alerts,omitempty"`
	TotalMessages int               `json:"total_messages,omitempty"`
	ErrorQueue    string            `json:"error_queue,omitempty"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

type PushStatus struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
}

type Subscriber struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
	URL        string `json:"url"`
}

type Alert struct {
	Type      string `json:"type"`
	Direction string `json:direction`
	Trigger   int    `json:trigger`
	Queue     string `queue`
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

// ConfigNew uses the specified settings over configuration specified in an iron.json file or
// environment variables to return a Queue object capable of acquiring information about or
// modifying the queue specified by queueName.
func ConfigNew(queueName string, settings *config.Settings) Queue {
	return Queue{Settings: config.ManualConfig("iron_mq", settings), Name: queueName}
}

func ListSettingsQueues(settings config.Settings, page int, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	q := New("")
	q.Settings = settings
	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func ListProjectQueues(projectId string, token string, page int, perPage int) (queues []Queue, err error) {
	settings := config.Config("iron_mq")
	settings.ProjectId = projectId
	settings.Token = token
	return ListSettingsQueues(settings, page, perPage)
}

func ListQueues(page, perPage int) (queues []Queue, err error) {
	settings := config.Config("iron_mq")
	return ListProjectQueues(settings.ProjectId, settings.Token, page, perPage)
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

// This method is left to support backward compatibility.
// This method is replaced by func ListQueues(page, perPage int) (queues []Queue, err error)
func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	return ListQueues(page, perPage)
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

func (q Queue) Update(qi QueueInfo) (QueueInfo, error) {
	out := QueueInfo{}
	err := q.queues(q.Name).Req("POST", qi, &out)
	return out, err
}

func (q Queue) Delete() (bool, error) {
	err := q.queues(q.Name).Req("DELETE", nil, nil)
	success := err == nil
	return success, err
}

type Subscription struct {
	PushType     string
	Retries      int
	RetriesDelay int
}

// RemoveSubscribers removes subscribers.
func (q Queue) RemoveSubscribers(subscribers ...string) (err error) {
	qi := QueueInfo{Subscribers: make([]QueueSubscriber, len(subscribers))}
	for i, subscriber := range subscribers {
		qi.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name, "subscribers").Req("DELETE", &qi, nil)
}

// AddSubscribers adds subscribers.
func (q Queue) AddSubscribers(subscribers ...string) (err error) {
	qi := QueueInfo{Subscribers: make([]QueueSubscriber, len(subscribers))}
	for i, subscriber := range subscribers {
		qi.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name, "subscribers").Req("POST", &qi, nil)
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// get N messages
func (q Queue) GetN(n int) (msgs []*Message, err error) {
	return q.GetNWithTimeoutAndWait(n, 0, 0)
}

func (q Queue) GetNWithTimeout(n, timeout int) (msgs []*Message, err error) {
	return q.GetNWithTimeoutAndWait(n, timeout, 0)
}

func (q Queue) GetNWithTimeoutAndWait(n, timeout, wait int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		QueryAdd("timeout", "%d", timeout).
		QueryAdd("wait", "%d", wait).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

func (q Queue) Peek() (msg *Message, err error) {
	msgs, err := q.PeekN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// peek N messages
func (q Queue) PeekN(n int) (msgs []*Message, err error) {
	msgs, err = q.PeekNWithTimeout(n, 0)

	return
}

func (q Queue) PeekNWithTimeout(n, timeout int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages", "peek").
		QueryAdd("n", "%d", n).
		QueryAdd("timeout", "%d", timeout).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

// Delete all messages in the queue
func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

// Delete message from queue
func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

// Reset timeout of message to keep it reserved
func (q Queue) TouchMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "touch").Req("POST", nil, nil)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (q Queue) ReleaseMessage(msgId string, delay int64) (err error) {
	in := struct {
		Delay int64 `json:"delay"`
	}{Delay: delay}
	return q.queues(q.Name, "messages", msgId, "release").Req("POST", &in, nil)
}

func (q Queue) MessageSubscribers(msgId string) ([]*Subscriber, error) {
	out := struct {
		Subscribers []*Subscriber `json:"subscribers"`
	}{}
	err := q.queues(q.Name, "messages", msgId, "subscribers").Req("GET", nil, &out)
	return out.Subscribers, err
}

func (q Queue) MessageSubscribersPollN(msgId string, n int) ([]*Subscriber, error) {
	subs, err := q.MessageSubscribers(msgId)
	for {
		time.Sleep(100 * time.Millisecond)
		subs, err = q.MessageSubscribers(msgId)
		if err != nil {
			return subs, err
		}
		if len(subs) >= n && actualPushStatus(subs) {
			return subs, nil
		}
	}
	return subs, err
}

func actualPushStatus(subs []*Subscriber) bool {
	for _, sub := range subs {
		if sub.Status == "queued" {
			return false
		}
	}

	return true
}

func (q Queue) AddAlerts(alerts ...*Alert) (err error) {
	in := struct {
		Alerts []*Alert `json:"alerts"`
	}{Alerts: alerts}
	return q.queues(q.Name, "alerts").Req("POST", &in, nil)
}

func (q Queue) UpdateAlerts(alerts ...*Alert) (err error) {
	in := struct {
		Alerts []*Alert `json:"alerts"`
	}{Alerts: alerts}
	return q.queues(q.Name, "alerts").Req("PUT", &in, nil)
}

func (q Queue) RemoveAllAlerts() (err error) {
	return q.queues(q.Name, "alerts").Req("DELETE", nil, nil)
}

type AlertInfo struct {
	Id string `json:"id"`
}

func (q Queue) RemoveAlerts(alertIds ...string) (err error) {
	in := struct {
		Alerts []AlertInfo `json:"alerts"`
	}{Alerts: make([]AlertInfo, len(alertIds))}
	for i, alertId := range alertIds {
		(in.Alerts[i]).Id = alertId
	}
	return q.queues(q.Name, "alerts").Req("DELETE", &in, nil)
}

func (q Queue) RemoveAlert(alertId string) (err error) {
	return q.queues(q.Name, "alerts", alertId).Req("DELETE", nil, nil)
}

// Delete message from queue
func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}

// Reset timeout of message to keep it reserved
func (m Message) Touch() (err error) {
	return m.q.TouchMessage(m.Id)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (m Message) Release(delay int64) (err error) {
	return m.q.ReleaseMessage(m.Id, delay)
}

func (m Message) Subscribers() (interface{}, error) {
	return m.q.MessageSubscribers(m.Id)
}
<commit_msg>add multi delete message<commit_after>// IronMQ (elastic message queue) client library
package mq

import (
	"errors"
	"time"

	"github.com/iron-io/iron_go/api"
	"github.com/iron-io/iron_go/config"
)

type Queue struct {
	Settings config.Settings
	Name     string
}

type QueueSubscriber struct {
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers,omitempty"`
}

type QueueInfo struct {
	Id            string            `json:"id,omitempty"`
	Name          string            `json:"name,omitempty"`
	PushType      string            `json:"push_type,omitempty"`
	Reserved      int               `json:"reserved,omitempty"`
	RetriesDelay  int               `json:"retries_delay,omitempty"`
	Retries       int               `json:"retries,omitempty"`
	Size          int               `json:"size,omitempty"`
	Subscribers   []QueueSubscriber `json:"subscribers,omitempty"`
	Alerts        []Alert           `json:"alerts,omitempty"`
	TotalMessages int               `json:"total_messages,omitempty"`
	ErrorQueue    string            `json:"error_queue,omitempty"`
}

type Message struct {
	Id   string `json:"id,omitempty"`
	Body string `json:"body"`
	// Timeout is the amount of time in seconds allowed for processing the
	// message.
	Timeout int64 `json:"timeout,omitempty"`
	// Delay is the amount of time in seconds to wait before adding the message
	// to the queue.
	Delay int64 `json:"delay,omitempty"`
	q     Queue
}

type PushStatus struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
}

type Subscriber struct {
	Retried    int    `json:"retried"`
	StatusCode int    `json:"status_code"`
	Status     string `json:"status"`
	URL        string `json:"url"`
}

type Alert struct {
	Type      string `json:"type"`
	Direction string `json:direction`
	Trigger   int    `json:trigger`
	Queue     string `queue`
}

func New(queueName string) *Queue {
	return &Queue{Settings: config.Config("iron_mq"), Name: queueName}
}

// ConfigNew uses the specified settings over configuration specified in an iron.json file or
// environment variables to return a Queue object capable of acquiring information about or
// modifying the queue specified by queueName.
func ConfigNew(queueName string, settings *config.Settings) Queue {
	return Queue{Settings: config.ManualConfig("iron_mq", settings), Name: queueName}
}

func ListSettingsQueues(settings config.Settings, page int, perPage int) (queues []Queue, err error) {
	out := []struct {
		Id         string
		Project_id string
		Name       string
	}{}

	q := New("")
	q.Settings = settings
	err = q.queues().
		QueryAdd("page", "%d", page).
		QueryAdd("per_page", "%d", perPage).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	queues = make([]Queue, 0, len(out))
	for _, item := range out {
		queues = append(queues, Queue{
			Settings: q.Settings,
			Name:     item.Name,
		})
	}

	return
}

func ListProjectQueues(projectId string, token string, page int, perPage int) (queues []Queue, err error) {
	settings := config.Config("iron_mq")
	settings.ProjectId = projectId
	settings.Token = token
	return ListSettingsQueues(settings, page, perPage)
}

func ListQueues(page, perPage int) (queues []Queue, err error) {
	settings := config.Config("iron_mq")
	return ListProjectQueues(settings.ProjectId, settings.Token, page, perPage)
}

func (q Queue) queues(s ...string) *api.URL { return api.Action(q.Settings, "queues", s...) }

// This method is left to support backward compatibility.
// This method is replaced by func ListQueues(page, perPage int) (queues []Queue, err error)
func (q Queue) ListQueues(page, perPage int) (queues []Queue, err error) {
	return ListQueues(page, perPage)
}

func (q Queue) Info() (QueueInfo, error) {
	qi := QueueInfo{}
	err := q.queues(q.Name).Req("GET", nil, &qi)
	return qi, err
}

func (q Queue) Update(qi QueueInfo) (QueueInfo, error) {
	out := QueueInfo{}
	err := q.queues(q.Name).Req("POST", qi, &out)
	return out, err
}

func (q Queue) Delete() (bool, error) {
	err := q.queues(q.Name).Req("DELETE", nil, nil)
	success := err == nil
	return success, err
}

type Subscription struct {
	PushType     string
	Retries      int
	RetriesDelay int
}

// RemoveSubscribers removes subscribers.
func (q Queue) RemoveSubscribers(subscribers ...string) (err error) {
	qi := QueueInfo{Subscribers: make([]QueueSubscriber, len(subscribers))}
	for i, subscriber := range subscribers {
		qi.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name, "subscribers").Req("DELETE", &qi, nil)
}

// AddSubscribers adds subscribers.
func (q Queue) AddSubscribers(subscribers ...string) (err error) {
	qi := QueueInfo{Subscribers: make([]QueueSubscriber, len(subscribers))}
	for i, subscriber := range subscribers {
		qi.Subscribers[i].URL = subscriber
	}
	return q.queues(q.Name, "subscribers").Req("POST", &qi, nil)
}

func (q Queue) PushString(body string) (id string, err error) {
	ids, err := q.PushStrings(body)
	if err != nil {
		return
	}
	return ids[0], nil
}

// Push adds one or more messages to the end of the queue using IronMQ's defaults:
//	timeout - 60 seconds
//	delay - none
//
// Identical to PushMessages with Message{Timeout: 60, Delay: 0}
func (q Queue) PushStrings(bodies ...string) (ids []string, err error) {
	msgs := make([]*Message, 0, len(bodies))
	for _, body := range bodies {
		msgs = append(msgs, &Message{Body: body})
	}

	return q.PushMessages(msgs...)
}

func (q Queue) PushMessage(msg *Message) (id string, err error) {
	ids, err := q.PushMessages(msg)
	if err != nil {
		return
	}
	return ids[0], nil
}

func (q Queue) PushMessages(msgs ...*Message) (ids []string, err error) {
	in := struct {
		Messages []*Message `json:"messages"`
	}{Messages: msgs}

	out := struct {
		IDs []string `json:"ids"`
		Msg string   `json:"msg"`
	}{}

	err = q.queues(q.Name, "messages").Req("POST", &in, &out)
	return out.IDs, err
}

// Get reserves a message from the queue.
// The message will not be deleted, but will be reserved until the timeout
// expires. If the timeout expires before the message is deleted, the message
// will be placed back onto the queue.
// As a result, be sure to Delete a message after you're done with it.
func (q Queue) Get() (msg *Message, err error) {
	msgs, err := q.GetN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// get N messages
func (q Queue) GetN(n int) (msgs []*Message, err error) {
	return q.GetNWithTimeoutAndWait(n, 0, 0)
}

func (q Queue) GetNWithTimeout(n, timeout int) (msgs []*Message, err error) {
	return q.GetNWithTimeoutAndWait(n, timeout, 0)
}

func (q Queue) GetNWithTimeoutAndWait(n, timeout, wait int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages").
		QueryAdd("n", "%d", n).
		QueryAdd("timeout", "%d", timeout).
		QueryAdd("wait", "%d", wait).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

func (q Queue) Peek() (msg *Message, err error) {
	msgs, err := q.PeekN(1)
	if err != nil {
		return
	}

	if len(msgs) > 0 {
		msg = msgs[0]
	} else {
		err = errors.New("Couldn't get a single message")
	}

	return
}

// peek N messages
func (q Queue) PeekN(n int) (msgs []*Message, err error) {
	msgs, err = q.PeekNWithTimeout(n, 0)

	return
}

func (q Queue) PeekNWithTimeout(n, timeout int) (msgs []*Message, err error) {
	out := struct {
		Messages []*Message `json:"messages"`
	}{}

	err = q.queues(q.Name, "messages", "peek").
		QueryAdd("n", "%d", n).
		QueryAdd("timeout", "%d", timeout).
		Req("GET", nil, &out)
	if err != nil {
		return
	}

	for _, msg := range out.Messages {
		msg.q = q
	}

	return out.Messages, nil
}

// Delete all messages in the queue
func (q Queue) Clear() (err error) {
	return q.queues(q.Name, "clear").Req("POST", nil, nil)
}

// Delete message from queue
func (q Queue) DeleteMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId).Req("DELETE", nil, nil)
}

func (q Queue) DeleteMessages(messages []*Message) error {
	values := make([]string, len(messages))

	for i, val := range messages {
		values[i] = val.Id
	}
	in := struct {
		Ids []string `json:"ids"`
	}{
		Ids: values,
	}
	return q.queues(q.Name, "messages").Req("DELETE", in, nil)
}

// Reset timeout of message to keep it reserved
func (q Queue) TouchMessage(msgId string) (err error) {
	return q.queues(q.Name, "messages", msgId, "touch").Req("POST", nil, nil)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (q Queue) ReleaseMessage(msgId string, delay int64) (err error) {
	in := struct {
		Delay int64 `json:"delay"`
	}{Delay: delay}
	return q.queues(q.Name, "messages", msgId, "release").Req("POST", &in, nil)
}

func (q Queue) MessageSubscribers(msgId string) ([]*Subscriber, error) {
	out := struct {
		Subscribers []*Subscriber `json:"subscribers"`
	}{}
	err := q.queues(q.Name, "messages", msgId, "subscribers").Req("GET", nil, &out)
	return out.Subscribers, err
}

func (q Queue) MessageSubscribersPollN(msgId string, n int) ([]*Subscriber, error) {
	subs, err := q.MessageSubscribers(msgId)
	for {
		time.Sleep(100 * time.Millisecond)
		subs, err = q.MessageSubscribers(msgId)
		if err != nil {
			return subs, err
		}
		if len(subs) >= n && actualPushStatus(subs) {
			return subs, nil
		}
	}
	return subs, err
}

func actualPushStatus(subs []*Subscriber) bool {
	for _, sub := range subs {
		if sub.Status == "queued" {
			return false
		}
	}

	return true
}

func (q Queue) AddAlerts(alerts ...*Alert) (err error) {
	in := struct {
		Alerts []*Alert `json:"alerts"`
	}{Alerts: alerts}
	return q.queues(q.Name, "alerts").Req("POST", &in, nil)
}

func (q Queue) UpdateAlerts(alerts ...*Alert) (err error) {
	in := struct {
		Alerts []*Alert `json:"alerts"`
	}{Alerts: alerts}
	return q.queues(q.Name, "alerts").Req("PUT", &in, nil)
}

func (q Queue) RemoveAllAlerts() (err error) {
	return q.queues(q.Name, "alerts").Req("DELETE", nil, nil)
}

type AlertInfo struct {
	Id string `json:"id"`
}

func (q Queue) RemoveAlerts(alertIds ...string) (err error) {
	in := struct {
		Alerts []AlertInfo `json:"alerts"`
	}{Alerts: make([]AlertInfo, len(alertIds))}
	for i, alertId := range alertIds {
		(in.Alerts[i]).Id = alertId
	}
	return q.queues(q.Name, "alerts").Req("DELETE", &in, nil)
}

func (q Queue) RemoveAlert(alertId string) (err error) {
	return q.queues(q.Name, "alerts", alertId).Req("DELETE", nil, nil)
}

// Delete message from queue
func (m Message) Delete() (err error) {
	return m.q.DeleteMessage(m.Id)
}

// Reset timeout of message to keep it reserved
func (m Message) Touch() (err error) {
	return m.q.TouchMessage(m.Id)
}

// Put message back in the queue, message will be available after +delay+ seconds.
func (m Message) Release(delay int64) (err error) {
	return m.q.ReleaseMessage(m.Id, delay)
}

func (m Message) Subscribers() (interface{}, error) {
	return m.q.MessageSubscribers(m.Id)
}
<|endoftext|>


<commit_before>package car

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

// Simple testing what different between Fatal and Error
func TestNew(t *testing.T) {
	c, err := New("", 100)
	if err != nil {
		t.Fatal("got errors:", err)
	}

	if c == nil {
		t.Error("car should be nil")
	}
}

// Simple testing with testify tool
func TestNewWithAssert(t *testing.T) {
	c, err := New("", 100)
	assert.NotNil(t, err)
	assert.Nil(t, c)
}

// Testing
func TestCar_SetName(t *testing.T) {
	type fields struct {
		Name  string
		Price float32
	}
	type args struct {
		name string
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   string
	}{
		{
			name: "input empty name",
			fields: fields{
				Name:  "foo",
				Price: 100,
			},
			args: args{
				name: "",
			},
			want: "foo",
		},
		{
			name: "input name",
			fields: fields{
				Name:  "foo",
				Price: 100,
			},
			args: args{
				name: "bar",
			},
			want: "bar",
		},
	}
	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			c := &Car{
				Name:  tt.fields.Name,
				Price: tt.fields.Price,
			}
			if got := c.SetName(tt.args.name); got != tt.want {
				t.Errorf("Car.SetName() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>fix variable in Parallel testing<commit_after>package car

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

// Simple testing what different between Fatal and Error
func TestNew(t *testing.T) {
	c, err := New("", 100)
	if err != nil {
		t.Fatal("got errors:", err)
	}

	if c == nil {
		t.Error("car shoud be nil")
	}
}

// Simple testing with testify tool
func TestNewWithAssert(t *testing.T) {
	c, err := New("", 100)
	assert.NotNil(t, err)
	assert.Error(t, err)
	assert.Nil(t, c)

	c, err = New("foo", 100)
	assert.Nil(t, err)
	assert.NoError(t, err)
	assert.NotNil(t, c)
	assert.Equal(t, "foo", c.Name)
}

func TestCar_SetName(t *testing.T) {
	type fields struct {
		Name  string
		Price float32
	}
	type args struct {
		name string
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   string
	}{
		{
			name: "no input name",
			fields: fields{
				Name:  "foo",
				Price: 100,
			},
			args: args{
				name: "",
			},
			want: "foo",
		},
		{
			name: "input name",
			fields: fields{
				Name:  "foo",
				Price: 100,
			},
			args: args{
				name: "bar",
			},
			want: "bar",
		},
	}
	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			c := &Car{
				Name:  tt.fields.Name,
				Price: tt.fields.Price,
			}
			if got := c.SetName(tt.args.name); got != tt.want {
				t.Errorf("Car.SetName() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>


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

// Marshalling and unmarshalling of
// bit torrent bencode data into Go structs using reflection.
//
// Based upon the standard Go language JSON package.

package bencode

import (
	"fmt"
	"io"
	"os"
	"reflect"
	"sort"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(val reflect.Value, i int64) {
	switch v := val.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	case *reflect.InterfaceValue:
		v.Set(reflect.NewValue(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}

	switch v := b.val.(type) {
	case *reflect.StringValue:
		v.Set(s)
	case *reflect.InterfaceValue:
		v.Set(reflect.NewValue(s))
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if strings.ToLower(field.Tag) == k ||
				strings.ToLower(field.Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the bencode syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string;
//		Addr string;
//	}
//
//	type Result struct {
//		Name string;
//		Phone string;
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the bencode syntax string
//
//	d5:emailld5:where4:home4:addr15:gre@example.come\
//  d5:where4:work4:addr12:gre@work.comee4:name14:Gr\
//  ace R. Emlin7:address15:123 Main Streete
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the bencode field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match bencode field names to struct field names.
//
// If you provide a tag string for a struct member, the tag string
// will be used as the bencode dictionary key for that member.
//
// To unmarshal a top-level bencode array, pass in a pointer to an empty
// slice of the correct type.
//

func Unmarshal(r io.Reader, val interface{}) (err os.Error) {
	// If e represents a value, the answer won't get back to the
	// caller.  Make sure it's a pointer.
	if _, ok := reflect.Typeof(val).(*reflect.PtrType); !ok {
		err = os.ErrorString("Attempt to unmarshal into a non-pointer")
		return
	}
	err = UnmarshalValue(r, reflect.NewValue(val))
	return
}

// This API is public primarily to make testing easier, but it is available if you
// have a use for it.

func UnmarshalValue(r io.Reader, v reflect.Value) (err os.Error) {
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	err = Parse(r, b)
	return
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "bencode cannot encode value of type " + e.T.String()
}

func writeArrayOrSlice(w io.Writer, val reflect.ArrayOrSliceValue) (err os.Error) {
	_, err = fmt.Fprint(w, "l")
	if err != nil {
		return
	}
	for i := 0; i < val.Len(); i++ {
		if err := writeValue(w, val.Elem(i)); err != nil {
			return err
		}
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return nil
}

type StringValue struct {
	key   string
	value reflect.Value
}

type StringValueArray []StringValue

// Satisfy sort.Interface

func (a StringValueArray) Len() int { return len(a) }

func (a StringValueArray) Less(i, j int) bool { return a[i].key < a[j].key }

func (a StringValueArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func writeSVList(w io.Writer, svList StringValueArray) (err os.Error) {
	sort.Sort(svList)

	for _, sv := range (svList) {
		s := sv.key
		_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
		if err != nil {
			return
		}

		if err = writeValue(w, sv.value); err != nil {
			return
		}
	}
	return
}

func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		return &MarshalError{val.Type()}
	}
	_, err = fmt.Fprint(w, "d")
	if err != nil {
		return
	}

	keys := val.Keys()

	// Sort keys

	svList := make(StringValueArray, len(keys))
	for i, key := range (keys) {
		svList[i].key = key.(*reflect.StringValue).Get()
		svList[i].value = val.Elem(key)
	}

	err = writeSVList(w, svList)
	if err != nil {
		return
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return
}

func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
	_, err = fmt.Fprint(w, "d")
	if err != nil {
		return
	}

	typ := val.Type().(*reflect.StructType)

	numFields := val.NumField()
	svList := make(StringValueArray, numFields)

	for i := 0; i < numFields; i++ {
		field := typ.Field(i)
		key := field.Name
		if len(field.Tag) > 0 {
			key = field.Tag
		}
		svList[i].key = key
		svList[i].value = val.Field(i)
	}

	err = writeSVList(w, svList)
	if err != nil {
		return
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return
}

func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
	if val == nil {
		err = os.NewError("Can't write null value")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		s := v.Get()
		_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
	case *reflect.IntValue:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.UintValue:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.Int64Value:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.Uint64Value:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.ArrayValue:
		err = writeArrayOrSlice(w, v)
	case *reflect.SliceValue:
		err = writeArrayOrSlice(w, v)
	case *reflect.MapValue:
		err = writeMap(w, v)
	case *reflect.StructValue:
		err = writeStruct(w, v)
	case *reflect.InterfaceValue:
		err = writeValue(w, v.Elem())
	default:
		err = &MarshalError{val.Type()}
	}
	return
}

func Marshal(w io.Writer, val interface{}) os.Error {
	return writeValue(w, reflect.NewValue(val))
}
<commit_msg>Skip nil values when marshaling.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Marshalling and unmarshalling of
// bit torrent bencode data into Go structs using reflection.
//
// Based upon the standard Go language JSON package.

package bencode

import (
	"fmt"
	"io"
	"os"
	"reflect"
	"sort"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(val reflect.Value, i int64) {
	switch v := val.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	case *reflect.InterfaceValue:
		v.Set(reflect.NewValue(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}

	switch v := b.val.(type) {
	case *reflect.StringValue:
		v.Set(s)
	case *reflect.InterfaceValue:
		v.Set(reflect.NewValue(s))
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			field := t.Field(i)
			if strings.ToLower(field.Tag) == k ||
				strings.ToLower(field.Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the bencode syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string;
//		Addr string;
//	}
//
//	type Result struct {
//		Name string;
//		Phone string;
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the bencode syntax string
//
//	d5:emailld5:where4:home4:addr15:gre@example.come\
//  d5:where4:work4:addr12:gre@work.comee4:name14:Gr\
//  ace R. Emlin7:address15:123 Main Streete
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the bencode field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match bencode field names to struct field names.
//
// If you provide a tag string for a struct member, the tag string
// will be used as the bencode dictionary key for that member.
//
// To unmarshal a top-level bencode array, pass in a pointer to an empty
// slice of the correct type.
//

func Unmarshal(r io.Reader, val interface{}) (err os.Error) {
	// If e represents a value, the answer won't get back to the
	// caller.  Make sure it's a pointer.
	if _, ok := reflect.Typeof(val).(*reflect.PtrType); !ok {
		err = os.ErrorString("Attempt to unmarshal into a non-pointer")
		return
	}
	err = UnmarshalValue(r, reflect.NewValue(val))
	return
}

// This API is public primarily to make testing easier, but it is available if you
// have a use for it.

func UnmarshalValue(r io.Reader, v reflect.Value) (err os.Error) {
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	err = Parse(r, b)
	return
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "bencode cannot encode value of type " + e.T.String()
}

func writeArrayOrSlice(w io.Writer, val reflect.ArrayOrSliceValue) (err os.Error) {
	_, err = fmt.Fprint(w, "l")
	if err != nil {
		return
	}
	for i := 0; i < val.Len(); i++ {
		if err := writeValue(w, val.Elem(i)); err != nil {
			return err
		}
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return nil
}

type StringValue struct {
	key   string
	value reflect.Value
}

type StringValueArray []StringValue

// Satisfy sort.Interface

func (a StringValueArray) Len() int { return len(a) }

func (a StringValueArray) Less(i, j int) bool { return a[i].key < a[j].key }

func (a StringValueArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

func writeSVList(w io.Writer, svList StringValueArray) (err os.Error) {
	sort.Sort(svList)

	for _, sv := range (svList) {
	    if isValueNil(sv.value) {
	        continue // Skip null values
	    }
		s := sv.key
		_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
		if err != nil {
			return
		}

		if err = writeValue(w, sv.value); err != nil {
			return
		}
	}
	return
}

func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		return &MarshalError{val.Type()}
	}
	_, err = fmt.Fprint(w, "d")
	if err != nil {
		return
	}

	keys := val.Keys()

	// Sort keys

	svList := make(StringValueArray, len(keys))
	for i, key := range (keys) {
		svList[i].key = key.(*reflect.StringValue).Get()
		svList[i].value = val.Elem(key)
	}

	err = writeSVList(w, svList)
	if err != nil {
		return
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return
}

func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
	_, err = fmt.Fprint(w, "d")
	if err != nil {
		return
	}

	typ := val.Type().(*reflect.StructType)

	numFields := val.NumField()
	svList := make(StringValueArray, numFields)

	for i := 0; i < numFields; i++ {
		field := typ.Field(i)
		key := field.Name
		if len(field.Tag) > 0 {
			key = field.Tag
		}
		svList[i].key = key
		svList[i].value = val.Field(i)
	}

	err = writeSVList(w, svList)
	if err != nil {
		return
	}

	_, err = fmt.Fprint(w, "e")
	if err != nil {
		return
	}
	return
}

func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
	if val == nil {
		err = os.NewError("Can't write null value")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		s := v.Get()
		_, err = fmt.Fprintf(w, "%d:%s", len(s), s)
	case *reflect.IntValue:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.UintValue:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.Int64Value:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.Uint64Value:
		_, err = fmt.Fprintf(w, "i%de", v.Get())
	case *reflect.ArrayValue:
		err = writeArrayOrSlice(w, v)
	case *reflect.SliceValue:
		err = writeArrayOrSlice(w, v)
	case *reflect.MapValue:
		err = writeMap(w, v)
	case *reflect.StructValue:
		err = writeStruct(w, v)
	case *reflect.InterfaceValue:
		err = writeValue(w, v.Elem())
	default:
		err = &MarshalError{val.Type()}
	}
	return
}

func isValueNil(val reflect.Value) bool {
    if val == nil {
        return true
    }
	switch v := val.(type) {
	case *reflect.InterfaceValue:
		return isValueNil(v.Elem())
	default:
	    return false
	}
	return false
}

func Marshal(w io.Writer, val interface{}) os.Error {
	return writeValue(w, reflect.NewValue(val))
}
<|endoftext|>


<commit_before>// Use cgo to interface with nflog
//
// Debian packages needed:
//   apt-get install iptables-dev linux-libc-dev libnetfilter-log-dev

// FIXME why the whole packet arriving and not just the headers?
// FIXME what does copy packet do?

package main

import (
	"log"
	"net"
	"syscall"
	"unsafe"
)

/*
#cgo LDFLAGS: -lnetfilter_log
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <libnetfilter_log/libnetfilter_log.h>

// Forward definition of Go function
void goCallback(void *, char *, int, void *);

// Callback to hand the data back to Go
static int _callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *nfd, void *data) {
	char *prefix = nflog_get_prefix(nfd);
	char *payload = 0;
	int payload_len = nflog_get_payload(nfd, &payload);
	// Could read timestamp nflog_get_timestamp(nfd, &tv)
	// Could read devices: nflog_get_indev(nfd) and nflog_get_outdev(nfd)
	goCallback(data, prefix, payload_len, payload);
	return 0;
 }

// Register the callback - can't be done from Go
static int _callback_register(struct nflog_g_handle *gh, void *data) {
	return nflog_callback_register(gh, _callback, data);
}
*/
import "C"

const (
	MAX_CAPLEN = 4096
)

// NfLog
type NfLog struct {
	// Main nflog_handle
	h *C.struct_nflog_handle
	// File descriptor for socket operations
	fd int
	// Group handles
	ghs []*C.struct_nflog_g_handle
	// The multicast address
	McastGroup int
	// Flavour of IP we are expecting, 4 or 6
	IpVersion byte
	// Are we account the source or the destination address
	Direction IpDirection
	// Flavour of IP packet we are decoding
	IpPacket *IpPacketInfo
	// Accounting
	a *Accounting
	// Quit the loop
	quit bool
}

// Create a new NfLog
//
// McastGroup is that specified in ip[6]tables
// IPv6 is a flag to say if it is IPv6 or not
// Direction is to monitor the source address or the dest address
func NewNfLog(McastGroup int, IpVersion byte, Direction IpDirection, a *Accounting) *NfLog {
	h := C.nflog_open()
	if h == nil {
		log.Fatalf("Failed to open NFLOG: %s", nflog_error())
	}
	log.Println("Binding nfnetlink_log to AF_INET")
	if C.nflog_bind_pf(h, C.AF_INET) < 0 {
		log.Fatalf("nflog_bind_pf failed: %s", nflog_error())
	}

	nflog := &NfLog{
		h:          h,
		fd:         int(C.nflog_fd(h)),
		McastGroup: McastGroup,
		IpVersion:  IpVersion,
		Direction:  Direction,
		a:          a,
	}
	switch IpVersion {
	case 4:
		nflog.IpPacket = Ip4Packet
	case 6:
		nflog.IpPacket = Ip6Packet
	default:
		log.Fatalf("Bad IP version %d", IpVersion)
	}
	nflog.makeGroup(McastGroup, nflog.IpPacket.HeaderSize)
	return nflog
}

// Receive data from nflog on a callback from C
//
//export goCallback
func goCallback(_nflog unsafe.Pointer, cprefix *C.char, payload_len C.int, payload unsafe.Pointer) {
	nflog := (*NfLog)(_nflog)
	//prefix := C.GoString(cprefix)
	packet := C.GoBytes(payload, payload_len)
	// Peek the IP Version out of the header
	ip_version := packet[IpVersion] >> IpVersionShift & IpVersionMask
	// log.Printf("Received %s: size %d, IPv%d", prefix, payload_len, ip_version)
	if ip_version != nflog.IpVersion {
		log.Printf("Bad IP version: %d", ip_version)
		return
	}
	i := nflog.IpPacket
	if len(packet) < i.HeaderSize {
		log.Printf("Short IPv%s packet %d/%d bytes", ip_version, len(packet), i.HeaderSize)
		return
	}

	var addr net.IP
	if nflog.Direction {
		addr = i.Src(packet)
	} else {
		addr = i.Dst(packet)
	}
	nflog.a.Packet(nflog.Direction, addr, i.Length(packet), ip_version)
}

// Current nflog error
func nflog_error() error {
	return syscall.Errno(C.nflog_errno)
}

// Connects to the group specified with the size
func (nflog *NfLog) makeGroup(group, size int) {
	log.Printf("Binding this socket to group %d", group)
	gh := C.nflog_bind_group(nflog.h, (C.u_int16_t)(group))
	if gh == nil {
		log.Fatalf("nflog_bind_group failed: %s", nflog_error())
	}

	//C.nflog_callback_register(gh, nflog_callback, nil)
	C._callback_register(gh, unsafe.Pointer(nflog))

	// FIXME set nflog_set_timeout?

	// FIXME do we need this? Should set large
	if C.nflog_set_qthresh(gh, 1024) < 0 {
		log.Fatalf("nflog_set_qthresh failed: %s", nflog_error())
	}

	log.Printf("Setting copy_packet mode to %d bytes", size)
	if C.nflog_set_mode(gh, C.NFULNL_COPY_PACKET, (C.uint)(size)) < 0 {
		log.Fatalf("nflog_set_mode failed: %s", nflog_error())
	}

	nflog.ghs = append(nflog.ghs, gh)
}

// Receive packets in a loop until quit
func (nflog *NfLog) Loop() {
	buf := make([]byte, syscall.Getpagesize())
	for !nflog.quit {
		nr, _, e := syscall.Recvfrom(nflog.fd, buf, 0)
		if e != nil {
			log.Printf("Recvfrom failed: %s", e)
		}
		// Handle messages in packet
		C.nflog_handle_packet(nflog.h, (*C.char)(unsafe.Pointer(&buf[0])), (C.int)(nr))
	}

}

// Close the NfLog down
func (nflog *NfLog) Close() {
	log.Printf("Unbinding this socket from %d groups", len(nflog.ghs))
	nflog.quit = true
	for _, gh := range nflog.ghs {
		C.nflog_unbind_group(gh)
	}
	log.Printf("Closing NFLOG")
	C.nflog_close(nflog.h)
}
<commit_msg>Check sequence numbers when reading packets and increase buffers<commit_after>// Use cgo to interface with nflog
//
// Docs: http://www.netfilter.org/projects/libnetfilter_log/doxygen/index.html
//
// Debian packages needed:
//   apt-get install iptables-dev linux-libc-dev libnetfilter-log-dev

// FIXME Get this under heavy load - ENOBUFS
// 2013/01/31 17:38:21 Recvfrom failed: no buffer space available
// Seems to be caused by buffer overflow

package main

import (
	"log"
	"net"
	"syscall"
	"unsafe"
)

/*
#cgo LDFLAGS: -lnetfilter_log
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <libnetfilter_log/libnetfilter_log.h>

// Forward definition of Go function
void goCallback(void *, u_int32_t, int, void *);

// Callback to hand the data back to Go
static int _callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *nfd, void *data) {
	char *payload = 0;
	int payload_len = nflog_get_payload(nfd, &payload);
	u_int32_t seq = 0;
	nflog_get_seq(nfd, &seq);
	goCallback(data, seq, payload_len, payload);
	return 0;
 }

// Register the callback - can't be done from Go
static int _callback_register(struct nflog_g_handle *gh, void *data) {
	return nflog_callback_register(gh, _callback, data);
}
*/
import "C"

const (
	RecvBufferSize = 64 * 1024
	MaxQueueLogs   = 1024
)

// NfLog
type NfLog struct {
	// Main nflog_handle
	h *C.struct_nflog_handle
	// File descriptor for socket operations
	fd int
	// Group handles
	ghs []*C.struct_nflog_g_handle
	// The multicast address
	McastGroup int
	// The next expected sequence number
	seq uint32
	// Errors
	errors int64
	// Flavour of IP we are expecting, 4 or 6
	IpVersion byte
	// Are we account the source or the destination address
	Direction IpDirection
	// Flavour of IP packet we are decoding
	IpPacket *IpPacketInfo
	// Accounting
	a *Accounting
	// Quit the loop
	quit bool
}

// Create a new NfLog
//
// McastGroup is that specified in ip[6]tables
// IPv6 is a flag to say if it is IPv6 or not
// Direction is to monitor the source address or the dest address
func NewNfLog(McastGroup int, IpVersion byte, Direction IpDirection, a *Accounting) *NfLog {
	h := C.nflog_open()
	if h == nil {
		log.Fatalf("Failed to open NFLOG: %s", nflog_error())
	}
	if *Debug {
		log.Println("Binding nfnetlink_log to AF_INET")
	}
	if C.nflog_bind_pf(h, C.AF_INET) < 0 {
		log.Fatalf("nflog_bind_pf failed: %s", nflog_error())
	}

	nflog := &NfLog{
		h:          h,
		fd:         int(C.nflog_fd(h)),
		McastGroup: McastGroup,
		IpVersion:  IpVersion,
		Direction:  Direction,
		a:          a,
	}
	switch IpVersion {
	case 4:
		nflog.IpPacket = Ip4Packet
	case 6:
		nflog.IpPacket = Ip6Packet
	default:
		log.Fatalf("Bad IP version %d", IpVersion)
	}
	nflog.makeGroup(McastGroup, nflog.IpPacket.HeaderSize)
	return nflog
}

// Receive data from nflog on a callback from C
//
//export goCallback
func goCallback(_nflog unsafe.Pointer, seq uint32, payload_len C.int, payload unsafe.Pointer) {
	nflog := (*NfLog)(_nflog)
	packet := C.GoBytes(payload, payload_len)

	// Peek the IP Version out of the header
	ip_version := packet[IpVersion] >> IpVersionShift & IpVersionMask
	// log.Printf("Received %d: size %d, IPv%d", seq, payload_len, ip_version)
	if seq != nflog.seq {
		nflog.errors++
		log.Printf("%d missing packets dectected", seq-nflog.seq)
	}
	nflog.seq = seq + 1
	if ip_version != nflog.IpVersion {
		nflog.errors++
		log.Printf("Bad IP version: %d", ip_version)
		return
	}
	i := nflog.IpPacket
	if len(packet) < i.HeaderSize {
		nflog.errors++
		log.Printf("Short IPv%s packet %d/%d bytes", ip_version, len(packet), i.HeaderSize)
		return
	}

	var addr net.IP
	if nflog.Direction {
		addr = i.Src(packet)
	} else {
		addr = i.Dst(packet)
	}
	nflog.a.Packet(nflog.Direction, addr, i.Length(packet), ip_version)
}

// Current nflog error
func nflog_error() error {
	return syscall.Errno(C.nflog_errno)
}

// Connects to the group specified with the size
func (nflog *NfLog) makeGroup(group, size int) {
	if *Debug {
		log.Printf("Binding this socket to group %d", group)
	}
	gh := C.nflog_bind_group(nflog.h, (C.u_int16_t)(group))
	if gh == nil {
		log.Fatalf("nflog_bind_group failed: %s", nflog_error())
	}

	C._callback_register(gh, unsafe.Pointer(nflog))

	// FIXME set nflog_set_timeout?

	// Set the maximum amount of logs in buffer for this group
	if C.nflog_set_qthresh(gh, MaxQueueLogs) < 0 {
		log.Fatalf("nflog_set_qthresh failed: %s", nflog_error())
	}

	// Set local sequence numbering to detect missing packets
	if C.nflog_set_flags(gh, C.NFULNL_CFG_F_SEQ) < 0 {
		log.Fatalf("nflog_set_flags failed: %s", nflog_error())
	}

	if *Debug {
		log.Printf("Setting copy_packet mode to %d bytes", size)
	}
	if C.nflog_set_mode(gh, C.NFULNL_COPY_PACKET, (C.uint)(size)) < 0 {
		log.Fatalf("nflog_set_mode failed: %s", nflog_error())
	}

	nflog.ghs = append(nflog.ghs, gh)
}

// Receive packets in a loop until quit
func (nflog *NfLog) Loop() {
	buf := make([]byte, RecvBufferSize)
	for !nflog.quit {
		nr, _, e := syscall.Recvfrom(nflog.fd, buf, 0)
		if e != nil {
			log.Printf("Recvfrom failed: %s", e)
			nflog.errors++
		} else {
			// Handle messages in packet
			C.nflog_handle_packet(nflog.h, (*C.char)(unsafe.Pointer(&buf[0])), (C.int)(nr))
		}
	}

}

// Close the NfLog down
func (nflog *NfLog) Close() {
	if *Debug {
		log.Printf("Unbinding this socket from %d groups", len(nflog.ghs))
	}
	nflog.quit = true
	for _, gh := range nflog.ghs {
		C.nflog_unbind_group(gh)
	}
	if *Debug {
		log.Printf("Closing NFLOG")
	}
	C.nflog_close(nflog.h)
}
<|endoftext|>


<commit_before>/*Package nikto parses Nikto XML data into a similary formed struct.*/
package nikto

import (
	"encoding/xml"
)

// NiktoRun contains all the data from a single nikto scan.
type NiktoRun struct {
	HostsTest        string       `xml:"hoststest,attr"`
	Options          string       `xml:"options,attr"`
	Version          string       `xml:"version,attr"`
	ScanStart        string       `xml:"scanstart,attr"`
	ScanEnd          string       `xml:"scanend,attr"`
	ScanElapsed      string       `xml:"scanelapsed,attr"`
	XMLOutputVersion string       `xml:"nxmlversion,attr"`
	ScanDetails      []ScanDetail `xml:"scandetails"`
}

// ScanDetails contains all the information for a single host scan.
type ScanDetail struct {
	SSL        SSL        `xml:"ssl"`
	Items      []Item     `xml:"item"`
	Statistics Statistics `xml:"statistics"`
}

// SSL contains the SSL cipher information
type SSL struct {
	Ciphers string `xml:"ciphers,attr"`
	Issuers string `xml:"issuers,attr"`
	Info    string `xml:"info,attr"`
}

// Item contains the nikto finding results
type Item struct {
	Description string `xml:"description"`
	URI         string `xml:"uri"`
	NameLink    string `xml:"namelink"`
	IPLink      string `xml:"iplink"`
}

// Statistics contains the final scan statistics
type Statistics struct {
	Elapsed    string `xml:"elapsed,attr"`
	ItemsFound string `xml:"itemsfound,attr"`
	EndTime    string `xml:"endtime,attr"`
}

// Parse takes a byte array of nikto xml data and unmarshals it into an
// NiktoRun struct. All elements are returned as strings, it is up to the caller
// to check and cast them to the proper type.
func Parse(content []byte) (*NiktoRun, error) {
	r := &NiktoRun{}
	err := xml.Unmarshal(content, r)
	if err != nil {
		return r, err
	}
	return r, nil
}
<commit_msg>Update XML parsing<commit_after>/*Package nikto parses Nikto XML data into a similary formed struct.*/
package nikto

import (
	"encoding/xml"
)

// NiktoData contains all the data from a single nikto scan.
type NiktoData struct {
	XMLName   xml.Name `xml:"niktoscan"`
	NiktoScan []Scan   `xml:"niktoscan"`
}

type Scan struct {
	HostsTest        string       `xml:"hoststest,attr"`
	Options          string       `xml:"options,attr"`
	Version          string       `xml:"version,attr"`
	ScanStart        string       `xml:"scanstart,attr"`
	ScanEnd          string       `xml:"scanend,attr"`
	ScanElapsed      string       `xml:"scanelapsed,attr"`
	XMLOutputVersion string       `xml:"nxmlversion,attr"`
	ScanDetails      []ScanDetail `xml:"scandetails"`
}

// ScanDetails contains all the information for a single host scan.
type ScanDetail struct {
	TargetIP       string     `xml:"targetip,attr"`
	TargetHostname string     `xml:"targethostname,attr"`
	TargetPort     int        `xml:"targetport,attr"`
	TargetBanner   string     `xml:"targetbanner,attr"`
	StartTime      string     `xml:"starttime,attr"`
	SiteName       string     `xml:"sitename,attr"`
	SiteIP         string     `xml:"siteip,attr"`
	HostHeader     string     `xml:"hostheader,attr"`
	Errors         int        `xml:"errors,attr"`
	Checks         int        `xml:"checks,attr"`
	SSL            SSL        `xml:"ssl"`
	Items          []Item     `xml:"item"`
	Statistics     Statistics `xml:"statistics"`
}

// SSL contains the SSL cipher information
type SSL struct {
	Ciphers string `xml:"ciphers,attr"`
	Issuers string `xml:"issuers,attr"`
	Info    string `xml:"info,attr"`
}

// Item contains the nikto finding results
type Item struct {
	ID          int    `xml:"id,attr"`
	OSVDBID     int    `xml:"osvdbid,attr"`
	OSVDBIDLink string `xml:"osvdbidlink,attr"`
	Method      string `xml:"method,attr"`
	Description string `xml:"description"`
	URI         string `xml:"uri"`
	NameLink    string `xml:"namelink"`
	IPLink      string `xml:"iplink"`
}

// Statistics contains the final scan statistics
type Statistics struct {
	Elapsed     string `xml:"elapsed,attr"`
	ItemsFound  int    `xml:"itemsfound,attr"`
	ItemsTested int    `xml:"itemstested,attr"`
	EndTime     string `xml:"endtime,attr"`
}

// Parse takes a byte array of nikto xml data and unmarshals it into an
// NiktoData struct. All elements are returned as strings, it is up to the caller
// to check and cast them to the proper type.
func Parse(content []byte) (*NiktoData, error) {
	r := &NiktoData{}
	err := xml.Unmarshal(content, r)
	if err != nil {
		return r, err
	}
	return r, nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package sqlite3

import (
	"database/sql"
	"fmt"
	"os"
	"testing"
)

type testModule struct {
	t        *testing.T
	intarray []int
}

type testVTab struct {
	intarray []int
}

type testVTabCursor struct {
	vTab  *testVTab
	index int
}

func (m testModule) Create(c *SQLiteConn, args []string) (VTab, error) {
	if len(args) != 6 {
		m.t.Fatal("six arguments expected")
	}
	if args[0] != "test" {
		m.t.Fatal("module name")
	}
	if args[1] != "main" {
		m.t.Fatal("db name")
	}
	if args[2] != "vtab" {
		m.t.Fatal("table name")
	}
	if args[3] != "'1'" {
		m.t.Fatal("first arg")
	}
	if args[4] != "2" {
		m.t.Fatal("second arg")
	}
	if args[5] != "three" {
		m.t.Fatal("third argsecond arg")
	}
	err := c.DeclareVTab("CREATE TABLE x(test TEXT)")
	if err != nil {
		return nil, err
	}
	return &testVTab{m.intarray}, nil
}

func (m testModule) Connect(c *SQLiteConn, args []string) (VTab, error) {
	return m.Create(c, args)
}

func (m testModule) DestroyModule() {}

func (v *testVTab) BestIndex(cst []InfoConstraint, ob []InfoOrderBy) (*IndexResult, error) {
	used := make([]bool, 0, len(cst))
	for range cst {
		used = append(used, false)
	}
	return &IndexResult{
		Used:           used,
		IdxNum:         0,
		IdxStr:         "test-index",
		AlreadyOrdered: true,
		EstimatedCost:  100,
		EstimatedRows:  200,
	}, nil
}

func (v *testVTab) Disconnect() error {
	return nil
}

func (v *testVTab) Destroy() error {
	return nil
}

func (v *testVTab) Open() (VTabCursor, error) {
	return &testVTabCursor{v, 0}, nil
}

func (vc *testVTabCursor) Close() error {
	return nil
}

func (vc *testVTabCursor) Filter(idxNum int, idxStr string, vals []interface{}) error {
	vc.index = 0
	return nil
}

func (vc *testVTabCursor) Next() error {
	vc.index++
	return nil
}

func (vc *testVTabCursor) EOF() bool {
	return vc.index >= len(vc.vTab.intarray)
}

func (vc *testVTabCursor) Column(c *SQLiteContext, col int) error {
	if col != 0 {
		return fmt.Errorf("column index out of bounds: %d", col)
	}
	c.ResultInt(vc.vTab.intarray[vc.index])
	return nil
}

func (vc *testVTabCursor) Rowid() (int64, error) {
	return int64(vc.index), nil
}

func TestCreateModule(t *testing.T) {
	tempFilename := TempFilename(t)
	defer os.Remove(tempFilename)
	intarray := []int{1, 2, 3}
	sql.Register("sqlite3_TestCreateModule", &SQLiteDriver{
		ConnectHook: func(conn *SQLiteConn) error {
			return conn.CreateModule("test", testModule{t, intarray})
		},
	})
	db, err := sql.Open("sqlite3_TestCreateModule", tempFilename)
	if err != nil {
		t.Fatalf("could not open db: %v", err)
	}
	_, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)")
	if err != nil {
		t.Fatalf("could not create vtable: %v", err)
	}

	var i, value int
	rows, err := db.Query("SELECT rowid, * FROM vtab WHERE test = '3'")
	if err != nil {
		t.Fatalf("couldn't select from virtual table: %v", err)
	}
	for rows.Next() {
		rows.Scan(&i, &value)
		if intarray[i] != value {
			t.Fatalf("want %v but %v", intarray[i], value)
		}
	}
	_, err = db.Exec("DROP TABLE vtab")
	if err != nil {
		t.Fatalf("couldn't drop virtual table: %v", err)
	}
}
<commit_msg>fix test<commit_after>// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build vtable

package sqlite3

import (
	"database/sql"
	"fmt"
	"os"
	"testing"
)

type testModule struct {
	t        *testing.T
	intarray []int
}

type testVTab struct {
	intarray []int
}

type testVTabCursor struct {
	vTab  *testVTab
	index int
}

func (m testModule) Create(c *SQLiteConn, args []string) (VTab, error) {
	if len(args) != 6 {
		m.t.Fatal("six arguments expected")
	}
	if args[0] != "test" {
		m.t.Fatal("module name")
	}
	if args[1] != "main" {
		m.t.Fatal("db name")
	}
	if args[2] != "vtab" {
		m.t.Fatal("table name")
	}
	if args[3] != "'1'" {
		m.t.Fatal("first arg")
	}
	if args[4] != "2" {
		m.t.Fatal("second arg")
	}
	if args[5] != "three" {
		m.t.Fatal("third argsecond arg")
	}
	err := c.DeclareVTab("CREATE TABLE x(test TEXT)")
	if err != nil {
		return nil, err
	}
	return &testVTab{m.intarray}, nil
}

func (m testModule) Connect(c *SQLiteConn, args []string) (VTab, error) {
	return m.Create(c, args)
}

func (m testModule) DestroyModule() {}

func (v *testVTab) BestIndex(cst []InfoConstraint, ob []InfoOrderBy) (*IndexResult, error) {
	used := make([]bool, 0, len(cst))
	for range cst {
		used = append(used, false)
	}
	return &IndexResult{
		Used:           used,
		IdxNum:         0,
		IdxStr:         "test-index",
		AlreadyOrdered: true,
		EstimatedCost:  100,
		EstimatedRows:  200,
	}, nil
}

func (v *testVTab) Disconnect() error {
	return nil
}

func (v *testVTab) Destroy() error {
	return nil
}

func (v *testVTab) Open() (VTabCursor, error) {
	return &testVTabCursor{v, 0}, nil
}

func (vc *testVTabCursor) Close() error {
	return nil
}

func (vc *testVTabCursor) Filter(idxNum int, idxStr string, vals []interface{}) error {
	vc.index = 0
	return nil
}

func (vc *testVTabCursor) Next() error {
	vc.index++
	return nil
}

func (vc *testVTabCursor) EOF() bool {
	return vc.index >= len(vc.vTab.intarray)
}

func (vc *testVTabCursor) Column(c *SQLiteContext, col int) error {
	if col != 0 {
		return fmt.Errorf("column index out of bounds: %d", col)
	}
	c.ResultInt(vc.vTab.intarray[vc.index])
	return nil
}

func (vc *testVTabCursor) Rowid() (int64, error) {
	return int64(vc.index), nil
}

func TestCreateModule(t *testing.T) {
	tempFilename := TempFilename(t)
	defer os.Remove(tempFilename)
	intarray := []int{1, 2, 3}
	sql.Register("sqlite3_TestCreateModule", &SQLiteDriver{
		ConnectHook: func(conn *SQLiteConn) error {
			return conn.CreateModule("test", testModule{t, intarray})
		},
	})
	db, err := sql.Open("sqlite3_TestCreateModule", tempFilename)
	if err != nil {
		t.Fatalf("could not open db: %v", err)
	}
	_, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)")
	if err != nil {
		t.Fatalf("could not create vtable: %v", err)
	}

	var i, value int
	rows, err := db.Query("SELECT rowid, * FROM vtab WHERE test = '3'")
	if err != nil {
		t.Fatalf("couldn't select from virtual table: %v", err)
	}
	for rows.Next() {
		rows.Scan(&i, &value)
		if intarray[i] != value {
			t.Fatalf("want %v but %v", intarray[i], value)
		}
	}
	_, err = db.Exec("DROP TABLE vtab")
	if err != nil {
		t.Fatalf("couldn't drop virtual table: %v", err)
	}
}
<|endoftext|>


<commit_before>// Package netns allows ultra-simple network namespace handling. NsHandles
// can be retrieved and set. Note that the current namespace is thread
// local so actions that set and reset namespaces should use LockOSThread
// to make sure the namespace doesn't change due to a goroutine switch.
// It is best to close NsHandles when you are done with them. This can be
// accomplished via a `defer ns.Close()` on the handle. Changing namespaces
// requires elevated privileges, so in most cases this code needs to be run
// as root.
package netns

import (
	"fmt"
	"syscall"
)

// NsHandle is a handle to a network namespace. It can be cast directly
// to an int and used as a file descriptor.
type NsHandle int

// Equal determines if two network handles refer to the same network
// namespace. This is done by comparing the device and inode that the
// file descripors point to.
func (ns NsHandle) Equal(other NsHandle) bool {
	if ns == other {
		return true
	}
	var s1, s2 syscall.Stat_t
	if err := syscall.Fstat(int(ns), &s1); err != nil {
		return false
	}
	if err := syscall.Fstat(int(other), &s2); err != nil {
		return false
	}
	return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino)
}

// String shows the file descriptor number and its dev and inode.
func (ns NsHandle) String() string {
	var s syscall.Stat_t
	if ns == -1 {
		return "NS(None)"
	}
	if err := syscall.Fstat(int(ns), &s); err != nil {
		return fmt.Sprintf("NS(%d: unknown)", ns)
	}
	return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
}

// IsOpen returns true if Close() has not been called.
func (ns NsHandle) IsOpen() bool {
	return ns != -1
}

// Close closes the NsHandle and resets its file descriptor to -1.
// It is not safe to use an NsHandle after Close() is called.
func (ns *NsHandle) Close() error {
	if err := syscall.Close(int(*ns)); err != nil {
		return err
	}
	(*ns) = -1
	return nil
}

// None gets an empty (closed) NsHandle.
func None() NsHandle {
	return NsHandle(-1)
}
<commit_msg>Added function UniqueId which returns a string that uniquely identifies (#14)<commit_after>// Package netns allows ultra-simple network namespace handling. NsHandles
// can be retrieved and set. Note that the current namespace is thread
// local so actions that set and reset namespaces should use LockOSThread
// to make sure the namespace doesn't change due to a goroutine switch.
// It is best to close NsHandles when you are done with them. This can be
// accomplished via a `defer ns.Close()` on the handle. Changing namespaces
// requires elevated privileges, so in most cases this code needs to be run
// as root.
package netns

import (
	"fmt"
	"syscall"
)

// NsHandle is a handle to a network namespace. It can be cast directly
// to an int and used as a file descriptor.
type NsHandle int

// Equal determines if two network handles refer to the same network
// namespace. This is done by comparing the device and inode that the
// file descripors point to.
func (ns NsHandle) Equal(other NsHandle) bool {
	if ns == other {
		return true
	}
	var s1, s2 syscall.Stat_t
	if err := syscall.Fstat(int(ns), &s1); err != nil {
		return false
	}
	if err := syscall.Fstat(int(other), &s2); err != nil {
		return false
	}
	return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino)
}

// String shows the file descriptor number and its dev and inode.
func (ns NsHandle) String() string {
	var s syscall.Stat_t
	if ns == -1 {
		return "NS(None)"
	}
	if err := syscall.Fstat(int(ns), &s); err != nil {
		return fmt.Sprintf("NS(%d: unknown)", ns)
	}
	return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
}

// UniqueId returns a string which uniquely identifies the namespace
// associated with the network handle.
func (ns NsHandle) UniqueId() string {
	var s syscall.Stat_t
	if ns == -1 {
		return "NS(none)"
	}
	if err := syscall.Fstat(int(ns), &s); err != nil {
		return "NS(unknown)"
	}
	return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino)
}

// IsOpen returns true if Close() has not been called.
func (ns NsHandle) IsOpen() bool {
	return ns != -1
}

// Close closes the NsHandle and resets its file descriptor to -1.
// It is not safe to use an NsHandle after Close() is called.
func (ns *NsHandle) Close() error {
	if err := syscall.Close(int(*ns)); err != nil {
		return err
	}
	(*ns) = -1
	return nil
}

// None gets an empty (closed) NsHandle.
func None() NsHandle {
	return NsHandle(-1)
}
<|endoftext|>