<commit_before>package fingerprint

import (
	"fmt"
	"log"

	"github.com/hashicorp/nomad/client/config"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/shirou/gopsutil/cpu"
)

// CPUFingerprint is used to fingerprint the CPU
type CPUFingerprint struct {
	StaticFingerprinter
	logger *log.Logger
}

// NewCPUFingerprint is used to create a CPU fingerprint
func NewCPUFingerprint(logger *log.Logger) Fingerprint {
	f := &CPUFingerprint{logger: logger}
	return f
}

func (f *CPUFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	cpuInfo, err := cpu.CPUInfo()
	if err != nil {
		f.logger.Println("[WARN] Error reading CPU information:", err)
		return false, err
	}

	var numCores int32
	var mhz float64
	var modelName string

	// Assume all CPUs found have same Model. Log if not.
	// If CPUInfo() returns nil above, this loop is still safe
	for _, c := range cpuInfo {
		numCores += c.Cores
		mhz += c.Mhz

		if modelName != "" && modelName != c.ModelName {
			f.logger.Println("[WARN] Found different model names in the same CPU information. Recording last found")
		}
		modelName = c.ModelName
	}
	// Get average CPU frequency
	mhz /= float64(len(cpuInfo))

	if mhz > 0 {
		node.Attributes["cpu.frequency"] = fmt.Sprintf("%.6f", mhz)
		f.logger.Printf("[DEBUG] fingerprint.cpu: frequency: %02.1fMHz", mhz)
	}

	if numCores > 0 {
		node.Attributes["cpu.numcores"] = fmt.Sprintf("%d", numCores)
		f.logger.Printf("[DEBUG] fingerprint.cpu: core count: %d", numCores)
	}

	if mhz > 0 && numCores > 0 {
		tc := float64(numCores) * mhz
		node.Attributes["cpu.totalcompute"] = fmt.Sprintf("%.6f", tc)

		if node.Resources == nil {
			node.Resources = &structs.Resources{}
		}

		node.Resources.CPU = int(tc)
	}

	if modelName != "" {
		node.Attributes["cpu.modelname"] = modelName
	}

	return true, nil
}
<commit_msg>Establish a floor of one core for the number of cores.<commit_after>package fingerprint

import (
	"fmt"
	"log"

	"github.com/hashicorp/nomad/client/config"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/shirou/gopsutil/cpu"
)

// CPUFingerprint is used to fingerprint the CPU
type CPUFingerprint struct {
	StaticFingerprinter
	logger *log.Logger
}

// NewCPUFingerprint is used to create a CPU fingerprint
func NewCPUFingerprint(logger *log.Logger) Fingerprint {
	f := &CPUFingerprint{logger: logger}
	return f
}

func (f *CPUFingerprint) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) {
	cpuInfo, err := cpu.CPUInfo()
	if err != nil {
		f.logger.Println("[WARN] Error reading CPU information:", err)
		return false, err
	}

	var numCores int32
	var mhz float64
	var modelName string

	// Assume all CPUs found have same Model. Log if not.
	// If CPUInfo() returns nil above, this loop is still safe
	for _, c := range cpuInfo {
		numCores += c.Cores
		mhz += c.Mhz

		if modelName != "" && modelName != c.ModelName {
			f.logger.Println("[WARN] Found different model names in the same CPU information. Recording last found")
		}
		modelName = c.ModelName
	}
	// Get average CPU frequency
	mhz /= float64(len(cpuInfo))

	if mhz > 0 {
		node.Attributes["cpu.frequency"] = fmt.Sprintf("%.6f", mhz)
		f.logger.Printf("[DEBUG] fingerprint.cpu: frequency: %02.1fMHz", mhz)
	}

	if numCores <= 0 {
		const defaultCPUCoreCount = 1
		f.logger.Printf("[DEBUG] fingerprint.cpu: unable to find core count, defaulting to %d", defaultCPUCoreCount)
		numCores = defaultCPUCoreCount
	}

	if numCores > 0 {
		node.Attributes["cpu.numcores"] = fmt.Sprintf("%d", numCores)
		f.logger.Printf("[DEBUG] fingerprint.cpu: core count: %d", numCores)
	}

	if mhz > 0 && numCores > 0 {
		tc := float64(numCores) * mhz
		node.Attributes["cpu.totalcompute"] = fmt.Sprintf("%.6f", tc)

		if node.Resources == nil {
			node.Resources = &structs.Resources{}
		}

		node.Resources.CPU = int(tc)
	}

	if modelName != "" {
		node.Attributes["cpu.modelname"] = modelName
	}

	return true, nil
}
<|endoftext|>


<commit_before>package commands

import (
	"os"

	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/locking"
	"github.com/rubyist/tracerx"
	"github.com/spf13/cobra"
)

// postCommitCommand is run through Git's post-commit hook. The hook passes
// no arguments.
// This hook checks that files which are lockable and not locked are made read-only,
// optimising that based on what was added / modified in the commit.
func postCommitCommand(cmd *cobra.Command, args []string) {
	requireGitVersion()

	lockClient, err := locking.NewClient(cfg)
	if err != nil {
		Exit("Unable to create lock system: %v", err)
	}

	// Skip this hook if no lockable patterns have been configured
	if len(lockClient.GetLockablePatterns()) == 0 ||
		!cfg.Os.Bool("GIT_LFS_SET_LOCKABLE_READONLY", true) {
		os.Exit(0)
	}

	tracerx.Printf("post-commit: checking file write flags at HEAD")
	// We can speed things up by looking at what changed in
	// HEAD, and only checking those lockable files
	files, err := git.GetFilesChanged("HEAD", "")

	if err != nil {
		LoggedError(err, "Warning: post-commit failed: %v", err)
		os.Exit(1)
	}
	tracerx.Printf("post-commit: checking write flags on %v", files)
	err = lockClient.FixLockableFileWriteFlags(files)
	if err != nil {
		LoggedError(err, "Warning: post-commit locked file check failed: %v", err)
	}

}

func init() {
	RegisterCommand("post-commit", postCommitCommand, nil)
}
<commit_msg>Explain the need for the post-commit hook (added files)<commit_after>package commands

import (
	"os"

	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/locking"
	"github.com/rubyist/tracerx"
	"github.com/spf13/cobra"
)

// postCommitCommand is run through Git's post-commit hook. The hook passes
// no arguments.
// This hook checks that files which are lockable and not locked are made read-only,
// optimising that based on what was added / modified in the commit.
// This is mainly to catch added files, since modified files should already be
// locked. If we didn't do this, any added files would remain read/write on disk
// even without a lock unless something else checked.
func postCommitCommand(cmd *cobra.Command, args []string) {
	requireGitVersion()

	lockClient, err := locking.NewClient(cfg)
	if err != nil {
		Exit("Unable to create lock system: %v", err)
	}

	// Skip this hook if no lockable patterns have been configured
	if len(lockClient.GetLockablePatterns()) == 0 ||
		!cfg.Os.Bool("GIT_LFS_SET_LOCKABLE_READONLY", true) {
		os.Exit(0)
	}

	tracerx.Printf("post-commit: checking file write flags at HEAD")
	// We can speed things up by looking at what changed in
	// HEAD, and only checking those lockable files
	files, err := git.GetFilesChanged("HEAD", "")

	if err != nil {
		LoggedError(err, "Warning: post-commit failed: %v", err)
		os.Exit(1)
	}
	tracerx.Printf("post-commit: checking write flags on %v", files)
	err = lockClient.FixLockableFileWriteFlags(files)
	if err != nil {
		LoggedError(err, "Warning: post-commit locked file check failed: %v", err)
	}

}

func init() {
	RegisterCommand("post-commit", postCommitCommand, nil)
}
<|endoftext|>


<commit_before>// Simple example of ReturnAddress in Go

package ReturnAddress

import "fmt"

type Request struct {
    data        []int
    resultChan  chan int
}

func sum(a []int) (s int) {
  for _, v := range a {
    s += v
  }
  return
}

func handle(queue chan *Request) {
  for req := range queue {
    req.resultChan <- sum(req.data)
  }
}

func main() {
  reqChannel := make(chan *Request, 10)
  go handle(reqChannel)
  request1 := &Request{[]int{3, 4, 5}, make(chan int)}
  request2 := &Request{[]int{1, 2, 3}, make(chan int)}
  reqChannel <- request1
  reqChannel <- request2
  fmt.Printf("answer: %d %d\n", <-request1.resultChan, <-request2.resultChan)
}
<commit_msg>added comments<commit_after>// Example implementations for Enterprise Integration Patterns
// www.EnterpriseIntegrationPatterns.com
//
// Simple example of ReturnAddress in Go

package ReturnAddress

import "fmt"

type Request struct {
    data        []int
    resultChan  chan int
}

func sum(a []int) (s int) {
  for _, v := range a {
    s += v
  }
  return
}

func handle(queue chan *Request) {
  for req := range queue {
    req.resultChan <- sum(req.data)
  }
}

func main() {
  reqChannel := make(chan *Request, 10)
  go handle(reqChannel)
  // Make two requests with separate return channels
  request1 := &Request{[]int{3, 4, 5}, make(chan int)}
  request2 := &Request{[]int{1, 2, 3}, make(chan int)}
  // Receive both results
  reqChannel <- request1
  reqChannel <- request2
  fmt.Printf("answer: %d %d\n", <-request1.resultChan, <-request2.resultChan)
}
<|endoftext|>


<commit_before>/*
The Ginkgo CLI

The Ginkgo CLI is fully documented [here](http://onsi.github.io/ginkgo/#the_ginkgo_cli)

To install:

	go install github.com/onsi/ginkgo/ginkgo

To run tests:

	ginkgo

To run tests in all subdirectories:

	ginkgo -r

To run tests in particular packages:

	ginkgo <flags> /path/to/package /path/to/another/package

By default, when running multiple tests (with -r or a list of packages) Ginkgo will abort when a test fails.  To have Ginkgo run subsequent test suites instead you can:

	ginkgo -keep-going

To monitor packages and rerun tests when changes occur:

	ginkgo -watch <-r> </path/to/package>

passing `ginkgo -watch` the `-r` flag will recursively detect all test suites under the current directory and monitor them.
`-watch` does not detect *new* packages. Moreover, changes in package X only rerun the tests for package X, tests for packages
that depend on X are not rerun.

[OSX only] To receive (desktop) notifications when a test run completes:

	ginkgo -notify

this is particularly useful with `ginkgo -watch`.  Notifications are currently only supported on OS X and require that you `brew install terminal-notifier`

To run tests in parallel

	ginkgo -nodes=N

where N is the number of nodes.  By default the Ginkgo CLI will spin up a server that the individual
test processes stream test output to.  The CLI then aggregates these streams into one coherent stream of output.
An alternative is to have the parallel nodes run and then present the resulting, final, output in one monolithic chunk - you can opt into this if streaming is giving you trouble:

	ginkgo -nodes=N -stream=false

On windows, the default value for stream is false.

To bootstrap a test suite:

	ginkgo bootstrap

To generate a test file:

	ginkgo generate <test_file_name>

To unfocus tests:

	ginkgo unfocus

To print out Ginkgo's version:

	ginkgo version

To get more help:

	ginkgo help
*/
package main

import (
	"flag"
	"fmt"
	"github.com/onsi/ginkgo/config"
	"github.com/onsi/ginkgo/ginkgo/testsuite"
	"os"
	"os/signal"
	"runtime"
	"time"
)

var numCPU int
var parallelStream bool
var recurse bool
var runMagicI bool
var race bool
var cover bool
var watch bool
var notify bool
var keepGoing bool

