<commit_before>// +build k8s

package test

import (
	"io/ioutil"
	"log"
	"testing"
	"time"

	"github.com/mholt/caddy"
	"github.com/miekg/dns"
)

// Test data for A records
var testdataLookupA = []struct {
	Query            string
	TotalAnswerCount int
	ARecordCount     int
}{
	// Matching queries
	{"mynginx.demo.coredns.local.", 1, 1}, // One A record, should exist

	// Failure queries
	{"mynginx.test.coredns.local.", 0, 0},                     // One A record, is not exposed
	{"someservicethatdoesnotexist.demo.coredns.local.", 0, 0}, // Record does not exist

	// Namespace wildcards
	{"mynginx.*.coredns.local.", 1, 1},                       // One A record, via wildcard namespace
	{"mynginx.any.coredns.local.", 1, 1},                     // One A record, via wildcard namespace
	{"someservicethatdoesnotexist.*.coredns.local.", 0, 0},   // Record does not exist with wildcard for namespace
	{"someservicethatdoesnotexist.any.coredns.local.", 0, 0}, // Record does not exist with wildcard for namespace
	{"*.demo.coredns.local.", 2, 2},                          // Two A records, via wildcard
	{"any.demo.coredns.local.", 2, 2},                        // Two A records, via wildcard
	{"*.test.coredns.local.", 0, 0},                          // Two A record, via wildcard that is not exposed
	{"any.test.coredns.local.", 0, 0},                        // Two A record, via wildcard that is not exposed
	{"*.*.coredns.local.", 2, 2},                             // Two A records, via namespace and service wildcard
}

// Test data for SRV records
var testdataLookupSRV = []struct {
	Query            string
	TotalAnswerCount int
	//	ARecordCount     int
	SRVRecordCount int
}{
	// Matching queries
	{"mynginx.demo.coredns.local.", 1, 1}, // One SRV record, should exist

	// Failure queries
	{"mynginx.test.coredns.local.", 0, 0},                     // One SRV record, is not exposed
	{"someservicethatdoesnotexist.demo.coredns.local.", 0, 0}, // Record does not exist

	// Namespace wildcards
	{"mynginx.*.coredns.local.", 1, 1},                       // One SRV record, via wildcard namespace
	{"mynginx.any.coredns.local.", 1, 1},                     // One SRV record, via wildcard namespace
	{"someservicethatdoesnotexist.*.coredns.local.", 0, 0},   // Record does not exist with wildcard for namespace
	{"someservicethatdoesnotexist.any.coredns.local.", 0, 0}, // Record does not exist with wildcard for namespace
	{"*.demo.coredns.local.", 2, 2},                          // Two (mynginx, webserver) SRV record, via wildcard
	{"any.demo.coredns.local.", 2, 2},                        // Two (mynginx, webserver) SRV record, via wildcard
	{"*.test.coredns.local.", 0, 0},                          // One SRV record, via wildcard that is not exposed
	{"any.test.coredns.local.", 0, 0},                        // One SRV record, via wildcard that is not exposed
	{"*.*.coredns.local.", 2, 2},                             // Two SRV record, via namespace and service wildcard
}

func TestKubernetesIntegration(t *testing.T) {

	// t.Skip("Skip Kubernetes Integration tests")
	// subtests here (Go 1.7 feature).
	testLookupA(t)
	testLookupSRV(t)
}

func createTestServer(t *testing.T, corefile string) (*caddy.Instance, string) {
	server, err := CoreDNSServer(corefile)
	if err != nil {
		t.Fatalf("Could not get CoreDNS serving instance: %s", err)
	}

	udp, _ := CoreDNSServerPorts(server, 0)
	if udp == "" {
		t.Fatalf("Could not get UDP listening port")
	}

	return server, udp
}

func testLookupA(t *testing.T) {
	corefile :=
		`.:0 {
    kubernetes coredns.local {
                endpoint http://localhost:8080
		namespaces demo
    }

`
	server, udp := createTestServer(t, corefile)
	defer server.Stop()

	log.SetOutput(ioutil.Discard)

	// Work-around for timing condition that results in no-data being returned in
	// test environment.
	time.Sleep(5 * time.Second)

	for _, testData := range testdataLookupA {
		dnsClient := new(dns.Client)
		dnsMessage := new(dns.Msg)

		dnsMessage.SetQuestion(testData.Query, dns.TypeA)
		dnsMessage.SetEdns0(4096, true)

		res, _, err := dnsClient.Exchange(dnsMessage, udp)
		if err != nil {
			t.Fatalf("Could not send query: %s", err)
		}
		// Count A records in the answer section
		ARecordCount := 0
		for _, a := range res.Answer {
			if a.Header().Rrtype == dns.TypeA {
				ARecordCount++
			}
		}

		if ARecordCount != testData.ARecordCount {
			t.Errorf("Expected '%v' A records in response. Instead got '%v' A records. Test query string: '%v'", testData.ARecordCount, ARecordCount, testData.Query)
		}
		if len(res.Answer) != testData.TotalAnswerCount {
			t.Errorf("Expected '%v' records in answer section. Instead got '%v' records in answer section. Test query string: '%v'", testData.TotalAnswerCount, len(res.Answer), testData.Query)
		}
	}
}

func testLookupSRV(t *testing.T) {
	corefile :=
		`.:0 {
    kubernetes coredns.local {
                endpoint http://localhost:8080
		namespaces demo
    }
`

	server, udp := createTestServer(t, corefile)
	defer server.Stop()

	log.SetOutput(ioutil.Discard)

	// Work-around for timing condition that results in no-data being returned in
	// test environment.
	time.Sleep(5 * time.Second)

	// TODO: Add checks for A records in additional section

	for _, testData := range testdataLookupSRV {
		dnsClient := new(dns.Client)
		dnsMessage := new(dns.Msg)

		dnsMessage.SetQuestion(testData.Query, dns.TypeSRV)
		dnsMessage.SetEdns0(4096, true)

		res, _, err := dnsClient.Exchange(dnsMessage, udp)
		if err != nil {
			t.Fatalf("Could not send query: %s", err)
		}
		// Count SRV records in the answer section
		srvRecordCount := 0
		for _, a := range res.Answer {
			if a.Header().Rrtype == dns.TypeSRV {
				srvRecordCount++
			}
		}

		if srvRecordCount != testData.SRVRecordCount {
			t.Errorf("Expected '%v' SRV records in response. Instead got '%v' SRV records. Test query string: '%v', res: %v", testData.SRVRecordCount, srvRecordCount, testData.Query, res)
		}
		if len(res.Answer) != testData.TotalAnswerCount {
			t.Errorf("Expected '%v' records in answer section. Instead got '%v' records in answer section. Test query string: '%v', res: %v", testData.TotalAnswerCount, len(res.Answer), testData.Query, res)
		}
	}
}
<commit_msg>Update k8s integration tests<commit_after>// +build k8s

package test

import (
	"io/ioutil"
	"log"
	"testing"
	"time"

	"github.com/mholt/caddy"
	"github.com/miekg/dns"
)

// Test data for A records
var testdataLookupA = []struct {
	Query            string
	TotalAnswerCount int
	ARecordCount     int
}{
	// Matching queries
	{"mynginx.demo.svc.coredns.local.", 1, 1}, // One A record, should exist

	// Failure queries
	{"mynginx.test.svc.coredns.local.", 0, 0},                     // One A record, is not exposed
	{"someservicethatdoesnotexist.demo.svc.coredns.local.", 0, 0}, // Record does not exist

	// Namespace wildcards
	{"mynginx.*.svc.coredns.local.", 1, 1},                       // One A record, via wildcard namespace
	{"mynginx.any.svc.coredns.local.", 1, 1},                     // One A record, via wildcard namespace
	{"someservicethatdoesnotexist.*.svc.coredns.local.", 0, 0},   // Record does not exist with wildcard for namespace
	{"someservicethatdoesnotexist.any.svc.coredns.local.", 0, 0}, // Record does not exist with wildcard for namespace
	{"*.demo.svc.coredns.local.", 2, 2},                          // Two A records, via wildcard
	{"any.demo.svc.coredns.local.", 2, 2},                        // Two A records, via wildcard
	{"*.test.svc.coredns.local.", 0, 0},                          // Two A record, via wildcard that is not exposed
	{"any.test.svc.coredns.local.", 0, 0},                        // Two A record, via wildcard that is not exposed
	{"*.*.svc.coredns.local.", 2, 2},                             // Two A records, via namespace and service wildcard
}

// Test data for SRV records
var testdataLookupSRV = []struct {
	Query            string
	TotalAnswerCount int
	//	ARecordCount     int
	SRVRecordCount int
}{
	// Matching queries
	{"mynginx.demo.svc.coredns.local.", 1, 1}, // One SRV record, should exist

	// Failure queries
	{"mynginx.test.svc.coredns.local.", 0, 0},                     // One SRV record, is not exposed
	{"someservicethatdoesnotexist.demo.svc.coredns.local.", 0, 0}, // Record does not exist

	// Namespace wildcards
	{"mynginx.*.svc.coredns.local.", 1, 1},                       // One SRV record, via wildcard namespace
	{"mynginx.any.svc.coredns.local.", 1, 1},                     // One SRV record, via wildcard namespace
	{"someservicethatdoesnotexist.*.svc.coredns.local.", 0, 0},   // Record does not exist with wildcard for namespace
	{"someservicethatdoesnotexist.any.svc.coredns.local.", 0, 0}, // Record does not exist with wildcard for namespace
	{"*.demo.svc.coredns.local.", 2, 2},                          // Two (mynginx, webserver) SRV record, via wildcard
	{"any.demo.svc.coredns.local.", 2, 2},                        // Two (mynginx, webserver) SRV record, via wildcard
	{"*.test.svc.coredns.local.", 0, 0},                          // One SRV record, via wildcard that is not exposed
	{"any.test.svc.coredns.local.", 0, 0},                        // One SRV record, via wildcard that is not exposed
	{"*.*.svc.coredns.local.", 2, 2},                             // Two SRV record, via namespace and service wildcard
}

func TestKubernetesIntegration(t *testing.T) {

	// t.Skip("Skip Kubernetes Integration tests")
	// subtests here (Go 1.7 feature).
	testLookupA(t)
	testLookupSRV(t)
}

func createTestServer(t *testing.T, corefile string) (*caddy.Instance, string) {
	server, err := CoreDNSServer(corefile)
	if err != nil {
		t.Fatalf("Could not get CoreDNS serving instance: %s", err)
	}

	udp, _ := CoreDNSServerPorts(server, 0)
	if udp == "" {
		t.Fatalf("Could not get UDP listening port")
	}

	return server, udp
}

func testLookupA(t *testing.T) {
	corefile :=
		`.:0 {
    kubernetes coredns.local {
                endpoint http://localhost:8080
		namespaces demo
    }

`
	server, udp := createTestServer(t, corefile)
	defer server.Stop()

	log.SetOutput(ioutil.Discard)

	// Work-around for timing condition that results in no-data being returned in
	// test environment.
	time.Sleep(5 * time.Second)

	for _, testData := range testdataLookupA {
		dnsClient := new(dns.Client)
		dnsMessage := new(dns.Msg)

		dnsMessage.SetQuestion(testData.Query, dns.TypeA)
		dnsMessage.SetEdns0(4096, true)

		res, _, err := dnsClient.Exchange(dnsMessage, udp)
		if err != nil {
			t.Fatalf("Could not send query: %s", err)
		}
		// Count A records in the answer section
		ARecordCount := 0
		for _, a := range res.Answer {
			if a.Header().Rrtype == dns.TypeA {
				ARecordCount++
			}
		}

		if ARecordCount != testData.ARecordCount {
			t.Errorf("Expected '%v' A records in response. Instead got '%v' A records. Test query string: '%v'", testData.ARecordCount, ARecordCount, testData.Query)
		}
		if len(res.Answer) != testData.TotalAnswerCount {
			t.Errorf("Expected '%v' records in answer section. Instead got '%v' records in answer section. Test query string: '%v'", testData.TotalAnswerCount, len(res.Answer), testData.Query)
		}
	}
}

