<commit_before>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package header

import (
	"encoding/binary"

	"gvisor.googlesource.com/gvisor/pkg/tcpip"
)

const (
	versIHL  = 0
	tos      = 1
	totalLen = 2
	id       = 4
	flagsFO  = 6
	ttl      = 8
	protocol = 9
	checksum = 10
	srcAddr  = 12
	dstAddr  = 16
)

// IPv4Fields contains the fields of an IPv4 packet. It is used to describe the
// fields of a packet that needs to be encoded.
type IPv4Fields struct {
	// IHL is the "internet header length" field of an IPv4 packet.
	IHL uint8

	// TOS is the "type of service" field of an IPv4 packet.
	TOS uint8

	// TotalLength is the "total length" field of an IPv4 packet.
	TotalLength uint16

	// ID is the "identification" field of an IPv4 packet.
	ID uint16

	// Flags is the "flags" field of an IPv4 packet.
	Flags uint8

	// FragmentOffset is the "fragment offset" field of an IPv4 packet.
	FragmentOffset uint16

	// TTL is the "time to live" field of an IPv4 packet.
	TTL uint8

	// Protocol is the "protocol" field of an IPv4 packet.
	Protocol uint8

	// Checksum is the "checksum" field of an IPv4 packet.
	Checksum uint16

	// SrcAddr is the "source ip address" of an IPv4 packet.
	SrcAddr tcpip.Address

	// DstAddr is the "destination ip address" of an IPv4 packet.
	DstAddr tcpip.Address
}

// IPv4 represents an ipv4 header stored in a byte array.
// Most of the methods of IPv4 access to the underlying slice without
// checking the boundaries and could panic because of 'index out of range'.
// Always call IsValid() to validate an instance of IPv4 before using other methods.
type IPv4 []byte

const (
	// IPv4MinimumSize is the minimum size of a valid IPv4 packet.
	IPv4MinimumSize = 20

	// IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given
	// that there are only 4 bits to represents the header length in 32-bit
	// units, the header cannot exceed 15*4 = 60 bytes.
	IPv4MaximumHeaderSize = 60

	// IPv4AddressSize is the size, in bytes, of an IPv4 address.
	IPv4AddressSize = 4

	// IPv4ProtocolNumber is IPv4's network protocol number.
	IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800

	// IPv4Version is the version of the ipv4 protocol.
	IPv4Version = 4

	// IPv4Broadcast is the broadcast address of the IPv4 procotol.
	IPv4Broadcast tcpip.Address = "\xff\xff\xff\xff"

	// IPv4Any is the non-routable IPv4 "any" meta address.
	IPv4Any tcpip.Address = "\x00\x00\x00\x00"
)

// Flags that may be set in an IPv4 packet.
const (
	IPv4FlagMoreFragments = 1 << iota
	IPv4FlagDontFragment
)

// IPVersion returns the version of IP used in the given packet. It returns -1
// if the packet is not large enough to contain the version field.
func IPVersion(b []byte) int {
	// Length must be at least offset+length of version field.
	if len(b) < versIHL+1 {
		return -1
	}
	return int(b[versIHL] >> 4)
}

// HeaderLength returns the value of the "header length" field of the ipv4
// header.
func (b IPv4) HeaderLength() uint8 {
	return (b[versIHL] & 0xf) * 4
}

// ID returns the value of the identifier field of the ipv4 header.
func (b IPv4) ID() uint16 {
	return binary.BigEndian.Uint16(b[id:])
}

// Protocol returns the value of the protocol field of the ipv4 header.
func (b IPv4) Protocol() uint8 {
	return b[protocol]
}

// Flags returns the "flags" field of the ipv4 header.
func (b IPv4) Flags() uint8 {
	return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13)
}

// TTL returns the "TTL" field of the ipv4 header.
func (b IPv4) TTL() uint8 {
	return b[ttl]
}

// FragmentOffset returns the "fragment offset" field of the ipv4 header.
func (b IPv4) FragmentOffset() uint16 {
	return binary.BigEndian.Uint16(b[flagsFO:]) << 3
}

// TotalLength returns the "total length" field of the ipv4 header.
func (b IPv4) TotalLength() uint16 {
	return binary.BigEndian.Uint16(b[totalLen:])
}

// Checksum returns the checksum field of the ipv4 header.
func (b IPv4) Checksum() uint16 {
	return binary.BigEndian.Uint16(b[checksum:])
}

// SourceAddress returns the "source address" field of the ipv4 header.
func (b IPv4) SourceAddress() tcpip.Address {
	return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize])
}

// DestinationAddress returns the "destination address" field of the ipv4
// header.
func (b IPv4) DestinationAddress() tcpip.Address {
	return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize])
}

// TransportProtocol implements Network.TransportProtocol.
func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber {
	return tcpip.TransportProtocolNumber(b.Protocol())
}

// Payload implements Network.Payload.
func (b IPv4) Payload() []byte {
	return b[b.HeaderLength():][:b.PayloadLength()]
}

// PayloadLength returns the length of the payload portion of the ipv4 packet.
func (b IPv4) PayloadLength() uint16 {
	return b.TotalLength() - uint16(b.HeaderLength())
}

// TOS returns the "type of service" field of the ipv4 header.
func (b IPv4) TOS() (uint8, uint32) {
	return b[tos], 0
}

// SetTOS sets the "type of service" field of the ipv4 header.
func (b IPv4) SetTOS(v uint8, _ uint32) {
	b[tos] = v
}

// SetTotalLength sets the "total length" field of the ipv4 header.
func (b IPv4) SetTotalLength(totalLength uint16) {
	binary.BigEndian.PutUint16(b[totalLen:], totalLength)
}

// SetChecksum sets the checksum field of the ipv4 header.
func (b IPv4) SetChecksum(v uint16) {
	binary.BigEndian.PutUint16(b[checksum:], v)
}

// SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the
// ipv4 header.
func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) {
	v := (uint16(flags) << 13) | (offset >> 3)
	binary.BigEndian.PutUint16(b[flagsFO:], v)
}

// SetSourceAddress sets the "source address" field of the ipv4 header.
func (b IPv4) SetSourceAddress(addr tcpip.Address) {
	copy(b[srcAddr:srcAddr+IPv4AddressSize], addr)
}

// SetDestinationAddress sets the "destination address" field of the ipv4
// header.
func (b IPv4) SetDestinationAddress(addr tcpip.Address) {
	copy(b[dstAddr:dstAddr+IPv4AddressSize], addr)
}

// CalculateChecksum calculates the checksum of the ipv4 header.
func (b IPv4) CalculateChecksum() uint16 {
	return Checksum(b[:b.HeaderLength()], 0)
}

// Encode encodes all the fields of the ipv4 header.
func (b IPv4) Encode(i *IPv4Fields) {
	b[versIHL] = (4 << 4) | ((i.IHL / 4) & 0xf)
	b[tos] = i.TOS
	b.SetTotalLength(i.TotalLength)
	binary.BigEndian.PutUint16(b[id:], i.ID)
	b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset)
	b[ttl] = i.TTL
	b[protocol] = i.Protocol
	b.SetChecksum(i.Checksum)
	copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr)
	copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr)
}

// EncodePartial updates the total length and checksum fields of ipv4 header,
// taking in the partial checksum, which is the checksum of the header without
// the total length and checksum fields. It is useful in cases when similar
// packets are produced.
func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) {
	b.SetTotalLength(totalLength)
	checksum := Checksum(b[totalLen:totalLen+2], partialChecksum)
	b.SetChecksum(^checksum)
}

// IsValid performs basic validation on the packet.
func (b IPv4) IsValid(pktSize int) bool {
	if len(b) < IPv4MinimumSize {
		return false
	}

	hlen := int(b.HeaderLength())
	tlen := int(b.TotalLength())
	if hlen > tlen || tlen > pktSize {
		return false
	}

	return true
}

// IsV4MulticastAddress determines if the provided address is an IPv4 multicast
// address (range 224.0.0.0 to 239.255.255.255). The four most significant bits
// will be 1110 = 0xe0.
func IsV4MulticastAddress(addr tcpip.Address) bool {
	if len(addr) != IPv4AddressSize {
		return false
	}
	return (addr[0] & 0xf0) == 0xe0
}
<commit_msg>Internal change.<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package header

import (
	"encoding/binary"

	"gvisor.googlesource.com/gvisor/pkg/tcpip"
)

const (
	versIHL  = 0
	tos      = 1
	totalLen = 2
	id       = 4
	flagsFO  = 6
	ttl      = 8
	protocol = 9
	checksum = 10
	srcAddr  = 12
	dstAddr  = 16
)

// IPv4Fields contains the fields of an IPv4 packet. It is used to describe the
// fields of a packet that needs to be encoded.
type IPv4Fields struct {
	// IHL is the "internet header length" field of an IPv4 packet.
	IHL uint8

	// TOS is the "type of service" field of an IPv4 packet.
	TOS uint8

	// TotalLength is the "total length" field of an IPv4 packet.
	TotalLength uint16

	// ID is the "identification" field of an IPv4 packet.
	ID uint16

	// Flags is the "flags" field of an IPv4 packet.
	Flags uint8

	// FragmentOffset is the "fragment offset" field of an IPv4 packet.
	FragmentOffset uint16

	// TTL is the "time to live" field of an IPv4 packet.
	TTL uint8

	// Protocol is the "protocol" field of an IPv4 packet.
	Protocol uint8

	// Checksum is the "checksum" field of an IPv4 packet.
	Checksum uint16

	// SrcAddr is the "source ip address" of an IPv4 packet.
	SrcAddr tcpip.Address

	// DstAddr is the "destination ip address" of an IPv4 packet.
	DstAddr tcpip.Address
}

// IPv4 represents an ipv4 header stored in a byte array.
// Most of the methods of IPv4 access to the underlying slice without
// checking the boundaries and could panic because of 'index out of range'.
// Always call IsValid() to validate an instance of IPv4 before using other methods.
type IPv4 []byte

const (
	// IPv4MinimumSize is the minimum size of a valid IPv4 packet.
	IPv4MinimumSize = 20

	// IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given
	// that there are only 4 bits to represents the header length in 32-bit
	// units, the header cannot exceed 15*4 = 60 bytes.
	IPv4MaximumHeaderSize = 60

	// IPv4AddressSize is the size, in bytes, of an IPv4 address.
	IPv4AddressSize = 4

	// IPv4ProtocolNumber is IPv4's network protocol number.
	IPv4ProtocolNumber tcpip.NetworkProtocolNumber = 0x0800

	// IPv4Version is the version of the ipv4 protocol.
	IPv4Version = 4

	// IPv4Broadcast is the broadcast address of the IPv4 procotol.
	IPv4Broadcast tcpip.Address = "\xff\xff\xff\xff"

	// IPv4Any is the non-routable IPv4 "any" meta address.
	IPv4Any tcpip.Address = "\x00\x00\x00\x00"
)

// Flags that may be set in an IPv4 packet.
const (
	IPv4FlagMoreFragments = 1 << iota
	IPv4FlagDontFragment
)

// IPVersion returns the version of IP used in the given packet. It returns -1
// if the packet is not large enough to contain the version field.
func IPVersion(b []byte) int {
	// Length must be at least offset+length of version field.
	if len(b) < versIHL+1 {
		return -1
	}
	return int(b[versIHL] >> 4)
}

// HeaderLength returns the value of the "header length" field of the ipv4
// header.
func (b IPv4) HeaderLength() uint8 {
	return (b[versIHL] & 0xf) * 4
}

// ID returns the value of the identifier field of the ipv4 header.
func (b IPv4) ID() uint16 {
	return binary.BigEndian.Uint16(b[id:])
}