func init() {
	onWindows := (runtime.GOOS == "windows")
	onOSX := (runtime.GOOS == "darwin")

	config.Flags("", false)

	flag.IntVar(&(numCPU), "nodes", 1, "The number of parallel test nodes to run")
	flag.BoolVar(&(parallelStream), "stream", !onWindows, "Aggregate parallel test output into one coherent stream (default: true)")
	flag.BoolVar(&(recurse), "r", false, "Find and run test suites under the current directory recursively")
	flag.BoolVar(&(runMagicI), "i", false, "Run go test -i first, then run the test suite")
	flag.BoolVar(&(race), "race", false, "Run tests with race detection enabled")
	flag.BoolVar(&(cover), "cover", false, "Run tests with coverage analysis, will generate coverage profiles with the package name in the current directory")
	flag.BoolVar(&(watch), "watch", false, "Monitor the target packages for changes, then run tests when changes are detected")
	flag.BoolVar(&(keepGoing), "keep-going", false, "When true, failures from earlier test suites do not prevent later test suites from running")
	if onOSX {
		flag.BoolVar(&(notify), "notify", false, "Send desktop notifications when a test run completes")
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of ginkgo:\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo <FLAGS> <DIRECTORY> ...\n  Run the tests in the passed in <DIRECTORY> (or the current directory if left blank).\n  ginkgo accepts the following flags:\n")
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintf(os.Stderr, "ginkgo bootstrap\n  Bootstrap a test suite for the current package.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo generate <SUBJECT>\n  Generate a test file for SUBJECT, the file will be named SUBJECT_test.go\n  If omitted, a file named after the package will be created.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo unfocus\n  Unfocuses any focused tests.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo version\n  Print ginkgo's version.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo help\n  Print this usage information.\n")
	}

	flag.Parse()
}

func main() {
	if flag.NArg() > 0 {
		args := flag.Args()
		handled := handleSubcommands(args)
		if handled {
			os.Exit(0)
		}
	}

	if notify {
		verifyNotificationsAreAvailable()
	}

	runner := newTestRunner(numCPU, parallelStream, runMagicI, race, cover)

	registerSignalHandler(runner)

	if watch {
		watchTests(runner)
	} else {
		runTests(runner)
	}
}

func handleSubcommands(args []string) bool {
	switch args[0] {
	case "bootstrap":
		generateBootstrap()
	case "generate":
		subject := ""
		if len(args) > 1 {
			subject = args[1]
		}
		generateSpec(subject)
	case "unfocus", "blur":
		unfocusSpecs()
	case "help":
		flag.Usage()
	case "version":
		fmt.Printf("Ginkgo V%s\n", config.VERSION)
	default:
		return false
	}

	return true
}

func findSuites() []*testsuite.TestSuite {
	suites := []*testsuite.TestSuite{}

	if flag.NArg() > 0 {
		for _, dir := range flag.Args() {
			suites = append(suites, testsuite.SuitesInDir(dir, recurse)...)
		}
	} else {
		suites = testsuite.SuitesInDir(".", recurse)
	}

	if len(suites) == 0 {
		fmt.Printf("Found no test suites.\nFor usage instructions:\n\tginkgo help\n")
		os.Exit(1)
	}

	return suites
}

func runTests(runner *testRunner) {
	t := time.Now()

	suites := findSuites()
	suitesThatFailed := []*testsuite.TestSuite{}

	passed := true
	for _, suite := range suites {
		suitePassed := runner.runSuite(suite)
		sendSuiteCompletionNotification(suite, suitePassed)

		if !suitePassed {
			passed = false
			suitesThatFailed = append(suitesThatFailed, suite)
			if !keepGoing {
				break
			}
		}
	}

	if keepGoing && !passed {
		fmt.Println("\nThere were failures detected in the following suites:")
		for _, suite := range suitesThatFailed {
			fmt.Printf("\t%s\n", suite.PackageName)
		}
	}

	fmt.Printf("\nGinkgo ran in %s\n", time.Since(t))

	if passed {
		fmt.Printf("Test Suite Passed\n")
		os.Exit(0)
	} else {
		fmt.Printf("Test Suite Failed\n")
		os.Exit(1)
	}
}

func watchTests(runner *testRunner) {
	suites := findSuites()

	modifiedSuite := make(chan *testsuite.TestSuite)
	for _, suite := range suites {
		go suite.Watch(modifiedSuite)
	}

	if !recurse {
		suitePassed := runner.runSuite(suites[0])
		sendSuiteCompletionNotification(suites[0], suitePassed)
	}

	for {
		suite := <-modifiedSuite
		sendNotification("Ginkgo", fmt.Sprintf(`Detected change in "%s"...`, suite.PackageName))

		fmt.Printf("\n\nDetected change in %s\n\n", suite.PackageName)
		suitePassed := runner.runSuite(suite)

		sendSuiteCompletionNotification(suite, suitePassed)
	}
}

func registerSignalHandler(runner *testRunner) {
	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt, os.Kill)

		select {
		case sig := <-c:
			runner.abort(sig)
			os.Exit(1)
		}
	}()
}
<commit_msg>keep-going => keepGoing<commit_after>/*
The Ginkgo CLI

The Ginkgo CLI is fully documented [here](http://onsi.github.io/ginkgo/#the_ginkgo_cli)

To install:

	go install github.com/onsi/ginkgo/ginkgo

To run tests:

	ginkgo

To run tests in all subdirectories:

	ginkgo -r

To run tests in particular packages:

	ginkgo <flags> /path/to/package /path/to/another/package

By default, when running multiple tests (with -r or a list of packages) Ginkgo will abort when a test fails.  To have Ginkgo run subsequent test suites instead you can:

	ginkgo -keepGoing

To monitor packages and rerun tests when changes occur:

	ginkgo -watch <-r> </path/to/package>

passing `ginkgo -watch` the `-r` flag will recursively detect all test suites under the current directory and monitor them.
`-watch` does not detect *new* packages. Moreover, changes in package X only rerun the tests for package X, tests for packages
that depend on X are not rerun.

[OSX only] To receive (desktop) notifications when a test run completes:

	ginkgo -notify

this is particularly useful with `ginkgo -watch`.  Notifications are currently only supported on OS X and require that you `brew install terminal-notifier`

To run tests in parallel

	ginkgo -nodes=N

where N is the number of nodes.  By default the Ginkgo CLI will spin up a server that the individual
test processes stream test output to.  The CLI then aggregates these streams into one coherent stream of output.
An alternative is to have the parallel nodes run and then present the resulting, final, output in one monolithic chunk - you can opt into this if streaming is giving you trouble:

	ginkgo -nodes=N -stream=false

On windows, the default value for stream is false.

To bootstrap a test suite:

	ginkgo bootstrap

To generate a test file:

	ginkgo generate <test_file_name>

To unfocus tests:

	ginkgo unfocus

To print out Ginkgo's version:

	ginkgo version

To get more help:

	ginkgo help
*/
package main

import (
	"flag"
	"fmt"
	"github.com/onsi/ginkgo/config"
	"github.com/onsi/ginkgo/ginkgo/testsuite"
	"os"
	"os/signal"
	"runtime"
	"time"
)

var numCPU int
var parallelStream bool
var recurse bool
var runMagicI bool
var race bool
var cover bool
var watch bool
var notify bool
var keepGoing bool

func init() {
	onWindows := (runtime.GOOS == "windows")
	onOSX := (runtime.GOOS == "darwin")

	config.Flags("", false)

	flag.IntVar(&(numCPU), "nodes", 1, "The number of parallel test nodes to run")
	flag.BoolVar(&(parallelStream), "stream", !onWindows, "Aggregate parallel test output into one coherent stream (default: true)")
	flag.BoolVar(&(recurse), "r", false, "Find and run test suites under the current directory recursively")
	flag.BoolVar(&(runMagicI), "i", false, "Run go test -i first, then run the test suite")
	flag.BoolVar(&(race), "race", false, "Run tests with race detection enabled")
	flag.BoolVar(&(cover), "cover", false, "Run tests with coverage analysis, will generate coverage profiles with the package name in the current directory")
	flag.BoolVar(&(watch), "watch", false, "Monitor the target packages for changes, then run tests when changes are detected")
	flag.BoolVar(&(keepGoing), "keepGoing", false, "When true, failures from earlier test suites do not prevent later test suites from running")
	if onOSX {
		flag.BoolVar(&(notify), "notify", false, "Send desktop notifications when a test run completes")
	}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of ginkgo:\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo <FLAGS> <DIRECTORY> ...\n  Run the tests in the passed in <DIRECTORY> (or the current directory if left blank).\n  ginkgo accepts the following flags:\n")
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintf(os.Stderr, "ginkgo bootstrap\n  Bootstrap a test suite for the current package.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo generate <SUBJECT>\n  Generate a test file for SUBJECT, the file will be named SUBJECT_test.go\n  If omitted, a file named after the package will be created.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo unfocus\n  Unfocuses any focused tests.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo version\n  Print ginkgo's version.\n\n")
		fmt.Fprintf(os.Stderr, "ginkgo help\n  Print this usage information.\n")
	}

	flag.Parse()
}

func main() {
	if flag.NArg() > 0 {
		args := flag.Args()
		handled := handleSubcommands(args)
		if handled {
			os.Exit(0)
		}
	}

	if notify {
		verifyNotificationsAreAvailable()
	}

	runner := newTestRunner(numCPU, parallelStream, runMagicI, race, cover)

	registerSignalHandler(runner)

	if watch {
		watchTests(runner)
	} else {
		runTests(runner)
	}
}

func handleSubcommands(args []string) bool {
	switch args[0] {
	case "bootstrap":
		generateBootstrap()
	case "generate":
		subject := ""
		if len(args) > 1 {
			subject = args[1]
		}
		generateSpec(subject)
	case "unfocus", "blur":
		unfocusSpecs()
	case "help":
		flag.Usage()
	case "version":
		fmt.Printf("Ginkgo V%s\n", config.VERSION)
	default:
		return false
	}

	return true
}

func findSuites() []*testsuite.TestSuite {
	suites := []*testsuite.TestSuite{}

	if flag.NArg() > 0 {
		for _, dir := range flag.Args() {
			suites = append(suites, testsuite.SuitesInDir(dir, recurse)...)
		}
	} else {
		suites = testsuite.SuitesInDir(".", recurse)
	}

	if len(suites) == 0 {
		fmt.Printf("Found no test suites.\nFor usage instructions:\n\tginkgo help\n")
		os.Exit(1)
	}

	return suites
}

func runTests(runner *testRunner) {
	t := time.Now()

	suites := findSuites()
	suitesThatFailed := []*testsuite.TestSuite{}

	passed := true
	for _, suite := range suites {
		suitePassed := runner.runSuite(suite)
		sendSuiteCompletionNotification(suite, suitePassed)

		if !suitePassed {
			passed = false
			suitesThatFailed = append(suitesThatFailed, suite)
			if !keepGoing {
				break
			}
		}
	}

	if keepGoing && !passed {
		fmt.Println("\nThere were failures detected in the following suites:")
		for _, suite := range suitesThatFailed {
			fmt.Printf("\t%s\n", suite.PackageName)
		}
	}

	fmt.Printf("\nGinkgo ran in %s\n", time.Since(t))

	if passed {
		fmt.Printf("Test Suite Passed\n")
		os.Exit(0)
	} else {
		fmt.Printf("Test Suite Failed\n")
		os.Exit(1)
	}
}

func watchTests(runner *testRunner) {
	suites := findSuites()

	modifiedSuite := make(chan *testsuite.TestSuite)
	for _, suite := range suites {
		go suite.Watch(modifiedSuite)
	}

	if !recurse {
		suitePassed := runner.runSuite(suites[0])
		sendSuiteCompletionNotification(suites[0], suitePassed)
	}

	for {
		suite := <-modifiedSuite
		sendNotification("Ginkgo", fmt.Sprintf(`Detected change in "%s"...`, suite.PackageName))

		fmt.Printf("\n\nDetected change in %s\n\n", suite.PackageName)
		suitePassed := runner.runSuite(suite)

		sendSuiteCompletionNotification(suite, suitePassed)
	}
}

func registerSignalHandler(runner *testRunner) {
	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt, os.Kill)

		select {
		case sig := <-c:
			runner.abort(sig)
			os.Exit(1)
		}
	}()
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"encoding/base64"
	"net/url"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/taskqueue"
)

type User struct {
	_kind    string    `goon:"kind,U"`
	Id       string    `datastore:"-" goon:"id"`
	Email    string    `datastore:"e,noindex"`
	Messages []string  `datastore:"m,noindex"`
	Read     time.Time `datastore:"r,noindex"`
	Options  string    `datastore:"o,noindex"`
}

func (u *User) String() string {
	return u.Email
}

// parent: User, key: "data"
type UserData struct {
	_kind  string         `goon:"kind,UD"`
	Id     string         `datastore:"-" goon:"id"`
	Parent *datastore.Key `datastore:"-" goon:"parent"`
	Opml   []byte         `datastore:"o,noindex"`
	Read   []byte         `datastore:"r,noindex"`
}