func testLookupSRV(t *testing.T) {
	corefile :=
		`.:0 {
    kubernetes coredns.local {
                endpoint http://localhost:8080
		namespaces demo
    }
`

	server, udp := createTestServer(t, corefile)
	defer server.Stop()

	log.SetOutput(ioutil.Discard)

	// Work-around for timing condition that results in no-data being returned in
	// test environment.
	time.Sleep(5 * time.Second)

	// TODO: Add checks for A records in additional section

	for _, testData := range testdataLookupSRV {
		dnsClient := new(dns.Client)
		dnsMessage := new(dns.Msg)

		dnsMessage.SetQuestion(testData.Query, dns.TypeSRV)
		dnsMessage.SetEdns0(4096, true)

		res, _, err := dnsClient.Exchange(dnsMessage, udp)
		if err != nil {
			t.Fatalf("Could not send query: %s", err)
		}
		// Count SRV records in the answer section
		srvRecordCount := 0
		for _, a := range res.Answer {
			if a.Header().Rrtype == dns.TypeSRV {
				srvRecordCount++
			}
		}

		if srvRecordCount != testData.SRVRecordCount {
			t.Errorf("Expected '%v' SRV records in response. Instead got '%v' SRV records. Test query string: '%v', res: %v", testData.SRVRecordCount, srvRecordCount, testData.Query, res)
		}
		if len(res.Answer) != testData.TotalAnswerCount {
			t.Errorf("Expected '%v' records in answer section. Instead got '%v' records in answer section. Test query string: '%v', res: %v", testData.TotalAnswerCount, len(res.Answer), testData.Query, res)
		}
	}
}
<|endoftext|>


<commit_before>package cruncy

// VERSION of the application
const VERSION = "0.5.0"
<commit_msg>0.5.1<commit_after>package cruncy

// VERSION of the application
const VERSION = "0.5.1"
<|endoftext|>


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

// Package crypto is a Subset of the Go `crypto` Package with a Resumable Hash
package crypto

import (
	"hash"
	"io"
	"strconv"
)

// Hash identifies a cryptographic hash function that is implemented in another
// package.
type Hash uint

// HashFunc simply returns the value of h so that Hash implements SignerOpts.
func (h Hash) HashFunc() Hash {
	return h
}

const (
	SHA224 Hash = 1 + iota // import crypto/sha256
	SHA256                 // import crypto/sha256
	SHA384                 // import crypto/sha512
	SHA512                 // import crypto/sha512
	maxHash
)

var digestSizes = []uint8{
	SHA224: 28,
	SHA256: 32,
	SHA384: 48,
	SHA512: 64,
}

// Size returns the length, in bytes, of a digest resulting from the given hash
// function. It doesn't require that the hash function in question be linked
// into the program.
func (h Hash) Size() int {
	if h > 0 && h < maxHash {
		return int(digestSizes[h])
	}
	panic("crypto: Size of unknown hash function")
}

// ResumableHash is the common interface implemented by all resumable hash
// functions.
type ResumableHash interface {
	// ResumableHash is a superset of hash.Hash
	hash.Hash
	// Len returns the number of bytes written to the Hash so far.
	Len() int64
	// State returns a snapshot of the state of the Hash.
	State() ([]byte, error)
	// Restore resets the Hash to the given state.
	Restore(state []byte) error
}

var hashes = make([]func() ResumableHash, maxHash)

// New returns a new ResumableHash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() ResumableHash {
	if h > 0 && h < maxHash {
		f := hashes[h]
		if f != nil {
			return f()
		}
	}
	panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
}

// Available reports whether the given hash function is linked into the binary.
func (h Hash) Available() bool {
	return h < maxHash && hashes[h] != nil
}

// RegisterHash registers a function that returns a new instance of the given
// hash function. This is intended to be called from the init function in
// packages that implement hash functions.
func RegisterHash(h Hash, f func() ResumableHash) {
	if h >= maxHash {
		panic("crypto: RegisterHash of unknown hash function")
	}
	hashes[h] = f
}
<commit_msg>Removed unused `io` import<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package crypto is a Subset of the Go `crypto` Package with a Resumable Hash
package crypto

import (
	"hash"
	"strconv"
)

// Hash identifies a cryptographic hash function that is implemented in another
// package.
type Hash uint

// HashFunc simply returns the value of h so that Hash implements SignerOpts.
func (h Hash) HashFunc() Hash {
	return h
}

const (
	SHA224 Hash = 1 + iota // import crypto/sha256
	SHA256                 // import crypto/sha256
	SHA384                 // import crypto/sha512
	SHA512                 // import crypto/sha512
	maxHash
)

var digestSizes = []uint8{
	SHA224: 28,
	SHA256: 32,
	SHA384: 48,
	SHA512: 64,
}

// Size returns the length, in bytes, of a digest resulting from the given hash
// function. It doesn't require that the hash function in question be linked
// into the program.
func (h Hash) Size() int {
	if h > 0 && h < maxHash {
		return int(digestSizes[h])
	}
	panic("crypto: Size of unknown hash function")
}

// ResumableHash is the common interface implemented by all resumable hash
// functions.
type ResumableHash interface {
	// ResumableHash is a superset of hash.Hash
	hash.Hash
	// Len returns the number of bytes written to the Hash so far.
	Len() int64
	// State returns a snapshot of the state of the Hash.
	State() ([]byte, error)
	// Restore resets the Hash to the given state.
	Restore(state []byte) error
}

var hashes = make([]func() ResumableHash, maxHash)

// New returns a new ResumableHash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() ResumableHash {
	if h > 0 && h < maxHash {
		f := hashes[h]
		if f != nil {
			return f()
		}
	}
	panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
}

// Available reports whether the given hash function is linked into the binary.
func (h Hash) Available() bool {
	return h < maxHash && hashes[h] != nil
}

// RegisterHash registers a function that returns a new instance of the given
// hash function. This is intended to be called from the init function in
// packages that implement hash functions.
func RegisterHash(h Hash, f func() ResumableHash) {
	if h >= maxHash {
		panic("crypto: RegisterHash of unknown hash function")
	}
	hashes[h] = f
}
<|endoftext|>


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

/*
Package daemon 0.5.1 for use with Go (golang) services.

Package daemon provides primitives for daemonization of golang services.
This package is not provide implementation of user daemon,
accordingly must have root rights to install/remove service.
In the current implementation is only supported Linux and Mac Os X daemon.

Example:

	// Example of a daemon with echo service
	package main

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

		"github.com/takama/daemon"
	)

	const (

		// name of the service
		name        = "myservice"
		description = "My Echo Service"

		// port which daemon should be listen
		port = ":9977"
	)

  // dependencies that are NOT required by the service, but might be used
  var dependencies = []string{"dummy.service"}

	var stdlog, errlog *log.Logger

	// Service has embedded daemon
	type Service struct {
		daemon.Daemon
	}

	// Manage by daemon commands or run the daemon
	func (service *Service) Manage() (string, error) {

		usage := "Usage: myservice install | remove | start | stop | status"

		// if received any kind of command, do it
		if len(os.Args) > 1 {
			command := os.Args[1]
			switch command {
			case "install":
				return service.Install()
			case "remove":
				return service.Remove()
			case "start":
				return service.Start()
			case "stop":
				return service.Stop()
			case "status":
				return service.Status()
			default:
				return usage, nil
			}
		}

		// Do something, call your goroutines, etc

		// Set up channel on which to send signal notifications.
		// We must use a buffered channel or risk missing the signal
		// if we're not ready to receive when the signal is sent.
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

		// Set up listener for defined host and port
		listener, err := net.Listen("tcp", port)
		if err != nil {
			return "Possibly was a problem with the port binding", err
		}

		// set up channel on which to send accepted connections
		listen := make(chan net.Conn, 100)
		go acceptConnection(listener, listen)

		// loop work cycle with accept connections or interrupt
		// by system signal
		for {
			select {
			case conn := <-listen:
				go handleClient(conn)
			case killSignal := <-interrupt:
				stdlog.Println("Got signal:", killSignal)
				stdlog.Println("Stoping listening on ", listener.Addr())
				listener.Close()
				if killSignal == os.Interrupt {
					return "Daemon was interruped by system signal", nil
				}
				return "Daemon was killed", nil
			}
		}

		// never happen, but need to complete code
		return usage, nil
	}

	// Accept a client connection and collect it in a channel
	func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
		for {
			conn, err := listener.Accept()
			if err != nil {
				continue
			}
			listen <- conn
		}
	}

	func handleClient(client net.Conn) {
		for {
			buf := make([]byte, 4096)
			numbytes, err := client.Read(buf)
			if numbytes == 0 || err != nil {
				return
			}
			client.Write(buf[:numbytes])
		}
	}

	func init() {
		stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
		errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
	}

	func main() {
		srv, err := daemon.New(name, description, dependencies...)
		if err != nil {
			errlog.Println("Error: ", err)
			os.Exit(1)
		}
		service := &Service{srv}
		status, err := service.Manage()
		if err != nil {
			errlog.Println(status, "\nError: ", err)
			os.Exit(1)
		}
		fmt.Println(status)
	}

Go daemon
*/
package daemon

import "strings"

// Daemon interface has a standard set of methods/commands
type Daemon interface {

	// Install the service into the system
	Install(args ...string) (string, error)

	// Remove the service and all corresponding files from the system
	Remove() (string, error)

	// Start the service
	Start() (string, error)

	// Stop the service
	Stop() (string, error)

	// Status - check the service status
	Status() (string, error)
}

// New - Create a new daemon
//
// name: name of the service
//
// description: any explanation, what is the service, its purpose
func New(name, description string, dependencies ...string) (Daemon, error) {
	return newDaemon(strings.Join(strings.Fields(name), "_"), description, dependencies)
}
<commit_msg>Bumped version number to 0.5.2<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.

/*
Package daemon 0.5.2 for use with Go (golang) services.

Package daemon provides primitives for daemonization of golang services.
This package is not provide implementation of user daemon,
accordingly must have root rights to install/remove service.
In the current implementation is only supported Linux and Mac Os X daemon.

Example:

	// Example of a daemon with echo service
	package main

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

		"github.com/takama/daemon"
	)

	const (

		// name of the service
		name        = "myservice"
		description = "My Echo Service"

		// port which daemon should be listen
		port = ":9977"
	)

  // dependencies that are NOT required by the service, but might be used
  var dependencies = []string{"dummy.service"}

	var stdlog, errlog *log.Logger

	// Service has embedded daemon
	type Service struct {
		daemon.Daemon
	}

	// Manage by daemon commands or run the daemon
	func (service *Service) Manage() (string, error) {

		usage := "Usage: myservice install | remove | start | stop | status"

		// if received any kind of command, do it
		if len(os.Args) > 1 {
			command := os.Args[1]
			switch command {
			case "install":
				return service.Install()
			case "remove":
				return service.Remove()
			case "start":
				return service.Start()
			case "stop":
				return service.Stop()
			case "status":
				return service.Status()
			default:
				return usage, nil
			}
		}

		// Do something, call your goroutines, etc

		// Set up channel on which to send signal notifications.
		// We must use a buffered channel or risk missing the signal
		// if we're not ready to receive when the signal is sent.
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

		// Set up listener for defined host and port
		listener, err := net.Listen("tcp", port)
		if err != nil {
			return "Possibly was a problem with the port binding", err
		}

		// set up channel on which to send accepted connections
		listen := make(chan net.Conn, 100)
		go acceptConnection(listener, listen)

		// loop work cycle with accept connections or interrupt
		// by system signal
		for {
			select {
			case conn := <-listen:
				go handleClient(conn)
			case killSignal := <-interrupt:
				stdlog.Println("Got signal:", killSignal)
				stdlog.Println("Stoping listening on ", listener.Addr())
				listener.Close()
				if killSignal == os.Interrupt {
					return "Daemon was interruped by system signal", nil
				}
				return "Daemon was killed", nil
			}
		}

		// never happen, but need to complete code
		return usage, nil
	}

	// Accept a client connection and collect it in a channel
	func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
		for {
			conn, err := listener.Accept()
			if err != nil {
				continue
			}
			listen <- conn
		}
	}

	func handleClient(client net.Conn) {
		for {
			buf := make([]byte, 4096)
			numbytes, err := client.Read(buf)
			if numbytes == 0 || err != nil {
				return
			}
			client.Write(buf[:numbytes])
		}
	}

	func init() {
		stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime)
		errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime)
	}

	func main() {
		srv, err := daemon.New(name, description, dependencies...)
		if err != nil {
			errlog.Println("Error: ", err)
			os.Exit(1)
		}
		service := &Service{srv}
		status, err := service.Manage()
		if err != nil {
			errlog.Println(status, "\nError: ", err)
			os.Exit(1)
		}
		fmt.Println(status)
	}

Go daemon
*/
package daemon