// Protocol returns the value of the protocol field of the ipv4 header.
func (b IPv4) Protocol() uint8 {
	return b[protocol]
}

// Flags returns the "flags" field of the ipv4 header.
func (b IPv4) Flags() uint8 {
	return uint8(binary.BigEndian.Uint16(b[flagsFO:]) >> 13)
}

// TTL returns the "TTL" field of the ipv4 header.
func (b IPv4) TTL() uint8 {
	return b[ttl]
}

// FragmentOffset returns the "fragment offset" field of the ipv4 header.
func (b IPv4) FragmentOffset() uint16 {
	return binary.BigEndian.Uint16(b[flagsFO:]) << 3
}

// TotalLength returns the "total length" field of the ipv4 header.
func (b IPv4) TotalLength() uint16 {
	return binary.BigEndian.Uint16(b[totalLen:])
}

// Checksum returns the checksum field of the ipv4 header.
func (b IPv4) Checksum() uint16 {
	return binary.BigEndian.Uint16(b[checksum:])
}

// SourceAddress returns the "source address" field of the ipv4 header.
func (b IPv4) SourceAddress() tcpip.Address {
	return tcpip.Address(b[srcAddr : srcAddr+IPv4AddressSize])
}

// DestinationAddress returns the "destination address" field of the ipv4
// header.
func (b IPv4) DestinationAddress() tcpip.Address {
	return tcpip.Address(b[dstAddr : dstAddr+IPv4AddressSize])
}

// TransportProtocol implements Network.TransportProtocol.
func (b IPv4) TransportProtocol() tcpip.TransportProtocolNumber {
	return tcpip.TransportProtocolNumber(b.Protocol())
}

// Payload implements Network.Payload.
func (b IPv4) Payload() []byte {
	return b[b.HeaderLength():][:b.PayloadLength()]
}

// PayloadLength returns the length of the payload portion of the ipv4 packet.
func (b IPv4) PayloadLength() uint16 {
	return b.TotalLength() - uint16(b.HeaderLength())
}

// TOS returns the "type of service" field of the ipv4 header.
func (b IPv4) TOS() (uint8, uint32) {
	return b[tos], 0
}

// SetTOS sets the "type of service" field of the ipv4 header.
func (b IPv4) SetTOS(v uint8, _ uint32) {
	b[tos] = v
}

// SetTotalLength sets the "total length" field of the ipv4 header.
func (b IPv4) SetTotalLength(totalLength uint16) {
	binary.BigEndian.PutUint16(b[totalLen:], totalLength)
}

// SetChecksum sets the checksum field of the ipv4 header.
func (b IPv4) SetChecksum(v uint16) {
	binary.BigEndian.PutUint16(b[checksum:], v)
}

// SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the
// ipv4 header.
func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16) {
	v := (uint16(flags) << 13) | (offset >> 3)
	binary.BigEndian.PutUint16(b[flagsFO:], v)
}

// SetID sets the identification field.
func (b IPv4) SetID(v uint16) {
	binary.BigEndian.PutUint16(b[id:], v)
}

// SetSourceAddress sets the "source address" field of the ipv4 header.
func (b IPv4) SetSourceAddress(addr tcpip.Address) {
	copy(b[srcAddr:srcAddr+IPv4AddressSize], addr)
}

// SetDestinationAddress sets the "destination address" field of the ipv4
// header.
func (b IPv4) SetDestinationAddress(addr tcpip.Address) {
	copy(b[dstAddr:dstAddr+IPv4AddressSize], addr)
}

// CalculateChecksum calculates the checksum of the ipv4 header.
func (b IPv4) CalculateChecksum() uint16 {
	return Checksum(b[:b.HeaderLength()], 0)
}

// Encode encodes all the fields of the ipv4 header.
func (b IPv4) Encode(i *IPv4Fields) {
	b[versIHL] = (4 << 4) | ((i.IHL / 4) & 0xf)
	b[tos] = i.TOS
	b.SetTotalLength(i.TotalLength)
	binary.BigEndian.PutUint16(b[id:], i.ID)
	b.SetFlagsFragmentOffset(i.Flags, i.FragmentOffset)
	b[ttl] = i.TTL
	b[protocol] = i.Protocol
	b.SetChecksum(i.Checksum)
	copy(b[srcAddr:srcAddr+IPv4AddressSize], i.SrcAddr)
	copy(b[dstAddr:dstAddr+IPv4AddressSize], i.DstAddr)
}

// EncodePartial updates the total length and checksum fields of ipv4 header,
// taking in the partial checksum, which is the checksum of the header without
// the total length and checksum fields. It is useful in cases when similar
// packets are produced.
func (b IPv4) EncodePartial(partialChecksum, totalLength uint16) {
	b.SetTotalLength(totalLength)
	checksum := Checksum(b[totalLen:totalLen+2], partialChecksum)
	b.SetChecksum(^checksum)
}

// IsValid performs basic validation on the packet.
func (b IPv4) IsValid(pktSize int) bool {
	if len(b) < IPv4MinimumSize {
		return false
	}

	hlen := int(b.HeaderLength())
	tlen := int(b.TotalLength())
	if hlen > tlen || tlen > pktSize {
		return false
	}

	return true
}