type Read map[string][]string

type Feed struct {
	_kind      string    `goon:"kind,F"`
	Url        string    `datastore:"-" goon:"id"`
	Title      string    `datastore:"t,noindex"`
	Updated    time.Time `datastore:"u,noindex"`
	Date       time.Time `datastore:"d,noindex"`
	Checked    time.Time `datastore:"c,noindex"`
	NextUpdate time.Time `datastore:"n"`
	Link       string    `datastore:"l,noindex"`
	Errors     int       `datastore:"e,noindex"`
	Image      string    `datastore:"i,noindex"`
	Subscribed time.Time `datastore:"s,noindex"`
}

func (f Feed) Subscribe(c appengine.Context) {
	if !f.IsSubscribed() {
		t := taskqueue.NewPOSTTask(routeUrl("subscribe-feed"), url.Values{
			"feed": {f.Url},
		})
		if _, err := taskqueue.Add(c, t, "update-manual"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		} else {
			c.Warningf("subscribe feed: %v", f.Url)
		}
	}
}

func (f Feed) IsSubscribed() bool {
	return !ENABLE_PUBSUBHUBBUB || time.Now().Before(f.Subscribed)
}

func (f Feed) PubSubURL() string {
	b := base64.URLEncoding.EncodeToString([]byte(f.Url))
	ru, _ := router.Get("subscribe-callback").URL("feed", b)
	ru.Scheme = "http"
	ru.Host = PUBSUBHUBBUB_HOST
	return ru.String()
}

// parent: Feed, key: story ID
type Story struct {
	_kind     string         `goon:"kind,S"`
	Id        string         `datastore:"-" goon:"id"`
	Parent    *datastore.Key `datastore:"-" goon:"parent" json:"-"`
	Title     string         `datastore:"t,noindex"`
	Link      string         `datastore:"l,noindex"`
	Created   time.Time      `datastore:"c" json:"-"`
	Published time.Time      `datastore:"p" json:"-"`
	Updated   time.Time      `datastore:"u,noindex" json:"-"`
	Date      int64          `datastore:"e,noindex"`
	Author    string         `datastore:"a,noindex"`
	Summary   string         `datastore:"s,noindex"`

	content string
}

const IDX_COL = "p"

// parent: Story, key: 1
type StoryContent struct {
	_kind   string         `goon:"kind,SC"`
	Id      int64          `datastore:"-" goon:"id"`
	Parent  *datastore.Key `datastore:"-" goon:"parent"`
	Content string         `datastore:"c,noindex"`
}

type OpmlOutline struct {
	Outline []*OpmlOutline `xml:"outline" json:",omitempty"`
	Title   string         `xml:"title,attr,omitempty" json:",omitempty"`
	XmlUrl  string         `xml:"xmlUrl,attr" json:",omitempty"`
	Type    string         `xml:"type,attr,omitempty" json:",omitempty"`
	Text    string         `xml:"text,attr,omitempty" json:",omitempty"`
	HtmlUrl string         `xml:"htmlUrl,attr,omitempty" json:",omitempty"`
}

type Opml struct {
	XMLName string         `xml:"opml"`
	Version string         `xml:"version,attr"`
	Outline []*OpmlOutline `xml:"body>outline"`
}

type DateFormat struct {
	Id     string         `datastore:"-" goon:"id"`
	_kind  string         `goon:"kind,DF"`
	Parent *datastore.Key `datastore:"-" goon:"parent"`
}

type Image struct {
	Id   string            `datastore:"-" goon:"id"`
	Blob appengine.BlobKey `datastore:"b,noindex"`
	Url  string            `datastore:"u,noindex"`
}
<commit_msg>Omit empty<commit_after>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goapp

import (
	"encoding/base64"
	"net/url"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/taskqueue"
)

type User struct {
	_kind    string    `goon:"kind,U"`
	Id       string    `datastore:"-" goon:"id"`
	Email    string    `datastore:"e,noindex"`
	Messages []string  `datastore:"m,noindex"`
	Read     time.Time `datastore:"r,noindex"`
	Options  string    `datastore:"o,noindex"`
}

func (u *User) String() string {
	return u.Email
}

// parent: User, key: "data"
type UserData struct {
	_kind  string         `goon:"kind,UD"`
	Id     string         `datastore:"-" goon:"id"`
	Parent *datastore.Key `datastore:"-" goon:"parent"`
	Opml   []byte         `datastore:"o,noindex"`
	Read   []byte         `datastore:"r,noindex"`
}

type Read map[string][]string

type Feed struct {
	_kind      string    `goon:"kind,F"`
	Url        string    `datastore:"-" goon:"id"`
	Title      string    `datastore:"t,noindex"`
	Updated    time.Time `datastore:"u,noindex"`
	Date       time.Time `datastore:"d,noindex"`
	Checked    time.Time `datastore:"c,noindex"`
	NextUpdate time.Time `datastore:"n"`
	Link       string    `datastore:"l,noindex"`
	Errors     int       `datastore:"e,noindex"`
	Image      string    `datastore:"i,noindex"`
	Subscribed time.Time `datastore:"s,noindex"`
}

func (f Feed) Subscribe(c appengine.Context) {
	if !f.IsSubscribed() {
		t := taskqueue.NewPOSTTask(routeUrl("subscribe-feed"), url.Values{
			"feed": {f.Url},
		})
		if _, err := taskqueue.Add(c, t, "update-manual"); err != nil {
			c.Errorf("taskqueue error: %v", err.Error())
		} else {
			c.Warningf("subscribe feed: %v", f.Url)
		}
	}
}

func (f Feed) IsSubscribed() bool {
	return !ENABLE_PUBSUBHUBBUB || time.Now().Before(f.Subscribed)
}

func (f Feed) PubSubURL() string {
	b := base64.URLEncoding.EncodeToString([]byte(f.Url))
	ru, _ := router.Get("subscribe-callback").URL("feed", b)
	ru.Scheme = "http"
	ru.Host = PUBSUBHUBBUB_HOST
	return ru.String()
}

// parent: Feed, key: story ID
type Story struct {
	_kind     string         `goon:"kind,S"`
	Id        string         `datastore:"-" goon:"id"`
	Parent    *datastore.Key `datastore:"-" goon:"parent" json:"-"`
	Title     string         `datastore:"t,noindex"`
	Link      string         `datastore:"l,noindex"`
	Created   time.Time      `datastore:"c" json:"-"`
	Published time.Time      `datastore:"p" json:"-"`
	Updated   time.Time      `datastore:"u,noindex" json:"-"`
	Date      int64          `datastore:"e,noindex"`
	Author    string         `datastore:"a,noindex" json:",omitempty"`
	Summary   string         `datastore:"s,noindex"`

	content string
}

const IDX_COL = "p"

// parent: Story, key: 1
type StoryContent struct {
	_kind   string         `goon:"kind,SC"`
	Id      int64          `datastore:"-" goon:"id"`
	Parent  *datastore.Key `datastore:"-" goon:"parent"`
	Content string         `datastore:"c,noindex"`
}

type OpmlOutline struct {
	Outline []*OpmlOutline `xml:"outline" json:",omitempty"`
	Title   string         `xml:"title,attr,omitempty" json:",omitempty"`
	XmlUrl  string         `xml:"xmlUrl,attr" json:",omitempty"`
	Type    string         `xml:"type,attr,omitempty" json:",omitempty"`
	Text    string         `xml:"text,attr,omitempty" json:",omitempty"`
	HtmlUrl string         `xml:"htmlUrl,attr,omitempty" json:",omitempty"`
}

type Opml struct {
	XMLName string         `xml:"opml"`
	Version string         `xml:"version,attr"`
	Outline []*OpmlOutline `xml:"body>outline"`
}

type DateFormat struct {
	Id     string         `datastore:"-" goon:"id"`
	_kind  string         `goon:"kind,DF"`
	Parent *datastore.Key `datastore:"-" goon:"parent"`
}

type Image struct {
	Id   string            `datastore:"-" goon:"id"`
	Blob appengine.BlobKey `datastore:"b,noindex"`
	Url  string            `datastore:"u,noindex"`
}
<|endoftext|>


<commit_before>package goenv

import (
	"fmt"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"

	"github.com/crgimenes/goconfig/structtag"
)

var (
	// Prefix is a string that would be placed at the beginning of the generated tags.
	Prefix string

	// Usage is the function that is called when an error occurs.
	Usage func()

	// PrintDefaultsOutput changes the default output help string
	PrintDefaultsOutput string
)

// Setup maps and variables
func Setup(tag string, tagDefault string) {
	Usage = DefaultUsage

	structtag.Setup()
	structtag.Prefix = Prefix
	SetTag(tag)
	SetTagDefault(tagDefault)

	structtag.ParseMap[reflect.Int64] = reflectInt
	structtag.ParseMap[reflect.Int] = reflectInt
	structtag.ParseMap[reflect.Float64] = reflectFloat
	structtag.ParseMap[reflect.String] = reflectString
	structtag.ParseMap[reflect.Bool] = reflectBool
}

// SetTag set a new tag
func SetTag(tag string) {
	structtag.Tag = tag
}

// SetTagDefault set a new TagDefault to retorn default values
func SetTagDefault(tag string) {
	structtag.TagDefault = tag
}

// Parse configuration
func Parse(config interface{}) (err error) {
	err = structtag.Parse(config, "")
	return
}

func parseValue(datatype string, value *reflect.Value) (ret string, ok bool) {
	switch datatype {
	case "bool":
		if value.Bool() {
			ret = "true"
			ok = true
		}
	case "string":
		ret = value.String()
		ok = ret != ""
	case "int":
		ret = strconv.FormatInt(value.Int(), 10)
		ok = ret != "0"
	case "float64":
		ret = strconv.FormatFloat(value.Float(), 'f', -1, 64)
		ok = ret != "0"
	}
	return
}

func getNewValue(field *reflect.StructField, value *reflect.Value, tag string, datatype string) (ret string) {
	defaultValue := field.Tag.Get(structtag.TagDefault)

	// create PrintDefaults output
	tag = strings.ToUpper(tag)
	sysvar := `$` + tag
	if runtime.GOOS == "windows" {
		sysvar = `%` + tag + `%`
	}

	output := fmt.Sprintf("  %v %v\n\n", sysvar, datatype)
	if defaultValue != "" {
		output = fmt.Sprintf("  %v %v\n\t(default %q)\n", sysvar, datatype, defaultValue)
	}
	PrintDefaultsOutput += output

	// get value from environment variable
	ret = os.Getenv(tag)
	if ret != "" {
		return
	}

	ret, ok := parseValue(datatype, value)
	if ok {
		return
	}

	// get value from default settings
	ret = defaultValue
	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "int")
	if newValue == "" {
		return
	}
	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}
	value.SetInt(intNewValue)
	return
}

func reflectFloat(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "float64")
	if newValue == "" {
		return
	}
	var floatNewValue float64
	floatNewValue, err = strconv.ParseFloat(newValue, 64)
	if err != nil {
		return
	}
	value.SetFloat(floatNewValue)
	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "string")
	if newValue == "" {
		return
	}
	value.SetString(newValue)
	return
}

func reflectBool(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "bool")
	if newValue == "" {
		return
	}
	newBoolValue := newValue == "true" || newValue == "t"
	value.SetBool(newBoolValue)
	return
}

// PrintDefaults print the default help
func PrintDefaults() {
	fmt.Println("Environment variables:")
	fmt.Println(PrintDefaultsOutput)
}