import "strings"

// Daemon interface has a standard set of methods/commands
type Daemon interface {

	// Install the service into the system
	Install(args ...string) (string, error)

	// Remove the service and all corresponding files from the system
	Remove() (string, error)

	// Start the service
	Start() (string, error)

	// Stop the service
	Stop() (string, error)

	// Status - check the service status
	Status() (string, error)
}

// New - Create a new daemon
//
// name: name of the service
//
// description: any explanation, what is the service, its purpose
func New(name, description string, dependencies ...string) (Daemon, error) {
	return newDaemon(strings.Join(strings.Fields(name), "_"), description, dependencies)
}
<|endoftext|>


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

package main // import "golang.org/x/build/cmd/coordinator/buildongce"

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	compute "google.golang.org/api/compute/v1"
)

var (
	proj        = flag.String("project", "symbolic-datum-552", "name of Project")
	zone        = flag.String("zone", "us-central1-a", "GCE zone")
	mach        = flag.String("machinetype", "n1-highcpu-2", "Machine type")
	instName    = flag.String("instance_name", "farmer", "Name of VM instance.")
	sshPub      = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
	staticIP    = flag.String("static_ip", "", "Static IP to use. If empty, automatic.")
	reuseDisk   = flag.Bool("reuse_disk", true, "Whether disk images should be reused between shutdowns/restarts.")
	ssd         = flag.Bool("ssd", false, "use a solid state disk (faster, more expensive)")
	coordinator = flag.String("coord", "https://storage.googleapis.com/go-builder-data/coordinator", "Coordinator binary URL")
)

func readFile(v string) string {
	slurp, err := ioutil.ReadFile(v)
	if err != nil {
		log.Fatalf("Error reading %s: %v", v, err)
	}
	return strings.TrimSpace(string(slurp))
}

var config = &oauth2.Config{
	// The client-id and secret should be for an "Installed Application" when using
	// the CLI. Later we'll use a web application with a callback.
	ClientID:     readFile("client-id.dat"),
	ClientSecret: readFile("client-secret.dat"),
	Endpoint:     google.Endpoint,
	Scopes: []string{
		compute.DevstorageFull_controlScope,
		compute.ComputeScope,
		"https://www.googleapis.com/auth/sqlservice",
		"https://www.googleapis.com/auth/sqlservice.admin",
	},
	RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
}

const baseConfig = `#cloud-config
coreos:
  update:
    group: alpha
    reboot-strategy: off
  units:
    - name: gobuild.service
      command: start
      content: |
        [Unit]
        Description=Go Builders
        After=docker.service
        Requires=docker.service

        [Service]
        ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/coordinator $COORDINATOR && chmod +x /opt/bin/coordinator'
        ExecStart=/opt/bin/coordinator
        RestartSec=10s
        Restart=always
        Type=simple

        [Install]
        WantedBy=multi-user.target
`

func main() {
	flag.Parse()
	if *proj == "" {
		log.Fatalf("Missing --project flag")
	}
	if *proj == "symbolic-datum-552" && *staticIP == "" {
		// Hard-code this, since GCP doesn't let you rename an IP address, and so
		// this IP is still called "go-buidler-1-ip" in our project, from our old
		// naming convention plan.
		*staticIP = "107.178.219.46"
	}
	prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
	machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach

	const tokenFileName = "token.dat"
	tokenFile := tokenCacheFile(tokenFileName)
	tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
	token, err := tokenSource.Token()
	if err != nil {
		log.Printf("Error getting token from %s: %v", tokenFileName, err)
		log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
		fmt.Print("\nEnter auth code: ")
		sc := bufio.NewScanner(os.Stdin)
		sc.Scan()
		authCode := strings.TrimSpace(sc.Text())
		token, err = config.Exchange(oauth2.NoContext, authCode)
		if err != nil {
			log.Fatalf("Error exchanging auth code for a token: %v", err)
		}
		if err := tokenFile.WriteToken(token); err != nil {
			log.Fatalf("Error writing to %s: %v", tokenFileName, err)
		}
		tokenSource = oauth2.ReuseTokenSource(token, nil)
	}

	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)

	computeService, _ := compute.New(oauthClient)

	natIP := *staticIP
	if natIP == "" {
		// Try to find it by name.
		aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
		if err != nil {
			log.Fatal(err)
		}
		// https://godoc.org/google.golang.org/api/compute/v1#AddressAggregatedList
	IPLoop:
		for _, asl := range aggAddrList.Items {
			for _, addr := range asl.Addresses {
				if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
					natIP = addr.Address
					break IPLoop
				}
			}
		}
	}

	cloudConfig := strings.Replace(baseConfig, "$COORDINATOR", *coordinator, 1)
	if *sshPub != "" {
		key := strings.TrimSpace(readFile(*sshPub))
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", key)
	}
	if os.Getenv("USER") == "bradfitz" {
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
	}
	const maxCloudConfig = 32 << 10 // per compute API docs
	if len(cloudConfig) > maxCloudConfig {
		log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
	}

	instance := &compute.Instance{
		Name:        *instName,
		Description: "Go Builder",
		MachineType: machType,
		Disks:       []*compute.AttachedDisk{instanceDisk(computeService)},
		Tags: &compute.Tags{
			Items: []string{"http-server", "https-server", "allow-ssh"},
		},
		Metadata: &compute.Metadata{
			Items: []*compute.MetadataItems{
				{
					Key:   "user-data",
					Value: cloudConfig,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			&compute.NetworkInterface{
				AccessConfigs: []*compute.AccessConfig{
					&compute.AccessConfig{
						Type:  "ONE_TO_ONE_NAT",
						Name:  "External NAT",
						NatIP: natIP,
					},
				},
				Network: prefix + "/global/networks/default",
			},
		},
		ServiceAccounts: []*compute.ServiceAccount{
			{
				Email: "default",
				Scopes: []string{
					compute.DevstorageFull_controlScope,
					compute.ComputeScope,
				},
			},
		},
	}

	log.Printf("Creating instance...")
	op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
	if err != nil {
		log.Fatalf("Failed to create instance: %v", err)
	}
	opName := op.Name
	log.Printf("Created. Waiting on operation %v", opName)
OpLoop:
	for {
		time.Sleep(2 * time.Second)
		op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
		if err != nil {
			log.Fatalf("Failed to get op %s: %v", opName, err)
		}
		switch op.Status {
		case "PENDING", "RUNNING":
			log.Printf("Waiting on operation %v", opName)
			continue
		case "DONE":
			if op.Error != nil {
				for _, operr := range op.Error.Errors {
					log.Printf("Error: %+v", operr)
				}
				log.Fatalf("Failed to start.")
			}
			log.Printf("Success. %+v", op)
			break OpLoop
		default:
			log.Fatalf("Unknown status %q: %+v", op.Status, op)
		}
	}

	inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
	if err != nil {
		log.Fatalf("Error getting instance after creation: %v", err)
	}
	ij, _ := json.MarshalIndent(inst, "", "    ")
	log.Printf("Instance: %s", ij)
}

func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
	const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-alpha-402-2-0-v20140807"
	diskName := *instName + "-coreos-stateless-pd"

	if *reuseDisk {
		dl, err := svc.Disks.List(*proj, *zone).Do()
		if err != nil {
			log.Fatalf("Error listing disks: %v", err)
		}
		for _, disk := range dl.Items {
			if disk.Name != diskName {
				continue
			}
			return &compute.AttachedDisk{
				AutoDelete: false,
				Boot:       true,
				DeviceName: diskName,
				Type:       "PERSISTENT",
				Source:     disk.SelfLink,
				Mode:       "READ_WRITE",

				// The GCP web UI's "Show REST API" link includes a
				// "zone" parameter, but it's not in the API
				// description. But it wants this form (disk.Zone, a
				// full zone URL, not *zone):
				// Zone: disk.Zone,
				// ... but it seems to work without it.  Keep this
				// comment here until I file a bug with the GCP
				// people.
			}
		}
	}

	diskType := ""
	if *ssd {
		diskType = "https://www.googleapis.com/compute/v1/projects/" + *proj + "/zones/" + *zone + "/diskTypes/pd-ssd"
	}

	return &compute.AttachedDisk{
		AutoDelete: !*reuseDisk,
		Boot:       true,
		Type:       "PERSISTENT",
		InitializeParams: &compute.AttachedDiskInitializeParams{
			DiskName:    diskName,
			SourceImage: imageURL,
			DiskSizeGb:  50,
			DiskType:    diskType,
		},
	}
}

type tokenCacheFile string

func (f tokenCacheFile) Token() (*oauth2.Token, error) {
	slurp, err := ioutil.ReadFile(string(f))
	if err != nil {
		return nil, err
	}
	t := new(oauth2.Token)
	if err := json.Unmarshal(slurp, t); err != nil {
		return nil, err
	}
	return t, nil
}

func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
	jt, err := json.Marshal(t)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(string(f), jt, 0600)
}
<commit_msg>cmd/coordinator/buildongce: add --dev flag, use dev token files, fix build<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main // import "golang.org/x/build/cmd/coordinator/buildongce"

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	compute "google.golang.org/api/compute/v1"
)

var (
	proj        = flag.String("project", "symbolic-datum-552", "name of Project")
	zone        = flag.String("zone", "us-central1-a", "GCE zone")
	mach        = flag.String("machinetype", "n1-highcpu-2", "Machine type")
	instName    = flag.String("instance_name", "farmer", "Name of VM instance.")
	sshPub      = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
	staticIP    = flag.String("static_ip", "", "Static IP to use. If empty, automatic.")
	reuseDisk   = flag.Bool("reuse_disk", true, "Whether disk images should be reused between shutdowns/restarts.")
	ssd         = flag.Bool("ssd", false, "use a solid state disk (faster, more expensive)")
	coordinator = flag.String("coord", "https://storage.googleapis.com/go-builder-data/coordinator", "Coordinator binary URL")
	dev         = flag.Bool("dev", false, "change default -project and -coordinator flags to their default dev cluster values, as well as use 'dev-' prefixed OAuth token files.")
)

func devPrefix() string {
	if *dev {
		return "dev-"
	}
	return ""
}

func readFile(v string) string {
	slurp, err := ioutil.ReadFile(v)
	if err != nil {
		log.Fatalf("Error reading %s: %v", v, err)
	}
	return strings.TrimSpace(string(slurp))
}

var oauthConfig *oauth2.Config

const baseConfig = `#cloud-config
coreos:
  update:
    group: alpha
    reboot-strategy: off
  units:
    - name: gobuild.service
      command: start
      content: |
        [Unit]
        Description=Go Builders
        After=docker.service
        Requires=docker.service

        [Service]
        ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/coordinator $COORDINATOR && chmod +x /opt/bin/coordinator'
        ExecStart=/opt/bin/coordinator
        RestartSec=10s
        Restart=always
        Type=simple

        [Install]
        WantedBy=multi-user.target
`