// IsV4MulticastAddress determines if the provided address is an IPv4 multicast
// address (range 224.0.0.0 to 239.255.255.255). The four most significant bits
// will be 1110 = 0xe0.
func IsV4MulticastAddress(addr tcpip.Address) bool {
	if len(addr) != IPv4AddressSize {
		return false
	}
	return (addr[0] & 0xf0) == 0xe0
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package testutil

import (
	"net"

	. "github.com/pingcap/check"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/pingcap/pd/pkg/rpcutil"
)

func MustRPCCall(c *C, conn net.Conn, request *pdpb.Request) *pdpb.Response {
	resp, err := rpcutil.Call(conn, 0, request)
	c.Assert(err, IsNil)
	c.Assert(resp, NotNil)
	return resp
}

func MustRPCRequest(c *C, urls string, request *pdpb.Request) *pdpb.Response {
	resp, err := rpcutil.Request(urls, 0, request)
	c.Assert(err, IsNil)
	c.Assert(resp, NotNil)
	return resp
}
<commit_msg>pkg/testutil: add some comments (#430)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package testutil

import (
	"net"

	"github.com/pingcap/check"
	"github.com/pingcap/kvproto/pkg/pdpb"
	"github.com/pingcap/pd/pkg/rpcutil"
)

// MustRPCCall fails current test if fails to make a RPC call.
func MustRPCCall(c *check.C, conn net.Conn, request *pdpb.Request) *pdpb.Response {
	resp, err := rpcutil.Call(conn, 0, request)
	c.Assert(err, check.IsNil)
	c.Assert(resp, check.NotNil)
	return resp
}

// MustRPCRequest fails current test if fails to make RPC requests.
func MustRPCRequest(c *check.C, urls string, request *pdpb.Request) *pdpb.Response {
	resp, err := rpcutil.Request(urls, 0, request)
	c.Assert(err, check.IsNil)
	c.Assert(resp, check.NotNil)
	return resp
}
<|endoftext|>


<commit_before>package nats

import (
	"errors"
	"net/rpc"
	"strings"
	"time"

	"github.com/nats-io/nats"

	"github.com/weaveworks/flux"
	"github.com/weaveworks/flux/guid"
	"github.com/weaveworks/flux/platform"
	fluxrpc "github.com/weaveworks/flux/platform/rpc"
)

const (
	timeout      = 5 * time.Second
	applyTimeout = 20 * time.Minute
	presenceTick = 50 * time.Millisecond
	encoderType  = nats.JSON_ENCODER

	methodKick         = ".Platform.Kick"
	methodPing         = ".Platform.Ping"
	methodVersion      = ".Platform.Version"
	methodAllServices  = ".Platform.AllServices"
	methodSomeServices = ".Platform.SomeServices"
	methodApply        = ".Platform.Apply"
)

type NATS struct {
	url string
	// It's convenient to send (or request) on an encoding connection,
	// since that'll do encoding work for us. When receiving though,
	// we want to decode based on the method as given in the subject,
	// so we use a regular connection and do the decoding ourselves.
	enc     *nats.EncodedConn
	raw     *nats.Conn
	metrics platform.BusMetrics
}

var _ platform.MessageBus = &NATS{}

func NewMessageBus(url string, metrics platform.BusMetrics) (*NATS, error) {
	conn, err := nats.Connect(url, nats.MaxReconnects(-1))
	if err != nil {
		return nil, err
	}
	encConn, err := nats.NewEncodedConn(conn, encoderType)
	if err != nil {
		return nil, err
	}
	return &NATS{
		url:     url,
		raw:     conn,
		enc:     encConn,
		metrics: metrics,
	}, nil
}

// Wait up to `timeout` for a particular instance to connect. Mostly
// useful for synchronising during testing.
func (n *NATS) AwaitPresence(instID flux.InstanceID, timeout time.Duration) error {
	timer := time.After(timeout)
	attempts := time.NewTicker(presenceTick)
	defer attempts.Stop()

	for {
		select {
		case <-attempts.C:
			if err := n.Ping(instID); err == nil {
				return nil
			}
		case <-timer:
			return errors.New("presence timeout")
		}
	}
}

func (n *NATS) Ping(instID flux.InstanceID) error {
	var response PingResponse
	err := n.enc.Request(string(instID)+methodPing, ping{}, &response, timeout)
	if err == nil {
		err = extractError(response.ErrorResponse)
	}
	return err
}

// ErrorResponse is for dropping into responses so they have
// appropriate fields. The field `Error` carries either an empty
// string (no error), or the error message to be reconstituted as an
// error). The field `Fatal` indicates that the error resulted in the
// connection to the daemon being torn down.
type ErrorResponse struct {
	Error string
	Fatal bool
}

type AllServicesResponse struct {
	Services []platform.Service
	ErrorResponse
}

type SomeServicesResponse struct {
	Services []platform.Service
	ErrorResponse
}

type ApplyResponse struct {
	Result fluxrpc.ApplyResult
	ErrorResponse
}

type ping struct{}

type PingResponse struct {
	ErrorResponse
}

type version struct{}

type VersionResponse struct {
	Version string
	ErrorResponse
}

func extractError(resp ErrorResponse) error {
	if resp.Error != "" {
		if resp.Fatal {
			return platform.FatalError{errors.New(resp.Error)}
		}
		return rpc.ServerError(resp.Error)
	}
	return nil
}

func makeErrorResponse(err error) (resp ErrorResponse) {
	if err == nil {
		return resp
	}
	if _, ok := err.(platform.FatalError); ok {
		resp.Fatal = true
	}
	resp.Error = err.Error()
	return resp
}

// natsPlatform collects the things you need to make a request via NATS
// together, and implements platform.Platform using that mechanism.
type natsPlatform struct {
	conn     *nats.EncodedConn
	instance string
}

func (r *natsPlatform) AllServices(ns string, ig flux.ServiceIDSet) ([]platform.Service, error) {
	var response AllServicesResponse
	if err := r.conn.Request(r.instance+methodAllServices, fluxrpc.AllServicesRequest{ns, ig}, &response, timeout); err != nil {
		return nil, err
	}
	return response.Services, extractError(response.ErrorResponse)
}

func (r *natsPlatform) SomeServices(incl []flux.ServiceID) ([]platform.Service, error) {
	var response SomeServicesResponse
	if err := r.conn.Request(r.instance+methodSomeServices, incl, &response, timeout); err != nil {
		return nil, err
	}
	return response.Services, extractError(response.ErrorResponse)
}

// Call Apply on the remote platform. Note that we use a much longer
// timeout, because for now at least, Applys can take an arbitrary
// amount of time, and we don't want to return an error if it's simply
// taking a while. The downside is that if the platform is actually
// not present, this won't return at all. This is somewhat mitigated
// because applys are done after other RPCs which have the normal
// timeout, but better would be to split Applys into RPCs which can
// each have a short timeout.
func (r *natsPlatform) Apply(specs []platform.ServiceDefinition) error {
	var response ApplyResponse
	if err := r.conn.Request(r.instance+methodApply, specs, &response, applyTimeout); err != nil {
		return err
	}
	if len(response.Result) > 0 {
		errs := platform.ApplyError{}
		for s, e := range response.Result {
			errs[s] = errors.New(e)
		}
		return errs
	}
	return extractError(response.ErrorResponse)
}

func (r *natsPlatform) Ping() error {
	var response PingResponse
	if err := r.conn.Request(r.instance+methodPing, ping{}, &response, timeout); err != nil {
		return err
	}
	return extractError(response.ErrorResponse)
}

func (r *natsPlatform) Version() (string, error) {
	var response VersionResponse
	if err := r.conn.Request(r.instance+methodVersion, version{}, &response, timeout); err != nil {
		return "", err
	}
	return response.Version, extractError(response.ErrorResponse)
}

// Connect returns a platform.Platform implementation that can be used
// to talk to a particular instance.
func (n *NATS) Connect(instID flux.InstanceID) (platform.Platform, error) {
	return &natsPlatform{
		conn:     n.enc,
		instance: string(instID),
	}, nil
}

// Subscribe registers a remote platform.Platform implementation as
// the daemon for an instance (identified by instID). Any
// platform.FatalError returned when processing requests will result
// in the platform being deregistered, with the error put on the
// channel `done`.
func (n *NATS) Subscribe(instID flux.InstanceID, remote platform.Platform, done chan<- error) {
	encoder := nats.EncoderForType(encoderType)

	requests := make(chan *nats.Msg)
	sub, err := n.raw.ChanSubscribe(string(instID)+".Platform.>", requests)
	if err != nil {
		done <- err
		return
	}

	// It's possible that more than one connection for a particular
	// instance will arrive at the service. To prevent confusion, when
	// a subscription arrives, it sends a "kick" message with a unique
	// ID (so it can recognise its own kick message). Any other
	// subscription for the instance _should_ then exit upon receipt
	// of the kick.
	myID := guid.New()
	n.raw.Publish(string(instID)+methodKick, []byte(myID))

	errc := make(chan error)

	processRequest := func(request *nats.Msg) {
		var err error
		switch {
		case strings.HasSuffix(request.Subject, methodKick):
			id := string(request.Data)
			if id != myID {
				n.metrics.IncrKicks(instID)
				err = platform.FatalError{errors.New("Kicked by new subscriber " + id)}
			}
		case strings.HasSuffix(request.Subject, methodPing):
			var p ping
			err = encoder.Decode(request.Subject, request.Data, &p)
			if err == nil {
				err = remote.Ping()
			}
			n.enc.Publish(request.Reply, PingResponse{makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodVersion):
			var vsn string
			vsn, err = remote.Version()
			n.enc.Publish(request.Reply, VersionResponse{vsn, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodAllServices):
			var (
				req fluxrpc.AllServicesRequest
				res []platform.Service
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				res, err = remote.AllServices(req.MaybeNamespace, req.Ignored)
			}
			n.enc.Publish(request.Reply, AllServicesResponse{res, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodSomeServices):
			var (
				req []flux.ServiceID
				res []platform.Service
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				res, err = remote.SomeServices(req)
			}
			n.enc.Publish(request.Reply, SomeServicesResponse{res, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodApply):
			var (
				req []platform.ServiceDefinition
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				err = remote.Apply(req)
			}
			response := ApplyResponse{}
			switch applyErr := err.(type) {
			case platform.ApplyError:
				result := fluxrpc.ApplyResult{}
				for s, e := range applyErr {
					result[s] = e.Error()
				}
				response.Result = result
			default:
				response.ErrorResponse = makeErrorResponse(err)
			}
			n.enc.Publish(request.Reply, response)
		default:
			err = errors.New("unknown message: " + request.Subject)
		}
		if err != nil {
			select {
			case errc <- err:
			default:
				// If the error channel is closed, it means that a
				// different RPC goroutine had a fatal error that
				// triggered the clean up and return of the parent
				// goroutine. It is likely that the error we have
				// encountered is due to the closure of the RPC
				// client whilst our request was still in progress
				// - don't panic.
			}
		}
	}

	go func() {
		for {
			select {
			// If both an error and a request are available, the runtime may
			// chose (by uniform pseudo-random selection) to process the
			// request first. This may seem like a problem, but even if we were
			// guaranteed to prefer the error channel there would still be a
			// race between selecting a request here and a failing goroutine
			// putting an error into the channel - it's an unavoidable
			// consequence of asynchronous request handling. The error will get
			// selected and handled soon enough.
			case err := <-errc:
				if _, ok := err.(platform.FatalError); ok && err != nil {
					close(errc)
					sub.Unsubscribe()
					close(requests)
					done <- err
					return
				}
			case request := <-requests:
				// Some of these operations (Apply in particular) can block for a long time;
				// dispatch in a goroutine and deliver any errors back to us so that we can
				// clean up on any hard failures.
				go processRequest(request)
			}
		}
	}()
}
<commit_msg>Avoid a loss of fatal errors in subscriber<commit_after>package nats

import (
	"errors"
	"net/rpc"
	"strings"
	"time"

	"github.com/nats-io/nats"

	"github.com/weaveworks/flux"
	"github.com/weaveworks/flux/guid"
	"github.com/weaveworks/flux/platform"
	fluxrpc "github.com/weaveworks/flux/platform/rpc"
)

const (
	timeout      = 5 * time.Second
	applyTimeout = 20 * time.Minute
	presenceTick = 50 * time.Millisecond
	encoderType  = nats.JSON_ENCODER

	methodKick         = ".Platform.Kick"
	methodPing         = ".Platform.Ping"
	methodVersion      = ".Platform.Version"
	methodAllServices  = ".Platform.AllServices"
	methodSomeServices = ".Platform.SomeServices"
	methodApply        = ".Platform.Apply"
)

type NATS struct {
	url string
	// It's convenient to send (or request) on an encoding connection,
	// since that'll do encoding work for us. When receiving though,
	// we want to decode based on the method as given in the subject,
	// so we use a regular connection and do the decoding ourselves.
	enc     *nats.EncodedConn
	raw     *nats.Conn
	metrics platform.BusMetrics
}

var _ platform.MessageBus = &NATS{}

func NewMessageBus(url string, metrics platform.BusMetrics) (*NATS, error) {
	conn, err := nats.Connect(url, nats.MaxReconnects(-1))
	if err != nil {
		return nil, err
	}
	encConn, err := nats.NewEncodedConn(conn, encoderType)
	if err != nil {
		return nil, err
	}
	return &NATS{
		url:     url,
		raw:     conn,
		enc:     encConn,
		metrics: metrics,
	}, nil
}

// Wait up to `timeout` for a particular instance to connect. Mostly
// useful for synchronising during testing.
func (n *NATS) AwaitPresence(instID flux.InstanceID, timeout time.Duration) error {
	timer := time.After(timeout)
	attempts := time.NewTicker(presenceTick)
	defer attempts.Stop()

	for {
		select {
		case <-attempts.C:
			if err := n.Ping(instID); err == nil {
				return nil
			}
		case <-timer:
			return errors.New("presence timeout")
		}
	}
}

func (n *NATS) Ping(instID flux.InstanceID) error {
	var response PingResponse
	err := n.enc.Request(string(instID)+methodPing, ping{}, &response, timeout)
	if err == nil {
		err = extractError(response.ErrorResponse)
	}
	return err
}

// ErrorResponse is for dropping into responses so they have
// appropriate fields. The field `Error` carries either an empty
// string (no error), or the error message to be reconstituted as an
// error). The field `Fatal` indicates that the error resulted in the
// connection to the daemon being torn down.
type ErrorResponse struct {
	Error string
	Fatal bool
}

type AllServicesResponse struct {
	Services []platform.Service
	ErrorResponse
}

type SomeServicesResponse struct {
	Services []platform.Service
	ErrorResponse
}

type ApplyResponse struct {
	Result fluxrpc.ApplyResult
	ErrorResponse
}

type ping struct{}

type PingResponse struct {
	ErrorResponse
}

type version struct{}

type VersionResponse struct {
	Version string
	ErrorResponse
}

func extractError(resp ErrorResponse) error {
	if resp.Error != "" {
		if resp.Fatal {
			return platform.FatalError{errors.New(resp.Error)}
		}
		return rpc.ServerError(resp.Error)
	}
	return nil
}

func makeErrorResponse(err error) (resp ErrorResponse) {
	if err == nil {
		return resp
	}
	if _, ok := err.(platform.FatalError); ok {
		resp.Fatal = true
	}
	resp.Error = err.Error()
	return resp
}

// natsPlatform collects the things you need to make a request via NATS
// together, and implements platform.Platform using that mechanism.
type natsPlatform struct {
	conn     *nats.EncodedConn
	instance string
}

func (r *natsPlatform) AllServices(ns string, ig flux.ServiceIDSet) ([]platform.Service, error) {
	var response AllServicesResponse
	if err := r.conn.Request(r.instance+methodAllServices, fluxrpc.AllServicesRequest{ns, ig}, &response, timeout); err != nil {
		return nil, err
	}
	return response.Services, extractError(response.ErrorResponse)
}

func (r *natsPlatform) SomeServices(incl []flux.ServiceID) ([]platform.Service, error) {
	var response SomeServicesResponse
	if err := r.conn.Request(r.instance+methodSomeServices, incl, &response, timeout); err != nil {
		return nil, err
	}
	return response.Services, extractError(response.ErrorResponse)
}

// Call Apply on the remote platform. Note that we use a much longer
// timeout, because for now at least, Applys can take an arbitrary
// amount of time, and we don't want to return an error if it's simply
// taking a while. The downside is that if the platform is actually
// not present, this won't return at all. This is somewhat mitigated
// because applys are done after other RPCs which have the normal
// timeout, but better would be to split Applys into RPCs which can
// each have a short timeout.
func (r *natsPlatform) Apply(specs []platform.ServiceDefinition) error {
	var response ApplyResponse
	if err := r.conn.Request(r.instance+methodApply, specs, &response, applyTimeout); err != nil {
		return err
	}
	if len(response.Result) > 0 {
		errs := platform.ApplyError{}
		for s, e := range response.Result {
			errs[s] = errors.New(e)
		}
		return errs
	}
	return extractError(response.ErrorResponse)
}

func (r *natsPlatform) Ping() error {
	var response PingResponse
	if err := r.conn.Request(r.instance+methodPing, ping{}, &response, timeout); err != nil {
		return err
	}
	return extractError(response.ErrorResponse)
}

func (r *natsPlatform) Version() (string, error) {
	var response VersionResponse
	if err := r.conn.Request(r.instance+methodVersion, version{}, &response, timeout); err != nil {
		return "", err
	}
	return response.Version, extractError(response.ErrorResponse)
}

// Connect returns a platform.Platform implementation that can be used
// to talk to a particular instance.
func (n *NATS) Connect(instID flux.InstanceID) (platform.Platform, error) {
	return &natsPlatform{
		conn:     n.enc,
		instance: string(instID),
	}, nil
}

// Subscribe registers a remote platform.Platform implementation as
// the daemon for an instance (identified by instID). Any
// platform.FatalError returned when processing requests will result
// in the platform being deregistered, with the error put on the
// channel `done`.
func (n *NATS) Subscribe(instID flux.InstanceID, remote platform.Platform, done chan<- error) {
	encoder := nats.EncoderForType(encoderType)

	requests := make(chan *nats.Msg)
	sub, err := n.raw.ChanSubscribe(string(instID)+".Platform.>", requests)
	if err != nil {
		done <- err
		return
	}

	// It's possible that more than one connection for a particular
	// instance will arrive at the service. To prevent confusion, when
	// a subscription arrives, it sends a "kick" message with a unique
	// ID (so it can recognise its own kick message). Any other
	// subscription for the instance _should_ then exit upon receipt
	// of the kick.
	myID := guid.New()
	n.raw.Publish(string(instID)+methodKick, []byte(myID))

	errc := make(chan error)

	processRequest := func(request *nats.Msg) {
		var err error
		switch {
		case strings.HasSuffix(request.Subject, methodKick):
			id := string(request.Data)
			if id != myID {
				n.metrics.IncrKicks(instID)
				err = platform.FatalError{errors.New("Kicked by new subscriber " + id)}
			}
		case strings.HasSuffix(request.Subject, methodPing):
			var p ping
			err = encoder.Decode(request.Subject, request.Data, &p)
			if err == nil {
				err = remote.Ping()
			}
			n.enc.Publish(request.Reply, PingResponse{makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodVersion):
			var vsn string
			vsn, err = remote.Version()
			n.enc.Publish(request.Reply, VersionResponse{vsn, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodAllServices):
			var (
				req fluxrpc.AllServicesRequest
				res []platform.Service
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				res, err = remote.AllServices(req.MaybeNamespace, req.Ignored)
			}
			n.enc.Publish(request.Reply, AllServicesResponse{res, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodSomeServices):
			var (
				req []flux.ServiceID
				res []platform.Service
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				res, err = remote.SomeServices(req)
			}
			n.enc.Publish(request.Reply, SomeServicesResponse{res, makeErrorResponse(err)})
		case strings.HasSuffix(request.Subject, methodApply):
			var (
				req []platform.ServiceDefinition
			)
			err = encoder.Decode(request.Subject, request.Data, &req)
			if err == nil {
				err = remote.Apply(req)
			}
			response := ApplyResponse{}
			switch applyErr := err.(type) {
			case platform.ApplyError:
				result := fluxrpc.ApplyResult{}
				for s, e := range applyErr {
					result[s] = e.Error()
				}
				response.Result = result
			default:
				response.ErrorResponse = makeErrorResponse(err)
			}
			n.enc.Publish(request.Reply, response)
		default:
			err = errors.New("unknown message: " + request.Subject)
		}
		if _, ok := err.(platform.FatalError); ok && err != nil {
			select {
			case errc <- err:
			default:
				// If the error channel is closed, it means that a
				// different RPC goroutine had a fatal error that
				// triggered the clean up and return of the parent
				// goroutine. It is likely that the error we have
				// encountered is due to the closure of the RPC
				// client whilst our request was still in progress
				// - don't panic.
			}
		}
	}

	go func() {
		for {
			select {
			// If both an error and a request are available, the runtime may
			// chose (by uniform pseudo-random selection) to process the
			// request first. This may seem like a problem, but even if we were
			// guaranteed to prefer the error channel there would still be a
			// race between selecting a request here and a failing goroutine
			// putting an error into the channel - it's an unavoidable
			// consequence of asynchronous request handling. The error will get
			// selected and handled soon enough.
			case err := <-errc:
				close(errc)
				sub.Unsubscribe()
				close(requests)
				done <- err
				return
			case request := <-requests:
				// Some of these operations (Apply in particular) can block for a long time;
				// dispatch in a goroutine and deliver any errors back to us so that we can
				// clean up on any hard failures.
				go processRequest(request)
			}
		}
	}()
}
<|endoftext|>


<commit_before>package randomword

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

const adjectives = `accountable
active
agile
anxious
appreciative
balanced
boisterous
bold
boring
brash
brave
bright
busy
chatty
cheerful
chipper
comedic
courteous
daring
delightful
empathic
excellent
exhausted
fantastic
fearless
fluent
forgiving
friendly
funny
generous
grateful
grouchy
grumpy
happy
hilarious
humble
impressive
insightful
intelligent
interested
kind
lean
nice
noisy
optimistic
patient
persistent
proud
quick
quiet
reflective
relaxed
reliable
responsible
responsive
rested
restless
shiny
shy
silly
sleepy
smart
spontaneous
surprised
sweet
talkative
terrific
thankful
timely
tired
turbulent
unexpected
wacky
wise
zany`

const nouns = `ardvark
aligator
antelope
baboon
badger
bandicoot
bat
bear
bilby
bongo
bonobo
buffalo
bushbuck
camel
cassowary
cat
cheetah
chimpanzee
chipmunk
civet
crane
crocodile
dingo
dog
dugong
duiker
echidna
eland
elephant
emu
fossa
fox
gazelle
gecko
gelada
genet
gerenuk
giraffe
gnu
gorilla
grysbok
hartebeest
hedgehog
hippopotamus
hyena
hyrax
impala
jackal
jaguar
kangaroo
klipspringer
koala
kob
kookaburra
kudu
lemur
leopard
lion
lizard
llama
lynx
manatee
mandrill
meerkat
mongoose
mouse
numbat
nyala
okapi
oribi
oryx
ostrich
otter
pangolin
panther
parrot
platypus
porcupine
possum
puku
quokka
quoll
rabbit
ratel
raven
reedbuck
rhinocerous
roan
sable
serval
shark
sitatunga
snake
springhare
squirrel
swan
tiger
topi
toucan
turtle
wallaby
warthog
waterbuck
wildebeest
wolf
wolverine
wombat
zebra`

type Generator struct{}

func (gen Generator) Babble() string {
	return fmt.Sprintf("%s-%s", gen.RandomAdjective(), gen.RandomNoun())
}

func (Generator) RandomAdjective() string {
	return randomElement(adjectives)
}

func (Generator) RandomNoun() string {
	return randomElement(nouns)
}

func randomElement(fullList string) string {
	rand.Seed(time.Now().UnixNano())
	wordList := strings.Split(fullList, "\n")
	randomWordIndex := rand.Int() % len(wordList)

	return wordList[randomWordIndex]
}
<commit_msg>Replace noun in random word generator list<commit_after>package randomword

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

const adjectives = `accountable
active
agile
anxious
appreciative
balanced
boisterous
bold
boring
brash
brave
bright
busy
chatty
cheerful
chipper
comedic
courteous
daring
delightful
empathic
excellent
exhausted
fantastic
fearless
fluent
forgiving
friendly
funny
generous
grateful
grouchy
grumpy
happy
hilarious
humble
impressive
insightful
intelligent
interested
kind
lean
nice
noisy
optimistic
patient
persistent
proud
quick
quiet
reflective
relaxed
reliable
responsible
responsive
rested
restless
shiny
shy
silly
sleepy
smart
spontaneous
surprised
sweet
talkative
terrific
thankful
timely
tired
turbulent
unexpected
wacky
wise
zany`

const nouns = `ardvark
aligator
antelope
baboon
badger
bandicoot
bat
bear
bilby
bongo
bonobo
buffalo
bushbuck
camel
cassowary
cat
cheetah
chimpanzee
chipmunk
civet
crane
crocodile
dingo
dog
dugong
duiker
echidna
eland
elephant
emu
fossa
fox
gazelle
gecko
gelada
genet
gerenuk
giraffe
gnu
gorilla
grysbok
hartebeest
hedgehog
hippopotamus
hyena
hyrax
impala
jackal
jaguar
kangaroo
klipspringer
koala
kob
kookaburra
kudu
lemur
leopard
lion
lizard
llama
lynx
manatee
mandrill
meerkat
mongoose
mouse
numbat
nyala
okapi
oribi
oryx
ostrich
otter
panda
pangolin
panther
parrot
platypus
porcupine
possum
puku
quokka
quoll
rabbit
ratel
raven
reedbuck
rhinocerous
roan
sable
serval
shark
sitatunga
springhare
squirrel
swan
tiger
topi
toucan
turtle
wallaby
warthog
waterbuck
wildebeest
wolf
wolverine
wombat
zebra`

type Generator struct{}

func (gen Generator) Babble() string {
	return fmt.Sprintf("%s-%s", gen.RandomAdjective(), gen.RandomNoun())
}

func (Generator) RandomAdjective() string {
	return randomElement(adjectives)
}

func (Generator) RandomNoun() string {
	return randomElement(nouns)
}

func randomElement(fullList string) string {
	rand.Seed(time.Now().UnixNano())
	wordList := strings.Split(fullList, "\n")
	randomWordIndex := rand.Int() % len(wordList)

	return wordList[randomWordIndex]
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
)

func init() {
	home := os.Getenv("HOME")
	if home == "" {
		panic("Cannot determine $HOME variable!")
	}
	f, err := os.Open(filepath.Join(home, ".gitlabclirc"))
	if err != nil {
		panic(err)
	}
	body, err := ioutil.ReadAll(f)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(body, &conf)
	if err != nil {
		panic(err)
	}
}

func CreateRepository(r string, extra *map[string]string) error {
	req, err := http.NewRequest("POST",
		fmt.Sprintf(conf.Endpoint+"projects?name=%s", r),
		nil,
	)
	c := http.Client{}
	if err != nil {
		return err
	}
	req.Header.Add("PRIVATE-TOKEN", conf.APIKey)
	if extra != nil {
		for k, v := range *extra {
			req.Header.Add(k, v)
		}
	}
	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(body))
	return nil
}

type ConfigFile struct {
	Endpoint string
	APIKey   string
}

var conf ConfigFile
var Create = flag.String("create", "", "The string of a repository to create")

func main() {
	flag.Parse()
	if *Create != "" {
		err := CreateRepository(*Create, nil)
		if err != nil {
			fmt.Println(err)
		}
	}
}
<commit_msg>Properly urlencode the additional parameters.<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

func init() {
	home := os.Getenv("HOME")
	if home == "" {
		panic("Cannot determine $HOME variable!")
	}
	f, err := os.Open(filepath.Join(home, ".gitlabclirc"))
	if err != nil {
		panic(err)
	}
	body, err := ioutil.ReadAll(f)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal(body, &conf)
	if err != nil {
		panic(err)
	}
}

func CreateRepository(r string, extra *map[string]string) error {
	path := fmt.Sprintf(conf.Endpoint+"projects?name=%s&", r)
	vals := url.Values{}
	if extra != nil {
		for k, v := range *extra {
			vals.Add(k, v)
		}
	}
	path = path + vals.Encode()
	req, err := http.NewRequest("POST",
		path,
		nil,
	)
	c := http.Client{}
	if err != nil {
		return err
	}
	req.Header.Add("PRIVATE-TOKEN", conf.APIKey)
	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(body))
	return nil
}

type ConfigFile struct {
	Endpoint string
	APIKey   string
}

var conf ConfigFile
var Create = flag.String("create", "", "The string of a repository to create")

func main() {
	flag.Parse()
	if *Create != "" {
		err := CreateRepository(*Create, nil)
		if err != nil {
			fmt.Println(err)
		}
	}
}
<|endoftext|>


<commit_before>package test

import (
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
	"time"

	"github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"

	etcdtest "github.com/coreos/etcd/tests"
	"github.com/coreos/etcd/server"
	goetcd "github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
)

type garbageHandler struct {
	t       *testing.T
	success bool
}

func (g *garbageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, client")
	println("HI")
	if r.URL.String() != "/v2/keys/_etcd/registry/1/node1" {
		g.t.Fatalf("Unexpected web request")
	}
	g.success = true
}

// TestDiscoveryDownNoBackupPeers ensures that etcd stops if it is started with a
// bad discovery URL and no backups.
func TestDiscoveryDownNoBackupPeers(t *testing.T) {
	g := garbageHandler{t: t}
	ts := httptest.NewServer(&g)
	defer ts.Close()

	discover := ts.URL + "/v2/keys/_etcd/registry/1"
	proc, err := startServer([]string{"-discovery", discover})

	if err != nil {
		t.Fatal(err.Error())
	}
	defer stopServer(proc)

	client := http.Client{}
	err = assertServerNotUp(client, "http")
	if err != nil {
		t.Fatal(err.Error())
	}

	if !g.success {
		t.Fatal("Discovery server never called")
	}
}

// TestDiscoveryDownWithBackupPeers ensures that etcd runs if it is started with a
// bad discovery URL and a peer list.
func TestDiscoveryDownWithBackupPeers(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		g := garbageHandler{t: t}
		ts := httptest.NewServer(&g)
		defer ts.Close()

		discover := ts.URL + "/v2/keys/_etcd/registry/1"
		u, ok := s.PeerURL("ETCDTEST")
		if !ok {
			t.Fatalf("Couldn't find the URL")
		}
		proc, err := startServer([]string{"-discovery", discover, "-peers", u})

		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerFunctional(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}

		if !g.success {
			t.Fatal("Discovery server never called")
		}
	})
}

// TestDiscoveryFirstPeer ensures that etcd starts as the leader if it
// registers as the first peer.
func TestDiscoveryFirstPeer(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerFunctional(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerFirstDown ensures that etcd stops if it is started with a
// correct discovery URL but no active machines are found.
func TestDiscoverySecondPeerFirstDown(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerNotUp(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerFirstNoResponse ensures that if the first etcd
// machine stops after heartbeating that the second machine fails too.
func TestDiscoverySecondPeerFirstNoResponse(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		v = url.Values{}
		v.Set("value", "http://127.0.0.1:49151")
		resp, err = etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/ETCDTEST"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-retry-interval", "0.2", "-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		// TODO(bp): etcd will take 30 seconds to shutdown, figure this
		// out instead
		time.Sleep(1 * time.Second)

		client := http.Client{}
		_, err = client.Get("/")
		if err != nil && strings.Contains(err.Error(), "connection reset by peer") {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerUp ensures that a second peer joining a discovery
// cluster works.
func TestDiscoverySecondPeerUp(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/3/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		u, ok := s.PeerURL("ETCDTEST")
		if !ok {
			t.Fatalf("Couldn't find the URL")
		}

		wc := goetcd.NewClient([]string{s.URL()})
		_, err = wc.Set("test", "0", 0)

		if err != nil {
			t.Fatalf("Couldn't set a test key on the leader %v", err)
		}

		receiver := make(chan *goetcd.Response)
		stop := make(chan bool)

		go wc.Watch("_etcd/registry/3/node1", 0, false, receiver, stop)

		v = url.Values{}
		v.Set("value", u)
		resp, err = etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/3/ETCDTEST"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/3"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		// Test to ensure the machine registered iteslf
		watchResp := <-receiver
		if watchResp.Node.Value != "http://127.0.0.1:7001" {
			t.Fatalf("Second peer didn't register! %s", watchResp.Node.Value)
		}

		// TODO(bp): need to have a better way of knowing a machine is up
		for i := 0; i < 10; i++ {
			time.Sleep(1 * time.Second)

			etcdc := goetcd.NewClient(nil)
			_, err = etcdc.Set("foobar", "baz", 0)
			if err == nil {
				break
			}
		}

		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

func assertServerNotUp(client http.Client, scheme string) error {
	path := fmt.Sprintf("%s://127.0.0.1:4001/v2/keys/foo", scheme)
	fields := url.Values(map[string][]string{"value": []string{"bar"}})

	for i := 0; i < 10; i++ {
		time.Sleep(1 * time.Second)

		_, err := client.PostForm(path, fields)
		if err == nil {
			return errors.New("Expected error during POST, got nil")
		} else {
			errString := err.Error()
			if strings.Contains(errString, "connection refused") {
				return nil
			} else {
				return err
			}
		}
	}

	return nil
}
<commit_msg>hack(tests/discovery): don't use go-etcd for watch<commit_after>package test

import (
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
	"time"

	"github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"

	etcdtest "github.com/coreos/etcd/tests"
	"github.com/coreos/etcd/server"
	goetcd "github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
)

type garbageHandler struct {
	t       *testing.T
	success bool
}

func (g *garbageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, client")
	println("HI")
	if r.URL.String() != "/v2/keys/_etcd/registry/1/node1" {
		g.t.Fatalf("Unexpected web request")
	}
	g.success = true
}

// TestDiscoveryDownNoBackupPeers ensures that etcd stops if it is started with a
// bad discovery URL and no backups.
func TestDiscoveryDownNoBackupPeers(t *testing.T) {
	g := garbageHandler{t: t}
	ts := httptest.NewServer(&g)
	defer ts.Close()

	discover := ts.URL + "/v2/keys/_etcd/registry/1"
	proc, err := startServer([]string{"-discovery", discover})

	if err != nil {
		t.Fatal(err.Error())
	}
	defer stopServer(proc)

	client := http.Client{}
	err = assertServerNotUp(client, "http")
	if err != nil {
		t.Fatal(err.Error())
	}

	if !g.success {
		t.Fatal("Discovery server never called")
	}
}

// TestDiscoveryDownWithBackupPeers ensures that etcd runs if it is started with a
// bad discovery URL and a peer list.
func TestDiscoveryDownWithBackupPeers(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		g := garbageHandler{t: t}
		ts := httptest.NewServer(&g)
		defer ts.Close()

		discover := ts.URL + "/v2/keys/_etcd/registry/1"
		u, ok := s.PeerURL("ETCDTEST")
		if !ok {
			t.Fatalf("Couldn't find the URL")
		}
		proc, err := startServer([]string{"-discovery", discover, "-peers", u})

		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerFunctional(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}

		if !g.success {
			t.Fatal("Discovery server never called")
		}
	})
}

// TestDiscoveryFirstPeer ensures that etcd starts as the leader if it
// registers as the first peer.
func TestDiscoveryFirstPeer(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerFunctional(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerFirstDown ensures that etcd stops if it is started with a
// correct discovery URL but no active machines are found.
func TestDiscoverySecondPeerFirstDown(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		client := http.Client{}
		err = assertServerNotUp(client, "http")
		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerFirstNoResponse ensures that if the first etcd
// machine stops after heartbeating that the second machine fails too.
func TestDiscoverySecondPeerFirstNoResponse(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		v = url.Values{}
		v.Set("value", "http://127.0.0.1:49151")
		resp, err = etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/2/ETCDTEST"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-retry-interval", "0.2", "-discovery", s.URL() + "/v2/keys/_etcd/registry/2"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		// TODO(bp): etcd will take 30 seconds to shutdown, figure this
		// out instead
		time.Sleep(1 * time.Second)

		client := http.Client{}
		_, err = client.Get("/")
		if err != nil && strings.Contains(err.Error(), "connection reset by peer") {
			t.Fatal(err.Error())
		}
	})
}

// TestDiscoverySecondPeerUp ensures that a second peer joining a discovery
// cluster works.
func TestDiscoverySecondPeerUp(t *testing.T) {
	etcdtest.RunServer(func(s *server.Server) {
		v := url.Values{}
		v.Set("value", "started")
		resp, err := etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/3/_state"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		u, ok := s.PeerURL("ETCDTEST")
		if !ok {
			t.Fatalf("Couldn't find the URL")
		}

		wc := goetcd.NewClient([]string{s.URL()})
		testResp, err := wc.Set("test", "0", 0)

		if err != nil {
			t.Fatalf("Couldn't set a test key on the leader %v", err)
		}

		v = url.Values{}
		v.Set("value", u)
		resp, err = etcdtest.PutForm(fmt.Sprintf("%s%s", s.URL(), "/v2/keys/_etcd/registry/3/ETCDTEST"), v)
		assert.Equal(t, resp.StatusCode, http.StatusCreated)

		proc, err := startServer([]string{"-discovery", s.URL() + "/v2/keys/_etcd/registry/3"})
		if err != nil {
			t.Fatal(err.Error())
		}
		defer stopServer(proc)

		watch := fmt.Sprintf("%s%s%d", s.URL(), "/v2/keys/_etcd/registry/3/node1?wait=true&waitIndex=", testResp.EtcdIndex)
		resp, err = http.Get(watch)
		if err != nil {
			t.Fatal(err.Error())
		}

		// TODO(bp): need to have a better way of knowing a machine is up
		for i := 0; i < 10; i++ {
			time.Sleep(1 * time.Second)

			etcdc := goetcd.NewClient(nil)
			_, err = etcdc.Set("foobar", "baz", 0)
			if err == nil {
				break
			}
		}

		if err != nil {
			t.Fatal(err.Error())
		}
	})
}

func assertServerNotUp(client http.Client, scheme string) error {
	path := fmt.Sprintf("%s://127.0.0.1:4001/v2/keys/foo", scheme)
	fields := url.Values(map[string][]string{"value": []string{"bar"}})

	for i := 0; i < 10; i++ {
		time.Sleep(1 * time.Second)

		_, err := client.PostForm(path, fields)
		if err == nil {
			return errors.New("Expected error during POST, got nil")
		} else {
			errString := err.Error()
			if strings.Contains(errString, "connection refused") {
				return nil
			} else {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/pressly/chi"
	"net/http"
	"os"
	"bufio"
	"fmt"
	"strings"
	"io"
	"time"
	"html/template"
	"io/ioutil"
	"flag"
	"log"
	"strconv"
)

var (
	usernameFlag *string
	passwordFlag *string
)

func main() {
	r := chi.NewRouter()

	r.With(basicAuth).Get("/", showFiles)
	r.With(basicAuth).Get("/*", showFiles)
	r.With(statusCodeHandler).Post("/", handlePost)
	r.With(statusCodeHandler).Post("/*", handlePost)

	port := flag.String("port", "80", "Specifies the port to listen for incoming connections")
	useTls := flag.Bool("tls", false, "Tells gobble to listen for secure connections (ie. https)")
	tlsPort := flag.String("tlsPort", "443", "Specifies the port to listen for incoming secure connections")
	tlsCert := flag.String("tlsCert", "cert.pem", "Specifies the path to the x509 certificate")
	tlsKey := flag.String("tlsKey", "key.pem", "Specifies the path to the private key corresponding to the x509 certificate")
	usernameFlag = flag.String("username", "", "Specify a username to protect againt unauthorized reading of your requests")
	passwordFlag = flag.String("password", "", "Specify a password to protect against unauthorized reading of your requests")

	homeDir := flag.String("dir", "public", "Specifies the root directory which all directories and requests will be stored under")
	flag.Parse()

	err := os.MkdirAll(*homeDir, 0644)
	if err != nil {
		panic("unable to create dir")
	}
	os.Chdir(*homeDir)

	if *useTls == true {
		go func(tlsPort *string, tlsCert *string, tlsKey *string) {
			log.Println("Starting secure server on port " + *tlsPort)
			log.Fatal(http.ListenAndServeTLS(":" + *tlsPort, *tlsCert, *tlsKey, r))
		}(tlsPort, tlsCert, tlsKey)
	}

	log.Println("Starting server on port " + *port)
	log.Fatal(http.ListenAndServe(":" + *port, r))
}

func showFiles(w http.ResponseWriter, r *http.Request) {

	t := template.Must(template.New("index").Parse(`{{define "index"}}
		{{range .Files}}
		{{.Name}}

		{{end}}
		{{end}}`))

	path := chi.URLParam(r, "*")

	if info, err := os.Stat("./" + path); err == nil {
		if info.IsDir() {
			files, err := ioutil.ReadDir("./" + path)
			if err != nil {
				panic("Unable to read directory")
			}

			templData := struct {
				Path  string
				Files []os.FileInfo
			}{
				info.Name(),
				files,
			}

			t.Execute(w, templData)
		} else {
			f, _ := ioutil.ReadFile(path)
			w.Write(f)
		}
	} else {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
	}
}

func handlePost(w http.ResponseWriter, r *http.Request) {
	t := time.Now()
	dir := r.URL.Query().Get("dir")
	if dir != "" {
		//Make sure the requested directory is around
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	} else {
		//No directory requested so we give them the default
		dir = t.Format("2006-01-02")
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	}

	//Create file which is named after the create time
	fo, err := os.Create("./" + dir + "/" + t.Format("15.04.05.0000"))
	if err != nil {
		panic(err)
	}
	// close fo on exit and check for its returned error
	defer func() {
		if err := fo.Close(); err != nil {
			panic(err)
		}
	}()

	writer := bufio.NewWriter(fo)
	defer writer.Flush()

	//Write headers to file
	for k, v := range r.Header {
		fmt.Fprintln(writer, k + ":", strings.Join(v, ","))
	}

	fmt.Fprintln(writer)
	//Write request body to file
	io.Copy(writer, r.Body)
	w.Write([]byte(fo.Name()[1:]))
}

func statusCodeHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Query().Get("status_code") != "" {
			status, err := strconv.Atoi(r.URL.Query().Get("status_code"))
			if err == nil {
				w.WriteHeader(status)
			} else {
				log.Println("Invalid number in status_code field")
			}
		}
		next.ServeHTTP(w, r)
	})
}

func basicAuth(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		username, password, _ := r.BasicAuth()

		//If no auth was set up then we just serve the page
		if *usernameFlag == "" || *passwordFlag == "" {
			h.ServeHTTP(w, r)
			return
		}

		//Auth was configured so we check to make sure the user has the correct credentials
		if username != *usernameFlag || password != *passwordFlag {
			w.Header().Add("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Not Authorized", http.StatusUnauthorized)
			return
		}
		h.ServeHTTP(w, r)
	})
}<commit_msg>Formatting<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/pressly/chi"
)

var (
	usernameFlag *string
	passwordFlag *string
)

func main() {
	r := chi.NewRouter()

	r.With(basicAuth).Get("/", showFiles)
	r.With(basicAuth).Get("/*", showFiles)
	r.With(statusCodeHandler).Post("/", handlePost)
	r.With(statusCodeHandler).Post("/*", handlePost)

	port := flag.String("port", "80", "Specifies the port to listen for incoming connections")
	useTls := flag.Bool("tls", false, "Tells gobble to listen for secure connections (ie. https)")
	tlsPort := flag.String("tlsPort", "443", "Specifies the port to listen for incoming secure connections")
	tlsCert := flag.String("tlsCert", "cert.pem", "Specifies the path to the x509 certificate")
	tlsKey := flag.String("tlsKey", "key.pem", "Specifies the path to the private key corresponding to the x509 certificate")
	usernameFlag = flag.String("username", "", "Specify a username to protect againt unauthorized reading of your requests")
	passwordFlag = flag.String("password", "", "Specify a password to protect against unauthorized reading of your requests")

	homeDir := flag.String("dir", "public", "Specifies the root directory which all directories and requests will be stored under")
	flag.Parse()

	err := os.MkdirAll(*homeDir, 0644)
	if err != nil {
		panic("unable to create dir")
	}
	os.Chdir(*homeDir)

	if *useTls == true {
		go func(tlsPort *string, tlsCert *string, tlsKey *string) {
			log.Println("Starting secure server on port " + *tlsPort)
			log.Fatal(http.ListenAndServeTLS(":" + *tlsPort, *tlsCert, *tlsKey, r))
		}(tlsPort, tlsCert, tlsKey)
	}

	log.Println("Starting server on port " + *port)
	log.Fatal(http.ListenAndServe(":" + *port, r))
}

func showFiles(w http.ResponseWriter, r *http.Request) {

	t := template.Must(template.New("index").Parse(`{{define "index"}}
		{{range .Files}}
		{{.Name}}

		{{end}}
		{{end}}`))

	path := chi.URLParam(r, "*")

	if info, err := os.Stat("./" + path); err == nil {
		if info.IsDir() {
			files, err := ioutil.ReadDir("./" + path)
			if err != nil {
				panic("Unable to read directory")
			}

			templData := struct {
				Path  string
				Files []os.FileInfo
			}{
				info.Name(),
				files,
			}

			t.Execute(w, templData)
		} else {
			f, _ := ioutil.ReadFile(path)
			w.Write(f)
		}
	} else {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
	}
}

func handlePost(w http.ResponseWriter, r *http.Request) {
	t := time.Now()
	dir := r.URL.Query().Get("dir")
	if dir != "" {
		//Make sure the requested directory is around
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	} else {
		//No directory requested so we give them the default
		dir = t.Format("2006-01-02")
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	}

	//Create file which is named after the create time
	fo, err := os.Create("./" + dir + "/" + t.Format("15.04.05.0000"))
	if err != nil {
		panic(err)
	}
	// close fo on exit and check for its returned error
	defer func() {
		if err := fo.Close(); err != nil {
			panic(err)
		}
	}()

	writer := bufio.NewWriter(fo)
	defer writer.Flush()

	//Write headers to file
	for k, v := range r.Header {
		fmt.Fprintln(writer, k+":", strings.Join(v, ","))
	}

	fmt.Fprintln(writer)
	//Write request body to file
	io.Copy(writer, r.Body)
	w.Write([]byte(fo.Name()[1:]))
}

func statusCodeHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Query().Get("status_code") != "" {
			status, err := strconv.Atoi(r.URL.Query().Get("status_code"))
			if err == nil {
				w.WriteHeader(status)
			} else {
				log.Println("Invalid number in status_code field")
			}
		}
		next.ServeHTTP(w, r)
	})
}

func basicAuth(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		username, password, _ := r.BasicAuth()

		//If no auth was set up then we just serve the page
		if *usernameFlag == "" || *passwordFlag == "" {
			h.ServeHTTP(w, r)
			return
		}

		//Auth was configured so we check to make sure the user has the correct credentials
		if username != *usernameFlag || password != *passwordFlag {
			w.Header().Add("WWW-Authenticate", `Basic realm="Restricted"`)
			http.Error(w, "Not Authorized", http.StatusUnauthorized)
			return
		}
		h.ServeHTTP(w, r)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/BluntSporks/calculation"
	"github.com/BluntSporks/readability"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	// Check arguments.
	if len(os.Args) == 1 {
		log.Fatal("Missing filename argument")
	}

	bytes, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	text := string(bytes)

	// Score ARI.
	ariScore := read.Ari(text)
	fmt.Printf("Automated Readability: %0.2f\n", ariScore)

	// Score CLI.
	cliScore := read.Cli(text)
	fmt.Printf("Coleman-Liau: %0.2f\n", cliScore)

	// Score Flesch-Kincaid.
	fkScore := read.Fk(text)
	fmt.Printf("Flesch-Kincaid: %0.2f\n", fkScore)

	// Score Gunning fog.
	gfiScore := read.Gfi(text)
	fmt.Printf("Gunning fog: %0.2f\n", gfiScore)

	// Score SMOG.
	smogScore := read.Smog(text)
	fmt.Printf("SMOG: %0.2f\n", smogScore)

	// Yield average score.
	values := []float64{ariScore, cliScore, fkScore, gfiScore, smogScore}
	avg := calc.Mean(values)
	fmt.Printf("Average score: %0.2f\n", avg)
}
<commit_msg>Adding sorted score list and std dev<commit_after>package main

import (
	"fmt"
	"github.com/BluntSporks/calculation"
	"github.com/BluntSporks/readability"
	"io/ioutil"
	"log"
	"os"
	"sort"
)

func main() {
	// Check arguments.
	if len(os.Args) == 1 {
		log.Fatal("Missing filename argument")
	}

	bytes, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	text := string(bytes)

	// Score ARI.
	ariScore := read.Ari(text)
	fmt.Printf("Automated Readability: %0.2f\n", ariScore)

	// Score CLI.
	cliScore := read.Cli(text)
	fmt.Printf("Coleman-Liau: %0.2f\n", cliScore)

	// Score Flesch-Kincaid.
	fkScore := read.Fk(text)
	fmt.Printf("Flesch-Kincaid: %0.2f\n", fkScore)

	// Score Gunning fog.
	gfiScore := read.Gfi(text)
	fmt.Printf("Gunning fog: %0.2f\n", gfiScore)

	// Score SMOG.
	smogScore := read.Smog(text)
	fmt.Printf("SMOG: %0.2f\n", smogScore)

	// Yield average score.
	values := []float64{ariScore, cliScore, fkScore, gfiScore, smogScore}
	sort.Float64s(values)
	avg := calc.Mean(values)
	stddev := calc.StdDev(values)
	fmt.Printf("Sorted scores: [%0.2f, %0.2f, %0.2f, %0.2f, %0.2f]\n", values[0], values[1], values[2], values[3], values[4])
	fmt.Printf("Average score: %0.2f\n", avg)
	fmt.Printf("Std Dev of scores: %0.2f\n", stddev)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"net/rpc"
	"os"
	"path/filepath"
	"strconv"
	"time"
	"unicode/utf8"
)

var (
	server = flag.Bool("s", false, "run a server instead of a client")
	format = flag.String("f", "nice", "output format (vim | emacs | nice | csv | json)")
	input  = flag.String("in", "", "use this file instead of stdin input")
	sock   = CreateSockFlag("sock", "socket type (unix | tcp)")
	addr   = flag.String("addr", "localhost:37373", "address for tcp socket")
)

// TODO: find a better place for this function
// returns truncated 'data' and amount of bytes skipped (for cursor pos adjustment)
func filterOutShebang(data []byte) ([]byte, int) {
	if len(data) > 2 && data[0] == '#' && data[1] == '!' {
		newline := bytes.Index(data, []byte("\n"))
		if newline != -1 && len(data) > newline+1 {
			return data[newline+1:], newline + 1
		}
	}
	return data, 0
}

//-------------------------------------------------------------------------
// Formatter interfaces
//-------------------------------------------------------------------------

type Formatter interface {
	WriteEmpty()
	WriteCandidates(names, types, classes []string, num int)
}

//-------------------------------------------------------------------------
// NiceFormatter (just for testing, simple textual output)
//-------------------------------------------------------------------------

type NiceFormatter struct{}

func (*NiceFormatter) WriteEmpty() {
	fmt.Printf("Nothing to complete.\n")
}

func (*NiceFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf("Found %d candidates:\n", len(names))
	for i := 0; i < len(names); i++ {
		abbr := fmt.Sprintf("%s %s %s", classes[i], names[i], types[i])
		if classes[i] == "func" {
			abbr = fmt.Sprintf("%s %s%s", classes[i], names[i], types[i][len("func"):])
		}
		fmt.Printf("  %s\n", abbr)
	}
}

//-------------------------------------------------------------------------
// VimFormatter
//-------------------------------------------------------------------------

type VimFormatter struct{}

func (*VimFormatter) WriteEmpty() {
	fmt.Print("[0, []]")
}

func (*VimFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf("[%d, [", num)
	for i := 0; i < len(names); i++ {
		word := names[i]
		if classes[i] == "func" {
			word += "("
			if len(types[i]) == 6 {
				word += ")"
			}
		}

		abbr := fmt.Sprintf("%s %s %s", classes[i], names[i], types[i])
		if classes[i] == "func" {
			abbr = fmt.Sprintf("%s %s%s", classes[i], names[i], types[i][len("func"):])
		}
		fmt.Printf("{'word': '%s', 'abbr': '%s'}", word, abbr)
		if i != len(names)-1 {
			fmt.Printf(", ")
		}

	}
	fmt.Printf("]]")
}

//-------------------------------------------------------------------------
// EmacsFormatter
//-------------------------------------------------------------------------

type EmacsFormatter struct{}

func (*EmacsFormatter) WriteEmpty() {
}

func (*EmacsFormatter) WriteCandidates(names, types, classes []string, num int) {
	for i := 0; i < len(names); i++ {
		name := names[i]
		hint := classes[i] + " " + types[i]
		if classes[i] == "func" {
			hint = types[i]
		}
		fmt.Printf("%s,,%s\n", name, hint)
	}
}

//-------------------------------------------------------------------------
// CSVFormatter
//-------------------------------------------------------------------------

type CSVFormatter struct{}

func (*CSVFormatter) WriteEmpty() {
}

func (*CSVFormatter) WriteCandidates(names, types, classes []string, num int) {
	for i := 0; i < len(names); i++ {
		fmt.Printf("%s,,%s,,%s\n", classes[i], names[i], types[i])
	}
}

//-------------------------------------------------------------------------
// JSONFormatter
//-------------------------------------------------------------------------

type JSONFormatter struct{}

func (*JSONFormatter) WriteEmpty() {
	fmt.Print("[]")
}

func (*JSONFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf(`[%d, [`, num)
	for i := 0; i < len(names); i++ {
		fmt.Printf(`{"class": "%s", "name": "%s", "type": "%s"}`,
			classes[i], names[i], types[i])
		if i != len(names)-1 {
			fmt.Printf(", ")
		}
	}
	fmt.Print("]]")
}

//-------------------------------------------------------------------------

func getFormatter() Formatter {
	switch *format {
	case "vim":
		return new(VimFormatter)
	case "emacs":
		return new(EmacsFormatter)
	case "nice":
		return new(NiceFormatter)
	case "csv":
		return new(CSVFormatter)
	case "json":
		return new(JSONFormatter)
	}
	return new(VimFormatter)
}

func getSocketFilename() string {
	user := os.Getenv("USER")
	if user == "" {
		user = "all"
	}
	return fmt.Sprintf("%s/acrserver.%s", os.TempDir(), user)
}

func fileExists(filename string) bool {
	_, err := os.Stat(filename)
	if err != nil {
		return false
	}
	return true
}

func serverFunc() int {
	readConfig(&Config)

	addr := *addr
	if *sock == "unix" {
		addr = getSocketFilename()
		if fileExists(addr) {
			fmt.Printf("unix socket: '%s' already exists\n", addr)
			return 1
		}
	}
	daemon = NewDaemon(*sock, addr)
	if *sock == "unix" {
		// cleanup unix socket file
		defer os.Remove(addr)
	}

	rpcremote := new(RPCRemote)
	rpc.Register(rpcremote)

	daemon.acr.Loop()
	return 0
}

func cmdStatus(c *rpc.Client) {
	fmt.Printf("%s\n", Client_Status(c, 0))
}

func cmdAutoComplete(c *rpc.Client) {
	var file []byte
	var err error

	if *input != "" {
		file, err = ioutil.ReadFile(*input)
	} else {
		file, err = ioutil.ReadAll(os.Stdin)
	}

	if err != nil {
		panic(err.Error())
	}

	var skipped int
	file, skipped = filterOutShebang(file)

	filename := *input
	cursor := -1

	offset := ""
	switch flag.NArg() {
	case 2:
		offset = flag.Arg(1)
	case 3:
		filename = flag.Arg(1) // Override default filename
		offset = flag.Arg(2)
	}

	if offset != "" {
		if offset[0] == 'c' || offset[0] == 'C' {
			cursor, _ = strconv.Atoi(offset[1:])
			cursor = charToByteOffset(file, cursor)
		} else {
			cursor, _ = strconv.Atoi(offset)
		}
	}

	cursor -= skipped
	if filename != "" && !filepath.IsAbs(filename) {
		cwd, _ := os.Getwd()
		filename = filepath.Join(cwd, filename)
	}

	formatter := getFormatter()
	names, types, classes, partial := Client_AutoComplete(c, file, filename, cursor)
	if names == nil {
		formatter.WriteEmpty()
		return
	}
	formatter.WriteCandidates(names, types, classes, partial)
}

func cmdClose(c *rpc.Client) {
	Client_Close(c, 0)
}

func cmdDropCache(c *rpc.Client) {
	Client_DropCache(c, 0)
}

func cmdSet(c *rpc.Client) {
	switch flag.NArg() {
	case 1:
		fmt.Print(Client_Set(c, "\x00", "\x00"))
	case 2:
		fmt.Print(Client_Set(c, flag.Arg(1), "\x00"))
	case 3:
		fmt.Print(Client_Set(c, flag.Arg(1), flag.Arg(2)))
	}
}

func tryRunServer() error {
	path := GetExecutableFileName()

	args := []string{os.Args[0], "-s", "-sock", *sock, "-addr", *addr}
	cwd, _ := os.Getwd()
	procattr := os.ProcAttr{Dir: cwd, Env: os.Environ(), Files: []*os.File{nil, nil, nil}}
	p, err := os.StartProcess(path, args, &procattr)

	if err != nil {
		return err
	}
	return p.Release()
}

func tryToConnect(network, address string) (client *rpc.Client, err error) {
	t := 0
	for {
		client, err = rpc.Dial(network, address)
		if err != nil && t < 1000 {
			time.Sleep(10e6) // wait 10 milliseconds
			t += 10
			continue
		}
		break
	}

	return
}

func clientFunc() int {
	addr := *addr
	if *sock == "unix" {
		addr = getSocketFilename()
	}

	// client
	client, err := rpc.Dial(*sock, addr)
	if err != nil {
		err = tryRunServer()
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			return 1
		}
		client, err = tryToConnect(*sock, addr)
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			return 1
		}
	}
	defer client.Close()

	if flag.NArg() > 0 {
		switch flag.Arg(0) {
		case "autocomplete":
			cmdAutoComplete(client)
		case "close":
			cmdClose(client)
		case "status":
			cmdStatus(client)
		case "drop-cache":
			cmdDropCache(client)
		case "set":
			cmdSet(client)
		}
	}
	return 0
}

func charToByteOffset(s []byte, offsetC int) (offsetB int) {
	for offsetB = 0; offsetC > 0 && offsetB < len(s); offsetB++ {
		if utf8.RuneStart(s[offsetB]) {
			offsetC--
		}
	}
	return offsetB
}

func main() {
	flag.Parse()

	var retval int
	if *server {
		retval = serverFunc()
	} else {
		retval = clientFunc()
	}
	os.Exit(retval)
}
<commit_msg>fix emission of closing parens<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"net/rpc"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

var (
	server = flag.Bool("s", false, "run a server instead of a client")
	format = flag.String("f", "nice", "output format (vim | emacs | nice | csv | json)")
	input  = flag.String("in", "", "use this file instead of stdin input")
	sock   = CreateSockFlag("sock", "socket type (unix | tcp)")
	addr   = flag.String("addr", "localhost:37373", "address for tcp socket")
)

// TODO: find a better place for this function
// returns truncated 'data' and amount of bytes skipped (for cursor pos adjustment)
func filterOutShebang(data []byte) ([]byte, int) {
	if len(data) > 2 && data[0] == '#' && data[1] == '!' {
		newline := bytes.Index(data, []byte("\n"))
		if newline != -1 && len(data) > newline+1 {
			return data[newline+1:], newline + 1
		}
	}
	return data, 0
}

//-------------------------------------------------------------------------
// Formatter interfaces
//-------------------------------------------------------------------------

type Formatter interface {
	WriteEmpty()
	WriteCandidates(names, types, classes []string, num int)
}

//-------------------------------------------------------------------------
// NiceFormatter (just for testing, simple textual output)
//-------------------------------------------------------------------------

type NiceFormatter struct{}

func (*NiceFormatter) WriteEmpty() {
	fmt.Printf("Nothing to complete.\n")
}

func (*NiceFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf("Found %d candidates:\n", len(names))
	for i := 0; i < len(names); i++ {
		abbr := fmt.Sprintf("%s %s %s", classes[i], names[i], types[i])
		if classes[i] == "func" {
			abbr = fmt.Sprintf("%s %s%s", classes[i], names[i], types[i][len("func"):])
		}
		fmt.Printf("  %s\n", abbr)
	}
}

//-------------------------------------------------------------------------
// VimFormatter
//-------------------------------------------------------------------------

type VimFormatter struct{}

func (*VimFormatter) WriteEmpty() {
	fmt.Print("[0, []]")
}

func (*VimFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf("[%d, [", num)
	for i := 0; i < len(names); i++ {
		word := names[i]
		if classes[i] == "func" {
			word += "("
			if strings.HasPrefix(types[i], "func()") {
				word += ")"
			}
		}

		abbr := fmt.Sprintf("%s %s %s", classes[i], names[i], types[i])
		if classes[i] == "func" {
			abbr = fmt.Sprintf("%s %s%s", classes[i], names[i], types[i][len("func"):])
		}
		fmt.Printf("{'word': '%s', 'abbr': '%s'}", word, abbr)
		if i != len(names)-1 {
			fmt.Printf(", ")
		}

	}
	fmt.Printf("]]")
}

//-------------------------------------------------------------------------
// EmacsFormatter
//-------------------------------------------------------------------------

type EmacsFormatter struct{}

func (*EmacsFormatter) WriteEmpty() {
}

func (*EmacsFormatter) WriteCandidates(names, types, classes []string, num int) {
	for i := 0; i < len(names); i++ {
		name := names[i]
		hint := classes[i] + " " + types[i]
		if classes[i] == "func" {
			hint = types[i]
		}
		fmt.Printf("%s,,%s\n", name, hint)
	}
}

//-------------------------------------------------------------------------
// CSVFormatter
//-------------------------------------------------------------------------

type CSVFormatter struct{}

func (*CSVFormatter) WriteEmpty() {
}

func (*CSVFormatter) WriteCandidates(names, types, classes []string, num int) {
	for i := 0; i < len(names); i++ {
		fmt.Printf("%s,,%s,,%s\n", classes[i], names[i], types[i])
	}
}

//-------------------------------------------------------------------------
// JSONFormatter
//-------------------------------------------------------------------------

type JSONFormatter struct{}

func (*JSONFormatter) WriteEmpty() {
	fmt.Print("[]")
}

func (*JSONFormatter) WriteCandidates(names, types, classes []string, num int) {
	fmt.Printf(`[%d, [`, num)
	for i := 0; i < len(names); i++ {
		fmt.Printf(`{"class": "%s", "name": "%s", "type": "%s"}`,
			classes[i], names[i], types[i])
		if i != len(names)-1 {
			fmt.Printf(", ")
		}
	}
	fmt.Print("]]")
}

//-------------------------------------------------------------------------

func getFormatter() Formatter {
	switch *format {
	case "vim":
		return new(VimFormatter)
	case "emacs":
		return new(EmacsFormatter)
	case "nice":
		return new(NiceFormatter)
	case "csv":
		return new(CSVFormatter)
	case "json":
		return new(JSONFormatter)
	}
	return new(VimFormatter)
}

func getSocketFilename() string {
	user := os.Getenv("USER")
	if user == "" {
		user = "all"
	}
	return fmt.Sprintf("%s/acrserver.%s", os.TempDir(), user)
}

func fileExists(filename string) bool {
	_, err := os.Stat(filename)
	if err != nil {
		return false
	}
	return true
}

func serverFunc() int {
	readConfig(&Config)

	addr := *addr
	if *sock == "unix" {
		addr = getSocketFilename()
		if fileExists(addr) {
			fmt.Printf("unix socket: '%s' already exists\n", addr)
			return 1
		}
	}
	daemon = NewDaemon(*sock, addr)
	if *sock == "unix" {
		// cleanup unix socket file
		defer os.Remove(addr)
	}

	rpcremote := new(RPCRemote)
	rpc.Register(rpcremote)

	daemon.acr.Loop()
	return 0
}

func cmdStatus(c *rpc.Client) {
	fmt.Printf("%s\n", Client_Status(c, 0))
}

func cmdAutoComplete(c *rpc.Client) {
	var file []byte
	var err error

	if *input != "" {
		file, err = ioutil.ReadFile(*input)
	} else {
		file, err = ioutil.ReadAll(os.Stdin)
	}

	if err != nil {
		panic(err.Error())
	}

	var skipped int
	file, skipped = filterOutShebang(file)

	filename := *input
	cursor := -1

	offset := ""
	switch flag.NArg() {
	case 2:
		offset = flag.Arg(1)
	case 3:
		filename = flag.Arg(1) // Override default filename
		offset = flag.Arg(2)
	}

	if offset != "" {
		if offset[0] == 'c' || offset[0] == 'C' {
			cursor, _ = strconv.Atoi(offset[1:])
			cursor = charToByteOffset(file, cursor)
		} else {
			cursor, _ = strconv.Atoi(offset)
		}
	}

	cursor -= skipped
	if filename != "" && !filepath.IsAbs(filename) {
		cwd, _ := os.Getwd()
		filename = filepath.Join(cwd, filename)
	}

	formatter := getFormatter()
	names, types, classes, partial := Client_AutoComplete(c, file, filename, cursor)
	if names == nil {
		formatter.WriteEmpty()
		return
	}
	formatter.WriteCandidates(names, types, classes, partial)
}

func cmdClose(c *rpc.Client) {
	Client_Close(c, 0)
}

func cmdDropCache(c *rpc.Client) {
	Client_DropCache(c, 0)
}

func cmdSet(c *rpc.Client) {
	switch flag.NArg() {
	case 1:
		fmt.Print(Client_Set(c, "\x00", "\x00"))
	case 2:
		fmt.Print(Client_Set(c, flag.Arg(1), "\x00"))
	case 3:
		fmt.Print(Client_Set(c, flag.Arg(1), flag.Arg(2)))
	}
}

func tryRunServer() error {
	path := GetExecutableFileName()

	args := []string{os.Args[0], "-s", "-sock", *sock, "-addr", *addr}
	cwd, _ := os.Getwd()
	procattr := os.ProcAttr{Dir: cwd, Env: os.Environ(), Files: []*os.File{nil, nil, nil}}
	p, err := os.StartProcess(path, args, &procattr)

	if err != nil {
		return err
	}
	return p.Release()
}

func tryToConnect(network, address string) (client *rpc.Client, err error) {
	t := 0
	for {
		client, err = rpc.Dial(network, address)
		if err != nil && t < 1000 {
			time.Sleep(10e6) // wait 10 milliseconds
			t += 10
			continue
		}
		break
	}

	return
}

func clientFunc() int {
	addr := *addr
	if *sock == "unix" {
		addr = getSocketFilename()
	}

	// client
	client, err := rpc.Dial(*sock, addr)
	if err != nil {
		err = tryRunServer()
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			return 1
		}
		client, err = tryToConnect(*sock, addr)
		if err != nil {
			fmt.Printf("%s\n", err.Error())
			return 1
		}
	}
	defer client.Close()

	if flag.NArg() > 0 {
		switch flag.Arg(0) {
		case "autocomplete":
			cmdAutoComplete(client)
		case "close":
			cmdClose(client)
		case "status":
			cmdStatus(client)
		case "drop-cache":
			cmdDropCache(client)
		case "set":
			cmdSet(client)
		}
	}
	return 0
}

func charToByteOffset(s []byte, offsetC int) (offsetB int) {
	for offsetB = 0; offsetC > 0 && offsetB < len(s); offsetB++ {
		if utf8.RuneStart(s[offsetB]) {
			offsetC--
		}
	}
	return offsetB
}

func main() {
	flag.Parse()

	var retval int
	if *server {
		retval = serverFunc()
	} else {
		retval = clientFunc()
	}
	os.Exit(retval)
}
<|endoftext|>


<commit_before>package brimutil

import (
	"math/rand"
	"time"
)

type Scrambled struct {
	r rand.Source
}

func NewScrambled() *Scrambled {
	return NewSeededScrambled(time.Now().UnixNano())
}

func NewSeededScrambled(seed int64) *Scrambled {
	return &Scrambled{r: rand.NewSource(seed)}
}

func (s *Scrambled) Read(bs []byte) {
	for i := len(bs) - 1; i >= 0; {
		v := s.r.Int63()
		for j := 7; i >= 0 && j >= 0; j-- {
			bs[i] = byte(v)
			i--
			v >>= 8
		}
	}
}
<commit_msg>Fixed off by 1 error<commit_after>package brimutil

import (
	"math/rand"
	"time"
)

type Scrambled struct {
	r rand.Source
}

func NewScrambled() *Scrambled {
	return NewSeededScrambled(time.Now().UnixNano())
}

func NewSeededScrambled(seed int64) *Scrambled {
	return &Scrambled{r: rand.NewSource(seed)}
}

func (s *Scrambled) Read(bs []byte) {
	for i := len(bs) - 1; i >= 0; {
		v := s.r.Int63()
		for j := 6; i >= 0 && j >= 0; j-- {
			bs[i] = byte(v)
			i--
			v >>= 8
		}
	}
}
<|endoftext|>


<commit_before>package socialauth

import (
	"errors"
	"fmt"
)

// The GoogleAuthProvider validates the token against the google api
type GoogleAuthProvider struct {
	validator *GoogleTokenValidator
}

// The config must contain a the "appClientId" key with the value
// for your project that can be found in your Google API's Dashboard
// https://developers.google.com/identity/protocols/OAuth2
func newGoogleAuthProvider(config map[string]string) *GoogleAuthProvider {
	return &GoogleAuthProvider{
		validator: NewGoogleTokenValidator(config["appClientId"]),
	}
}

// VerifyToken verifies the given token against the server's provider (Facebook, Google...)
// And returns the user ID or an error
func (p *GoogleAuthProvider) VerifyToken(userToken string) (string, error) {
	userID, err := p.validator.Validate(userToken)

	if err != nil {
		fmt.Println("Invalid Token!", err)
		return "", errors.New("Authentication failed.")
	}

	return userID, nil
}
<commit_msg>The provider should return the same error it got<commit_after>package socialauth

// The GoogleAuthProvider validates the token against the google api
type GoogleAuthProvider struct {
	validator *GoogleTokenValidator
}

// The config must contain a the "appClientId" key with the value
// for your project that can be found in your Google API's Dashboard
// https://developers.google.com/identity/protocols/OAuth2
func newGoogleAuthProvider(config map[string]string) *GoogleAuthProvider {
	return &GoogleAuthProvider{
		validator: NewGoogleTokenValidator(config["appClientId"]),
	}
}

// VerifyToken verifies the given token against the server's provider (Facebook, Google...)
// And returns the user ID or an error
func (p *GoogleAuthProvider) VerifyToken(userToken string) (string, error) {
	userID, err := p.validator.Validate(userToken)

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

	return userID, nil
}
<|endoftext|>


<commit_before>// Package darkstat implements a plugin to see stats from darkstat.
package darkstat

import (
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/StalkR/goircbot/bot"
	"github.com/StalkR/goircbot/lib/darkstat"
	"github.com/StalkR/goircbot/lib/size"
)

// bw handles command to display either all darkstat or a single one by name.
func bw(b *bot.Bot, e *bot.Event, c map[string]*darkstat.Conn) {
	name := strings.TrimSpace(e.Args)
	var stats string
	var err error
	if ds, ok := c[name]; ok {
		stats, err = single(name, ds)
	} else {
		stats, err = multiple(c)
	}
	if err != nil {
		log.Print("darkstat: error: ", err)
		b.Conn.Privmsg(e.Target, "darkstat: failed (see logs)")
		return
	}
	b.Conn.Privmsg(e.Target, stats)
}

// single formats bandwidth stats for a single darkstat.
func single(name string, ds *darkstat.Conn) (string, error) {
	i, o, err := ds.Bandwidth()
	if err != nil {
		return "", err
	}
	in, out := size.Byte(i).String(), size.Byte(o).String()
	return fmt.Sprintf("%v: %v/s in, %v/s out", name, in, out), nil
}

// multiple formats bandwidth stats for multiple darkstat.
func multiple(c map[string]*darkstat.Conn) (string, error) {
	var stats []string
	for name, ds := range c {
		stat, err := single(name, ds)
		if err != nil {
			log.Printf("darkstat: error %v: %v", name, err)
			continue
		}
		stats = append(stats, stat)
	}
	if len(stats) == 0 {
		return "", errors.New("darkstat: all failed")
	}
	return strings.Join(stats, " - "), nil
}

// Register registers the plugin with a bot.
func Register(b *bot.Bot, URLs map[string]string) {
	c := make(map[string]*darkstat.Conn)
	for name, url := range URLs {
		ds, err := darkstat.New(url)
		if err != nil {
			panic(err)
		}
		c[name] = ds
	}

	b.AddCommand("bw", bot.Command{
		Help:    "See current bandwidth stats from darkstat",
		Handler: func(b *bot.Bot, e *bot.Event) { bw(b, e, c) },
		Pub:     true,
		Priv:    false,
		Hidden:  false})
}
<commit_msg>plugins/darkstat: rewrite with new bot<commit_after>// Package darkstat implements a plugin to see stats from darkstat.
package darkstat

import (
	"errors"
	"fmt"
	"log"
	"strings"

	"github.com/StalkR/goircbot/bot"
	"github.com/StalkR/goircbot/lib/darkstat"
	"github.com/StalkR/goircbot/lib/size"
)

// bw handles command to display either all darkstat or a single one by name.
func bw(e *bot.Event, c map[string]*darkstat.Conn) {
	name := strings.TrimSpace(e.Args)
	var stats string
	var err error
	if ds, ok := c[name]; ok {
		stats, err = single(name, ds)
	} else {
		stats, err = multiple(c)
	}
	if err != nil {
		log.Print("darkstat: error: ", err)
		e.Bot.Privmsg(e.Target, "darkstat: failed (see logs)")
		return
	}
	e.Bot.Privmsg(e.Target, stats)
}

// single formats bandwidth stats for a single darkstat.
func single(name string, ds *darkstat.Conn) (string, error) {
	i, o, err := ds.Bandwidth()
	if err != nil {
		return "", err
	}
	in, out := size.Byte(i).String(), size.Byte(o).String()
	return fmt.Sprintf("%v: %v/s in, %v/s out", name, in, out), nil
}

// multiple formats bandwidth stats for multiple darkstat.
func multiple(c map[string]*darkstat.Conn) (string, error) {
	var stats []string
	for name, ds := range c {
		stat, err := single(name, ds)
		if err != nil {
			log.Printf("darkstat: error %v: %v", name, err)
			continue
		}
		stats = append(stats, stat)
	}
	if len(stats) == 0 {
		return "", errors.New("darkstat: all failed")
	}
	return strings.Join(stats, " - "), nil
}

// Register registers the plugin with a bot.
func Register(b bot.Bot, URLs map[string]string) {
	c := make(map[string]*darkstat.Conn)
	for name, url := range URLs {
		ds, err := darkstat.New(url)
		if err != nil {
			panic(err)
		}
		c[name] = ds
	}

	b.Commands().Add("bw", bot.Command{
		Help:    "See current bandwidth stats from darkstat",
		Handler: func(e *bot.Event) { bw(e, c) },
		Pub:     true,
		Priv:    false,
		Hidden:  false})
}
<|endoftext|>