// DefaultUsage is assigned for Usage function by default
func DefaultUsage() {
	fmt.Println("Usage")
	PrintDefaults()
}
<commit_msg>replace GetEnv by the LookupEnv function (#42)<commit_after>package goenv

import (
	"fmt"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"

	"github.com/crgimenes/goconfig/structtag"
)

var (
	// Prefix is a string that would be placed at the beginning of the generated tags.
	Prefix string

	// Usage is the function that is called when an error occurs.
	Usage func()

	// PrintDefaultsOutput changes the default output help string
	PrintDefaultsOutput string
)

// Setup maps and variables
func Setup(tag string, tagDefault string) {
	Usage = DefaultUsage

	structtag.Setup()
	structtag.Prefix = Prefix
	SetTag(tag)
	SetTagDefault(tagDefault)

	structtag.ParseMap[reflect.Int64] = reflectInt
	structtag.ParseMap[reflect.Int] = reflectInt
	structtag.ParseMap[reflect.Float64] = reflectFloat
	structtag.ParseMap[reflect.String] = reflectString
	structtag.ParseMap[reflect.Bool] = reflectBool
}

// SetTag set a new tag
func SetTag(tag string) {
	structtag.Tag = tag
}

// SetTagDefault set a new TagDefault to retorn default values
func SetTagDefault(tag string) {
	structtag.TagDefault = tag
}

// Parse configuration
func Parse(config interface{}) (err error) {
	err = structtag.Parse(config, "")
	return
}

func parseValue(datatype string, value *reflect.Value) (ret string, ok bool) {
	switch datatype {
	case "bool":
		if value.Bool() {
			ret = "true"
			ok = true
		}
	case "string":
		ret = value.String()
		ok = ret != ""
	case "int":
		ret = strconv.FormatInt(value.Int(), 10)
		ok = ret != "0"
	case "float64":
		ret = strconv.FormatFloat(value.Float(), 'f', -1, 64)
		ok = ret != "0"
	}
	return
}

func getNewValue(field *reflect.StructField, value *reflect.Value, tag string, datatype string) (ret string) {
	defaultValue := field.Tag.Get(structtag.TagDefault)

	// create PrintDefaults output
	tag = strings.ToUpper(tag)
	sysvar := `$` + tag
	if runtime.GOOS == "windows" {
		sysvar = `%` + tag + `%`
	}

	output := fmt.Sprintf("  %v %v\n\n", sysvar, datatype)
	if defaultValue != "" {
		output = fmt.Sprintf("  %v %v\n\t(default %q)\n", sysvar, datatype, defaultValue)
	}
	PrintDefaultsOutput += output

	// get value from environment variable
	ret, ok := os.LookupEnv(tag)
	if ok {
		return
	}

	ret, ok = parseValue(datatype, value)
	if ok {
		return
	}

	// get value from default settings
	ret = defaultValue
	return
}

func reflectInt(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "int")
	if newValue == "" {
		return
	}
	var intNewValue int64
	intNewValue, err = strconv.ParseInt(newValue, 10, 64)
	if err != nil {
		return
	}
	value.SetInt(intNewValue)
	return
}

func reflectFloat(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "float64")
	if newValue == "" {
		return
	}
	var floatNewValue float64
	floatNewValue, err = strconv.ParseFloat(newValue, 64)
	if err != nil {
		return
	}
	value.SetFloat(floatNewValue)
	return
}

func reflectString(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "string")
	if newValue == "" {
		return
	}
	value.SetString(newValue)
	return
}

func reflectBool(field *reflect.StructField, value *reflect.Value, tag string) (err error) {
	newValue := getNewValue(field, value, tag, "bool")
	if newValue == "" {
		return
	}
	newBoolValue := newValue == "true" || newValue == "t"
	value.SetBool(newBoolValue)
	return
}

// PrintDefaults print the default help
func PrintDefaults() {
	fmt.Println("Environment variables:")
	fmt.Println(PrintDefaultsOutput)
}

// DefaultUsage is assigned for Usage function by default
func DefaultUsage() {
	fmt.Println("Usage")
	PrintDefaults()
}
<|endoftext|>


<commit_before>package gopikacloud

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
)

const (
	defaultBaseURL = "https://pikacloud.com/api/"
	apiVersion     = "v1"
)

// Client manages communication with Pikacloud API.
type Client struct {
	// API Token for authenticating
	APIToken string
	// HTTP client used to communicate with the Pikacloud API.
	HTTPClient *http.Client
	// Base URL for API requests.
	BaseURL string
}

// NewClient users
func NewClient(apiToken string) *Client {
	return &Client{APIToken: apiToken, HTTPClient: &http.Client{}, BaseURL: defaultBaseURL}
}

func (client *Client) makeRequest(method, path string, body io.Reader) (*http.Request, error) {
	url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path)
	req, err := http.NewRequest(method, url, body)
	req.Header.Add("Authorization: Token", fmt.Sprintf("%s", client.APIToken))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	if err != nil {
		return nil, err
	}
	return req, nil
}

func (client *Client) get(path string, val interface{}) error {
	body, _, err := client.sendRequest("GET", path, nil)
	if err != nil {
		return err
	}

	if err = json.Unmarshal([]byte(body), &val); err != nil {
		return err
	}

	return nil
}

func (client *Client) delete(path string, val interface{}) error {
	_, _, err := client.sendRequest("DELETE", path, nil)
	if err != nil {
		return err
	}
	return nil
}

func (client *Client) sendRequest(method, path string, body io.Reader) (string, int, error) {
	req, err := client.makeRequest(method, path, body)
	if err != nil {
		return "", 0, err
	}

	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		return "", 0, err
	}
	defer resp.Body.Close()

	responseBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", 0, err
	}

	return string(responseBytes), resp.StatusCode, nil
}
<commit_msg>fix auth header key<commit_after>package gopikacloud

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
)

const (
	defaultBaseURL = "https://pikacloud.com/api/"
	apiVersion     = "v1"
)

// Client manages communication with Pikacloud API.
type Client struct {
	// API Token for authenticating
	APIToken string
	// HTTP client used to communicate with the Pikacloud API.
	HTTPClient *http.Client
	// Base URL for API requests.
	BaseURL string
}

// NewClient users
func NewClient(apiToken string) *Client {
	return &Client{APIToken: apiToken, HTTPClient: &http.Client{}, BaseURL: defaultBaseURL}
}

func (client *Client) makeRequest(method, path string, body io.Reader) (*http.Request, error) {
	url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path)
	req, err := http.NewRequest(method, url, body)
	req.Header.Add("Authorization", fmt.Sprintf("Token: %s", client.APIToken))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	if err != nil {
		return nil, err
	}
	return req, nil
}

func (client *Client) get(path string, val interface{}) error {
	body, _, err := client.sendRequest("GET", path, nil)
	if err != nil {
		return err
	}

	if err = json.Unmarshal([]byte(body), &val); err != nil {
		return err
	}

	return nil
}

func (client *Client) delete(path string, val interface{}) error {
	_, _, err := client.sendRequest("DELETE", path, nil)
	if err != nil {
		return err
	}
	return nil
}

func (client *Client) sendRequest(method, path string, body io.Reader) (string, int, error) {
	req, err := client.makeRequest(method, path, body)
	if err != nil {
		return "", 0, err
	}

	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		return "", 0, err
	}
	defer resp.Body.Close()

	responseBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", 0, err
	}

	return string(responseBytes), resp.StatusCode, nil
}
<|endoftext|>


<commit_before>package gorobokassa

import (
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	QUERY_OUT_SUMM    = "OutSum"
	QUERY_INV_ID      = "InvId"
	QUERY_CRC         = "SignatureValue"
	QUERY_DESCRIPTION = "Desc"
	QUERY_LOGIN       = "MrchLogin"
	ROBOKASSA_HOST    = "auth.robokassa.ru"
	ROBOKASSA_PATH    = "Merchant/Index.aspx"
	SCHEME            = "https"
	DELIMETER         = ":"
)

var (
	ErrIncorrectValue = errors.New("incorrect value")
)

type Client struct {
	login          string
	firstPassword  string
	secondPassword string
}

// формирование URL переадресации пользователя на оплату
func (client *Client) Url(invoice, value int, description string) string {
	return buildRedirectUrl(client.login, client.firstPassword, invoice, value, description)
}

// получение уведомления об исполнении операции (ResultURL)
func (client *Client) CheckResult(r *http.Request) bool {
	return verifyRequest(client.secondPassword, r)
}

// проверка параметров в скрипте завершения операции (SuccessURL)
func (client *Client) CheckSuccess(r *http.Request) bool {
	return verifyRequest(client.firstPassword, r)
}

func New(login, password1, password2 string) *Client {
	return &Client{login, password1, password2}
}

// join values with delimeter and return hex of md5
func CRC(v ...interface{}) string {
	s := make([]string, len(v))
	for key, value := range v {
		s[key] = fmt.Sprintf("%v", value)
	}
	h := md5.New()
	io.WriteString(h, strings.Join(s, DELIMETER))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func buildRedirectUrl(login, password string, invoice, value int, description string) string {
	q := url.URL{}
	q.Host = ROBOKASSA_HOST
	q.Scheme = SCHEME
	q.Path = ROBOKASSA_PATH

	params := url.Values{}
	params.Add(QUERY_LOGIN, login)
	params.Add(QUERY_OUT_SUMM, strconv.Itoa(value))
	params.Add(QUERY_INV_ID, strconv.Itoa(invoice))
	params.Add(QUERY_DESCRIPTION, description)
	params.Add(QUERY_CRC, CRC(login, value, invoice, password))

	q.RawQuery = params.Encode()
	return q.String()
}

func verifyResult(password string, invoice, value int, crc string) bool {
	return strings.ToUpper(crc) == strings.ToUpper(CRC(value, invoice, password))
}

func verifyRequest(password string, r *http.Request) bool {
	q := r.URL.Query()
	value, err := strconv.Atoi(q.Get(QUERY_OUT_SUMM))
	if err != nil {
		log.Println(err)
		return false
	}
	invoice, err := strconv.Atoi(q.Get(QUERY_INV_ID))
	if err != nil {
		log.Println(err)
		return false
	}
	crc := q.Get(QUERY_CRC)
	return verifyResult(password, invoice, value, crc)
}
<commit_msg>removed errors<commit_after>package gorobokassa

import (
	"crypto/md5"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	QUERY_OUT_SUMM    = "OutSum"
	QUERY_INV_ID      = "InvId"
	QUERY_CRC         = "SignatureValue"
	QUERY_DESCRIPTION = "Desc"
	QUERY_LOGIN       = "MrchLogin"
	ROBOKASSA_HOST    = "auth.robokassa.ru"
	ROBOKASSA_PATH    = "Merchant/Index.aspx"
	SCHEME            = "https"
	DELIMETER         = ":"
)

type Client struct {
	login          string
	firstPassword  string
	secondPassword string
}

// формирование URL переадресации пользователя на оплату
func (client *Client) Url(invoice, value int, description string) string {
	return buildRedirectUrl(client.login, client.firstPassword, invoice, value, description)
}

// получение уведомления об исполнении операции (ResultURL)
func (client *Client) CheckResult(r *http.Request) bool {
	return verifyRequest(client.secondPassword, r)
}

// проверка параметров в скрипте завершения операции (SuccessURL)
func (client *Client) CheckSuccess(r *http.Request) bool {
	return verifyRequest(client.firstPassword, r)
}

func New(login, password1, password2 string) *Client {
	return &Client{login, password1, password2}
}

// join values with delimeter and return hex of md5
func CRC(v ...interface{}) string {
	s := make([]string, len(v))
	for key, value := range v {
		s[key] = fmt.Sprintf("%v", value)
	}
	h := md5.New()
	io.WriteString(h, strings.Join(s, DELIMETER))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func buildRedirectUrl(login, password string, invoice, value int, description string) string {
	q := url.URL{}
	q.Host = ROBOKASSA_HOST
	q.Scheme = SCHEME
	q.Path = ROBOKASSA_PATH

	params := url.Values{}
	params.Add(QUERY_LOGIN, login)
	params.Add(QUERY_OUT_SUMM, strconv.Itoa(value))
	params.Add(QUERY_INV_ID, strconv.Itoa(invoice))
	params.Add(QUERY_DESCRIPTION, description)
	params.Add(QUERY_CRC, CRC(login, value, invoice, password))

	q.RawQuery = params.Encode()
	return q.String()
}

func verifyResult(password string, invoice, value int, crc string) bool {
	return strings.ToUpper(crc) == strings.ToUpper(CRC(value, invoice, password))
}

func verifyRequest(password string, r *http.Request) bool {
	q := r.URL.Query()
	value, err := strconv.Atoi(q.Get(QUERY_OUT_SUMM))
	if err != nil {
		log.Println(err)
		return false
	}
	invoice, err := strconv.Atoi(q.Get(QUERY_INV_ID))
	if err != nil {
		log.Println(err)
		return false
	}
	crc := q.Get(QUERY_CRC)
	return verifyResult(password, invoice, value, crc)
}
<|endoftext|>


<commit_before>// Riemann middleware for martini framework
//
// Copyright (C) 2014 by Christopher Gilbert <christopher.john.gilbert@gmail.com>
package gorymartini

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

	"github.com/bigdatadev/goryman"
	"github.com/go-martini/martini"
)

// NewGoryMartini - Factory
func NewGoryMartini(host string) (*goryman.GorymanClient, martini.Handler) {
	riemann := goryman.NewGorymanClient(host)
	err := riemann.Connect()
	if err != nil {
		return nil, nil
	}

	return riemann, func(res http.ResponseWriter, req *http.Request, c martini.Context, log *log.Logger) {
		start := time.Now()

		rw := res.(martini.ResponseWriter)
		c.Next()

		metric := float64(time.Since(start))

		err := riemann.SendEvent(&goryman.Event{
			Service:     "http req",
			Metric:      metric,
			Description: fmt.Sprintf("Request took %f seconds.", metric),
			Tags: []string{
				"http",
			},
			Attributes: map[string]string{
				"path":   req.URL.Path,
				"status": strconv.Itoa(rw.Status()),
			},
		})
		if err != nil {
			log.Fatal("Riemann client SendEvent failed!")
		}
	}
}
<commit_msg>Fixed time conversion<commit_after>// Riemann middleware for martini framework
//
// Copyright (C) 2014 by Christopher Gilbert <christopher.john.gilbert@gmail.com>
package gorymartini

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

	"github.com/bigdatadev/goryman"
	"github.com/go-martini/martini"
)