func main() {
	flag.Parse()

	oauthConfig = &oauth2.Config{
		// The client-id and secret should be for an "Installed Application" when using
		// the CLI. Later we'll use a web application with a callback.
		ClientID:     readFile(devPrefix() + "client-id.dat"),
		ClientSecret: readFile(devPrefix() + "client-secret.dat"),
		Endpoint:     google.Endpoint,
		Scopes: []string{
			compute.DevstorageFullControlScope,
			compute.ComputeScope,
			"https://www.googleapis.com/auth/sqlservice",
			"https://www.googleapis.com/auth/sqlservice.admin",
		},
		RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
	}

	if *dev {
		if *proj == "symbolic-datum-552" {
			*proj = "go-dashboard-dev"
		}
		if *coordinator == "https://storage.googleapis.com/go-builder-data/coordinator" {
			*coordinator = "https://storage.googleapis.com/dev-go-builder-data/coordinator"
		}
	}
	if *proj == "" {
		log.Fatalf("Missing --project flag")
	}
	if *proj == "symbolic-datum-552" && *staticIP == "" {
		// Hard-code this, since GCP doesn't let you rename an IP address, and so
		// this IP is still called "go-buidler-1-ip" in our project, from our old
		// naming convention plan.
		*staticIP = "107.178.219.46"
	}
	prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
	machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach

	tokenFileName := devPrefix() + "token.dat"
	tokenFile := tokenCacheFile(tokenFileName)
	tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
	token, err := tokenSource.Token()
	if err != nil {
		log.Printf("Error getting token from %s: %v", tokenFileName, err)
		log.Printf("Get auth code from %v", oauthConfig.AuthCodeURL("my-state"))
		fmt.Print("\nEnter auth code: ")
		sc := bufio.NewScanner(os.Stdin)
		sc.Scan()
		authCode := strings.TrimSpace(sc.Text())
		token, err = oauthConfig.Exchange(oauth2.NoContext, authCode)
		if err != nil {
			log.Fatalf("Error exchanging auth code for a token: %v", err)
		}
		if err := tokenFile.WriteToken(token); err != nil {
			log.Fatalf("Error writing to %s: %v", tokenFileName, err)
		}
		tokenSource = oauth2.ReuseTokenSource(token, nil)
	}

	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)

	computeService, _ := compute.New(oauthClient)

	natIP := *staticIP
	if natIP == "" {
		// Try to find it by name.
		aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
		if err != nil {
			log.Fatal(err)
		}
		// https://godoc.org/google.golang.org/api/compute/v1#AddressAggregatedList
	IPLoop:
		for _, asl := range aggAddrList.Items {
			for _, addr := range asl.Addresses {
				if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
					natIP = addr.Address
					break IPLoop
				}
			}
		}
	}

	cloudConfig := strings.Replace(baseConfig, "$COORDINATOR", *coordinator, 1)
	if *sshPub != "" {
		key := strings.TrimSpace(readFile(*sshPub))
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", key)
	}
	if os.Getenv("USER") == "bradfitz" {
		cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
	}
	const maxCloudConfig = 32 << 10 // per compute API docs
	if len(cloudConfig) > maxCloudConfig {
		log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
	}

	instance := &compute.Instance{
		Name:        *instName,
		Description: "Go Builder",
		MachineType: machType,
		Disks:       []*compute.AttachedDisk{instanceDisk(computeService)},
		Tags: &compute.Tags{
			Items: []string{"http-server", "https-server", "allow-ssh"},
		},
		Metadata: &compute.Metadata{
			Items: []*compute.MetadataItems{
				{
					Key:   "user-data",
					Value: cloudConfig,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			&compute.NetworkInterface{
				AccessConfigs: []*compute.AccessConfig{
					&compute.AccessConfig{
						Type:  "ONE_TO_ONE_NAT",
						Name:  "External NAT",
						NatIP: natIP,
					},
				},
				Network: prefix + "/global/networks/default",
			},
		},
		ServiceAccounts: []*compute.ServiceAccount{
			{
				Email: "default",
				Scopes: []string{
					compute.DevstorageFullControlScope,
					compute.ComputeScope,
				},
			},
		},
	}

	log.Printf("Creating instance...")
	op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
	if err != nil {
		log.Fatalf("Failed to create instance: %v", err)
	}
	opName := op.Name
	log.Printf("Created. Waiting on operation %v", opName)
OpLoop:
	for {
		time.Sleep(2 * time.Second)
		op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
		if err != nil {
			log.Fatalf("Failed to get op %s: %v", opName, err)
		}
		switch op.Status {
		case "PENDING", "RUNNING":
			log.Printf("Waiting on operation %v", opName)
			continue
		case "DONE":
			if op.Error != nil {
				for _, operr := range op.Error.Errors {
					log.Printf("Error: %+v", operr)
				}
				log.Fatalf("Failed to start.")
			}
			log.Printf("Success. %+v", op)
			break OpLoop
		default:
			log.Fatalf("Unknown status %q: %+v", op.Status, op)
		}
	}

	inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
	if err != nil {
		log.Fatalf("Error getting instance after creation: %v", err)
	}
	ij, _ := json.MarshalIndent(inst, "", "    ")
	log.Printf("Instance: %s", ij)
}

func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
	const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-alpha-402-2-0-v20140807"
	diskName := *instName + "-coreos-stateless-pd"

	if *reuseDisk {
		dl, err := svc.Disks.List(*proj, *zone).Do()
		if err != nil {
			log.Fatalf("Error listing disks: %v", err)
		}
		for _, disk := range dl.Items {
			if disk.Name != diskName {
				continue
			}
			return &compute.AttachedDisk{
				AutoDelete: false,
				Boot:       true,
				DeviceName: diskName,
				Type:       "PERSISTENT",
				Source:     disk.SelfLink,
				Mode:       "READ_WRITE",

				// The GCP web UI's "Show REST API" link includes a
				// "zone" parameter, but it's not in the API
				// description. But it wants this form (disk.Zone, a
				// full zone URL, not *zone):
				// Zone: disk.Zone,
				// ... but it seems to work without it.  Keep this
				// comment here until I file a bug with the GCP
				// people.
			}
		}
	}

	diskType := ""
	if *ssd {
		diskType = "https://www.googleapis.com/compute/v1/projects/" + *proj + "/zones/" + *zone + "/diskTypes/pd-ssd"
	}

	return &compute.AttachedDisk{
		AutoDelete: !*reuseDisk,
		Boot:       true,
		Type:       "PERSISTENT",
		InitializeParams: &compute.AttachedDiskInitializeParams{
			DiskName:    diskName,
			SourceImage: imageURL,
			DiskSizeGb:  50,
			DiskType:    diskType,
		},
	}
}

type tokenCacheFile string

func (f tokenCacheFile) Token() (*oauth2.Token, error) {
	slurp, err := ioutil.ReadFile(string(f))
	if err != nil {
		return nil, err
	}
	t := new(oauth2.Token)
	if err := json.Unmarshal(slurp, t); err != nil {
		return nil, err
	}
	return t, nil
}

func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
	jt, err := json.Marshal(t)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(string(f), jt, 0600)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"text/tabwriter"

	"github.com/golang/glog"
)

func (w *wizard) allTranscodingOptions() map[int]string {
	resp, err := http.Get(fmt.Sprintf("http://%v:%v/getAvailableTranscodingOptions", w.host, w.httpPort))
	if err != nil {
		glog.Errorf("Error getting all transcoding options: %v", err)
		return nil
	}

	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		glog.Errorf("Error reading response: %v", err)
		return nil
	}

	var opts []string
	err = json.Unmarshal(result, &opts)
	if err != nil {
		glog.Errorf("Error unmarshalling all transcoding options: %v", err)
		return nil
	}

	optIds := make(map[int]string)

	wtr := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
	fmt.Fprintln(wtr, "Identifier\tTranscoding Options")
	for idx, opt := range opts {
		fmt.Fprintf(wtr, "%v\t%v\n", idx, opt)
		optIds[idx] = opt
	}

	wtr.Flush()

	return optIds
}

func (w *wizard) setBroadcastConfig() {
	fmt.Printf("Enter a maximum transcoding price per pixel, in wei per pixels (pricePerUnit / pixelsPerUnit).\n")
	fmt.Printf("eg. 1 wei / 10 pixels = 0,1 wei per pixel \n")
	fmt.Printf("\n")
	fmt.Printf("Enter amount of pixels that make up a single unit (default: 1 pixel) - ")
	pixelsPerUnit := w.readDefaultInt(1)
	fmt.Printf("\n")
	fmt.Printf("Enter the maximum price to pay for %d pixels in Wei (required) - ", pixelsPerUnit)
	maxPricePerUnit := w.readDefaultInt(0)

	opts := w.allTranscodingOptions()
	if opts == nil {
		return
	}

	fmt.Printf("Enter the identifiers of the video profiles you would like to use (use a comma as the delimiter in a list of identifiers) - ")
	idList := w.readString()

	transOpts, err := w.idListToVideoProfileList(idList, opts)
	if err != nil {
		glog.Error(err)
		return
	}

	val := url.Values{
		"pixelsPerUnit":      {fmt.Sprintf("%v", strconv.Itoa(pixelsPerUnit))},
		"maxPricePerUnit":    {fmt.Sprintf("%v", strconv.Itoa(maxPricePerUnit))},
		"transcodingOptions": {fmt.Sprintf("%v", transOpts)},
	}

	httpPostWithParams(fmt.Sprintf("http://%v:%v/setBroadcastConfig", w.host, w.httpPort), val)
}

func (w *wizard) idListToVideoProfileList(idList string, opts map[int]string) (string, error) {
	ids := strings.Split(idList, ",")

	var pListBuf bytes.Buffer
	for i, id := range ids {
		val, err := strconv.Atoi(strings.TrimSpace(id))
		if err != nil {
			return "", err
		}

		p, ok := opts[val]
		if !ok {
			return "", fmt.Errorf("not a valid identifier")
		} else {
			pListBuf.WriteString(p)

			if i < len(ids)-1 {
				pListBuf.WriteString(",")
			}
		}
	}

	return pListBuf.String(), nil
}
<commit_msg>cmd: fixed order for video profiles when setting broadcaster config in CLI<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"sort"
	"strconv"
	"strings"
	"text/tabwriter"

	"github.com/golang/glog"
)

func (w *wizard) allTranscodingOptions() map[int]string {
	resp, err := http.Get(fmt.Sprintf("http://%v:%v/getAvailableTranscodingOptions", w.host, w.httpPort))
	if err != nil {
		glog.Errorf("Error getting all transcoding options: %v", err)
		return nil
	}

	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		glog.Errorf("Error reading response: %v", err)
		return nil
	}

	var opts []string
	err = json.Unmarshal(result, &opts)
	if err != nil {
		glog.Errorf("Error unmarshalling all transcoding options: %v", err)
		return nil
	}
	sort.Strings(opts)

	optIds := make(map[int]string)

	wtr := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
	fmt.Fprintln(wtr, "Identifier\tTranscoding Options")
	for idx, opt := range opts {
		fmt.Fprintf(wtr, "%v\t%v\n", idx, opt)
		optIds[idx] = opt
	}

	wtr.Flush()

	return optIds
}

func (w *wizard) setBroadcastConfig() {
	fmt.Printf("Enter a maximum transcoding price per pixel, in wei per pixels (pricePerUnit / pixelsPerUnit).\n")
	fmt.Printf("eg. 1 wei / 10 pixels = 0,1 wei per pixel \n")
	fmt.Printf("\n")
	fmt.Printf("Enter amount of pixels that make up a single unit (default: 1 pixel) - ")
	pixelsPerUnit := w.readDefaultInt(1)
	fmt.Printf("\n")
	fmt.Printf("Enter the maximum price to pay for %d pixels in Wei (required) - ", pixelsPerUnit)
	maxPricePerUnit := w.readDefaultInt(0)

	opts := w.allTranscodingOptions()
	if opts == nil {
		return
	}

	fmt.Printf("Enter the identifiers of the video profiles you would like to use (use a comma as the delimiter in a list of identifiers) - ")
	idList := w.readString()

	transOpts, err := w.idListToVideoProfileList(idList, opts)
	if err != nil {
		glog.Error(err)
		return
	}

	val := url.Values{
		"pixelsPerUnit":      {fmt.Sprintf("%v", strconv.Itoa(pixelsPerUnit))},
		"maxPricePerUnit":    {fmt.Sprintf("%v", strconv.Itoa(maxPricePerUnit))},
		"transcodingOptions": {fmt.Sprintf("%v", transOpts)},
	}

	httpPostWithParams(fmt.Sprintf("http://%v:%v/setBroadcastConfig", w.host, w.httpPort), val)
}