// NewGoryMartini - Factory
func NewGoryMartini(host string) (*goryman.GorymanClient, martini.Handler) {
	riemann := goryman.NewGorymanClient(host)
	err := riemann.Connect()
	if err != nil {
		return nil, nil
	}

	return riemann, func(res http.ResponseWriter, req *http.Request, c martini.Context, log *log.Logger) {
		start := time.Now()

		rw := res.(martini.ResponseWriter)
		c.Next()

		metric := float64(time.Since(start)) / float64(time.Millisecond)

		err := riemann.SendEvent(&goryman.Event{
			Service:     "http req",
			Metric:      metric,
			Description: fmt.Sprintf("Request took %f seconds.", metric),
			Tags: []string{
				"http",
			},
			Attributes: map[string]string{
				"path":   req.URL.Path,
				"status": strconv.Itoa(rw.Status()),
			},
		})
		if err != nil {
			log.Fatal("Riemann client SendEvent failed!")
		}
	}
}
<|endoftext|>


<commit_before>// Package gowebsocket is a websocket library.
// Currently functional api - will improve and add OO alternative.
package gowebsocket

import (
	"fmt"
	"golang.org/x/net/websocket"
	"io"
	"math"
	"net/http"
	"strconv"
	"time"
)

// WebscketServer is the main struct representing the server.
type WebsocketServer struct{}

// SocketHandler is an alias.
type SocketHandler func(*websocket.Conn)

// CustomHandler is an alias.
type CustomHandler func([]byte, func(string))

// NewWensocketServer returns a new WebsocketServer.
func NewWebsocketServer() *WebsocketServer {
	return &WebsocketServer{}
}

// Add adds a route and an associated handler function.
func (s *WebsocketServer) Add(route string, handlerFn CustomHandler) {
	http.Handle(route, websocket.Handler(getSocketHandler(handlerFn)))
}

// Start starts the server listening for the specified routes.
func (s *WebsocketServer) Start() {
	fmt.Println("Starting websocket server...")
	// Server an example client html page.
	s.serveExampleClientPage()
	// Add builtin fixed routes - will probably remove.
	s.addBuiltinRoutes()
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}

// getSocketHandler returns a handler to be asscociated with a route.
// The handler wraps the client-provided handler, receives request data
// from the websocket, passes it on to the wrapped handler, along with a
// send function for the wrapped handler to use to send the response.
func getSocketHandler(myCustHandler CustomHandler) SocketHandler {
	return func(ws *websocket.Conn) {
		var in []byte
		if err := websocket.Message.Receive(ws, &in); err != nil {
			fmt.Println("Err,", err)
		}
		outFn := func(msg string) {
			websocket.Message.Send(ws, msg)
		}
		myCustHandler(in, outFn)
	}
}

/*
 * The below is non-essential and will be (re)moved at some point.
 */

// serveExampleClientPage serves a html page which will communicate with the websocket server.
func (s *WebsocketServer) serveExampleClientPage() {
	handler := func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "socketbasic.html")
	}
	http.HandleFunc("/", handler)
}

// addBuiltinRoutes adds some routes that might be useful, eg for debugging.
func (s *WebsocketServer) addBuiltinRoutes() {
	// Http handlers - http://
	//http.HandleFunc("/", reqDump)
	//fs := http.FileServer(http.Dir("."))
	//http.Handle("/builtin/", http.StripPrefix("/builtin/", fs))

	//http.Handle("/", http.FileServer(http.Dir(".")))

	// Websocket handlers - ws://
	//http.Handle("/echo", websocket.Handler(webHandler))
	//http.Handle("/", websocket.Handler(webHandler))
}

// reqDump might be useful for debugging.
func reqDump(c http.ResponseWriter, req *http.Request) {
	fmt.Println("Received request for url:", req.URL)
	c.Write([]byte("Nice."))
}

// echoHandler might be useful for debugging.
func echoHandler(ws *websocket.Conn) {
	fmt.Println("Echoing.")
	io.Copy(ws, ws)
}

// webHandler is a sample fake data feed.
func webHandler(ws *websocket.Conn) {
	fmt.Println("rx")
	var in []byte
	if err := websocket.Message.Receive(ws, &in); err != nil {
		fmt.Println("Err,", err)
		return
	}

	for i := 0; i < 100; i++ {
		for j := 0; j < 10; j++ {
			rad := (math.Pi * 2) / 10 * float64(j)
			response := strconv.FormatFloat(rad, 'f', 6, 64)
			websocket.Message.Send(ws, response)
			time.Sleep(time.Millisecond * 100)
		}
	}
}
<commit_msg>Moved socket client route to a separate object.<commit_after>// Package gowebsocket is a websocket library.
// Currently functional api - will improve and add OO alternative.
package gowebsocket

import (
	"fmt"
	"golang.org/x/net/websocket"
	"io"
	"math"
	"net/http"
	"strconv"
	"time"
)

// WebsocketServer is the main struct representing the websocket server.
type WebsocketServer struct{}

// WebServer is a simple html server, useful for serving a websocket client.
type WebServer struct{}

// SocketHandler is an alias.
type SocketHandler func(*websocket.Conn)

// CustomHandler is an alias.
type CustomHandler func([]byte, func(string))

// NewWebsocketServer returns a new WebsocketServer.
func NewWebsocketServer() *WebsocketServer {
	return &WebsocketServer{}
}

// NewWebServer returns a new WebServer.
func NewWebServer() *WebServer {
	return &WebServer{}
}

// Add adds a route and an associated handler function.
func (s *WebsocketServer) Add(route string, handlerFn CustomHandler) {
	http.Handle(route, websocket.Handler(getSocketHandler(handlerFn)))
}

// Start starts the server listening for the specified routes.
func (s *WebsocketServer) Start() {
	fmt.Println("Starting websocket server...")
	// Serve an example client html page.
	w := NewWebServer()
	w.serveExampleClientPage()
	// Add builtin fixed routes - will probably remove.
	s.addBuiltinRoutes()
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}

// getSocketHandler returns a handler to be asscociated with a route.
// The handler wraps the client-provided handler, receives request data
// from the websocket, passes it on to the wrapped handler, along with a
// send function for the wrapped handler to use to send the response.
func getSocketHandler(myCustHandler CustomHandler) SocketHandler {
	return func(ws *websocket.Conn) {
		var in []byte
		if err := websocket.Message.Receive(ws, &in); err != nil {
			fmt.Println("Err,", err)
		}
		outFn := func(msg string) {
			websocket.Message.Send(ws, msg)
		}
		myCustHandler(in, outFn)
	}
}

/*
 * The below is non-essential and will be (re)moved at some point.
 */

// serveExampleClientPage serves a html page which will communicate with the websocket server.
func (s *WebServer) serveExampleClientPage() {
	handler := func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "socketbasic.html")
	}
	http.HandleFunc("/", handler)
	// Putting this here for possible later use.
	//err := http.ListenAndServe(":8081", nil)
	//if err != nil {
	//	panic("ListenAndServe: " + err.Error())
	//}

}

// addBuiltinRoutes adds some routes that might be useful, eg for debugging.
func (s *WebsocketServer) addBuiltinRoutes() {
	// Http handlers - http://
	//http.HandleFunc("/", reqDump)
	//fs := http.FileServer(http.Dir("."))
	//http.Handle("/builtin/", http.StripPrefix("/builtin/", fs))

	//http.Handle("/", http.FileServer(http.Dir(".")))

	// Websocket handlers - ws://
	//http.Handle("/echo", websocket.Handler(webHandler))
	//http.Handle("/", websocket.Handler(webHandler))
}

// reqDump might be useful for debugging.
func reqDump(c http.ResponseWriter, req *http.Request) {
	fmt.Println("Received request for url:", req.URL)
	c.Write([]byte("Nice."))
}

// echoHandler might be useful for debugging.
func echoHandler(ws *websocket.Conn) {
	fmt.Println("Echoing.")
	io.Copy(ws, ws)
}

// webHandler is a sample fake data feed.
func webHandler(ws *websocket.Conn) {
	fmt.Println("rx")
	var in []byte
	if err := websocket.Message.Receive(ws, &in); err != nil {
		fmt.Println("Err,", err)
		return
	}

	for i := 0; i < 100; i++ {
		for j := 0; j < 10; j++ {
			rad := (math.Pi * 2) / 10 * float64(j)
			response := strconv.FormatFloat(rad, 'f', 6, 64)
			websocket.Message.Send(ws, response)
			time.Sleep(time.Millisecond * 100)
		}
	}
}
<|endoftext|>


<commit_before>package parser

import (
	"reflect"
	"strings"
	"testing"

	"github.com/elpinal/coco3/extra/ast"
)

func TestParse(t *testing.T) {
	tests := []struct {
		src  string
		name string
		args []ast.Expr
	}{
		{
			src:  "aa 'b'",
			name: "aa",
			args: []ast.Expr{&ast.String{Lit: "b"}},
		},
		{
			src:  "a 'u' : 'v' : []",
			name: "a",
			args: []ast.Expr{
				&ast.Cons{
					Head: "u",
					Tail: &ast.Cons{
						Head: "v",
						Tail: &ast.Empty{},
					},
				},
			},
		},
		{
			src:  "a-b ['u', 'v']",
			name: "a-b",
			args: []ast.Expr{
				&ast.Cons{
					Head: "u",
					Tail: &ast.Cons{
						Head: "v",
						Tail: &ast.Empty{},
					},
				},
			},
		},
		{
			src:  "a-b1-2190 [''] 8",
			name: "a-b1-2190",
			args: []ast.Expr{
				&ast.Cons{
					Head: "",
					Tail: &ast.Empty{},
				},
				&ast.Int{
					Lit: "8",
				},
			},
		},
		{
			src:  `a '{{range .Imports}}{{. | printf "%s\\n"}}{{end}}'`,
			name: "a",
			args: []ast.Expr{
				&ast.String{
					Lit: `{{range .Imports}}{{. | printf "%s\n"}}{{end}}`,
				},
			},
		},
		{
			src:  "!cmd",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}},
		},
		{
			src:  "!cmd []",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}, &ast.Empty{}},
		},
		{
			src:  "! cmd ['arg']",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}, &ast.Cons{&ast.String{"arg"}, &ast.Empty{}}},
		},
	}
	for _, test := range tests {
		x, err := Parse([]byte(test.src))
		if err != nil {
			t.Fatalf("Parse(%q): %v", test.src, err)
		}
		if x.Name.Lit != test.name {
			t.Fatalf("Parse(%q).Lit != %s; got %s", test.src, test.name, x.Name.Lit)
		}
		if !reflect.DeepEqual(x.Args, test.args) {
			t.Errorf("Parse(%q).Args != %v; got %v", test.src, test.args, x.Args)
		}
	}
}

func TestParseFail(t *testing.T) {
	tests := []string{
		"aa '",
		"'a'",
		"12",
		"a :",
		"a [",
		"a ?--#b",
		`a "bc\3df"`,
		"a ['",
	}
	for _, src := range tests {
		got, err := Parse([]byte(src))
		if err == nil {
			t.Errorf("Parse(%q): unexpectedly succeeded", src)
			t.Fatalf("got: %v", got)
		}
	}
}

func match(s, q string) bool {
	return strings.Contains(s, q)
}

func TestInvalidEscapeSequence(t *testing.T) {
	_, err := Parse([]byte(`a '\Z'`))
	if err == nil {
		t.Fatalf("Parse: unexpectedly succeeded")
	}
	p := `unknown escape sequence: \Z`
	if !match(err.(*ParseError).Msg, p) {
		t.Log("missing message about escape sequence in error message")
		t.Logf("pattern %q not found", p)
		t.FailNow()
	}
}
<commit_msg>Fix test<commit_after>package parser

import (
	"reflect"
	"strings"
	"testing"

	"github.com/elpinal/coco3/extra/ast"
)

func TestParse(t *testing.T) {
	tests := []struct {
		src  string
		name string
		args []ast.Expr
	}{
		{
			src:  "aa 'b'",
			name: "aa",
			args: []ast.Expr{&ast.String{Lit: "b"}},
		},
		{
			src:  "a 'u' : 'v' : []",
			name: "a",
			args: []ast.Expr{
				&ast.Cons{
					Head: "u",
					Tail: &ast.Cons{
						Head: "v",
						Tail: &ast.Empty{},
					},
				},
			},
		},
		{
			src:  "a-b ['u', 'v']",
			name: "a-b",
			args: []ast.Expr{
				&ast.Cons{
					Head: "u",
					Tail: &ast.Cons{
						Head: "v",
						Tail: &ast.Empty{},
					},
				},
			},
		},
		{
			src:  "a-b1-2190 [''] 8",
			name: "a-b1-2190",
			args: []ast.Expr{
				&ast.Cons{
					Head: "",
					Tail: &ast.Empty{},
				},
				&ast.Int{
					Lit: "8",
				},
			},
		},
		{
			src:  `a '{{range .Imports}}{{. | printf "%s\\n"}}{{end}}'`,
			name: "a",
			args: []ast.Expr{
				&ast.String{
					Lit: `{{range .Imports}}{{. | printf "%s\n"}}{{end}}`,
				},
			},
		},
		{
			src:  "!cmd",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}},
		},
		{
			src:  "!cmd []",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}, &ast.Empty{}},
		},
		{
			src:  "! cmd ['arg']",
			name: "exec",
			args: []ast.Expr{&ast.String{Lit: "cmd"}, &ast.Cons{"arg", &ast.Empty{}}},
		},
	}
	for _, test := range tests {
		x, err := Parse([]byte(test.src))
		if err != nil {
			t.Fatalf("Parse(%q): %v", test.src, err)
		}
		if x.Name.Lit != test.name {
			t.Fatalf("Parse(%q).Lit != %s; got %s", test.src, test.name, x.Name.Lit)
		}
		if !reflect.DeepEqual(x.Args, test.args) {
			t.Errorf("Parse(%q).Args != %v; got %v", test.src, test.args, x.Args)
		}
	}
}

func TestParseFail(t *testing.T) {
	tests := []string{
		"aa '",
		"'a'",
		"12",
		"a :",
		"a [",
		"a ?--#b",
		`a "bc\3df"`,
		"a ['",
	}
	for _, src := range tests {
		got, err := Parse([]byte(src))
		if err == nil {
			t.Errorf("Parse(%q): unexpectedly succeeded", src)
			t.Fatalf("got: %v", got)
		}
	}
}

func match(s, q string) bool {
	return strings.Contains(s, q)
}

func TestInvalidEscapeSequence(t *testing.T) {
	_, err := Parse([]byte(`a '\Z'`))
	if err == nil {
		t.Fatalf("Parse: unexpectedly succeeded")
	}
	p := `unknown escape sequence: \Z`
	if !match(err.(*ParseError).Msg, p) {
		t.Log("missing message about escape sequence in error message")
		t.Logf("pattern %q not found", p)
		t.FailNow()
	}
}
<|endoftext|>


<commit_before>package message

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)

// Errors used by implementers of the MessageSet interface.
var (
	ErrMultipleCodecs = errors.New("multiple codecs found")
	ErrNoMessages     = errors.New("no messages provided")
	ErrNilMessages    = errors.New("nil messages provided")
)

// Constants used by implementers of the MessageSet interface.
const (
	OffsetLength  = 8
	MsgSizeLength = 4
	MsgOverhead   = MsgSizeLength + OffsetLength
)

// MessageSet is an in-memory sequential Message container with a fixed
// serialization format.
//
// With no compression enabled, each Message is laid out sequentially
// and preceded by a header containing its offset and size.
//
//  -----------------------------------------------------------------
//  | offset | size | message | ... | offset+N | size N | message N |
//  -----------------------------------------------------------------
//
// With compression enabled, the previous byte slice is compressed and set as
// the value of a single Message within the MessageSet.
//
//  -----------------------------
//  | offset+N | size | message |
//  -----------------------------
//
type MessageSet struct{ buf []byte }

// NewMessageSet returns a MessageSet containing the provided Messages.
// The first offset is set to the provided one and increments from there for
// each Message.
//
// The compression Codec is found by iterating over all passed Messages and
// verifying that they all have the same Codec, or an error is returned.
// In case the Codec is valid, the resulting MessageSet will have a single
// Message with its value set to the compressed original MessageSet.
// If the compression fails an error will be returned.
func NewMessageSet(offset uint64, msgs ...Message) (*MessageSet, error) {
	if len(msgs) == 0 {
		return nil, ErrNoMessages
	} else if msgs[0] == nil {
		return nil, ErrNilMessages
	}
	codec, size := msgs[0].Codec(), MsgOverhead+msgs[0].Size()

	for i := 1; i < len(msgs); i++ {
		if msgs[i] == nil {
			return nil, ErrNilMessages
		} else if msgs[i].Codec() != codec {
			return nil, ErrMultipleCodecs
		}
		size += MsgOverhead + msgs[i].Size()
	}

	ms := &MessageSet{make([]byte, size)}
	ms.set(offset, msgs...)
	if err := ms.compress(offset, codec); err != nil {
		return nil, err
	}
	return ms, nil
}

// Iterate calls fn for each Message in the MessageSet.
// TODO: Support decompression.
func (ms *MessageSet) Iterate(fn func(offset uint64, msg Message) bool) bool {
	var (
		offset uint64
		size   uint32
	)
	for i := 0; i < ms.Size(); i += int(MsgOverhead + size) {
		offset = binary.BigEndian.Uint64(ms.buf[i : i+OffsetLength])
		size = binary.BigEndian.Uint32(ms.buf[i+OffsetLength : i+MsgOverhead])
		if fn(offset, Message(ms.buf[i+MsgOverhead:i+int(MsgOverhead+size)])) {
			return true // Halt iteration
		}
	}
	return false
}

// Size returns the byte size of the MessageSet.
func (ms *MessageSet) Size() int {
	return len(ms.buf)
}

// Equal returns whether other MessageSet is equal to ms.
func (ms *MessageSet) Equal(other MessageSet) bool {
	return bytes.Equal(ms.buf, other.buf)
}

// WriteTo implements the io.WriterTo interface.
func (ms *MessageSet) WriteTo(w io.Writer) (int64, error) {
	n, err := w.Write(ms.buf)
	return int64(n), err
}

// String implements the fmt.Stringer interface.
func (ms *MessageSet) String() string {
	var (
		str bytes.Buffer
		lim = 100
	)

	fmt.Fprintln(&str, "MessageSet{")
	halted := ms.Iterate(func(_ uint64, msg Message) bool {
		if lim -= 1; lim == 0 {
			return true
		}
		fmt.Fprintln(&str, "  ", msg, ",")
		return false
	})

	if halted {
		fmt.Fprintln(&str, "  ...")
	}

	fmt.Fprint(&str, "}")

	return str.String()
}

// set writes the provided Messages to the MessageSet
// starting with the provided offset.
func (ms *MessageSet) set(offset uint64, msgs ...Message) {
	var n uint32
	for i, msg := range msgs {
		binary.BigEndian.PutUint64(ms.buf[n:], offset+uint64(i))
		binary.BigEndian.PutUint32(ms.buf[n+OffsetLength:], msg.Size())
		n += uint32(MsgOverhead + copy(ms.buf[n+MsgOverhead:], msg))
	}
	ms.buf = ms.buf[:n]
}

// compress reduces the MessageSet to a single Message which holds the
// compressed payload in its value.
// It returns an error when the Codec fails to compress.
func (ms *MessageSet) compress(offset uint64, codec Codec) error {
	if codec == NoCodec {
		return nil
	}

	value, err := codec.Compress(ms.buf)
	if err != nil {
		return err
	}

	ms.set(offset-1, NewMessage(nil, value, codec))

	return nil
}
<commit_msg>message: MessageOffset<commit_after>package message

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)

// Errors used by implementers of the MessageSet interface.
var (
	ErrMultipleCodecs = errors.New("multiple codecs found")
	ErrNoMessages     = errors.New("no messages provided")
	ErrNilMessages    = errors.New("nil messages provided")
)

// Constants used by implementers of the MessageSet interface.
const (
	OffsetLength  = 8
	MsgSizeLength = 4
	MsgOverhead   = MsgSizeLength + OffsetLength
)

// MessageOffset is an utility type wrapping a Message and its offset within a
// MessageSet.
type MessageOffset struct {
	Offset uint64
	Message
}

// MessageSet is an in-memory sequential Message container with a fixed
// serialization format.
//
// With no compression enabled, each Message is laid out sequentially
// and preceded by a header containing its offset and size.
//
//  -----------------------------------------------------------------
//  | offset | size | message | ... | offset+N | size N | message N |
//  -----------------------------------------------------------------
//
// With compression enabled, the previous byte slice is compressed and set as
// the value of a single Message within the MessageSet.
//
//  -----------------------------
//  | offset+N | size | message |
//  -----------------------------
//
type MessageSet struct{ buf []byte }

// NewMessageSet returns a MessageSet containing the provided Messages.
// The first offset is set to the provided one and increments from there for
// each Message.
//
// The compression Codec is found by iterating over all passed Messages and
// verifying that they all have the same Codec, or an error is returned.
// In case the Codec is valid, the resulting MessageSet will have a single
// Message with its value set to the compressed original MessageSet.
// If the compression fails an error will be returned.
func NewMessageSet(offset uint64, msgs ...Message) (*MessageSet, error) {
	if len(msgs) == 0 {
		return nil, ErrNoMessages
	} else if msgs[0] == nil {
		return nil, ErrNilMessages
	}
	codec, size := msgs[0].Codec(), MsgOverhead+msgs[0].Size()

	for i := 1; i < len(msgs); i++ {
		if msgs[i] == nil {
			return nil, ErrNilMessages
		} else if msgs[i].Codec() != codec {
			return nil, ErrMultipleCodecs
		}
		size += MsgOverhead + msgs[i].Size()
	}

	ms := &MessageSet{make([]byte, size)}
	ms.set(offset, msgs...)
	if err := ms.compress(offset, codec); err != nil {
		return nil, err
	}
	return ms, nil
}

// Iterate calls fn for each Message in the MessageSet.
// TODO: Support decompression.
func (ms *MessageSet) Iterate(fn func(m MessageOffset) bool) bool {
	var (
		offset uint64
		size   uint32
		msg    Message
	)
	for i := 0; i < ms.Size(); i += int(MsgOverhead + size) {
		offset = binary.BigEndian.Uint64(ms.buf[i : i+OffsetLength])
		size = binary.BigEndian.Uint32(ms.buf[i+OffsetLength : i+MsgOverhead])
		msg = Message(ms.buf[i+MsgOverhead : i+int(MsgOverhead+size)])
		if fn(MessageOffset{Offset: offset, Message: msg}) {
			return true // Halt iteration
		}
	}
	return false
}

// Size returns the byte size of the MessageSet.
func (ms *MessageSet) Size() int {
	return len(ms.buf)
}

// Equal returns whether other MessageSet is equal to ms.
func (ms *MessageSet) Equal(other MessageSet) bool {
	return bytes.Equal(ms.buf, other.buf)
}