func (w *wizard) idListToVideoProfileList(idList string, opts map[int]string) (string, error) {
	ids := strings.Split(idList, ",")

	var pListBuf bytes.Buffer
	for i, id := range ids {
		val, err := strconv.Atoi(strings.TrimSpace(id))
		if err != nil {
			return "", err
		}

		p, ok := opts[val]
		if !ok {
			return "", fmt.Errorf("not a valid identifier")
		} else {
			pListBuf.WriteString(p)

			if i < len(ids)-1 {
				pListBuf.WriteString(",")
			}
		}
	}

	return pListBuf.String(), nil
}
<|endoftext|>


<commit_before>package messagestore

import log "github.com/repbin/repbin/deferconsole"

// ExpireFromFS expires data based on filesystem last change
func (store Store) ExpireFromFS() {
	store.ExpireFromIndex(0)
}

// ExpireFromIndex reads the expire index and expires messages as they are recorded
func (store Store) ExpireFromIndex(cycles int) {
	// ExpireRun
	delMessages, err := store.db.SelectMessageExpire(CurrentTime())
	if err != nil {
		log.Errorf("ExpireFromIndex, SelectMessageExpire: %s", err)
		return
	}
	for _, msg := range delMessages {
		err := store.db.DeleteBlob(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteBlob: %s %x", err, msg.MessageID)
			continue
		}
		err = store.db.DeleteMessageByID(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteMessageByID: %s %x", err, msg.MessageID)
		}
	}
	_, _, err = store.db.ExpireSigners(MaxAgeSigners)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireSigners: %s", err)
	}
	err = store.db.ExpireMessageCounter(MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireMessageCounter: %s", err)
	}
	err = store.db.ForgetMessages(CurrentTime() - MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ForgetMessages: %s", err)
	}
}
<commit_msg>Add missing newlines to the messages<commit_after>package messagestore

import log "github.com/repbin/repbin/deferconsole"

// ExpireFromFS expires data based on filesystem last change
func (store Store) ExpireFromFS() {
	store.ExpireFromIndex(0)
}

// ExpireFromIndex reads the expire index and expires messages as they are recorded
func (store Store) ExpireFromIndex(cycles int) {
	// ExpireRun
	delMessages, err := store.db.SelectMessageExpire(CurrentTime())
	if err != nil {
		log.Errorf("ExpireFromIndex, SelectMessageExpire: %s\n", err)
		return
	}
	for _, msg := range delMessages {
		err := store.db.DeleteBlob(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteBlob: %s %x\n", err, msg.MessageID)
			continue
		}
		err = store.db.DeleteMessageByID(&msg.MessageID)
		if err != nil {
			log.Errorf("ExpireFromIndex, DeleteMessageByID: %s %x\n", err, msg.MessageID)
		}
	}
	_, _, err = store.db.ExpireSigners(MaxAgeSigners)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireSigners: %s\n", err)
	}
	err = store.db.ExpireMessageCounter(MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ExpireMessageCounter: %s\n", err)
	}
	err = store.db.ForgetMessages(CurrentTime() - MaxAgeRecipients)
	if err != nil {
		log.Errorf("ExpireFromIndex, ForgetMessages: %s\n", err)
	}
}
<|endoftext|>


<commit_before>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

// 实现一些Go的Image转vcl/lcl的
package bitmap

import (
	"bytes"
	"errors"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"unsafe"

	"github.com/ying32/govcl/vcl/types"

	"github.com/ying32/govcl/vcl"
)

var (
	ErrPixelDataEmpty        = errors.New("the pixel data is empty")
	ErrUnsupportedDataFormat = errors.New("unsupported pixel data format")
	ErrBitmapInvalid         = errors.New("bitmap invalid")
)