// WriteTo implements the io.WriterTo interface.
func (ms *MessageSet) WriteTo(w io.Writer) (int64, error) {
	n, err := w.Write(ms.buf)
	return int64(n), err
}

// String implements the fmt.Stringer interface.
func (ms *MessageSet) String() string {
	var (
		str bytes.Buffer
		lim = 100
	)

	fmt.Fprintln(&str, "MessageSet{")
	halted := ms.Iterate(func(m MessageOffset) bool {
		if lim -= 1; lim == 0 {
			return true
		}
		fmt.Fprintf(&str, "  %d: %s,\n", m.Offset, m)
		return false
	})

	if halted {
		fmt.Fprintln(&str, "  ...")
	}

	fmt.Fprint(&str, "}")

	return str.String()
}

// set writes the provided Messages to the MessageSet
// starting with the provided offset.
func (ms *MessageSet) set(offset uint64, msgs ...Message) {
	var n uint32
	for i, msg := range msgs {
		binary.BigEndian.PutUint64(ms.buf[n:], offset+uint64(i))
		binary.BigEndian.PutUint32(ms.buf[n+OffsetLength:], msg.Size())
		n += uint32(MsgOverhead + copy(ms.buf[n+MsgOverhead:], msg))
	}
	ms.buf = ms.buf[:n]
}

// compress reduces the MessageSet to a single Message which holds the
// compressed payload in its value.
// It returns an error when the Codec fails to compress.
func (ms *MessageSet) compress(offset uint64, codec Codec) error {
	if codec == NoCodec {
		return nil
	}

	value, err := codec.Compress(ms.buf)
	if err != nil {
		return err
	}

	ms.set(offset-1, NewMessage(nil, value, codec))

	return nil
}
<|endoftext|>


<commit_before>package framework

import (
	"fmt"
	"time"

	"github.com/hashicorp/vault/logical"
)

// LeaseExtend returns an OperationFunc that can be used to simply extend the
// lease of the auth/secret for the duration that was requested.
//
// backendIncrement is the backend's requested increment -- perhaps from a user
// request, perhaps from a role/config value. If not set, uses the mount/system
// value.
//
// backendMax is the backend's requested increment -- this can be more
// restrictive than the mount/system value but not less.
//
// systemView is the system view from the calling backend, used to determine
// and/or correct default/max times.
func LeaseExtend(backendIncrement, backendMax time.Duration, systemView logical.SystemView) OperationFunc {
	return func(req *logical.Request, data *FieldData) (*logical.Response, error) {
		var leaseOpts *logical.LeaseOptions
		switch {
		case req.Auth != nil:
			leaseOpts = &req.Auth.LeaseOptions
		case req.Secret != nil:
			leaseOpts = &req.Secret.LeaseOptions
		default:
			return nil, fmt.Errorf("no lease options for request")
		}

		// Use the mount's configured max unless the backend specifies
		// something more restrictive (perhaps from a role configuration
		// parameter)
		max := systemView.MaxLeaseTTL()
		if backendMax > 0 && backendMax < max {
			max = backendMax
		}

		// Should never happen, but guard anyways
		if max < 0 {
			return nil, fmt.Errorf("max TTL is negative")
		}

		// We cannot go past this time
		maxValidTime := leaseOpts.IssueTime.UTC().Add(max)

		// Get the current time
		now := time.Now().UTC()

		// If we are past the max TTL, we shouldn't be in this function...but
		// fast path out if we are
		if maxValidTime.Before(now) {
			return nil, fmt.Errorf("past the max TTL, cannot renew")
		}

		// Basic max safety checks have passed, now let's figure out our
		// increment. We'll use the backend-provided value if possible, or the
		// mount/system default if not. We won't change the LeaseOpts value,
		// just adjust accordingly.
		increment := leaseOpts.Increment
		if backendIncrement > 0 {
			increment = backendIncrement
		}
		if increment <= 0 {
			increment = systemView.DefaultLeaseTTL()
		}

		proposedExpiration := leaseOpts.IssueTime.UTC().Add(increment)

		// If the proposed expiration is after the maximum TTL of the lease,
		// cap the increment to whatever is left
		if maxValidTime.Before(proposedExpiration) {
			increment = maxValidTime.Sub(now)
		}

		// Set the lease
		leaseOpts.TTL = increment

		return &logical.Response{Auth: req.Auth, Secret: req.Secret}, nil
	}
}
<commit_msg>Update proposed time<commit_after>package framework

import (
	"fmt"
	"time"

	"github.com/hashicorp/vault/logical"
)

// LeaseExtend returns an OperationFunc that can be used to simply extend the
// lease of the auth/secret for the duration that was requested.
//
// backendIncrement is the backend's requested increment -- perhaps from a user
// request, perhaps from a role/config value. If not set, uses the mount/system
// value.
//
// backendMax is the backend's requested increment -- this can be more
// restrictive than the mount/system value but not less.
//
// systemView is the system view from the calling backend, used to determine
// and/or correct default/max times.
func LeaseExtend(backendIncrement, backendMax time.Duration, systemView logical.SystemView) OperationFunc {
	return func(req *logical.Request, data *FieldData) (*logical.Response, error) {
		var leaseOpts *logical.LeaseOptions
		switch {
		case req.Auth != nil:
			leaseOpts = &req.Auth.LeaseOptions
		case req.Secret != nil:
			leaseOpts = &req.Secret.LeaseOptions
		default:
			return nil, fmt.Errorf("no lease options for request")
		}

		// Use the mount's configured max unless the backend specifies
		// something more restrictive (perhaps from a role configuration
		// parameter)
		max := systemView.MaxLeaseTTL()
		if backendMax > 0 && backendMax < max {
			max = backendMax
		}

		// Should never happen, but guard anyways
		if max < 0 {
			return nil, fmt.Errorf("max TTL is negative")
		}

		// We cannot go past this time
		maxValidTime := leaseOpts.IssueTime.UTC().Add(max)

		// Get the current time
		now := time.Now().UTC()

		// If we are past the max TTL, we shouldn't be in this function...but
		// fast path out if we are
		if maxValidTime.Before(now) {
			return nil, fmt.Errorf("past the max TTL, cannot renew")
		}

		// Basic max safety checks have passed, now let's figure out our
		// increment. We'll use the backend-provided value if possible, or the
		// mount/system default if not. We won't change the LeaseOpts value,
		// just adjust accordingly.
		increment := leaseOpts.Increment
		if backendIncrement > 0 {
			increment = backendIncrement
		}
		if increment <= 0 {
			increment = systemView.DefaultLeaseTTL()
		}

		// We are proposing a time of the current time plus the increment
		proposedExpiration := now.Add(increment)

		// If the proposed expiration is after the maximum TTL of the lease,
		// cap the increment to whatever is left
		if maxValidTime.Before(proposedExpiration) {
			increment = maxValidTime.Sub(now)
		}

		// Set the lease
		leaseOpts.TTL = increment

		return &logical.Response{Auth: req.Auth, Secret: req.Secret}, nil
	}
}
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

// Package semtech provides useful methods and types to handle communications with a gateway.
//
// This package relies on the SemTech Protocol 1.2 accessible on github: https://github.com/TheThingsNetwork/packet_forwarder/blob/master/PROTOCOL.TXT
package semtech

import (
	"encoding/base64"
	"fmt"
	"time"
)

type DeviceAddress [4]byte

// RXPK represents an uplink json message format sent by the gateway
type RXPK struct {
	Chan    *uint          `json:"chan,omitempty"` // Concentrator "IF" channel used for RX (unsigned integer)
	Codr    *string        `json:"codr,omitempty"` // LoRa ECC coding rate identifier
	Data    *string        `json:"data,omitempty"` // Base64 encoded RF packet payload, padded
	Datr    *string        `json:"-"`              // FSK datarate (unsigned in bit per second) || LoRa datarate identifier
	Freq    *float64       `json:"freq,omitempty"` // RX Central frequency in MHx (unsigned float, Hz precision)
	Lsnr    *float64       `json:"lsnr,omitempty"` // LoRa SNR ratio in dB (signed float, 0.1 dB precision)
	Modu    *string        `json:"modu,omitempty"` // Modulation identifier "LORA" or "FSK"
	Rfch    *uint          `json:"rfch,omitempty"` // Concentrator "RF chain" used for RX (unsigned integer)
	Rssi    *int           `json:"rssi,omitempty"` // RSSI in dBm (signed integer, 1 dB precision)
	Size    *uint          `json:"size,omitempty"` // RF packet payload size in bytes (unsigned integer)
	Stat    *int           `json:"stat,omitempty"` // CRC status: 1 - OK, -1 = fail, 0 = no CRC
	Time    *time.Time     `json:"-"`              // UTC time of pkt RX, us precision, ISO 8601 'compact' format
	Tmst    *uint          `json:"tmst,omitempty"` // Internal timestamp of "RX finished" event (32b unsigned)
	devAddr *DeviceAddress // End-Device address, according to the Data. Memoized here.
}

// DevAddr returns the end-device address described in the payload
func (rxpk *RXPK) DevAddr() *DeviceAddress {
	if rxpk.devAddr != nil {
		return rxpk.devAddr
	}

	if rxpk.Data == nil {
		return nil
	}

	buf, err := base64.StdEncoding.DecodeString(*rxpk.Data)
	if err != nil || len(buf) < 5 {
		return nil
	}

	rxpk.devAddr = new(DeviceAddress)
	copy((*rxpk.devAddr)[:], buf[1:5]) // Device Address corresponds to the first 4 bytes of the Frame Header, after one byte of MAC_HEADER
	return rxpk.devAddr
}

// TXPK represents a downlink j,omitemptyson message format received by the gateway.
// Most field are optional.
type TXPK struct {
	Codr    *string        `json:"codr,omitempty"`  // LoRa ECC coding rate identifier
	Data    *string        `json:"data,omirtmepty"` // Base64 encoded RF packet payload, padding optional
	Datr    *string        `json:"-"`               // LoRa datarate identifier (eg. SF12BW500) || FSK Datarate (unsigned, in bits per second)
	Fdev    *uint          `json:"fdev,omitempty"`  // FSK frequency deviation (unsigned integer, in Hz)
	Freq    *float64       `json:"freq,omitempty"`  // TX central frequency in MHz (unsigned float, Hz precision)
	Imme    *bool          `json:"imme,omitempty"`  // Send packet immediately (will ignore tmst & time)
	Ipol    *bool          `json:"ipol,omitempty"`  // Lora modulation polarization inversion
	Modu    *string        `json:"modu,omitempty"`  // Modulation identifier "LORA" or "FSK"
	Ncrc    *bool          `json:"ncrc,omitempty"`  // If true, disable the CRC of the physical layer (optional)
	Powe    *uint          `json:"powe,omitempty"`  // TX output power in dBm (unsigned integer, dBm precision)
	Prea    *uint          `json:"prea,omitempty"`  // RF preamble size (unsigned integer)
	Rfch    *uint          `json:"rfch,omitempty"`  // Concentrator "RF chain" used for TX (unsigned integer)
	Size    *uint          `json:"size,omitempty"`  // RF packet payload size in bytes (unsigned integer)
	Time    *time.Time     `json:"-"`               // Send packet at a certain time (GPS synchronization required)
	Tmst    *uint          `json:"tmst,omitempty"`  // Send packet on a certain timestamp value (will ignore time)
	devAddr *DeviceAddress // End-Device address, according to the Data. Memoized here.
}

// DevAddr returns the end-device address described in the payload
func (txpk *TXPK) DevAddr() *DeviceAddress {
	if txpk.devAddr != nil {
		return txpk.devAddr
	}

	if txpk.Data == nil {
		return nil
	}

	buf, err := base64.StdEncoding.DecodeString(*txpk.Data)
	if err != nil || len(buf) < 5 {
		return nil
	}

	txpk.devAddr = new(DeviceAddress)
	copy((*txpk.devAddr)[:], buf[1:5]) // Device Address corresponds to the first 4 bytes of the Frame Header, after one byte of MAC_HEADER
	return txpk.devAddr
}

// Stat represents a status json message format sent by the gateway
type Stat struct {
	Ackr *float64   `json:"ackr,omitempty"` // Percentage of upstream datagrams that were acknowledged
	Alti *int       `json:"alti,omitempty"` // GPS altitude of the gateway in meter RX (integer)
	Dwnb *uint      `json:"dwnb,omitempty"` // Number of downlink datagrams received (unsigned integer)
	Lati *float64   `json:"lati,omitempty"` // GPS latitude of the gateway in degree (float, N is +)
	Long *float64   `json:"long,omitempty"` // GPS latitude of the gateway in dgree (float, E is +)
	Rxfw *uint      `json:"rxfw,omitempty"` // Number of radio packets forwarded (unsigned integer)
	Rxnb *uint      `json:"rxnb,omitempty"` // Number of radio packets received (unsigned integer)
	Rxok *uint      `json:"rxok,omitempty"` // Number of radio packets received with a valid PHY CRC
	Time *time.Time `json:"-"`              // UTC 'system' time of the gateway, ISO 8601 'expanded' format
	Txnb *uint      `json:"txnb,omitempty"` // Number of packets emitted (unsigned integer)
}

// Packet as seen by the gateway.
type Packet struct {
	Version    byte     // Protocol version, should always be 1 here
	Token      []byte   // Random number generated by the gateway on some request. 2-bytes long.
	Identifier byte     // Packet's command identifier
	GatewayId  []byte   // Source gateway's identifier (Only PULL_DATA and PUSH_DATA)
	Payload    *Payload // JSON payload transmitted if any, nil otherwise
}

// Payload refers to the JSON payload sent by a gateway or a server.
type Payload struct {
	Raw  []byte `json:"-"`              // The raw unparsed response
	RXPK []RXPK `json:"rxpk,omitempty"` // A list of RXPK messages transmitted if any
	Stat *Stat  `json:"stat,omitempty"` // A Stat message transmitted if any
	TXPK *TXPK  `json:"txpk,omitempty"` // A TXPK message transmitted if any
}

// UniformDevAddr tries to extract a device address from the different part of a payload. If the
// payload is composed of messages coming from several end-device, the method will fail.
func (p Payload) UniformDevAddr() (*DeviceAddress, error) {
	var devAddr *DeviceAddress

	// Determine the devAddress associated to that payload
	if p.RXPK == nil || len(p.RXPK) == 0 { // NOTE are those conditions significantly different ?
		if p.TXPK == nil {
			return nil, fmt.Errorf("Unable to determine device address. No RXPK neither TXPK messages")
		}
		if devAddr = p.TXPK.DevAddr(); devAddr == nil {
			return nil, fmt.Errorf("Unable to determine device address from TXPK")
		}

	} else {
		// We check them all to be sure, but all RXPK should refer to the same End-Device
		for _, rxpk := range p.RXPK {
			addr := rxpk.DevAddr()
			if addr == nil || (devAddr != nil && *devAddr != *addr) {
				return nil, fmt.Errorf("Payload is composed of messages from several end-devices")
			}
			devAddr = addr
		}
	}
	return devAddr, nil
}

// Available packet commands
const (
	PUSH_DATA byte = iota // Sent by the gateway for an uplink message with data
	PUSH_ACK              // Sent by the gateway's recipient in response to a PUSH_DATA
	PULL_DATA             // Sent periodically by the gateway to keep a connection open
	PULL_RESP             // Sent by the gateway's recipient to transmit back data to the Gateway
	PULL_ACK              // Sent by the gateway's recipient in response to PULL_DATA
)

// Protocol version in use
const VERSION = 0x01
<commit_msg>[router] Remove NOTE. Conditions were actually different.<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

// Package semtech provides useful methods and types to handle communications with a gateway.
//
// This package relies on the SemTech Protocol 1.2 accessible on github: https://github.com/TheThingsNetwork/packet_forwarder/blob/master/PROTOCOL.TXT
package semtech

import (
	"encoding/base64"
	"fmt"
	"time"
)

type DeviceAddress [4]byte

// RXPK represents an uplink json message format sent by the gateway
type RXPK struct {
	Chan    *uint          `json:"chan,omitempty"` // Concentrator "IF" channel used for RX (unsigned integer)
	Codr    *string        `json:"codr,omitempty"` // LoRa ECC coding rate identifier
	Data    *string        `json:"data,omitempty"` // Base64 encoded RF packet payload, padded
	Datr    *string        `json:"-"`              // FSK datarate (unsigned in bit per second) || LoRa datarate identifier
	Freq    *float64       `json:"freq,omitempty"` // RX Central frequency in MHx (unsigned float, Hz precision)
	Lsnr    *float64       `json:"lsnr,omitempty"` // LoRa SNR ratio in dB (signed float, 0.1 dB precision)
	Modu    *string        `json:"modu,omitempty"` // Modulation identifier "LORA" or "FSK"
	Rfch    *uint          `json:"rfch,omitempty"` // Concentrator "RF chain" used for RX (unsigned integer)
	Rssi    *int           `json:"rssi,omitempty"` // RSSI in dBm (signed integer, 1 dB precision)
	Size    *uint          `json:"size,omitempty"` // RF packet payload size in bytes (unsigned integer)
	Stat    *int           `json:"stat,omitempty"` // CRC status: 1 - OK, -1 = fail, 0 = no CRC
	Time    *time.Time     `json:"-"`              // UTC time of pkt RX, us precision, ISO 8601 'compact' format
	Tmst    *uint          `json:"tmst,omitempty"` // Internal timestamp of "RX finished" event (32b unsigned)
	devAddr *DeviceAddress // End-Device address, according to the Data. Memoized here.
}

// DevAddr returns the end-device address described in the payload
func (rxpk *RXPK) DevAddr() *DeviceAddress {
	if rxpk.devAddr != nil {
		return rxpk.devAddr
	}

	if rxpk.Data == nil {
		return nil
	}

	buf, err := base64.StdEncoding.DecodeString(*rxpk.Data)
	if err != nil || len(buf) < 5 {
		return nil
	}

	rxpk.devAddr = new(DeviceAddress)
	copy((*rxpk.devAddr)[:], buf[1:5]) // Device Address corresponds to the first 4 bytes of the Frame Header, after one byte of MAC_HEADER
	return rxpk.devAddr
}

// TXPK represents a downlink j,omitemptyson message format received by the gateway.
// Most field are optional.
type TXPK struct {
	Codr    *string        `json:"codr,omitempty"`  // LoRa ECC coding rate identifier
	Data    *string        `json:"data,omirtmepty"` // Base64 encoded RF packet payload, padding optional
	Datr    *string        `json:"-"`               // LoRa datarate identifier (eg. SF12BW500) || FSK Datarate (unsigned, in bits per second)
	Fdev    *uint          `json:"fdev,omitempty"`  // FSK frequency deviation (unsigned integer, in Hz)
	Freq    *float64       `json:"freq,omitempty"`  // TX central frequency in MHz (unsigned float, Hz precision)
	Imme    *bool          `json:"imme,omitempty"`  // Send packet immediately (will ignore tmst & time)
	Ipol    *bool          `json:"ipol,omitempty"`  // Lora modulation polarization inversion
	Modu    *string        `json:"modu,omitempty"`  // Modulation identifier "LORA" or "FSK"
	Ncrc    *bool          `json:"ncrc,omitempty"`  // If true, disable the CRC of the physical layer (optional)
	Powe    *uint          `json:"powe,omitempty"`  // TX output power in dBm (unsigned integer, dBm precision)
	Prea    *uint          `json:"prea,omitempty"`  // RF preamble size (unsigned integer)
	Rfch    *uint          `json:"rfch,omitempty"`  // Concentrator "RF chain" used for TX (unsigned integer)
	Size    *uint          `json:"size,omitempty"`  // RF packet payload size in bytes (unsigned integer)
	Time    *time.Time     `json:"-"`               // Send packet at a certain time (GPS synchronization required)
	Tmst    *uint          `json:"tmst,omitempty"`  // Send packet on a certain timestamp value (will ignore time)
	devAddr *DeviceAddress // End-Device address, according to the Data. Memoized here.
}

// DevAddr returns the end-device address described in the payload
func (txpk *TXPK) DevAddr() *DeviceAddress {
	if txpk.devAddr != nil {
		return txpk.devAddr
	}

	if txpk.Data == nil {
		return nil
	}

	buf, err := base64.StdEncoding.DecodeString(*txpk.Data)
	if err != nil || len(buf) < 5 {
		return nil
	}

	txpk.devAddr = new(DeviceAddress)
	copy((*txpk.devAddr)[:], buf[1:5]) // Device Address corresponds to the first 4 bytes of the Frame Header, after one byte of MAC_HEADER
	return txpk.devAddr
}

// Stat represents a status json message format sent by the gateway
type Stat struct {
	Ackr *float64   `json:"ackr,omitempty"` // Percentage of upstream datagrams that were acknowledged
	Alti *int       `json:"alti,omitempty"` // GPS altitude of the gateway in meter RX (integer)
	Dwnb *uint      `json:"dwnb,omitempty"` // Number of downlink datagrams received (unsigned integer)
	Lati *float64   `json:"lati,omitempty"` // GPS latitude of the gateway in degree (float, N is +)
	Long *float64   `json:"long,omitempty"` // GPS latitude of the gateway in dgree (float, E is +)
	Rxfw *uint      `json:"rxfw,omitempty"` // Number of radio packets forwarded (unsigned integer)
	Rxnb *uint      `json:"rxnb,omitempty"` // Number of radio packets received (unsigned integer)
	Rxok *uint      `json:"rxok,omitempty"` // Number of radio packets received with a valid PHY CRC
	Time *time.Time `json:"-"`              // UTC 'system' time of the gateway, ISO 8601 'expanded' format
	Txnb *uint      `json:"txnb,omitempty"` // Number of packets emitted (unsigned integer)
}

// Packet as seen by the gateway.
type Packet struct {
	Version    byte     // Protocol version, should always be 1 here
	Token      []byte   // Random number generated by the gateway on some request. 2-bytes long.
	Identifier byte     // Packet's command identifier
	GatewayId  []byte   // Source gateway's identifier (Only PULL_DATA and PUSH_DATA)
	Payload    *Payload // JSON payload transmitted if any, nil otherwise
}

// Payload refers to the JSON payload sent by a gateway or a server.
type Payload struct {
	Raw  []byte `json:"-"`              // The raw unparsed response
	RXPK []RXPK `json:"rxpk,omitempty"` // A list of RXPK messages transmitted if any
	Stat *Stat  `json:"stat,omitempty"` // A Stat message transmitted if any
	TXPK *TXPK  `json:"txpk,omitempty"` // A TXPK message transmitted if any
}

// UniformDevAddr tries to extract a device address from the different part of a payload. If the
// payload is composed of messages coming from several end-device, the method will fail.
func (p Payload) UniformDevAddr() (*DeviceAddress, error) {
	var devAddr *DeviceAddress

	// Determine the devAddress associated to that payload
	if p.RXPK == nil || len(p.RXPK) == 0 {
		if p.TXPK == nil {
			return nil, fmt.Errorf("Unable to determine device address. No RXPK neither TXPK messages")
		}
		if devAddr = p.TXPK.DevAddr(); devAddr == nil {
			return nil, fmt.Errorf("Unable to determine device address from TXPK")
		}

	} else {
		// We check them all to be sure, but all RXPK should refer to the same End-Device
		for _, rxpk := range p.RXPK {
			addr := rxpk.DevAddr()
			if addr == nil || (devAddr != nil && *devAddr != *addr) {
				return nil, fmt.Errorf("Payload is composed of messages from several end-devices")
			}
			devAddr = addr
		}
	}
	return devAddr, nil
}

// Available packet commands
const (
	PUSH_DATA byte = iota // Sent by the gateway for an uplink message with data
	PUSH_ACK              // Sent by the gateway's recipient in response to a PUSH_DATA
	PULL_DATA             // Sent periodically by the gateway to keep a connection open
	PULL_RESP             // Sent by the gateway's recipient to transmit back data to the Gateway
	PULL_ACK              // Sent by the gateway's recipient in response to PULL_DATA
)

// Protocol version in use
const VERSION = 0x01
<|endoftext|>


<commit_before><commit_msg>log/syslog: document if network=="" for Dial, it will connect to local syslog server. Fixes issue 7828.<commit_after><|endoftext|>


<commit_before><commit_msg>please vet<commit_after><|endoftext|>