// 将Go的Image转为VCL/LCL的 TPngImage
// 返回的Png对象用完记得Free掉
func ToPngImage(img image.Image) (*vcl.TPngImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := png.Encode(buff, img); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewPngImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

// 32bit bmp
// 返回的Bmp对象用完记得Free掉
func ToBitmap(img image.Image) (*vcl.TBitmap, error) {
	bmp := vcl.NewBitmap()
	if err := ToBitmap2(img, bmp); err != nil {
		defer bmp.Free()
		return nil, err
	}
	return bmp, nil
}

func ToBitmap2(img image.Image, bmp *vcl.TBitmap) error {
	if bmp == nil || !bmp.IsValid() {
		return ErrBitmapInvalid
	}
	switch img.(type) {
	case *image.RGBA:
		data, _ := img.(*image.RGBA)
		err := toBitmap(img.Bounds().Size().X, img.Bounds().Size().Y, data.Pix, bmp)
		if err != nil {
			return err
		}
	case *image.NRGBA:
		data, _ := img.(*image.NRGBA)
		err := toBitmap(img.Bounds().Size().X, img.Bounds().Size().Y, data.Pix, bmp)
		if err != nil {
			return err
		}
	default:
		return ErrUnsupportedDataFormat
	}
	return nil
}

// 将Go的Image转为VCL/LCL的 TJPEGImage
// 返回的jpg对象用完记得Free掉
func ToJPEGImage(img image.Image, quality int) (*vcl.TJPEGImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := jpeg.Encode(buff, img, &jpeg.Options{quality}); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewJPEGImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

// 将Go的Image转为VCL/LCL的 TGIFImage
// 返回的gif对象用完记得Free掉
func ToGIFImage(img image.Image) (*vcl.TGIFImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := gif.Encode(buff, img, &gif.Options{NumColors: 256}); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewGIFImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

func toBitmap(width, height int, pix []uint8, bmp *vcl.TBitmap) error {
	if len(pix) == 0 {
		return ErrPixelDataEmpty
	}
	if bmp == nil || !bmp.IsValid() {
		return ErrBitmapInvalid
	}

	bmp.SetSize(int32(width), int32(height))
	// 总是32位，不然没办法透明。
	bmp.SetPixelFormat(types.Pf32bit)
	bmp.SetHandleType(types.BmDIB)
	if !vcl.LclLoaded() {
		// libvcl开启这个就会透明，liblcl无此属性，自动透明
		bmp.SetAlphaFormat(types.AfDefined)
	}

	if vcl.LclLoaded() {
		bmp.BeginUpdate(false)
		defer bmp.EndUpdate(false)
	}
	// 填充，左下角为起点
	for h := height - 1; h >= 0; h-- {
		ptr := bmp.ScanLine(int32(h))
		for w := 0; w < width; w++ {
			index := (h*width + w) * 4
			c := (*rgba)(unsafe.Pointer(ptr + uintptr(w*4)))
			c.R = pix[index+0]
			c.G = pix[index+1]
			c.B = pix[index+2]
			c.A = pix[index+3]
		}
	}
	return nil
}

// 将vcl/lcl的Graphic对象转为Go的Image
func ToGoImage(obj *vcl.TGraphic) (image.Image, error) {
	if obj == nil || !obj.IsValid() {
		return nil, errors.New("obj is invalid")
	}
	buff := bytes.NewBuffer([]byte{})
	mem := vcl.NewMemoryStream()
	defer mem.Free()
	obj.SaveToStream(mem)
	mem.SetPosition(0)
	_, bs := mem.Read(int32(mem.Size()))
	buff.Write(bs)
	if obj.InheritsFrom(vcl.TBitmapClass()) {
		height := int(obj.Height())
		width := int(obj.Width())
		img := image.NewRGBA(image.Rect(0, 0, width, height))

		bmp := obj.As().Bitmap()
		switch bmp.PixelFormat() {

		// 还有待测试。。。
		case types.Pf24bit:

			for h := height - 1; h >= 0; h-- {
				ptr := bmp.ScanLine(int32(h))
				for w := 0; w < width; w++ {
					index := (h*width + w) * 4
					c := (*rgb)(unsafe.Pointer(ptr + uintptr(w*3)))
					img.Pix[index+0] = c.R
					img.Pix[index+1] = c.G
					img.Pix[index+2] = c.B
					img.Pix[index+3] = 0
				}
			}

		case types.Pf32bit:
			for h := height - 1; h >= 0; h-- {
				ptr := bmp.ScanLine(int32(h))
				for w := 0; w < width; w++ {
					index := (h*width + w) * 4
					c := (*rgba)(unsafe.Pointer(ptr + uintptr(w*4)))
					img.Pix[index+0] = c.R
					img.Pix[index+1] = c.G
					img.Pix[index+2] = c.B
					img.Pix[index+3] = c.A
				}
			}
		default:
			//case types.Pf1bit:
			//case types.Pf4bit:
			//case types.Pf8bit:
			//case types.Pf15bit:
			//case types.Pf16bit:
			//case types.PfCustom:
			return nil, ErrUnsupportedDataFormat
		}
		return img, nil
	} else if obj.Is().PngImage() {
		img, err := png.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	} else if obj.Is().JPEGImage() {
		img, err := jpeg.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	} else if obj.Is().GIFImage() {
		img, err := gif.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	}
	return nil, errors.New("unknown error")
}
<commit_msg>Update bitmap package.<commit_after>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

// 实现一些Go的Image转vcl/lcl的
package bitmap

import (
	"bytes"
	"errors"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"unsafe"

	"github.com/ying32/govcl/vcl/types"

	"github.com/ying32/govcl/vcl"
)

var (
	ErrPixelDataEmpty        = errors.New("the pixel data is empty")
	ErrUnsupportedDataFormat = errors.New("unsupported pixel data format")
	ErrBitmapInvalid         = errors.New("bitmap invalid")
)

// 将Go的Image转为VCL/LCL的 TPngImage
// 返回的Png对象用完记得Free掉
func ToPngImage(img image.Image) (*vcl.TPngImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := png.Encode(buff, img); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewPngImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

// 32bit bmp
// 返回的Bmp对象用完记得Free掉
func ToBitmap(img image.Image) (*vcl.TBitmap, error) {
	bmp := vcl.NewBitmap()
	if err := ToBitmap2(img, bmp); err != nil {
		defer bmp.Free()
		return nil, err
	}
	return bmp, nil
}

func ToBitmap2(img image.Image, bmp *vcl.TBitmap) error {
	if bmp == nil || !bmp.IsValid() {
		return ErrBitmapInvalid
	}
	switch img.(type) {
	case *image.RGBA:
		data, _ := img.(*image.RGBA)
		err := toBitmap(img.Bounds().Size().X, img.Bounds().Size().Y, data.Pix, bmp)
		if err != nil {
			return err
		}
	case *image.NRGBA:
		data, _ := img.(*image.NRGBA)
		err := toBitmap(img.Bounds().Size().X, img.Bounds().Size().Y, data.Pix, bmp)
		if err != nil {
			return err
		}
	default:
		return ErrUnsupportedDataFormat
	}
	return nil
}

// 将Go的Image转为VCL/LCL的 TJPEGImage
// 返回的jpg对象用完记得Free掉
func ToJPEGImage(img image.Image, quality int) (*vcl.TJPEGImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := jpeg.Encode(buff, img, &jpeg.Options{quality}); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewJPEGImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

// 将Go的Image转为VCL/LCL的 TGIFImage
// 返回的gif对象用完记得Free掉
func ToGIFImage(img image.Image) (*vcl.TGIFImage, error) {
	buff := bytes.NewBuffer([]byte{})
	if err := gif.Encode(buff, img, &gif.Options{NumColors: 256}); err != nil {
		return nil, err
	}
	mem := vcl.NewMemoryStreamFromBytes(buff.Bytes())
	defer mem.Free()
	mem.SetPosition(0)
	obj := vcl.NewGIFImage()
	obj.LoadFromStream(mem)
	return obj, nil
}

func toBitmap(width, height int, pix []uint8, bmp *vcl.TBitmap) error {
	if len(pix) == 0 {
		return ErrPixelDataEmpty
	}
	if bmp == nil || !bmp.IsValid() {
		return ErrBitmapInvalid
	}

	bmp.SetSize(int32(width), int32(height))
	// 总是32位，不然没办法透明。
	bmp.SetPixelFormat(types.Pf32bit)
	bmp.SetHandleType(types.BmDIB)
	if !vcl.LclLoaded() {
		// libvcl开启这个就会透明，liblcl无此属性，自动透明
		bmp.SetAlphaFormat(types.AfDefined)
	}

	if vcl.LclLoaded() {
		bmp.BeginUpdate(false)
		defer bmp.EndUpdate(false)
	}
	// 填充，左下角为起点
	for h := height - 1; h >= 0; h-- {
		ptr := bmp.ScanLine(int32(h))
		for w := 0; w < width; w++ {
			index := (h*width + w) * 4
			c := (*rgba)(unsafe.Pointer(ptr + uintptr(w*4)))
			c.R = pix[index+0]
			c.G = pix[index+1]
			c.B = pix[index+2]
			c.A = pix[index+3]
		}
	}
	return nil
}

// 将vcl/lcl的Graphic对象转为Go的Image
func ToGoImage(obj *vcl.TGraphic) (image.Image, error) {
	if obj == nil || !obj.IsValid() {
		return nil, errors.New("obj is invalid")
	}
	buff := bytes.NewBuffer([]byte{})
	mem := vcl.NewMemoryStream()
	defer mem.Free()
	obj.SaveToStream(mem)
	mem.SetPosition(0)
	_, bs := mem.Read(int32(mem.Size()))
	buff.Write(bs)
	if obj.InheritsFrom(vcl.TBitmapClass()) {
		height := int(obj.Height())
		width := int(obj.Width())
		img := image.NewRGBA(image.Rect(0, 0, width, height))

		bmp := vcl.AsBitmap(obj)
		switch bmp.PixelFormat() {

		// 还有待测试。。。
		case types.Pf24bit:

			for h := height - 1; h >= 0; h-- {
				ptr := bmp.ScanLine(int32(h))
				for w := 0; w < width; w++ {
					index := (h*width + w) * 4
					c := (*rgb)(unsafe.Pointer(ptr + uintptr(w*3)))
					img.Pix[index+0] = c.R
					img.Pix[index+1] = c.G
					img.Pix[index+2] = c.B
					img.Pix[index+3] = 0
				}
			}

		case types.Pf32bit:
			for h := height - 1; h >= 0; h-- {
				ptr := bmp.ScanLine(int32(h))
				for w := 0; w < width; w++ {
					index := (h*width + w) * 4
					c := (*rgba)(unsafe.Pointer(ptr + uintptr(w*4)))
					img.Pix[index+0] = c.R
					img.Pix[index+1] = c.G
					img.Pix[index+2] = c.B
					img.Pix[index+3] = c.A
				}
			}
		default:
			//case types.Pf1bit:
			//case types.Pf4bit:
			//case types.Pf8bit:
			//case types.Pf15bit:
			//case types.Pf16bit:
			//case types.PfCustom:
			return nil, ErrUnsupportedDataFormat
		}
		return img, nil
	} else if obj.Is().PngImage() {
		img, err := png.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	} else if obj.Is().JPEGImage() {
		img, err := jpeg.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	} else if obj.Is().GIFImage() {
		img, err := gif.Decode(buff)
		if err != nil {
			return nil, err
		}
		return img, nil
	}
	return nil, errors.New("unknown error")
}
<|endoftext|>


<commit_before>package common

import (
	"encoding/binary"
	"io"
	"xd/lib/log"
	"xd/lib/util"
)

// WireMessageType is type for wire message id
type WireMessageType byte

// Chock is message id for choke message
const Choke = WireMessageType(0)

// UnChoke is message id for unchoke message
const UnChoke = WireMessageType(1)

// Interested is messageid for interested message
const Interested = WireMessageType(2)

// NotInterested is messageid for not-interested message
const NotInterested = WireMessageType(3)

// Have is messageid for have message
const Have = WireMessageType(4)

// BitField is messageid for bitfield message
const BitField = WireMessageType(5)

// Request is messageid for piece request message
const Request = WireMessageType(6)

// Piece is messageid for response to Request message
const Piece = WireMessageType(7)

// Cancel is messageid for a Cancel message, used to cancel a pending request
const Cancel = WireMessageType(8)

// Extended is messageid for ExtendedOptions message
const Extended = WireMessageType(20)

func (t WireMessageType) String() string {
	switch t {
	case Choke:
		return "Choke"
	case UnChoke:
		return "UnChoke"
	case Interested:
		return "Interested"
	case NotInterested:
		return "NotInterested"
	case Have:
		return "Have"
	case BitField:
		return "BitField"
	case Request:
		return "Request"
	case Piece:
		return "Piece"
	case Cancel:
		return "Cancel"
	case Extended:
		return "Extended"
	default:
		return "???"
	}
}

// WireMessage is a serializable bittorrent wire message
type WireMessage struct {
	data []byte
}

// KeepAlive makes a WireMessage of size 0
func KeepAlive() *WireMessage {
	return &WireMessage{
		data: []byte{0, 0, 0, 0},
	}
}

// NewWireMessage creates new wire message with id and body
func NewWireMessage(id WireMessageType, body []byte) (msg *WireMessage) {
	if body == nil {
		body = []byte{}
	}
	var hdr [5]byte
	l := uint32(len(body)) + 5
	binary.BigEndian.PutUint32(hdr[:], l-4)
	hdr[4] = byte(id)
	msg = new(WireMessage)
	msg.data = append(hdr[:], body...)
	return msg
}

// KeepAlive returns true if this message is a keepalive message
func (msg *WireMessage) KeepAlive() bool {
	return msg.Len() == 0
}

// Len returns the length of the body of this message
func (msg *WireMessage) Len() uint32 {
	if msg.data == nil {
		return 0
	}
	return binary.BigEndian.Uint32(msg.data)
}

// Payload returns a byteslice for the body of this message
func (msg *WireMessage) Payload() []byte {
	if msg.Len() > 0 {
		return msg.data[5:]
	} else {
		return nil
	}
}

// MessageID returns the id of this message
func (msg *WireMessage) MessageID() WireMessageType {
	return WireMessageType(msg.data[4])
}

// Recv reads message from reader
func (msg *WireMessage) Recv(r io.Reader) (err error) {
	// read header
	var hdr [4]byte
	var n int
	n, err = io.ReadFull(r, hdr[:])
	log.Debugf("recv'd header %d bytes", n)
	msg.data = hdr[:]
	if err == nil {
		l := binary.BigEndian.Uint32(msg.data[:])
		if l > 0 {
			// read body

			// XXX: yes this is a magic number
			var buf [1730]byte
			for l > 0 && err == nil {
				var readbuf []byte
				if l < uint32(len(buf)) {
					readbuf = buf[:l]
				} else {
					readbuf = buf[:]
				}
				n, err = r.Read(readbuf)
				if n > 0 {
					l -= uint32(n)
					readbuf = readbuf[:n]
					msg.data = append(msg.data, readbuf...)
				}
			}
		}
	}
	return
}

// Send writes WireMessage via writer
func (msg *WireMessage) Send(w io.Writer) (err error) {
	err = util.WriteFull(w, msg.data)
	return
}

// ToWireMessage serialize to BitTorrent wire message
func (p *PieceData) ToWireMessage() *WireMessage {
	var hdr [8]byte
	var body []byte
	binary.BigEndian.PutUint32(hdr[:], p.Index)
	binary.BigEndian.PutUint32(hdr[4:], p.Begin)
	body = append(hdr[:], p.Data...)
	return NewWireMessage(Piece, body)
}

// ToWireMessage serialize to BitTorrent wire message
func (req *PieceRequest) ToWireMessage() *WireMessage {
	var body [12]byte
	binary.BigEndian.PutUint32(body[:], req.Index)
	binary.BigEndian.PutUint32(body[4:], req.Begin)
	binary.BigEndian.PutUint32(body[8:], req.Length)
	return NewWireMessage(Request, body[:])
}

// GetPieceData gets this wire message as a PieceData if applicable
func (msg *WireMessage) GetPieceData() (p *PieceData) {

	if msg.MessageID() == Piece {
		data := msg.Payload()
		if len(data) > 8 {
			p = new(PieceData)
			p.Index = binary.BigEndian.Uint32(data)
			p.Begin = binary.BigEndian.Uint32(data[4:])
			p.Data = data[8:]
		}
	}
	return
}

// GetPieceRequest gets piece request from wire message
func (msg WireMessage) GetPieceRequest() (req *PieceRequest) {
	if msg.MessageID() == Request {
		data := msg.Payload()
		if len(data) == 12 {
			req = new(PieceRequest)
			req.Index = binary.BigEndian.Uint32(data[:])
			req.Begin = binary.BigEndian.Uint32(data[4:])
			req.Length = binary.BigEndian.Uint32(data[8:])
		}
	}
	return
}

// GetHave gets the piece index of a have message
func (msg *WireMessage) GetHave() (h uint32) {
	if msg.MessageID() == Have {
		data := msg.Payload()
		if len(data) == 4 {
			h = binary.BigEndian.Uint32(data[:])
		}
	}
	return
}

// NewHave creates a new have message
func NewHave(idx uint32) *WireMessage {
	var body [4]byte
	binary.BigEndian.PutUint32(body[:], idx)
	return NewWireMessage(Have, body[:])
}

// NewNotInterested creates a new NotInterested message
func NewNotInterested() *WireMessage {
	return NewWireMessage(NotInterested, nil)
}

// NewInterested creates a new Interested message
func NewInterested() *WireMessage {
	return NewWireMessage(Interested, nil)
}
<commit_msg>make unknown messageid for wire messages logged<commit_after>package common

import (
	"encoding/binary"
	"fmt"
	"io"
	"xd/lib/log"
	"xd/lib/util"
)

// WireMessageType is type for wire message id
type WireMessageType byte

// Chock is message id for choke message
const Choke = WireMessageType(0)

// UnChoke is message id for unchoke message
const UnChoke = WireMessageType(1)

// Interested is messageid for interested message
const Interested = WireMessageType(2)

// NotInterested is messageid for not-interested message
const NotInterested = WireMessageType(3)

// Have is messageid for have message
const Have = WireMessageType(4)

// BitField is messageid for bitfield message
const BitField = WireMessageType(5)

// Request is messageid for piece request message
const Request = WireMessageType(6)

// Piece is messageid for response to Request message
const Piece = WireMessageType(7)

// Cancel is messageid for a Cancel message, used to cancel a pending request
const Cancel = WireMessageType(8)

// Extended is messageid for ExtendedOptions message
const Extended = WireMessageType(20)

func (t WireMessageType) String() string {
	switch t {
	case Choke:
		return "Choke"
	case UnChoke:
		return "UnChoke"
	case Interested:
		return "Interested"
	case NotInterested:
		return "NotInterested"
	case Have:
		return "Have"
	case BitField:
		return "BitField"
	case Request:
		return "Request"
	case Piece:
		return "Piece"
	case Cancel:
		return "Cancel"
	case Extended:
		return "Extended"
	default:
		return fmt.Sprintf("??? (%d)", uint8(t))
	}
}

// WireMessage is a serializable bittorrent wire message
type WireMessage struct {
	data []byte
}

// KeepAlive makes a WireMessage of size 0
func KeepAlive() *WireMessage {
	return &WireMessage{
		data: []byte{0, 0, 0, 0},
	}
}

// NewWireMessage creates new wire message with id and body
func NewWireMessage(id WireMessageType, body []byte) (msg *WireMessage) {
	if body == nil {
		body = []byte{}
	}
	var hdr [5]byte
	l := uint32(len(body)) + 5
	binary.BigEndian.PutUint32(hdr[:], l-4)
	hdr[4] = byte(id)
	msg = new(WireMessage)
	msg.data = append(hdr[:], body...)
	return msg
}

// KeepAlive returns true if this message is a keepalive message
func (msg *WireMessage) KeepAlive() bool {
	return msg.Len() == 0
}

// Len returns the length of the body of this message
func (msg *WireMessage) Len() uint32 {
	if msg.data == nil {
		return 0
	}
	return binary.BigEndian.Uint32(msg.data)
}

// Payload returns a byteslice for the body of this message
func (msg *WireMessage) Payload() []byte {
	if msg.Len() > 0 {
		return msg.data[5:]
	} else {
		return nil
	}
}

// MessageID returns the id of this message
func (msg *WireMessage) MessageID() WireMessageType {
	return WireMessageType(msg.data[4])
}

// Recv reads message from reader
func (msg *WireMessage) Recv(r io.Reader) (err error) {
	// read header
	var hdr [4]byte
	var n int
	n, err = io.ReadFull(r, hdr[:])
	log.Debugf("recv'd header %d bytes", n)
	msg.data = hdr[:]
	if err == nil {
		l := binary.BigEndian.Uint32(msg.data[:])
		if l > 0 {
			// read body

			// XXX: yes this is a magic number
			var buf [1730]byte
			for l > 0 && err == nil {
				var readbuf []byte
				if l < uint32(len(buf)) {
					readbuf = buf[:l]
				} else {
					readbuf = buf[:]
				}
				n, err = r.Read(readbuf)
				if n > 0 {
					l -= uint32(n)
					readbuf = readbuf[:n]
					msg.data = append(msg.data, readbuf...)
				}
			}
		}
	}
	return
}

// Send writes WireMessage via writer
func (msg *WireMessage) Send(w io.Writer) (err error) {
	err = util.WriteFull(w, msg.data)
	return
}

// ToWireMessage serialize to BitTorrent wire message
func (p *PieceData) ToWireMessage() *WireMessage {
	var hdr [8]byte
	var body []byte
	binary.BigEndian.PutUint32(hdr[:], p.Index)
	binary.BigEndian.PutUint32(hdr[4:], p.Begin)
	body = append(hdr[:], p.Data...)
	return NewWireMessage(Piece, body)
}

// ToWireMessage serialize to BitTorrent wire message
func (req *PieceRequest) ToWireMessage() *WireMessage {
	var body [12]byte
	binary.BigEndian.PutUint32(body[:], req.Index)
	binary.BigEndian.PutUint32(body[4:], req.Begin)
	binary.BigEndian.PutUint32(body[8:], req.Length)
	return NewWireMessage(Request, body[:])
}

// GetPieceData gets this wire message as a PieceData if applicable
func (msg *WireMessage) GetPieceData() (p *PieceData) {

	if msg.MessageID() == Piece {
		data := msg.Payload()
		if len(data) > 8 {
			p = new(PieceData)
			p.Index = binary.BigEndian.Uint32(data)
			p.Begin = binary.BigEndian.Uint32(data[4:])
			p.Data = data[8:]
		}
	}
	return
}

// GetPieceRequest gets piece request from wire message
func (msg WireMessage) GetPieceRequest() (req *PieceRequest) {
	if msg.MessageID() == Request {
		data := msg.Payload()
		if len(data) == 12 {
			req = new(PieceRequest)
			req.Index = binary.BigEndian.Uint32(data[:])
			req.Begin = binary.BigEndian.Uint32(data[4:])
			req.Length = binary.BigEndian.Uint32(data[8:])
		}
	}
	return
}

// GetHave gets the piece index of a have message
func (msg *WireMessage) GetHave() (h uint32) {
	if msg.MessageID() == Have {
		data := msg.Payload()
		if len(data) == 4 {
			h = binary.BigEndian.Uint32(data[:])
		}
	}
	return
}

// NewHave creates a new have message
func NewHave(idx uint32) *WireMessage {
	var body [4]byte
	binary.BigEndian.PutUint32(body[:], idx)
	return NewWireMessage(Have, body[:])
}

// NewNotInterested creates a new NotInterested message
func NewNotInterested() *WireMessage {
	return NewWireMessage(NotInterested, nil)
}

// NewInterested creates a new Interested message
func NewInterested() *WireMessage {
	return NewWireMessage(Interested, nil)
}
<|endoftext|>


<commit_before>package nsf

type Apu struct {
	S1, S2 Square

	Odd        bool
	FC         byte
	FT         byte
	IrqDisable bool
}

type Square struct {
	Envelope
	Timer
	Length
	Sweep
	Duty

	Enable bool
}

type Duty struct {
	Type    byte
	Counter byte
}

type Sweep struct {
	Shift     byte
	Negate    bool
	Period    byte
	Enable    bool
	Divider   byte
	Reset     bool
	NegOffset int
}

type Envelope struct {
	Volume   byte
	Divider  byte
	Counter  byte
	Loop     bool
	Constant bool
	Start    bool
}

type Timer struct {
	Tick   uint16
	Length uint16
}

type Length struct {
	Halt    bool
	Counter byte
}

func (a *Apu) Init() {
	a.S1.Sweep.NegOffset = -1
	for i := uint16(0x4000); i <= 0x400f; i++ {
		a.Write(i, 0)
	}
	a.Write(0x4010, 0x10)
	a.Write(0x4011, 0)
	a.Write(0x4012, 0)
	a.Write(0x4013, 0)
	a.Write(0x4015, 0xf)
	a.Write(0x4017, 0)
}

func (a *Apu) Write(v uint16, b byte) {
	switch v & 0xff {
	case 0x00:
		a.S1.Control1(b)
	case 0x01:
		a.S1.Control2(b)
	case 0x02:
		a.S1.Control3(b)
	case 0x03:
		a.S1.Control4(b)
	case 0x04:
		a.S2.Control1(b)
	case 0x05:
		a.S2.Control2(b)
	case 0x06:
		a.S2.Control3(b)
	case 0x07:
		a.S2.Control4(b)
	case 0x15:
		a.S1.Disable(b&0x1 == 0)
		a.S2.Disable(b&0x2 == 0)
	case 0x17:
		a.FT = 0
		if b&0x80 != 0 {
			a.FC = 5
			a.FrameStep()
		} else {
			a.FC = 4
		}
		a.IrqDisable = b&0x40 != 0
	}
}

func (s *Square) Control1(b byte) {
	s.Envelope.Control(b)
	s.Duty.Control(b)
	s.Length.Halt = b&0x20 != 0
}

func (s *Square) Control2(b byte) {
	s.Sweep.Control(b)
}

func (s *Square) Control3(b byte) {
	s.Timer.Length &= 0xff00
	s.Timer.Length |= uint16(b)
}

func (s *Square) Control4(b byte) {
	s.Timer.Length &= 0xff
	s.Timer.Length |= uint16(b&0x7) << 8
	s.Length.Set(b >> 3)

	s.Envelope.Start = true
	s.Duty.Counter = 0
}

func (d *Duty) Control(b byte) {
	d.Type = b >> 6
}

func (s *Sweep) Control(b byte) {
	s.Shift = b & 0x7
	s.Negate = b&0x8 != 0
	s.Period = (b >> 4) & 0x7
	s.Enable = b&0x80 != 0
	s.Reset = true
}

func (e *Envelope) Control(b byte) {
	e.Volume = b & 0xf
	e.Constant = b&0x10 != 0
	e.Loop = b&0x20 != 0
}

func (l *Length) Set(b byte) {
	if !l.Halt {
		l.Counter = LenLookup[b]
	}
}

func (l *Length) Enabled() bool {
	return l.Counter != 0
}

func (s *Square) Disable(b bool) {
	s.Enable = !b
	if b {
		s.Length.Counter = 0
	}
}

func (a *Apu) Read(v uint16) byte {
	var b byte
	if v == 0x4015 {
		if a.S1.Length.Counter > 0 {
			b |= 0x1
		}
		if a.S2.Length.Counter > 0 {
			b |= 0x2
		}
	}
	return b
}

func (d *Duty) Clock() {
	if d.Counter == 0 {
		d.Counter = 7
	} else {
		d.Counter--
	}
}

func (s *Sweep) Clock() (r bool) {
	if s.Divider == 0 {
		s.Divider = s.Period
		r = true
	} else {
		s.Divider--
	}
	if s.Reset {
		s.Divider = 0
		s.Reset = false
	}
	return
}

func (e *Envelope) Clock() {
	if e.Start {
		e.Start = false
		e.Counter = 15
	} else {
		if e.Divider == 0 {
			e.Divider = e.Volume
			if e.Counter != 0 {
				e.Counter--
			} else if e.Loop {
				e.Counter = 15
			}
		} else {
			e.Divider--
		}
	}
}

func (t *Timer) Clock() bool {
	if t.Tick == 0 {
		t.Tick = t.Length
	} else {
		t.Tick--
	}
	return t.Tick == t.Length
}

func (s *Square) Clock() {
	if s.Timer.Clock() {
		s.Duty.Clock()
	}
}

func (a *Apu) Step() {
	if a.Odd {
		if a.S1.Enable {
			a.S1.Clock()
		}
		if a.S2.Enable {
			a.S2.Clock()
		}
	}
	a.Odd = !a.Odd
	}
}

func (a *Apu) FrameStep() {
	a.FT++
	if a.FT == a.FC {
		a.FT = 0
	}
	if a.FT <= 3 {
		a.S1.Envelope.Clock()
	}
	if a.FT == 1 || a.FT == 3 {
		a.S1.FrameStep()
		a.S2.FrameStep()
	}
	if a.FC == 4 && a.FT == 3 && !a.IrqDisable {
		// todo: assert cpu irq line
	}
}

func (s *Square) FrameStep() {
	s.Length.Clock()
	if s.Sweep.Clock() && s.Sweep.Enable && s.Sweep.Shift > 0 {
		r := s.SweepResult()
		if r <= 0x7ff {
			s.Timer.Tick = r
		}
	}
}

func (l *Length) Clock() {
	if !l.Halt && l.Counter > 0 {
		l.Counter--
	}
}

func (a *Apu) Volume() float32 {
	p := PulseOut[a.S1.Volume()+a.S2.Volume()]
	return p
}

func (s *Square) Volume() uint8 {
	if s.Enable && s.Duty.Enabled() && s.Length.Enabled() && s.Timer.Tick >= 8 && s.SweepResult() <= 0x7ff {
		return s.Envelope.Output()
	}
	return 0
}

func (e *Envelope) Output() byte {
	if e.Constant {
		return e.Volume
	}
	return e.Counter
}

func (s *Square) SweepResult() uint16 {
	r := int(s.Timer.Tick >> s.Sweep.Shift)
	if s.Sweep.Negate {
		r =  - r
	}
	r += int(s.Timer.Tick)
	if r > 0x7ff {
		r = 0x800
	}
	return uint16(r)
}

func (d *Duty) Enabled() bool {
	return DutyCycle[d.Type][d.Counter] == 1
}

var (
	PulseOut  [32]float32
	DutyCycle = [4][8]byte{
		{0, 1, 0, 0, 0, 0, 0, 0},
		{0, 1, 1, 0, 0, 0, 0, 0},
		{0, 1, 1, 1, 1, 0, 0, 0},
		{1, 0, 0, 1, 1, 1, 1, 1},
	}
	LenLookup = []byte{
		0x0a, 0xfe, 0x14, 0x02,
		0x28, 0x04, 0x50, 0x06,
		0xa0, 0x08, 0x3c, 0x0a,
		0x0e, 0x0c, 0x1a, 0x0e,
		0x0c, 0x10, 0x18, 0x12,
		0x30, 0x14, 0x60, 0x16,
		0xc0, 0x18, 0x48, 0x1a,
		0x10, 0x1c, 0x20, 0x1e,
	}
)

func init() {
	for i := range PulseOut {
		PulseOut[i] = 95.88 / (8128/float32(i) + 100)
	}
}
<commit_msg>gofmt<commit_after>package nsf

type Apu struct {
	S1, S2 Square

	Odd        bool
	FC         byte
	FT         byte
	IrqDisable bool
}

type Square struct {
	Envelope
	Timer
	Length
	Sweep
	Duty

	Enable bool
}

type Duty struct {
	Type    byte
	Counter byte
}

type Sweep struct {
	Shift     byte
	Negate    bool
	Period    byte
	Enable    bool
	Divider   byte
	Reset     bool
	NegOffset int
}

type Envelope struct {
	Volume   byte
	Divider  byte
	Counter  byte
	Loop     bool
	Constant bool
	Start    bool
}

type Timer struct {
	Tick   uint16
	Length uint16
}

type Length struct {
	Halt    bool
	Counter byte
}

func (a *Apu) Init() {
	a.S1.Sweep.NegOffset = -1
	for i := uint16(0x4000); i <= 0x400f; i++ {
		a.Write(i, 0)
	}
	a.Write(0x4010, 0x10)
	a.Write(0x4011, 0)
	a.Write(0x4012, 0)
	a.Write(0x4013, 0)
	a.Write(0x4015, 0xf)
	a.Write(0x4017, 0)
}

func (a *Apu) Write(v uint16, b byte) {
	switch v & 0xff {
	case 0x00:
		a.S1.Control1(b)
	case 0x01:
		a.S1.Control2(b)
	case 0x02:
		a.S1.Control3(b)
	case 0x03:
		a.S1.Control4(b)
	case 0x04:
		a.S2.Control1(b)
	case 0x05:
		a.S2.Control2(b)
	case 0x06:
		a.S2.Control3(b)
	case 0x07:
		a.S2.Control4(b)
	case 0x15:
		a.S1.Disable(b&0x1 == 0)
		a.S2.Disable(b&0x2 == 0)
	case 0x17:
		a.FT = 0
		if b&0x80 != 0 {
			a.FC = 5
			a.FrameStep()
		} else {
			a.FC = 4
		}
		a.IrqDisable = b&0x40 != 0
	}
}

func (s *Square) Control1(b byte) {
	s.Envelope.Control(b)
	s.Duty.Control(b)
	s.Length.Halt = b&0x20 != 0
}

func (s *Square) Control2(b byte) {
	s.Sweep.Control(b)
}

func (s *Square) Control3(b byte) {
	s.Timer.Length &= 0xff00
	s.Timer.Length |= uint16(b)
}

func (s *Square) Control4(b byte) {
	s.Timer.Length &= 0xff
	s.Timer.Length |= uint16(b&0x7) << 8
	s.Length.Set(b >> 3)

	s.Envelope.Start = true
	s.Duty.Counter = 0
}

func (d *Duty) Control(b byte) {
	d.Type = b >> 6
}

func (s *Sweep) Control(b byte) {
	s.Shift = b & 0x7
	s.Negate = b&0x8 != 0
	s.Period = (b >> 4) & 0x7
	s.Enable = b&0x80 != 0
	s.Reset = true
}

func (e *Envelope) Control(b byte) {
	e.Volume = b & 0xf
	e.Constant = b&0x10 != 0
	e.Loop = b&0x20 != 0
}

func (l *Length) Set(b byte) {
	if !l.Halt {
		l.Counter = LenLookup[b]
	}
}

func (l *Length) Enabled() bool {
	return l.Counter != 0
}

func (s *Square) Disable(b bool) {
	s.Enable = !b
	if b {
		s.Length.Counter = 0
	}
}

func (a *Apu) Read(v uint16) byte {
	var b byte
	if v == 0x4015 {
		if a.S1.Length.Counter > 0 {
			b |= 0x1
		}
		if a.S2.Length.Counter > 0 {
			b |= 0x2
		}
	}
	return b
}

func (d *Duty) Clock() {
	if d.Counter == 0 {
		d.Counter = 7
	} else {
		d.Counter--
	}
}

func (s *Sweep) Clock() (r bool) {
	if s.Divider == 0 {
		s.Divider = s.Period
		r = true
	} else {
		s.Divider--
	}
	if s.Reset {
		s.Divider = 0
		s.Reset = false
	}
	return
}

func (e *Envelope) Clock() {
	if e.Start {
		e.Start = false
		e.Counter = 15
	} else {
		if e.Divider == 0 {
			e.Divider = e.Volume
			if e.Counter != 0 {
				e.Counter--
			} else if e.Loop {
				e.Counter = 15
			}
		} else {
			e.Divider--
		}
	}
}

func (t *Timer) Clock() bool {
	if t.Tick == 0 {
		t.Tick = t.Length
	} else {
		t.Tick--
	}
	return t.Tick == t.Length
}

func (s *Square) Clock() {
	if s.Timer.Clock() {
		s.Duty.Clock()
	}
}

func (a *Apu) Step() {
	if a.Odd {
		if a.S1.Enable {
			a.S1.Clock()
		}
		if a.S2.Enable {
			a.S2.Clock()
		}
	}
	a.Odd = !a.Odd
	}
}

func (a *Apu) FrameStep() {
	a.FT++
	if a.FT == a.FC {
		a.FT = 0
	}
	if a.FT <= 3 {
		a.S1.Envelope.Clock()
	}
	if a.FT == 1 || a.FT == 3 {
		a.S1.FrameStep()
		a.S2.FrameStep()
	}
	if a.FC == 4 && a.FT == 3 && !a.IrqDisable {
		// todo: assert cpu irq line
	}
}

func (s *Square) FrameStep() {
	s.Length.Clock()
	if s.Sweep.Clock() && s.Sweep.Enable && s.Sweep.Shift > 0 {
		r := s.SweepResult()
		if r <= 0x7ff {
			s.Timer.Tick = r
		}
	}
}

func (l *Length) Clock() {
	if !l.Halt && l.Counter > 0 {
		l.Counter--
	}
}

func (a *Apu) Volume() float32 {
	p := PulseOut[a.S1.Volume()+a.S2.Volume()]
	return p
}

func (s *Square) Volume() uint8 {
	if s.Enable && s.Duty.Enabled() && s.Length.Enabled() && s.Timer.Tick >= 8 && s.SweepResult() <= 0x7ff {
		return s.Envelope.Output()
	}
	return 0
}

func (e *Envelope) Output() byte {
	if e.Constant {
		return e.Volume
	}
	return e.Counter
}

func (s *Square) SweepResult() uint16 {
	r := int(s.Timer.Tick >> s.Sweep.Shift)
	if s.Sweep.Negate {
		r = -r
	}
	r += int(s.Timer.Tick)
	if r > 0x7ff {
		r = 0x800
	}
	return uint16(r)
}

func (d *Duty) Enabled() bool {
	return DutyCycle[d.Type][d.Counter] == 1
}

var (
	PulseOut  [32]float32
	DutyCycle = [4][8]byte{
		{0, 1, 0, 0, 0, 0, 0, 0},
		{0, 1, 1, 0, 0, 0, 0, 0},
		{0, 1, 1, 1, 1, 0, 0, 0},
		{1, 0, 0, 1, 1, 1, 1, 1},
	}
	LenLookup = []byte{
		0x0a, 0xfe, 0x14, 0x02,
		0x28, 0x04, 0x50, 0x06,
		0xa0, 0x08, 0x3c, 0x0a,
		0x0e, 0x0c, 0x1a, 0x0e,
		0x0c, 0x10, 0x18, 0x12,
		0x30, 0x14, 0x60, 0x16,
		0xc0, 0x18, 0x48, 0x1a,
		0x10, 0x1c, 0x20, 0x1e,
	}
)

func init() {
	for i := range PulseOut {
		PulseOut[i] = 95.88 / (8128/float32(i) + 100)
	}
}
<|endoftext|>


<commit_before>package kit

import (
	"encoding/json"

	"testing"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"
)

func TestTransportHTTPSemiotics(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.TestDataFull), s)

	s = s.Resolve(s)

	sts, err := GenerateTransportHTTPSemiotics(common.NewContext(), s)
	common.TestEquals(t, nil, err)
	common.TestEquals(t, transportHTTPSemioticsExpecteds[0], string(sts[0].Content))
}

var transportHTTPSemioticsExpecteds = []string{`package account

import (
	"encoding/json"
	"net/http"

	"golang.org/x/net/context"

	"github.com/go-kit/kit/endpoint"
	httptransport "github.com/go-kit/kit/transport/http"
)

// Decode Request functions

func decodeCreateRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeDeleteRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeOneRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeSomeRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeUpdateRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

// Decode Response functions

func decodeCreateResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeDeleteResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeOneResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeSomeResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeUpdateResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

// Encode request function

func encodeRequest(r *http.Request, request interface{}) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(request); err != nil {
		return err
	}
	r.Body = ioutil.NopCloser(&buf)
	return nil
}

// Encode response function

func encodeResponse(rw http.ResponseWriter, response interface{}) error {
	return json.NewEncoder(rw).Encode(response)
}
`}
<commit_msg>Kit: update http semiotics test<commit_after>package kit

import (
	"encoding/json"

	"testing"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/gene/testdata"
	"github.com/cihangir/schema"
)

func TestTransportHTTPSemiotics(t *testing.T) {
	s := &schema.Schema{}
	err := json.Unmarshal([]byte(testdata.TestDataFull), s)

	s = s.Resolve(s)

	sts, err := GenerateTransportHTTPSemiotics(common.NewContext(), s)
	common.TestEquals(t, nil, err)
	common.TestEquals(t, transportHTTPSemioticsExpecteds[0], string(sts[0].Content))
}

var transportHTTPSemioticsExpecteds = []string{`package account

import (
	"encoding/json"
	"net/http"

	"golang.org/x/net/context"

	"github.com/go-kit/kit/endpoint"
	httptransport "github.com/go-kit/kit/transport/http"
)

type semiotic struct {
	Method             string
	Endpoint           string
	DecodeRequestFunc  httptransport.DecodeRequestFunc
	EncodeRequestFunc  httptransport.EncodeRequestFunc
	EncodeResponseFunc httptransport.EncodeResponseFunc
	DecodeResponseFunc httptransport.DecodeResponseFunc
}

var semiotics = map[string]semiotic{

	"create": semiotic{
		Method:             "POST",
		Endpoint:           "create",
		DecodeRequestFunc:  decodeCreateRequest,
		EncodeRequestFunc:  encodeRequest,
		EncodeResponseFunc: encodeResponse,
		DecodeResponseFunc: decodeCreateResponse,
	},

	"delete": semiotic{
		Method:             "POST",
		Endpoint:           "delete",
		DecodeRequestFunc:  decodeDeleteRequest,
		EncodeRequestFunc:  encodeRequest,
		EncodeResponseFunc: encodeResponse,
		DecodeResponseFunc: decodeDeleteResponse,
	},

	"one": semiotic{
		Method:             "POST",
		Endpoint:           "one",
		DecodeRequestFunc:  decodeOneRequest,
		EncodeRequestFunc:  encodeRequest,
		EncodeResponseFunc: encodeResponse,
		DecodeResponseFunc: decodeOneResponse,
	},

	"some": semiotic{
		Method:             "POST",
		Endpoint:           "some",
		DecodeRequestFunc:  decodeSomeRequest,
		EncodeRequestFunc:  encodeRequest,
		EncodeResponseFunc: encodeResponse,
		DecodeResponseFunc: decodeSomeResponse,
	},

	"update": semiotic{
		Method:             "POST",
		Endpoint:           "update",
		DecodeRequestFunc:  decodeUpdateRequest,
		EncodeRequestFunc:  encodeRequest,
		EncodeResponseFunc: encodeResponse,
		DecodeResponseFunc: decodeUpdateResponse,
	},
}

// Decode Request functions

func decodeCreateRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeDeleteRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeOneRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeSomeRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

func decodeUpdateRequest(r *http.Request) (interface{}, error) {
	var req models.Account
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return nil, err
	}
	return &req, nil
}

// Decode Response functions

func decodeCreateResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeDeleteResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeOneResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeSomeResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

func decodeUpdateResponse(r *http.Response) (interface{}, error) {
	var res models.Account
	if err := json.NewDecoder(r.Body).Decode(&res); err != nil {
		return nil, err
	}
	return &res, nil
}

// Encode request function

func encodeRequest(r *http.Request, request interface{}) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(request); err != nil {
		return err
	}
	r.Body = ioutil.NopCloser(&buf)
	return nil
}

// Encode response function

func encodeResponse(rw http.ResponseWriter, response interface{}) error {
	return json.NewEncoder(rw).Encode(response)
}
`}
<|endoftext|>