<commit_before>// Copyright (c) 2017 Pani Networks
// All Rights Reserved.
//
// 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.

// Romana CNI plugin configures kubernetes pods on Romana network.
package cni

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"runtime"
	"syscall"

	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	log "github.com/romana/rlog"
	"github.com/vishvananda/netlink"
)

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

// cmdAdd is a callback functions that gets called by skel.PluginMain
// in response to ADD method.
func CmdAdd(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, err := loadConf(args.StdinData)
	if err != nil {
		return err
	}
	cniVersion := netConf.CNIVersion
	log.Debugf("Loaded netConf %v", netConf)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return fmt.Errorf("Failed to types.LoadArgs, err=(%s)", err)
	}
	log.Debugf("Loaded Kubernetes args %v", k8sargs)

	// Retrieves additional information about the pod
	pod, err := GetPodDescription(k8sargs, netConf.KubernetesConfig)
	if err != nil {
		return err
	}

	romanaClient, err := MakeRomanaClient(netConf)
	if err != nil {
		return err
	}

	// Deferring deallocation before allocating ip address,
	// deallocation will be called on any return unless
	// flag set to false.
	var deallocateOnExit = true
	defer func() {
		if deallocateOnExit {
			deallocator, err := NewRomanaAddressManager(DefaultProvider)

			// don't want to panic here
			if netConf != nil && err == nil {
				log.Errorf("Deallocating IP on exit, something went wrong")
				_ = deallocator.Deallocate(*netConf, romanaClient, pod.Name)
			}
		}
	}()

	// Allocating ip address.
	allocator, err := NewRomanaAddressManager(DefaultProvider)
	if err != nil {
		return err
	}
	podAddress, err := allocator.Allocate(*netConf, romanaClient, RomanaAllocatorPodDescription{
		Name:        pod.Name,
		Hostname:    netConf.RomanaHostName,
		Namespace:   pod.Namespace,
		Labels:      pod.Labels,
		Annotations: pod.Annotations,
	})
	if err != nil {
		return err
	}

	// Networking setup
	/* replaced with static for now
	gwAddr, err := GetRomanaGwAddr()
	if err != nil {
		return fmt.Errorf("Failed to detect ipv4 address on romana-gw interface, err=(%s)", err)
	}
	*/
	gwAddr := &net.IPNet{IP: net.ParseIP("127.42.0.1"), Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	// Magic variables for callback.
	contIface := &current.Interface{}
	hostIface := &current.Interface{}
	ifName := "eth0"
	mtu := 1500 //TODO for stas, make configurable
	_, defaultNet, _ := net.ParseCIDR("0.0.0.0/0")

	// And this is a callback inside the callback, it sets up networking
	// withing a pod namespace, nice thing it save us from shellouts
	// but still, callback within a callback.
	err = netns.Do(func(hostNS ns.NetNS) error {
		// Creates veth interfacces.
		hostVeth, containerVeth, err := SetupVeth(ifName, k8sargs.MakeVethName(), mtu, hostNS)
		if err != nil {
			return err
		}

		// transportNet is a romana-gw cidr turned into romana-gw.IP/32
		transportNet := net.IPNet{IP: gwAddr.IP, Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}
		transportRoute := netlink.Route{
			LinkIndex: containerVeth.Index,
			Dst:       &transportNet,
		}

		// sets up transport route to allow installing default route
		err = netlink.RouteAdd(&transportRoute)
		if err != nil {
			return fmt.Errorf("route add error=(%s)", err)
		}

		// default route for the pod
		defaultRoute := netlink.Route{
			Dst:       defaultNet,
			LinkIndex: containerVeth.Index,
		}
		err = netlink.RouteAdd(&defaultRoute)
		if err != nil {
			return fmt.Errorf("route add default error=(%s)", err)
		}

		containerVethLink, err := netlink.LinkByIndex(containerVeth.Index)
		if err != nil {
			return fmt.Errorf("failed to discover container veth, err=(%s)", err)
		}

		podIP, err := netlink.ParseAddr(podAddress.String())
		if err != nil {
			return fmt.Errorf("netlink failed to parse address %s, err=(%s)", podAddress, err)
		}

		err = netlink.AddrAdd(containerVethLink, podIP)
		if err != nil {
			return fmt.Errorf("failed to add ip address %s to the interface %s, err=(%s)", podIP, containerVeth.Name, err)
		}

		contIface.Name = containerVeth.Name
		contIface.Mac = containerVeth.HardwareAddr.String()
		contIface.Sandbox = netns.Path()
		hostIface.Name = hostVeth.Name
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create veth interfaces in namespace %v, err=(%s)", netns, err)
	}

	// Return route.
	err = AddEndpointRoute(hostIface.Name, podAddress)
	if err != nil {
		return fmt.Errorf("Failed to setup return route to %s via interface %s, err=(%s)", podAddress, hostIface.Name, err)
	}

	/* disabled for pre-2.0
	err = NotifyAgent(podAddress, hostIface.Name, NotifyPodUp)
	if err != nil {
		return err
	}
	*/

	result := &current.Result{
		IPs: []*current.IPConfig{
			&current.IPConfig{
				Version:   "4",
				Address:   *podAddress,
				Interface: 0,
			},
		},
	}

	result.Interfaces = []*current.Interface{hostIface}

	deallocateOnExit = false
	return types.PrintResult(result, cniVersion)
}

// cmdDel is a callback functions that gets called by skel.PluginMain
// in response to DEL method.
func CmdDel(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, err := loadConf(args.StdinData)
	if err != nil {
		return err
	}

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return err
	}

	romanaClient, err := MakeRomanaClient(netConf)
	if err != nil {
		return err
	}

	deallocator, err := NewRomanaAddressManager(DefaultProvider)
	if err != nil {
		return err
	}

	err = deallocator.Deallocate(*netConf, romanaClient, k8sargs.MakePodName())
	if err != nil {
		return fmt.Errorf("Failed to tear down pod network for %s, err=(%s)", k8sargs.MakePodName(), err)
	}

	/* disabled for pre-2.0
	err = NotifyAgent(nil, k8sargs.MakeVethName(), NotifyPodDown)
	if err != nil {
		return err
	}
	*/

	return nil
}

// GetRomanaGwAddr detects ip address assigned to romana-gw interface.
func GetRomanaGwAddr() (*net.IPNet, error) {
	const gwIface = "romana-gw"
	romanaGw, err := netlink.LinkByName(gwIface)
	if err != nil {
		return nil, err
	}

	addr, err := netlink.AddrList(romanaGw, syscall.AF_INET)
	if err != nil {
		return nil, err
	}

	if len(addr) != 1 {
		return nil, fmt.Errorf("Expected exactly 1 ipv4 address on romana-gw interface, found %d", len(addr))
	}

	return addr[0].IPNet, nil
}

// AddEndpointRoute adds return /32 route from host to pod.
func AddEndpointRoute(ifaceName string, ip *net.IPNet) error {
	veth, err := netlink.LinkByName(ifaceName)
	if err != nil {
		return err
	}

	returnRoute := netlink.Route{
		Dst:       ip,
		LinkIndex: veth.Attrs().Index,
	}

	err = netlink.RouteAdd(&returnRoute)
	if err != nil {
		return err
	}

	return nil
}

// loadConf initializes romana config from stdin.
func loadConf(bytes []byte) (*NetConf, error) {
	n := &NetConf{}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, fmt.Errorf("failed to load netconf: %s", err)
	}

	// TODO for stas
	// verify config here
	if n.RomanaHostName == "" {
		hostname, err := os.Hostname()
		if err != nil {
			return nil, fmt.Errorf("failed to load netconf: %s", err)
		}

		n.RomanaHostName = hostname
	}

	return n, nil
}
<commit_msg>Fix error when CNI tries to create existing route<commit_after>// Copyright (c) 2017 Pani Networks
// All Rights Reserved.
//
// 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.

// Romana CNI plugin configures kubernetes pods on Romana network.
package cni

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"runtime"
	"syscall"

	"github.com/containernetworking/cni/pkg/ns"
	"github.com/containernetworking/cni/pkg/skel"
	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/types/current"
	log "github.com/romana/rlog"
	"github.com/vishvananda/netlink"
)

func init() {
	// This ensures that main runs only on main thread (thread group leader).
	// since namespace ops (unshare, setns) are done for a single thread, we
	// must ensure that the goroutine does not jump from OS thread to thread
	runtime.LockOSThread()
}

// cmdAdd is a callback functions that gets called by skel.PluginMain
// in response to ADD method.
func CmdAdd(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, err := loadConf(args.StdinData)
	if err != nil {
		return err
	}
	cniVersion := netConf.CNIVersion
	log.Debugf("Loaded netConf %v", netConf)

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return fmt.Errorf("Failed to types.LoadArgs, err=(%s)", err)
	}
	log.Debugf("Loaded Kubernetes args %v", k8sargs)

	// Retrieves additional information about the pod
	pod, err := GetPodDescription(k8sargs, netConf.KubernetesConfig)
	if err != nil {
		return err
	}

	romanaClient, err := MakeRomanaClient(netConf)
	if err != nil {
		return err
	}

	// Deferring deallocation before allocating ip address,
	// deallocation will be called on any return unless
	// flag set to false.
	var deallocateOnExit = true
	defer func() {
		if deallocateOnExit {
			deallocator, err := NewRomanaAddressManager(DefaultProvider)

			// don't want to panic here
			if netConf != nil && err == nil {
				log.Errorf("Deallocating IP on exit, something went wrong")
				_ = deallocator.Deallocate(*netConf, romanaClient, pod.Name)
			}
		}
	}()

	// Allocating ip address.
	allocator, err := NewRomanaAddressManager(DefaultProvider)
	if err != nil {
		return err
	}
	podAddress, err := allocator.Allocate(*netConf, romanaClient, RomanaAllocatorPodDescription{
		Name:        pod.Name,
		Hostname:    netConf.RomanaHostName,
		Namespace:   pod.Namespace,
		Labels:      pod.Labels,
		Annotations: pod.Annotations,
	})
	if err != nil {
		return err
	}

	// Networking setup
	/* replaced with static for now
	gwAddr, err := GetRomanaGwAddr()
	if err != nil {
		return fmt.Errorf("Failed to detect ipv4 address on romana-gw interface, err=(%s)", err)
	}
	*/
	gwAddr := &net.IPNet{IP: net.ParseIP("127.42.0.1"), Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}

	netns, err := ns.GetNS(args.Netns)
	if err != nil {
		return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
	}
	defer netns.Close()

	// Magic variables for callback.
	contIface := &current.Interface{}
	hostIface := &current.Interface{}
	ifName := "eth0"
	mtu := 1500 //TODO for stas, make configurable
	_, defaultNet, _ := net.ParseCIDR("0.0.0.0/0")

	// And this is a callback inside the callback, it sets up networking
	// withing a pod namespace, nice thing it save us from shellouts
	// but still, callback within a callback.
	err = netns.Do(func(hostNS ns.NetNS) error {
		// Creates veth interfacces.
		hostVeth, containerVeth, err := SetupVeth(ifName, k8sargs.MakeVethName(), mtu, hostNS)
		if err != nil {
			return err
		}

		// transportNet is a romana-gw cidr turned into romana-gw.IP/32
		transportNet := net.IPNet{IP: gwAddr.IP, Mask: net.IPMask([]byte{0xff, 0xff, 0xff, 0xff})}
		transportRoute := netlink.Route{
			LinkIndex: containerVeth.Index,
			Dst:       &transportNet,
		}

		// sets up transport route to allow installing default route
		err = netlink.RouteAdd(&transportRoute)
		if err != nil {
			return fmt.Errorf("route add error=(%s)", err)
		}

		// default route for the pod
		defaultRoute := netlink.Route{
			Dst:       defaultNet,
			LinkIndex: containerVeth.Index,
		}
		err = netlink.RouteAdd(&defaultRoute)
		if err != nil {
			return fmt.Errorf("route add default error=(%s)", err)
		}

		containerVethLink, err := netlink.LinkByIndex(containerVeth.Index)
		if err != nil {
			return fmt.Errorf("failed to discover container veth, err=(%s)", err)
		}

		podIP, err := netlink.ParseAddr(podAddress.String())
		if err != nil {
			return fmt.Errorf("netlink failed to parse address %s, err=(%s)", podAddress, err)
		}

		err = netlink.AddrAdd(containerVethLink, podIP)
		if err != nil {
			return fmt.Errorf("failed to add ip address %s to the interface %s, err=(%s)", podIP, containerVeth.Name, err)
		}

		contIface.Name = containerVeth.Name
		contIface.Mac = containerVeth.HardwareAddr.String()
		contIface.Sandbox = netns.Path()
		hostIface.Name = hostVeth.Name
		return nil
	})
	if err != nil {
		return fmt.Errorf("Failed to create veth interfaces in namespace %v, err=(%s)", netns, err)
	}

	// Return route.
	err = AddEndpointRoute(hostIface.Name, podAddress)
	// There is exactly one case when this error doesn't count,
	// it is when we are trying to create something that exists.
	if err != nil {
		errno, ok := err.(syscall.Errno)
		if !ok {
			return fmt.Errorf("Failed to setup return route to %s via interface %s, err=(%s.(%T))", podAddress, hostIface.Name, err, err)
		}

		if errno != syscall.EEXIST {
			return fmt.Errorf("Failed to setup return route to %s via interface %s, err=(%s)", podAddress, hostIface.Name, errno)
		}
	}

	/* disabled for pre-2.0
	err = NotifyAgent(podAddress, hostIface.Name, NotifyPodUp)
	if err != nil {
		return err
	}
	*/

	result := &current.Result{
		IPs: []*current.IPConfig{
			&current.IPConfig{
				Version:   "4",
				Address:   *podAddress,
				Interface: 0,
			},
		},
	}

	result.Interfaces = []*current.Interface{hostIface}

	deallocateOnExit = false
	return types.PrintResult(result, cniVersion)
}

// cmdDel is a callback functions that gets called by skel.PluginMain
// in response to DEL method.
func CmdDel(args *skel.CmdArgs) error {
	var err error
	// netConf stores Romana related config
	// that comes form stdin.
	netConf, err := loadConf(args.StdinData)
	if err != nil {
		return err
	}

	// LoadArgs parses kubernetes related parameters from CNI
	// environment variables.
	k8sargs := K8sArgs{}
	err = types.LoadArgs(args.Args, &k8sargs)
	if err != nil {
		return err
	}

	romanaClient, err := MakeRomanaClient(netConf)
	if err != nil {
		return err
	}

	deallocator, err := NewRomanaAddressManager(DefaultProvider)
	if err != nil {
		return err
	}

	err = deallocator.Deallocate(*netConf, romanaClient, k8sargs.MakePodName())
	if err != nil {
		return fmt.Errorf("Failed to tear down pod network for %s, err=(%s)", k8sargs.MakePodName(), err)
	}

	/* disabled for pre-2.0
	err = NotifyAgent(nil, k8sargs.MakeVethName(), NotifyPodDown)
	if err != nil {
		return err
	}
	*/

	return nil
}

// GetRomanaGwAddr detects ip address assigned to romana-gw interface.
func GetRomanaGwAddr() (*net.IPNet, error) {
	const gwIface = "romana-gw"
	romanaGw, err := netlink.LinkByName(gwIface)
	if err != nil {
		return nil, err
	}

	addr, err := netlink.AddrList(romanaGw, syscall.AF_INET)
	if err != nil {
		return nil, err
	}

	if len(addr) != 1 {
		return nil, fmt.Errorf("Expected exactly 1 ipv4 address on romana-gw interface, found %d", len(addr))
	}

	return addr[0].IPNet, nil
}

// AddEndpointRoute adds return /32 route from host to pod.
func AddEndpointRoute(ifaceName string, ip *net.IPNet) error {
	veth, err := netlink.LinkByName(ifaceName)
	if err != nil {
		return err
	}

	returnRoute := netlink.Route{
		Dst:       ip,
		LinkIndex: veth.Attrs().Index,
	}

	err = netlink.RouteAdd(&returnRoute)
	if err != nil {
		return err
	}

	return nil
}

// loadConf initializes romana config from stdin.
func loadConf(bytes []byte) (*NetConf, error) {
	n := &NetConf{}
	if err := json.Unmarshal(bytes, n); err != nil {
		return nil, fmt.Errorf("failed to load netconf: %s", err)
	}

	// TODO for stas
	// verify config here
	if n.RomanaHostName == "" {
		hostname, err := os.Hostname()
		if err != nil {
			return nil, fmt.Errorf("failed to load netconf: %s", err)
		}

		n.RomanaHostName = hostname
	}

	return n, nil
}
<|endoftext|>


<commit_before>package util

import (
	"unicode"
	"unicode/utf8"
	"unsafe"
)

type Chars struct {
	slice           []byte // or []rune
	inBytes         bool
	trimLengthKnown bool
	trimLength      uint16

	// XXX Piggybacking item index here is a horrible idea. But I'm trying to
	// minimize the memory footprint by not wasting padded spaces.
	Index int32
}

// ToChars converts byte array into rune array
func ToChars(bytes []byte) Chars {
	var runes []rune
	inBytes := true
	numBytes := len(bytes)
	for i := 0; i < numBytes; {
		if bytes[i] < utf8.RuneSelf {
			if !inBytes {
				runes = append(runes, rune(bytes[i]))
			}
			i++
		} else {
			if inBytes {
				inBytes = false
				runes = make([]rune, i, numBytes)
				for j := 0; j < i; j++ {
					runes[j] = rune(bytes[j])
				}
			}
			r, sz := utf8.DecodeRune(bytes[i:])
			i += sz
			runes = append(runes, r)
		}
	}
	if inBytes {
		return Chars{slice: bytes, inBytes: inBytes}
	}
	return RunesToChars(runes)
}

func RunesToChars(runes []rune) Chars {
	return Chars{slice: *(*[]byte)(unsafe.Pointer(&runes)), inBytes: false}
}

func (chars *Chars) optionalRunes() []rune {
	if chars.inBytes {
		return nil
	}
	return *(*[]rune)(unsafe.Pointer(&chars.slice))
}

func (chars *Chars) Get(i int) rune {
	if runes := chars.optionalRunes(); runes != nil {
		return runes[i]
	}
	return rune(chars.slice[i])
}

func (chars *Chars) Length() int {
	if runes := chars.optionalRunes(); runes != nil {
		return len(runes)
	}
	return len(chars.slice)
}

// TrimLength returns the length after trimming leading and trailing whitespaces
func (chars *Chars) TrimLength() uint16 {
	if chars.trimLengthKnown {
		return chars.trimLength
	}
	chars.trimLengthKnown = true
	var i int
	len := chars.Length()
	for i = len - 1; i >= 0; i-- {
		char := chars.Get(i)
		if !unicode.IsSpace(char) {
			break
		}
	}
	// Completely empty
	if i < 0 {
		return 0
	}

	var j int
	for j = 0; j < len; j++ {
		char := chars.Get(j)
		if !unicode.IsSpace(char) {
			break
		}
	}
	chars.trimLength = AsUint16(i - j + 1)
	return chars.trimLength
}

func (chars *Chars) TrailingWhitespaces() int {
	whitespaces := 0
	for i := chars.Length() - 1; i >= 0; i-- {
		char := chars.Get(i)
		if !unicode.IsSpace(char) {
			break
		}
		whitespaces++
	}
	return whitespaces
}

func (chars *Chars) ToString() string {
	if runes := chars.optionalRunes(); runes != nil {
		return string(runes)
	}
	return string(chars.slice)
}

func (chars *Chars) ToRunes() []rune {
	if runes := chars.optionalRunes(); runes != nil {
		return runes
	}
	bytes := chars.slice
	runes := make([]rune, len(bytes))
	for idx, b := range bytes {
		runes[idx] = rune(b)
	}
	return runes
}

func (chars *Chars) CopyRunes(dest []rune) {
	if runes := chars.optionalRunes(); runes != nil {
		copy(dest, runes)
		return
	}
	for idx, b := range chars.slice {
		dest[idx] = rune(b)
	}
	return
}

func (chars *Chars) Slice(b int, e int) Chars {
	if runes := chars.optionalRunes(); runes != nil {
		return RunesToChars(runes[b:e])
	}
	return Chars{slice: chars.slice[b:e], inBytes: true}
}

func (chars *Chars) Split(delimiter string) []Chars {
	delim := []rune(delimiter)
	numChars := chars.Length()
	numDelim := len(delim)
	begin := 0
	ret := make([]Chars, 0, 1)

	for index := 0; index < numChars; {
		if index+numDelim <= numChars {
			match := true
			for off, d := range delim {
				if chars.Get(index+off) != d {
					match = false
					break
				}
			}
			// Found the delimiter
			if match {
				incr := Max(numDelim, 1)
				ret = append(ret, chars.Slice(begin, index+incr))
				index += incr
				begin = index
				continue
			}
		} else {
			// Impossible to find the delimiter in the remaining substring
			break
		}
		index++
	}
	if begin < numChars || len(ret) == 0 {
		ret = append(ret, chars.Slice(begin, numChars))
	}
	return ret
}
<commit_msg>Speed up initial scanning with bitwise AND operation<commit_after>package util

import (
	"unicode"
	"unicode/utf8"
	"unsafe"
)

const (
	overflow64 uint64 = 0x8080808080808080
	overflow32 uint32 = 0x80808080
)

type Chars struct {
	slice           []byte // or []rune
	inBytes         bool
	trimLengthKnown bool
	trimLength      uint16

	// XXX Piggybacking item index here is a horrible idea. But I'm trying to
	// minimize the memory footprint by not wasting padded spaces.
	Index int32
}

func checkAscii(bytes []byte) (bool, int) {
	i := 0
	for ; i < len(bytes)-8; i += 8 {
		if (overflow64 & *(*uint64)(unsafe.Pointer(&bytes[i]))) > 0 {
			return false, i
		}
	}
	for ; i < len(bytes)-4; i += 4 {
		if (overflow32 & *(*uint32)(unsafe.Pointer(&bytes[i]))) > 0 {
			return false, i
		}
	}
	for ; i < len(bytes); i++ {
		if bytes[i] >= utf8.RuneSelf {
			return false, i
		}
	}
	return true, 0
}

// ToChars converts byte array into rune array
func ToChars(bytes []byte) Chars {
	inBytes, bytesUntil := checkAscii(bytes)
	if inBytes {
		return Chars{slice: bytes, inBytes: inBytes}
	}

	runes := make([]rune, bytesUntil, len(bytes))
	for i := 0; i < bytesUntil; i++ {
		runes[i] = rune(bytes[i])
	}
	for i := bytesUntil; i < len(bytes); {
		r, sz := utf8.DecodeRune(bytes[i:])
		i += sz
		runes = append(runes, r)
	}
	return RunesToChars(runes)
}

func RunesToChars(runes []rune) Chars {
	return Chars{slice: *(*[]byte)(unsafe.Pointer(&runes)), inBytes: false}
}

func (chars *Chars) optionalRunes() []rune {
	if chars.inBytes {
		return nil
	}
	return *(*[]rune)(unsafe.Pointer(&chars.slice))
}

func (chars *Chars) Get(i int) rune {
	if runes := chars.optionalRunes(); runes != nil {
		return runes[i]
	}
	return rune(chars.slice[i])
}

func (chars *Chars) Length() int {
	if runes := chars.optionalRunes(); runes != nil {
		return len(runes)
	}
	return len(chars.slice)
}

// TrimLength returns the length after trimming leading and trailing whitespaces
func (chars *Chars) TrimLength() uint16 {
	if chars.trimLengthKnown {
		return chars.trimLength
	}
	chars.trimLengthKnown = true
	var i int
	len := chars.Length()
	for i = len - 1; i >= 0; i-- {
		char := chars.Get(i)
		if !unicode.IsSpace(char) {
			break
		}
	}
	// Completely empty
	if i < 0 {
		return 0
	}

	var j int
	for j = 0; j < len; j++ {
		char := chars.Get(j)
		if !unicode.IsSpace(char) {
			break
		}
	}
	chars.trimLength = AsUint16(i - j + 1)
	return chars.trimLength
}

func (chars *Chars) TrailingWhitespaces() int {
	whitespaces := 0
	for i := chars.Length() - 1; i >= 0; i-- {
		char := chars.Get(i)
		if !unicode.IsSpace(char) {
			break
		}
		whitespaces++
	}
	return whitespaces
}

func (chars *Chars) ToString() string {
	if runes := chars.optionalRunes(); runes != nil {
		return string(runes)
	}
	return string(chars.slice)
}

func (chars *Chars) ToRunes() []rune {
	if runes := chars.optionalRunes(); runes != nil {
		return runes
	}
	bytes := chars.slice
	runes := make([]rune, len(bytes))
	for idx, b := range bytes {
		runes[idx] = rune(b)
	}
	return runes
}

func (chars *Chars) CopyRunes(dest []rune) {
	if runes := chars.optionalRunes(); runes != nil {
		copy(dest, runes)
		return
	}
	for idx, b := range chars.slice {
		dest[idx] = rune(b)
	}
	return
}

func (chars *Chars) Slice(b int, e int) Chars {
	if runes := chars.optionalRunes(); runes != nil {
		return RunesToChars(runes[b:e])
	}
	return Chars{slice: chars.slice[b:e], inBytes: true}
}

func (chars *Chars) Split(delimiter string) []Chars {
	delim := []rune(delimiter)
	numChars := chars.Length()
	numDelim := len(delim)
	begin := 0
	ret := make([]Chars, 0, 1)

	for index := 0; index < numChars; {
		if index+numDelim <= numChars {
			match := true
			for off, d := range delim {
				if chars.Get(index+off) != d {
					match = false
					break
				}
			}
			// Found the delimiter
			if match {
				incr := Max(numDelim, 1)
				ret = append(ret, chars.Slice(begin, index+incr))
				index += incr
				begin = index
				continue
			}
		} else {
			// Impossible to find the delimiter in the remaining substring
			break
		}
		index++
	}
	if begin < numChars || len(ret) == 0 {
		ret = append(ret, chars.Slice(begin, numChars))
	}
	return ret
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package btrees

// LCA returns the lowest common ancestor in
// the binary tree t for the nodes n0, n1.
func LCA(t, n0, n1 *BTree) *BTree {
	var findLCA func(t, n0, n1 *BTree) (cnt int, ancestor *BTree)
	findLCA = func(t, n0, n1 *BTree) (cnt int, ancestor *BTree) {
		if t == nil {
			return 0, nil // Base case.
		}

		// Post-order walk.
		lc, la := findLCA(t.left, n0, n1)
		if lc == 2 {
			return lc, la
		}
		rc, ra := findLCA(t.right, n0, n1)
		if rc == 2 {
			return rc, ra
		}

		cnt = lc + rc
		if t == n0 {
			cnt++
		}
		if t == n1 {
			cnt++
		}
		if cnt == 2 {
			ancestor = t
		}
		return cnt, ancestor
	}
	_, a := findLCA(t, n0, n1)
	return a
}
<commit_msg>Remove unnecessary variable passing to function literal<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package btrees

// LCA returns the lowest common ancestor in
// the binary tree t for the nodes n0, n1.
func LCA(t, n0, n1 *BTree) *BTree {
	var findLCA func(t *BTree) (cnt int, ancestor *BTree)
	findLCA = func(t *BTree) (cnt int, ancestor *BTree) {
		if t == nil {
			return 0, nil // Base case.
		}

		// Post-order walk.
		lc, la := findLCA(t.left)
		if lc == 2 {
			return lc, la
		}
		rc, ra := findLCA(t.right)
		if rc == 2 {
			return rc, ra
		}

		cnt = lc + rc
		if t == n0 {
			cnt++
		}
		if t == n1 {
			cnt++
		}
		if cnt == 2 {
			ancestor = t
		}
		return cnt, ancestor
	}

	_, a := findLCA(t)
	return a
}
<|endoftext|>


<commit_before>package printer

import (
	"bufio"
	"fmt"
	"github.com/tinylib/msgp/gen"
	"github.com/tinylib/msgp/parse"
	"github.com/ttacon/chalk"
	"golang.org/x/tools/imports"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

func infof(s string, v ...interface{}) {
	fmt.Printf(chalk.Magenta.Color(s), v...)
}

// PrintFile prints the methods for the provided list
// of elements to the given file name and canonical
// package path.
func PrintFile(file string, f *parse.FileSet, mode gen.Method) error {
	err := generate(file, f, mode)
	if err != nil {
		return err
	}
	infof(">>> Generated \"%s\"\n", file)
	err = format(file)
	if err != nil {
		return err
	}
	infof(">>> Formatted \"%s\"\n", file)
	infof(">>> Done.\n")
	return nil
}

func format(file string) error {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	data, err = imports.Process(file, data, nil)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, data, 0600)
}

func generate(file string, f *parse.FileSet, mode gen.Method) error {
	if mode&^gen.Test == 0 {
		return nil
	}

	outfile, err := os.Create(file)
	if err != nil {
		return err
	}
	defer outfile.Close()
	outwr := bufio.NewWriter(outfile)
	defer outwr.Flush()

	err = writePkgHeader(outwr, f.Package)
	if err != nil {
		return err
	}
	err = writeImportHeader(outwr, "github.com/tinylib/msgp/msgp")
	if err != nil {
		return err
	}

	var testwr *bufio.Writer
	if mode&gen.Test == gen.Test {
		tfname := strings.TrimSuffix(file, ".go") + "_test.go"
		testfile, err := os.Create(strings.TrimSuffix(file, ".go") + "_test.go")
		if err != nil {
			return err
		}
		infof(">>> Tests in \"%s\"\n", tfname)
		defer testfile.Close()
		testwr = bufio.NewWriter(testfile)
		defer testwr.Flush()
		err = writePkgHeader(testwr, f.Package)
		if err != nil {
			return err
		}
		err = writeImportHeader(testwr, "bytes", "github.com/tinylib/msgp/msgp", "testing")
	}
	return f.PrintTo(gen.NewPrinter(mode, outwr, testwr))
}

func writePkgHeader(w io.Writer, name string) error {
	_, err := fmt.Fprintln(w, "package", name, "\n")
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, "// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT EDIT\n\n")
	return err
}

func writeImportHeader(w io.Writer, imports ...string) error {
	_, err := io.WriteString(w, "import (\n")
	if err != nil {
		return err
	}
	for _, im := range imports {
		_, err = io.WriteString(w, fmt.Sprintf("\t%q\n", im))
		if err != nil {
			return err
		}
	}
	_, err = io.WriteString(w, ")\n\n")
	return err
}
<commit_msg>Remove unnecessary import in generated tests<commit_after>package printer

import (
	"bufio"
	"fmt"
	"github.com/tinylib/msgp/gen"
	"github.com/tinylib/msgp/parse"
	"github.com/ttacon/chalk"
	"golang.org/x/tools/imports"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

func infof(s string, v ...interface{}) {
	fmt.Printf(chalk.Magenta.Color(s), v...)
}

// PrintFile prints the methods for the provided list
// of elements to the given file name and canonical
// package path.
func PrintFile(file string, f *parse.FileSet, mode gen.Method) error {
	err := generate(file, f, mode)
	if err != nil {
		return err
	}
	infof(">>> Generated \"%s\"\n", file)
	err = format(file)
	if err != nil {
		return err
	}
	infof(">>> Formatted \"%s\"\n", file)
	infof(">>> Done.\n")
	return nil
}

func format(file string) error {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	data, err = imports.Process(file, data, nil)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, data, 0600)
}

func generate(file string, f *parse.FileSet, mode gen.Method) error {
	if mode&^gen.Test == 0 {
		return nil
	}

	outfile, err := os.Create(file)
	if err != nil {
		return err
	}
	defer outfile.Close()
	outwr := bufio.NewWriter(outfile)
	defer outwr.Flush()

	err = writePkgHeader(outwr, f.Package)
	if err != nil {
		return err
	}
	err = writeImportHeader(outwr, "github.com/tinylib/msgp/msgp")
	if err != nil {
		return err
	}

	var testwr *bufio.Writer
	if mode&gen.Test == gen.Test {
		tfname := strings.TrimSuffix(file, ".go") + "_test.go"
		testfile, err := os.Create(strings.TrimSuffix(file, ".go") + "_test.go")
		if err != nil {
			return err
		}
		infof(">>> Tests in \"%s\"\n", tfname)
		defer testfile.Close()
		testwr = bufio.NewWriter(testfile)
		defer testwr.Flush()
		err = writePkgHeader(testwr, f.Package)
		if err != nil {
			return err
		}
		if mode&(gen.Encode|gen.Decode) != 0 {
			err = writeImportHeader(testwr, "bytes", "github.com/tinylib/msgp/msgp", "testing")
		} else {
			err = writeImportHeader(testwr, "github.com/tinylib/msgp/msgp", "testing")
		}
	}
	return f.PrintTo(gen.NewPrinter(mode, outwr, testwr))
}

func writePkgHeader(w io.Writer, name string) error {
	_, err := fmt.Fprintln(w, "package", name, "\n")
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, "// NOTE: THIS FILE WAS PRODUCED BY THE\n// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp)\n// DO NOT EDIT\n\n")
	return err
}

func writeImportHeader(w io.Writer, imports ...string) error {
	_, err := io.WriteString(w, "import (\n")
	if err != nil {
		return err
	}
	for _, im := range imports {
		_, err = io.WriteString(w, fmt.Sprintf("\t%q\n", im))
		if err != nil {
			return err
		}
	}
	_, err = io.WriteString(w, ")\n\n")
	return err
}
<|endoftext|>


<commit_before>package udp

import (
	"encoding/binary"
	"github.com/davyxu/cellnet/codec"
)

const MTU = 1472

func recvPacket(pktData []byte) (msg interface{}, err error) {

	// 用小端格式读取Size
	datasize := binary.LittleEndian.Uint16(pktData)

	// 出错，等待下次数据
	if int(datasize) != len(pktData) || datasize > MTU {
		return nil, nil
	}

	// 读取消息ID
	msgid := binary.LittleEndian.Uint16(pktData[2:])

	msgData := pktData[headerSize:]

	// 将字节数组和消息ID用户解出消息
	msg, _, err = codec.DecodeMessage(int(msgid), msgData)
	if err != nil {
		// TODO 接收错误时，返回消息
		return nil, err
	}

	return
}
<commit_msg>修复: upd 发小包时，导致的crash<commit_after>package udp

import (
	"encoding/binary"
	"github.com/davyxu/cellnet/codec"
)

const MTU = 1472

func recvPacket(pktData []byte) (msg interface{}, err error) {

	// 小于包头，使用nc指令测试时，为1
	if len(pktData) < 2 {
		return nil, nil
	}

	// 用小端格式读取Size
	datasize := binary.LittleEndian.Uint16(pktData)

	// 出错，等待下次数据
	if int(datasize) != len(pktData) || datasize > MTU {
		return nil, nil
	}

	// 读取消息ID
	msgid := binary.LittleEndian.Uint16(pktData[2:])

	msgData := pktData[headerSize:]

	// 将字节数组和消息ID用户解出消息
	msg, _, err = codec.DecodeMessage(int(msgid), msgData)
	if err != nil {
		// TODO 接收错误时，返回消息
		return nil, err
	}

	return
}
<|endoftext|>


<commit_before>package datachannel

import (
	"bytes"
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"gopkg.in/logex.v1"

	"github.com/chzyer/flow"
	"github.com/chzyer/next/packet"
	"github.com/chzyer/next/util"
)

const (
	DataChannelSize = 4
)

type dcSlot struct {
	Addr        string
	On          bool
	Port        uint16
	backoffTime time.Time
	dc          *DC
}

func newDcSlot(host string, port int) dcSlot {
	return dcSlot{
		Addr: host,
		Port: uint16(port),
	}
}

type Client struct {
	slots   []dcSlot
	ports   []int
	host    string
	flow    *flow.Flow
	session *packet.SessionIV
	running int32

	mutex sync.Mutex

	in           chan *packet.Packet
	out          chan *packet.Packet
	dcExit       chan int
	onAllBackoff func()
	kickFire     chan struct{}
}

func NewClient(f *flow.Flow, host string, port int, s *packet.SessionIV,
	dcIn, dcOut chan *packet.Packet) *Client {

	dc := &Client{
		session: s,
		host:    host,
		ports:   []int{port},

		in:       dcIn,
		out:      dcOut,
		dcExit:   make(chan int),
		kickFire: make(chan struct{}, 1),
	}
	f.ForkTo(&dc.flow, dc.Close)
	dc.slots = dc.makeSlots(dc.ports, DataChannelSize)
	go dc.loop()
	return dc
}

func (d *Client) Close() {
	d.flow.Close()
}

func (d *Client) SetOnAllChannelsBackoff(f func()) {
	d.onAllBackoff = f
}

func (d *Client) loop() {
	for {
		d.mutex.Lock()
		slotIdx, wait := d.findOff()
		d.mutex.Unlock()
		if slotIdx < 0 {
			select {
			case <-d.kickFire:
			case <-time.After(wait):
			case <-d.flow.IsClose():
				return
			}
			continue
		}

		_, err := d.newDC(slotIdx)
		if err != nil {
			logex.Error(err, d.running)
		}
	}
}

func (d *Client) findOff() (int, time.Duration) {
	now := time.Now()
	var wait time.Duration
	for idx := range d.slots {
		if !d.slots[idx].On {
			duration := d.slots[idx].backoffTime.Sub(now)
			if duration <= 0 {
				return idx, 0
			} else {
				if wait == 0 {
					wait = duration
				} else if duration < wait {
					wait = duration
				}
			}
		}
	}
	if wait == 0 {
		wait = time.Minute
	}
	return -1, wait
}

func (d *Client) makeSlots(ports []int, size int) []dcSlot {
	slots := make([]dcSlot, 0, len(ports)*size)
	for i := 0; i < size; i++ {
		for _, port := range ports {
			slots = append(slots, newDcSlot(d.host, port))
		}
	}
	return slots
}

func (d *Client) compareSlots(ports []int) (remain []int, newp []int) {
	for _, p := range d.ports {
		if util.IntIn(p, ports) {
			remain = append(remain, p)
		}
	}
	for _, p := range ports {
		if !util.IntIn(p, remain) {
			newp = append(newp, p)
		}
	}
	return
}

func (d *Client) makeNewSlots(ports []int) {
	remain, newp := d.compareSlots(ports)
	// not new and not delete
	if len(newp) == 0 && len(remain) == len(d.ports) {
		return
	}

	d.mutex.Lock()
	defer d.mutex.Unlock()
	newSlots := make([]dcSlot, 0, (len(newp)+len(remain))*DataChannelSize)

	for _, slot := range d.slots {
		if util.IntIn(int(slot.Port), remain) {
			newSlots = append(newSlots, slot)
		}
	}
	for _, p := range newp {
		for i := 0; i < DataChannelSize; i++ {
			newSlots = append(newSlots, newDcSlot(d.host, p))
		}
	}
	d.slots = newSlots
}

func (d *Client) UpdateRemoteAddrs(ports []int) {
	logex.Info("new client", ports)
	d.makeNewSlots(ports)

	select {
	case d.kickFire <- struct{}{}:
	default:
	}
}

func (d *Client) getSlot(idx int) dcSlot {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	return d.slots[idx]
}

func (d *Client) setSlot(idx int, f func(*dcSlot)) {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	f(&d.slots[idx])
}

func (d *Client) newDC(idx int) (*DC, error) {
	slot := d.getSlot(idx)
	endpoint := fmt.Sprintf("%v:%v", slot.Addr, slot.Port)
	dc, err := DialDC(endpoint, d.flow, d.session.Clone(slot.Port),
		d.onDataChannelExits(idx), d.in, d.out)
	if err != nil {
		d.setSlot(idx, func(d *dcSlot) {
			d.backoffTime = time.Now().Add(10 * time.Second)
		})
		return nil, logex.Trace(err)
	}
	atomic.AddInt32(&d.running, 1)

	d.setSlot(idx, func(s *dcSlot) {
		s.On = true
		s.dc = dc
	})

	logex.Info("new datachannel to", slot.Addr)
	return dc, nil
}

func (d *Client) GetStats() string {
	d.mutex.Lock()
	defer d.mutex.Unlock()

	buf := bytes.NewBuffer(nil)
	for _, slot := range d.slots {
		dc := slot.dc
		if dc != nil {
			buf.WriteString(dc.Name() + ": " + dc.GetStat().String() + "\n")
		}
	}
	return buf.String()
}

func (d *Client) onDataChannelExits(idx int) func() {
	return func() {
		d.setSlot(idx, func(d *dcSlot) {
			d.On = false
			d.dc = nil
		})
		if atomic.AddInt32(&d.running, -1) == 0 {
			if d.onAllBackoff != nil {
				d.onAllBackoff()
			}
		}
		select {
		case d.kickFire <- struct{}{}:
		default:
		}
	}
}
<commit_msg>[dchan] add connect fail wait<commit_after>package datachannel

import (
	"bytes"
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"gopkg.in/logex.v1"

	"github.com/chzyer/flow"
	"github.com/chzyer/next/packet"
	"github.com/chzyer/next/util"
)

const (
	DataChannelSize = 4
)

type dcSlot struct {
	Addr        string
	On          bool
	Port        uint16
	backoffTime time.Time
	dc          *DC
}

func newDcSlot(host string, port int) dcSlot {
	return dcSlot{
		Addr: host,
		Port: uint16(port),
	}
}

type Client struct {
	slots   []dcSlot
	ports   []int
	host    string
	flow    *flow.Flow
	session *packet.SessionIV
	running int32

	mutex sync.Mutex

	in           chan *packet.Packet
	out          chan *packet.Packet
	dcExit       chan int
	onAllBackoff func()
	kickFire     chan struct{}
}

func NewClient(f *flow.Flow, host string, port int, s *packet.SessionIV,
	dcIn, dcOut chan *packet.Packet) *Client {

	dc := &Client{
		session: s,
		host:    host,
		ports:   []int{port},

		in:       dcIn,
		out:      dcOut,
		dcExit:   make(chan int),
		kickFire: make(chan struct{}, 1),
	}
	f.ForkTo(&dc.flow, dc.Close)
	dc.slots = dc.makeSlots(dc.ports, DataChannelSize)
	go dc.loop()
	return dc
}

func (d *Client) Close() {
	d.flow.Close()
}

func (d *Client) SetOnAllChannelsBackoff(f func()) {
	d.onAllBackoff = f
}

func (d *Client) loop() {
	for {
		d.mutex.Lock()
		slotIdx, wait := d.findOff()
		d.mutex.Unlock()
		if slotIdx < 0 {
			select {
			case <-d.kickFire:
			case <-time.After(wait):
			case <-d.flow.IsClose():
				return
			}
			continue
		}

		_, err := d.newDC(slotIdx)
		if err != nil {
			time.Sleep(time.Second)
			logex.Error(err, d.running)
		}
	}
}

func (d *Client) findOff() (int, time.Duration) {
	now := time.Now()
	var wait time.Duration
	for idx := range d.slots {
		if !d.slots[idx].On {
			duration := d.slots[idx].backoffTime.Sub(now)
			if duration <= 0 {
				return idx, 0
			} else {
				if wait == 0 {
					wait = duration
				} else if duration < wait {
					wait = duration
				}
			}
		}
	}
	if wait == 0 {
		wait = time.Minute
	}
	return -1, wait
}

func (d *Client) makeSlots(ports []int, size int) []dcSlot {
	slots := make([]dcSlot, 0, len(ports)*size)
	for i := 0; i < size; i++ {
		for _, port := range ports {
			slots = append(slots, newDcSlot(d.host, port))
		}
	}
	return slots
}

func (d *Client) compareSlots(ports []int) (remain []int, newp []int) {
	for _, p := range d.ports {
		if util.IntIn(p, ports) {
			remain = append(remain, p)
		}
	}
	for _, p := range ports {
		if !util.IntIn(p, remain) {
			newp = append(newp, p)
		}
	}
	return
}

func (d *Client) makeNewSlots(ports []int) {
	remain, newp := d.compareSlots(ports)
	// not new and not delete
	if len(newp) == 0 && len(remain) == len(d.ports) {
		return
	}

	d.mutex.Lock()
	defer d.mutex.Unlock()
	newSlots := make([]dcSlot, 0, (len(newp)+len(remain))*DataChannelSize)

	for _, slot := range d.slots {
		if util.IntIn(int(slot.Port), remain) {
			newSlots = append(newSlots, slot)
		}
	}
	for _, p := range newp {
		for i := 0; i < DataChannelSize; i++ {
			newSlots = append(newSlots, newDcSlot(d.host, p))
		}
	}
	d.slots = newSlots
}

func (d *Client) UpdateRemoteAddrs(ports []int) {
	logex.Info("new client", ports)
	d.makeNewSlots(ports)

	select {
	case d.kickFire <- struct{}{}:
	default:
	}
}

func (d *Client) getSlot(idx int) dcSlot {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	return d.slots[idx]
}

func (d *Client) setSlot(idx int, f func(*dcSlot)) {
	d.mutex.Lock()
	defer d.mutex.Unlock()
	f(&d.slots[idx])
}

func (d *Client) newDC(idx int) (*DC, error) {
	slot := d.getSlot(idx)
	endpoint := fmt.Sprintf("%v:%v", slot.Addr, slot.Port)
	dc, err := DialDC(endpoint, d.flow, d.session.Clone(slot.Port),
		d.onDataChannelExits(idx), d.in, d.out)
	if err != nil {
		d.setSlot(idx, func(d *dcSlot) {
			d.backoffTime = time.Now().Add(10 * time.Second)
		})
		return nil, logex.Trace(err)
	}
	atomic.AddInt32(&d.running, 1)

	d.setSlot(idx, func(s *dcSlot) {
		s.On = true
		s.dc = dc
	})

	logex.Info("new datachannel to", slot.Addr)
	return dc, nil
}

func (d *Client) GetStats() string {
	d.mutex.Lock()
	defer d.mutex.Unlock()

	buf := bytes.NewBuffer(nil)
	for _, slot := range d.slots {
		dc := slot.dc
		if dc != nil {
			buf.WriteString(dc.Name() + ": " + dc.GetStat().String() + "\n")
		}
	}
	return buf.String()
}

func (d *Client) onDataChannelExits(idx int) func() {
	return func() {
		d.setSlot(idx, func(d *dcSlot) {
			d.On = false
			d.dc = nil
		})
		if atomic.AddInt32(&d.running, -1) == 0 {
			if d.onAllBackoff != nil {
				d.onAllBackoff()
			}
		}
		select {
		case d.kickFire <- struct{}{}:
		default:
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"math"
	"math/rand"

	. "github.com/peterstace/grayt/grayt"
)

func main() {
	Run("sphere_tree", Scene{
		Camera: Cam(1.3),
		Objects: Group(
			Tree(),
			Floor,
			Ceiling,
			BackWall,
			LeftWall.With(ColourRGB(Red)),
			RightWall.With(ColourRGB(Green)),
			CeilingLight().With(Emittance(5.0)),
		),
	})
}
func Cam(d float64) Camera {
	return Camera{
		Location:             Vect(0.5, 0.5, d),
		ViewDirection:        Vect(0.0, 0.0, -1.0),
		UpDirection:          Vect(0.0, 1.0, 0.0),
		FieldOfViewInDegrees: 2 * math.Asin(0.5/math.Sqrt(0.25+d*d)) * 180 / math.Pi,
		FocalLength:          0.5 + d,
		FocalRatio:           math.Inf(+1),
	}
}

var (
	Floor     = AlignedSquare(Vect(0, 0, 0), Vect(1, 0, -1))
	Ceiling   = AlignedSquare(Vect(0, 1, 0), Vect(1, 1, -1))
	BackWall  = ZPlane(-1)
	LeftWall  = AlignedSquare(Vect(0, 0, 0), Vect(0, 1, -1))
	RightWall = AlignedSquare(Vect(1, 0, 0), Vect(1, 1, -1))
)

func CeilingLight() ObjectList {
	const size = 0.9
	return AlignedBox(
		Vect(size, 1.0, -size),
		Vect(1.0-size, 0.999, -1.0+size),
	)
}

type sphere struct {
	c Vector
	r float64
}

func Tree() ObjectList {
	var ol ObjectList
	for _, s := range recurse(sphere{Vect(0.5, 0, -0.5), 0.2}, 8) {
		ol = Group(ol, Sphere(s.c, s.r))
	}
	return ol
}

const radiusScaleDown = 0.8

var rnd = rand.New(rand.NewSource(2))

func recurse(parent sphere, level int) []sphere {

	if level == 0 {
		return []sphere{parent}
	}

	var spheres []sphere
	for i := 0; i < 2; i++ {
		var child sphere
		matches := false
		for !matches {
			rndUnit := Vector{rnd.NormFloat64(), rnd.NormFloat64(), rnd.NormFloat64()}.Unit()
			child.c = parent.c.Add(rndUnit.Scale(parent.r))
			child.r = radiusScaleDown * parent.r
			matches = true &&
				child.c.X > child.r &&
				child.c.X < 1.0-child.r &&
				child.c.Y > child.r &&
				child.c.Y < 1.0-child.r &&
				child.c.Z < -child.r &&
				child.c.Z > -1.0+child.r
		}
		spheres = append(spheres, recurse(child, level-1)...)
	}
	return append(spheres, parent)
}
<commit_msg>Reject spheres that are touching others spheres (except for their direct parents)<commit_after>package main

import (
	"math"
	"math/rand"

	. "github.com/peterstace/grayt/grayt"
)

func main() {
	Run("sphere_tree", Scene{
		Camera: Cam(1.3),
		Objects: Group(
			Tree(),
			Floor,
			Ceiling,
			BackWall,
			LeftWall.With(ColourRGB(Red)),
			RightWall.With(ColourRGB(Green)),
			CeilingLight().With(Emittance(5.0)),
		),
	})
}
func Cam(d float64) Camera {
	return Camera{
		Location:             Vect(0.5, 0.5, d),
		ViewDirection:        Vect(0.0, 0.0, -1.0),
		UpDirection:          Vect(0.0, 1.0, 0.0),
		FieldOfViewInDegrees: 2 * math.Asin(0.5/math.Sqrt(0.25+d*d)) * 180 / math.Pi,
		FocalLength:          0.5 + d,
		FocalRatio:           math.Inf(+1),
	}
}

var (
	Floor     = AlignedSquare(Vect(0, 0, 0), Vect(1, 0, -1))
	Ceiling   = AlignedSquare(Vect(0, 1, 0), Vect(1, 1, -1))
	BackWall  = ZPlane(-1)
	LeftWall  = AlignedSquare(Vect(0, 0, 0), Vect(0, 1, -1))
	RightWall = AlignedSquare(Vect(1, 0, 0), Vect(1, 1, -1))
)

func CeilingLight() ObjectList {
	const size = 0.9
	return AlignedBox(
		Vect(size, 1.0, -size),
		Vect(1.0-size, 0.999, -1.0+size),
	)
}

type sphere struct {
	c Vector
	r float64
}

func Tree() ObjectList {

	root := sphere{Vect(0.5, 0, -0.5), 0.2}
	spheres := new([]sphere)
	*spheres = append(*spheres, root)
	recurse(spheres, root, 9)

	var objList ObjectList
	for _, s := range *spheres {
		objList = Group(objList, Sphere(s.c, s.r))
	}
	return objList
}

const radiusScaleDown = 0.7

func recurse(spheres *[]sphere, parent sphere, level int) {

	if level == 0 {
		return
	}

	child1, child2 := findChildren(spheres, parent)

	*spheres = append(*spheres, child1)
	*spheres = append(*spheres, child2)

	recurse(spheres, child1, level-1)
	recurse(spheres, child2, level-1)
}

func findChildren(spheres *[]sphere, parent sphere) (sphere, sphere) {
	var child1, child2 sphere
	for true {
		child1 = createChild(parent)
		child2 = createChild(parent)
		if !isValidChild(child1, parent, spheres) {
			continue
		}
		if !isValidChild(child2, parent, spheres) {
			continue
		}
		if spheresIntersect(child1, child2) {
			continue
		}
		break
	}
	return child1, child2
}

var rnd = rand.New(rand.NewSource(0))

func createChild(parent sphere) sphere {
	rndUnit := Vector{rnd.NormFloat64(), rnd.NormFloat64(), rnd.NormFloat64()}.Unit()
	return sphere{
		parent.c.Add(rndUnit.Scale(parent.r)),
		radiusScaleDown * parent.r,
	}
}

func isValidChild(child, parent sphere, spheres *[]sphere) bool {

	// Check for intersection with other spheres (ignore the parent).
	for _, s := range *spheres {
		if s.c == parent.c && s.r == parent.r {
			continue
		}
		if spheresIntersect(s, child) {
			return false
		}
	}

	// Check for wall/floor/ceiling intersection.
	return true &&
		child.c.X > child.r &&
		child.c.X < 1.0-child.r &&
		child.c.Y > child.r &&
		child.c.Y < 1.0-child.r &&
		child.c.Z < -child.r &&
		child.c.Z > -1.0+child.r
}

func spheresIntersect(s1, s2 sphere) bool {
	return s1.c.Sub(s2.c).Length() < s1.r+s2.r
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/turnage/graw"
)

const usage = "Usage of stalker: ./stalker [user] [user] ...\n"

const agent = "graw:stalker-demo-bot:1.0.0 by /u/roxven"

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage)
		os.Exit(0)
	}
}

type stalker struct{}

func (a *stalker) UserPost(p *graw.Post) error {
	fmt.Printf(
		"[%s in %s]: Posted \"%s\"\n",
		p.Author, p.Subreddit, p.Title,
	)
	return nil
}

func (a *stalker) UserComment(c *graw.Comment) error {
	fmt.Printf(
		"[%s in %s]: Commented on \"%s\"\n",
		c.Author, c.Subreddit, c.LinkTitle,
	)
	return nil
}

func main() {
	flag.Parse()
	if len(flag.Args()) == 0 {
		flag.Usage()
	}

	fmt.Printf(
		"Error: %v\n", graw.Run(
			graw.Config{
				Agent: agent,
				Users: flag.Args(),
			},
			&stalker{},
		),
	)
}
<commit_msg>Exit on incorrect usage of stalker.<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/turnage/graw"
)

const usage = "Usage of stalker: ./stalker [user] [user] ...\n"

const agent = "graw:stalker-demo-bot:1.0.0 by /u/roxven"

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage)
		os.Exit(0)
	}
}

type stalker struct{}

func (a *stalker) UserPost(p *graw.Post) error {
	fmt.Printf(
		"[%s in %s]: Posted \"%s\"\n",
		p.Author, p.Subreddit, p.Title,
	)
	return nil
}

func (a *stalker) UserComment(c *graw.Comment) error {
	fmt.Printf(
		"[%s in %s]: Commented on \"%s\"\n",
		c.Author, c.Subreddit, c.LinkTitle,
	)
	return nil
}

func main() {
	flag.Parse()
	if len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(-1)
	}

	fmt.Printf(
		"Error: %v\n", graw.Run(
			graw.Config{
				Agent: agent,
				Users: flag.Args(),
			},
			&stalker{},
		),
	)
}
<|endoftext|>


<commit_before>// © 2014, Robert Hülle

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

const (
	CollectionNameSuffix = "@en-US"
	CollectionNameFile   = ".collection.name"
)

var AllowedFiles = []string{".pdf", ".mobi"}

type Collection struct {
	Items      []string `json:"items"`
	LastAccess int      `json:"lastAccess"`
}

func EncodeCollections(collections map[string]Collection) ([]byte, error) {
	b, err := json.Marshal(collections)
	return b, err
}

func DecodeCollections(data []byte) (map[string]Collection, error) {
	col := make(map[string]Collection)
	err := json.Unmarshal(data, &col)
	if err != nil {
		return nil, err
	}
	return col, nil
}

func FindFiles(path string) map[string][]string {
	files := make(map[string][]string)
	col := CollectionName("", path+"/documents")
	DirWalk(col, path+"/documents", files)
	return files
}

func DirWalk(col, path string, files map[string][]string) {
	fis, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading directory '%s': %v\n", path, err)
	}
	for _, fi := range fis {
		if fi.Name()[0] == '.' {
			continue
		}
		if fi.IsDir() {
			npath := path + "/" + fi.Name()
			ncol := CollectionName(col, npath)
			DirWalk(ncol, npath, files)
			continue
		}
		if !AllowedFile(fi.Name()) {
			continue
		}
		if col == "" {
			continue
		}
		name := path + "/" + fi.Name()
		files[name] = append(files[name], col)
	}
}

func CollectionName(old, path string) string {
	b, err := ioutil.ReadFile(path + "/" + CollectionNameFile)
	if os.IsNotExist(err) {
		return old
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "can not open '%s': %v\n",
			path+"/"+CollectionNameFile, err)
		return old
	}
	by := bytes.SplitN(b, []byte("\n"), 2)
	if len(by) < 1 {
		return old
	}
	return string(by[0])
}

func AllowedFile(name string) bool {
	for _, s := range AllowedFiles {
		if strings.HasSuffix(name, s) {
			return true
		}
	}
	return false
}

func BuildCollection(files map[string][]string,
	old map[string]Collection) map[string]Collection {
	collections := make(map[string]Collection)
	hashCache := make(map[string]string)
	for file, colls := range files {
		for _, collectionName := range colls {
			cname := collectionName + CollectionNameSuffix
			hash := hashCache[file]
			if len(hash) == 0 {
				hash = bookHash(file)
				hashCache[file] = hash
			}
			items := collections[cname].Items
			items = append(items, hash)
			collections[cname] = Collection{Items: items}
		}
	}
	if old != nil {
		for cname, v := range collections {
			v.LastAccess = old[cname].LastAccess
		}
	}
	return collections
}
<commit_msg>support multi collections per file<commit_after>// © 2014, Robert Hülle

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

const (
	CollectionNameSuffix = "@en-US"
	CollectionNameFile   = ".collection.name"
)

var AllowedFiles = []string{".pdf", ".mobi"}

type Collection struct {
	Items      []string `json:"items"`
	LastAccess int      `json:"lastAccess"`
}

func EncodeCollections(collections map[string]Collection) ([]byte, error) {
	b, err := json.Marshal(collections)
	return b, err
}

func DecodeCollections(data []byte) (map[string]Collection, error) {
	col := make(map[string]Collection)
	err := json.Unmarshal(data, &col)
	if err != nil {
		return nil, err
	}
	return col, nil
}

func FindFiles(path string) map[string][]string {
	files := make(map[string][]string)
	col := CollectionName(nil, path+"/documents")
	DirWalk(col, path+"/documents", files)
	return files
}

func DirWalk(col []string, path string, files map[string][]string) {
	fis, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading directory '%s': %v\n", path, err)
	}
	for _, fi := range fis {
		if fi.Name()[0] == '.' {
			continue
		}
		if fi.IsDir() {
			npath := path + "/" + fi.Name()
			ncol := CollectionName(col, npath)
			DirWalk(ncol, npath, files)
			continue
		}
		if !AllowedFile(fi.Name()) {
			continue
		}
		if len(col) == 0 {
			continue
		}
		name := path + "/" + fi.Name()
		files[name] = append(files[name], col...)
	}
}

func CollectionName(old []string, path string) []string {
	b, err := ioutil.ReadFile(path + "/" + CollectionNameFile)
	if os.IsNotExist(err) {
		return old
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "can not open '%s': %v\n",
			path+"/"+CollectionNameFile, err)
		return old
	}
	by := bytes.Split(b, []byte("\n"))
	ncols := make([]string, 0, len(by))
	for _, line := range by {
		if len(line) > 0 {
			ncols = append(ncols, string(line))
		}
	}
	return ncols
}

func AllowedFile(name string) bool {
	for _, s := range AllowedFiles {
		if strings.HasSuffix(name, s) {
			return true
		}
	}
	return false
}

func BuildCollection(files map[string][]string,
	old map[string]Collection) map[string]Collection {
	collections := make(map[string]Collection)
	hashCache := make(map[string]string)
	for file, colls := range files {
		for _, collectionName := range colls {
			cname := collectionName + CollectionNameSuffix
			hash := hashCache[file]
			if len(hash) == 0 {
				hash = bookHash(file)
				hashCache[file] = hash
			}
			items := collections[cname].Items
			items = append(items, hash)
			collections[cname] = Collection{Items: items}
		}
	}
	if old != nil {
		for cname, v := range collections {
			v.LastAccess = old[cname].LastAccess
		}
	}
	return collections
}
<|endoftext|>


<commit_before>package magick

// #include <magick/api.h>
import "C"

// When encoding an output image, the colorspaces RGB, CMYK, and GRAY
// may be specified. The CMYK option is only applicable when writing
// TIFF, JPEG, and Adobe Photoshop bitmap (PSD) files.
type Colorspace C.ColorspaceType

const (
	RGB           Colorspace = C.RGBColorspace         // Red, Green, Blue colorspace.
	GRAY          Colorspace = C.GRAYColorspace        // Similar to Luma (Y) according to ITU-R 601
	TRANSPARENT   Colorspace = C.TransparentColorspace // RGB which preserves the matte while quantizing colors.
	OHTA          Colorspace = C.OHTAColorspace
	XYZ           Colorspace = C.XYZColorspace // CIE XYZ
	YCC           Colorspace = C.YCCColorspace // Kodak PhotoCD PhotoYCC
	YIQ           Colorspace = C.YIQColorspace
	YPBPR         Colorspace = C.YPbPrColorspace
	YUV           Colorspace = C.YUVColorspace         // YUV colorspace as used for computer video.
	CMYK          Colorspace = C.CMYKColorspace        // Cyan, Magenta, Yellow, Black colorspace.
	SRGB          Colorspace = C.sRGBColorspace        // Kodak PhotoCD sRGB
	HSL           Colorspace = C.HSLColorspace         // Hue, saturation, luminosity
	HWB           Colorspace = C.HWBColorspace         // Hue, whiteness, blackness
	LAB           Colorspace = C.LABColorspace         // ITU LAB
	REC_601_LUMA  Colorspace = C.Rec601LumaColorspace  // Luma (Y) according to ITU-R 601
	REC_601_YCBCR Colorspace = C.Rec601YCbCrColorspace // YCbCr according to ITU-R 601
	REC_709_LUMA  Colorspace = C.Rec709LumaColorspace  // Luma (Y) according to ITU-R 709
	REC_709_YCBCR Colorspace = C.Rec709YCbCrColorspace // YCbCr according to ITU-R 709
)

// Colorspace returns the image colorspace.
func (im *Image) Colorspace() Colorspace {
	return Colorspace(im.image.colorspace)
}

// SetColorspace changes the image colorspace. Note
// that this only changes how the pixels are interpreted.
// If you want to transform the image to another colorspace
// use TransformColorspace().
func (im *Image) SetColorspace(cs Colorspace) {
	im.image.colorspace = C.ColorspaceType(cs)
}

// TransformColorspace changes the image colorspace while also
// changing the pixels to represent the same image in the
// new colorspace.
func (im *Image) TransformColorspace(cs Colorspace) (*Image, error) {
	return im.transformColorspace(cs)
}
<commit_msg>Make TransformColorspace not alter the source image<commit_after>package magick

// #include <magick/api.h>
import "C"

// When encoding an output image, the colorspaces RGB, CMYK, and GRAY
// may be specified. The CMYK option is only applicable when writing
// TIFF, JPEG, and Adobe Photoshop bitmap (PSD) files.
type Colorspace C.ColorspaceType

const (
	RGB           Colorspace = C.RGBColorspace         // Red, Green, Blue colorspace.
	GRAY          Colorspace = C.GRAYColorspace        // Similar to Luma (Y) according to ITU-R 601
	TRANSPARENT   Colorspace = C.TransparentColorspace // RGB which preserves the matte while quantizing colors.
	OHTA          Colorspace = C.OHTAColorspace
	XYZ           Colorspace = C.XYZColorspace // CIE XYZ
	YCC           Colorspace = C.YCCColorspace // Kodak PhotoCD PhotoYCC
	YIQ           Colorspace = C.YIQColorspace
	YPBPR         Colorspace = C.YPbPrColorspace
	YUV           Colorspace = C.YUVColorspace         // YUV colorspace as used for computer video.
	CMYK          Colorspace = C.CMYKColorspace        // Cyan, Magenta, Yellow, Black colorspace.
	SRGB          Colorspace = C.sRGBColorspace        // Kodak PhotoCD sRGB
	HSL           Colorspace = C.HSLColorspace         // Hue, saturation, luminosity
	HWB           Colorspace = C.HWBColorspace         // Hue, whiteness, blackness
	LAB           Colorspace = C.LABColorspace         // ITU LAB
	REC_601_LUMA  Colorspace = C.Rec601LumaColorspace  // Luma (Y) according to ITU-R 601
	REC_601_YCBCR Colorspace = C.Rec601YCbCrColorspace // YCbCr according to ITU-R 601
	REC_709_LUMA  Colorspace = C.Rec709LumaColorspace  // Luma (Y) according to ITU-R 709
	REC_709_YCBCR Colorspace = C.Rec709YCbCrColorspace // YCbCr according to ITU-R 709
)

// Colorspace returns the image colorspace.
func (im *Image) Colorspace() Colorspace {
	return Colorspace(im.image.colorspace)
}

// SetColorspace changes the image colorspace. Note
// that this only changes how the pixels are interpreted.
// If you want to transform the image to another colorspace
// use TransformColorspace().
func (im *Image) SetColorspace(cs Colorspace) {
	im.image.colorspace = C.ColorspaceType(cs)
}

// TransformColorspace returns a new image by covnerting the original to
// the given colorspace while also changing the pixels to represent the
// same image in the new colorspace.
func (im *Image) TransformColorspace(cs Colorspace) (*Image, error) {
	clone, err := im.Clone()
	if err != nil {
		return nil, err
	}
	if err := clone.ToColorspace(cs); err != nil {
		return nil, err
	}
	return clone, nil
}

// ToColorspace changes the image colorspace in place.
func (im *Image) ToColorspace(cs Colorspace) error {
	_, err := im.transformColorspace(cs)
	return err
}
<|endoftext|>


<commit_before>package protocol

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/xml"
	"github.com/amdonov/xmlsig"
	"log"
	"net/http"
	"text/template"
)

func NewPOSTResponseMarshaller(signer xmlsig.Signer) ResponseMarshaller {
	generator := &postResponseMarshaller{signer: signer}
	generator.template = template.New("postResponse")
	generator.template.Parse(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Note: Since your browser does not support JavaScript,
you must press the Continue button once to proceed.

<form action="{{ .AssertionConsumerServiceURL }}"
method="post">

<input type="hidden" name="RelayState"
value="{{ .RelayState }}"/>
<input type="hidden" name="SAMLResponse"
value="{{ .SAMLResponse }}"/>

<input type="submit" value="Continue"/>

</form>

`)
	return generator
}

type postResponseMarshaller struct {
	template *template.Template
	signer   xmlsig.Signer
}

func (gen *postResponseMarshaller) Marshal(writer http.ResponseWriter, request *http.Request,
	response *Response, authRequest *AuthnRequest, relayState string) {
	// Don't need to change the response. Go ahead and sign it
	signature, err := gen.signer.Sign(response.Assertion)
	if err != nil {
		log.Println(err)
		return
	}
	response.Assertion.Signature = signature
	var xmlbuff bytes.Buffer
	memWriter := bufio.NewWriter(&xmlbuff)
	memWriter.Write([]byte(xml.Header))
	encoder := xml.NewEncoder(memWriter)
	encoder.Encode(response)
	memWriter.Flush()

	samlMessage := base64.StdEncoding.EncodeToString(xmlbuff.Bytes())
	postResponse := POSTResponse{relayState, samlMessage, authRequest.AssertionConsumerServiceURL}
	gen.template.Execute(writer, postResponse)
}

type POSTResponse struct {
	RelayState                  string
	SAMLResponse                string
	AssertionConsumerServiceURL string
}
<commit_msg>ff fix: post saml form via getElementById<commit_after>package protocol

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/xml"
	"github.com/amdonov/xmlsig"
	"log"
	"net/http"
	"text/template"
)

func NewPOSTResponseMarshaller(signer xmlsig.Signer) ResponseMarshaller {
	generator := &postResponseMarshaller{signer: signer}
	generator.template = template.New("postResponse")
	generator.template.Parse(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Note: Since your browser does not support JavaScript,
you must press the Continue button once to proceed.

<form action="{{ .AssertionConsumerServiceURL }}" method="post" id="samlpost">

<input type="hidden" name="RelayState"
value="{{ .RelayState }}"/>
<input type="hidden" name="SAMLResponse"
value="{{ .SAMLResponse }}"/>

<input type="submit" value="Continue"/>

</form>

`)
	return generator
}

type postResponseMarshaller struct {
	template *template.Template
	signer   xmlsig.Signer
}

func (gen *postResponseMarshaller) Marshal(writer http.ResponseWriter, request *http.Request,
	response *Response, authRequest *AuthnRequest, relayState string) {
	// Don't need to change the response. Go ahead and sign it
	signature, err := gen.signer.Sign(response.Assertion)
	if err != nil {
		log.Println(err)
		return
	}
	response.Assertion.Signature = signature
	var xmlbuff bytes.Buffer
	memWriter := bufio.NewWriter(&xmlbuff)
	memWriter.Write([]byte(xml.Header))
	encoder := xml.NewEncoder(memWriter)
	encoder.Encode(response)
	memWriter.Flush()

	samlMessage := base64.StdEncoding.EncodeToString(xmlbuff.Bytes())
	postResponse := POSTResponse{relayState, samlMessage, authRequest.AssertionConsumerServiceURL}
	gen.template.Execute(writer, postResponse)
}

type POSTResponse struct {
	RelayState                  string
	SAMLResponse                string
	AssertionConsumerServiceURL string
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 The Protocol Authors.

package protocol

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"testing"
	"testing/quick"

	"github.com/calmh/xdr"
)

var (
	c0ID = NewDeviceID([]byte{1})
	c1ID = NewDeviceID([]byte{2})
)

func TestHeaderFunctions(t *testing.T) {
	f := func(ver, id, typ int) bool {
		ver = int(uint(ver) % 16)
		id = int(uint(id) % 4096)
		typ = int(uint(typ) % 256)
		h0 := header{version: ver, msgID: id, msgType: typ}
		h1 := decodeHeader(encodeHeader(h0))
		return h0 == h1
	}
	if err := quick.Check(f, nil); err != nil {
		t.Error(err)
	}
}

func TestHeaderLayout(t *testing.T) {
	var e, a uint32

	// Version are the first four bits
	e = 0xf0000000
	a = encodeHeader(header{version: 0xf})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}

	// Message ID are the following 12 bits
	e = 0x0fff0000
	a = encodeHeader(header{msgID: 0xfff})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}

	// Type are the last 8 bits before reserved
	e = 0x0000ff00
	a = encodeHeader(header{msgType: 0xff})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}
}

func TestPing(t *testing.T) {
	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, newTestModel(), "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, newTestModel(), "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	if ok := c0.ping(); !ok {
		t.Error("c0 ping failed")
	}
	if ok := c1.ping(); !ok {
		t.Error("c1 ping failed")
	}
}

func TestPingErr(t *testing.T) {
	e := errors.New("something broke")

	for i := 0; i < 32; i++ {
		for j := 0; j < 32; j++ {
			m0 := newTestModel()
			m1 := newTestModel()

			ar, aw := io.Pipe()
			br, bw := io.Pipe()
			eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
			ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}

			c0 := NewConnection(c0ID, ar, ebw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
			c0.Start()
			c1 := NewConnection(c1ID, br, eaw, m1, "name", CompressAlways)
			c1.Start()
			c0.ClusterConfig(ClusterConfigMessage{})
			c1.ClusterConfig(ClusterConfigMessage{})

			res := c0.ping()
			if (i < 8 || j < 8) && res {
				// This should have resulted in failure, as there is no way an empty ClusterConfig plus a Ping message fits in eight bytes.
				t.Errorf("Unexpected ping success; i=%d, j=%d", i, j)
			} else if (i >= 28 && j >= 28) && !res {
				// This should have worked though, as 28 bytes is plenty for both.
				t.Errorf("Unexpected ping fail; i=%d, j=%d", i, j)
			}
		}
	}
}

// func TestRequestResponseErr(t *testing.T) {
// 	e := errors.New("something broke")

// 	var pass bool
// 	for i := 0; i < 48; i++ {
// 		for j := 0; j < 38; j++ {
// 			m0 := newTestModel()
// 			m0.data = []byte("response data")
// 			m1 := newTestModel()

// 			ar, aw := io.Pipe()
// 			br, bw := io.Pipe()
// 			eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
// 			ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}

// 			NewConnection(c0ID, ar, ebw, m0, nil)
// 			c1 := NewConnection(c1ID, br, eaw, m1, nil).(wireFormatConnection).next.(*rawConnection)

// 			d, err := c1.Request("default", "tn", 1234, 5678)
// 			if err == e || err == ErrClosed {
// 				t.Logf("Error at %d+%d bytes", i, j)
// 				if !m1.isClosed() {
// 					t.Fatal("c1 not closed")
// 				}
// 				if !m0.isClosed() {
// 					t.Fatal("c0 not closed")
// 				}
// 				continue
// 			}
// 			if err != nil {
// 				t.Fatal(err)
// 			}
// 			if string(d) != "response data" {
// 				t.Fatalf("Incorrect response data %q", string(d))
// 			}
// 			if m0.folder != "default" {
// 				t.Fatalf("Incorrect folder %q", m0.folder)
// 			}
// 			if m0.name != "tn" {
// 				t.Fatalf("Incorrect name %q", m0.name)
// 			}
// 			if m0.offset != 1234 {
// 				t.Fatalf("Incorrect offset %d", m0.offset)
// 			}
// 			if m0.size != 5678 {
// 				t.Fatalf("Incorrect size %d", m0.size)
// 			}
// 			t.Logf("Pass at %d+%d bytes", i, j)
// 			pass = true
// 		}
// 	}
// 	if !pass {
// 		t.Fatal("Never passed")
// 	}
// }

func TestVersionErr(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	w := xdr.NewWriter(c0.cw)
	w.WriteUint32(encodeHeader(header{
		version: 2,
		msgID:   0,
		msgType: 0,
	}))
	w.WriteUint32(0) // Avoids reader closing due to EOF

	if !m1.isClosed() {
		t.Error("Connection should close due to unknown version")
	}
}

func TestTypeErr(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	w := xdr.NewWriter(c0.cw)
	w.WriteUint32(encodeHeader(header{
		version: 0,
		msgID:   0,
		msgType: 42,
	}))
	w.WriteUint32(0) // Avoids reader closing due to EOF

	if !m1.isClosed() {
		t.Error("Connection should close due to unknown message type")
	}
}

func TestClose(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	c0.close(nil)

	<-c0.closed
	if !m0.isClosed() {
		t.Fatal("Connection should be closed")
	}

	// None of these should panic, some should return an error

	if c0.ping() {
		t.Error("Ping should not return true")
	}

	c0.Index("default", nil, 0, nil)
	c0.Index("default", nil, 0, nil)

	if _, err := c0.Request("default", "foo", 0, 0, nil, 0, nil); err == nil {
		t.Error("Request should return an error")
	}
}

func TestElementSizeExceededNested(t *testing.T) {
	m := ClusterConfigMessage{
		Folders: []Folder{
			{ID: "longstringlongstringlongstringinglongstringlongstringlonlongstringlongstringlon"},
		},
	}
	_, err := m.EncodeXDR(ioutil.Discard)
	if err == nil {
		t.Errorf("ID length %d > max 64, but no error", len(m.Folders[0].ID))
	}
}

func TestMarshalIndexMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 IndexMessage) bool {
		for _, f := range m1.Files {
			for i := range f.Blocks {
				f.Blocks[i].Offset = 0
				if len(f.Blocks[i].Hash) == 0 {
					f.Blocks[i].Hash = nil
				}
			}
		}

		return testMarshal(t, "index", &m1, &IndexMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalRequestMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 RequestMessage) bool {
		return testMarshal(t, "request", &m1, &RequestMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalResponseMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 ResponseMessage) bool {
		if len(m1.Data) == 0 {
			m1.Data = nil
		}
		return testMarshal(t, "response", &m1, &ResponseMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalClusterConfigMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 ClusterConfigMessage) bool {
		return testMarshal(t, "clusterconfig", &m1, &ClusterConfigMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalCloseMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 CloseMessage) bool {
		return testMarshal(t, "close", &m1, &CloseMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

type message interface {
	EncodeXDR(io.Writer) (int, error)
	DecodeXDR(io.Reader) error
}

func testMarshal(t *testing.T, prefix string, m1, m2 message) bool {
	var buf bytes.Buffer

	failed := func(bc []byte) {
		bs, _ := json.MarshalIndent(m1, "", "  ")
		ioutil.WriteFile(prefix+"-1.txt", bs, 0644)
		bs, _ = json.MarshalIndent(m2, "", "  ")
		ioutil.WriteFile(prefix+"-2.txt", bs, 0644)
		if len(bc) > 0 {
			f, _ := os.Create(prefix + "-data.txt")
			fmt.Fprint(f, hex.Dump(bc))
			f.Close()
		}
	}

	_, err := m1.EncodeXDR(&buf)
	if err != nil && strings.Contains(err.Error(), "exceeds size") {
		return true
	}
	if err != nil {
		failed(nil)
		t.Fatal(err)
	}

	bc := make([]byte, len(buf.Bytes()))
	copy(bc, buf.Bytes())

	err = m2.DecodeXDR(&buf)
	if err != nil {
		failed(bc)
		t.Fatal(err)
	}

	ok := reflect.DeepEqual(m1, m2)
	if !ok {
		failed(bc)
	}
	return ok
}
<commit_msg>Fix tests<commit_after>// Copyright (C) 2014 The Protocol Authors.

package protocol

import (
	"bytes"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"strings"
	"testing"
	"testing/quick"

	"github.com/calmh/xdr"
)

var (
	c0ID = NewDeviceID([]byte{1})
	c1ID = NewDeviceID([]byte{2})
)

func TestHeaderFunctions(t *testing.T) {
	f := func(ver, id, typ int) bool {
		ver = int(uint(ver) % 16)
		id = int(uint(id) % 4096)
		typ = int(uint(typ) % 256)
		h0 := header{version: ver, msgID: id, msgType: typ}
		h1 := decodeHeader(encodeHeader(h0))
		return h0 == h1
	}
	if err := quick.Check(f, nil); err != nil {
		t.Error(err)
	}
}

func TestHeaderLayout(t *testing.T) {
	var e, a uint32

	// Version are the first four bits
	e = 0xf0000000
	a = encodeHeader(header{version: 0xf})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}

	// Message ID are the following 12 bits
	e = 0x0fff0000
	a = encodeHeader(header{msgID: 0xfff})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}

	// Type are the last 8 bits before reserved
	e = 0x0000ff00
	a = encodeHeader(header{msgType: 0xff})
	if a != e {
		t.Errorf("Header layout incorrect; %08x != %08x", a, e)
	}
}

func TestPing(t *testing.T) {
	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, newTestModel(), "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, newTestModel(), "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	if ok := c0.ping(); !ok {
		t.Error("c0 ping failed")
	}
	if ok := c1.ping(); !ok {
		t.Error("c1 ping failed")
	}
}

func TestPingErr(t *testing.T) {
	e := errors.New("something broke")

	for i := 0; i < 32; i++ {
		for j := 0; j < 32; j++ {
			m0 := newTestModel()
			m1 := newTestModel()

			ar, aw := io.Pipe()
			br, bw := io.Pipe()
			eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
			ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}

			c0 := NewConnection(c0ID, ar, ebw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
			c0.Start()
			c1 := NewConnection(c1ID, br, eaw, m1, "name", CompressAlways)
			c1.Start()
			c0.ClusterConfig(ClusterConfigMessage{})
			c1.ClusterConfig(ClusterConfigMessage{})

			res := c0.ping()
			if (i < 8 || j < 8) && res {
				// This should have resulted in failure, as there is no way an empty ClusterConfig plus a Ping message fits in eight bytes.
				t.Errorf("Unexpected ping success; i=%d, j=%d", i, j)
			} else if (i >= 28 && j >= 28) && !res {
				// This should have worked though, as 28 bytes is plenty for both.
				t.Errorf("Unexpected ping fail; i=%d, j=%d", i, j)
			}
		}
	}
}

// func TestRequestResponseErr(t *testing.T) {
// 	e := errors.New("something broke")

// 	var pass bool
// 	for i := 0; i < 48; i++ {
// 		for j := 0; j < 38; j++ {
// 			m0 := newTestModel()
// 			m0.data = []byte("response data")
// 			m1 := newTestModel()

// 			ar, aw := io.Pipe()
// 			br, bw := io.Pipe()
// 			eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
// 			ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}

// 			NewConnection(c0ID, ar, ebw, m0, nil)
// 			c1 := NewConnection(c1ID, br, eaw, m1, nil).(wireFormatConnection).next.(*rawConnection)

// 			d, err := c1.Request("default", "tn", 1234, 5678)
// 			if err == e || err == ErrClosed {
// 				t.Logf("Error at %d+%d bytes", i, j)
// 				if !m1.isClosed() {
// 					t.Fatal("c1 not closed")
// 				}
// 				if !m0.isClosed() {
// 					t.Fatal("c0 not closed")
// 				}
// 				continue
// 			}
// 			if err != nil {
// 				t.Fatal(err)
// 			}
// 			if string(d) != "response data" {
// 				t.Fatalf("Incorrect response data %q", string(d))
// 			}
// 			if m0.folder != "default" {
// 				t.Fatalf("Incorrect folder %q", m0.folder)
// 			}
// 			if m0.name != "tn" {
// 				t.Fatalf("Incorrect name %q", m0.name)
// 			}
// 			if m0.offset != 1234 {
// 				t.Fatalf("Incorrect offset %d", m0.offset)
// 			}
// 			if m0.size != 5678 {
// 				t.Fatalf("Incorrect size %d", m0.size)
// 			}
// 			t.Logf("Pass at %d+%d bytes", i, j)
// 			pass = true
// 		}
// 	}
// 	if !pass {
// 		t.Fatal("Never passed")
// 	}
// }

func TestVersionErr(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	w := xdr.NewWriter(c0.cw)
	w.WriteUint32(encodeHeader(header{
		version: 2,
		msgID:   0,
		msgType: 0,
	}))
	w.WriteUint32(0) // Avoids reader closing due to EOF

	if !m1.isClosed() {
		t.Error("Connection should close due to unknown version")
	}
}

func TestTypeErr(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	w := xdr.NewWriter(c0.cw)
	w.WriteUint32(encodeHeader(header{
		version: 0,
		msgID:   0,
		msgType: 42,
	}))
	w.WriteUint32(0) // Avoids reader closing due to EOF

	if !m1.isClosed() {
		t.Error("Connection should close due to unknown message type")
	}
}

func TestClose(t *testing.T) {
	m0 := newTestModel()
	m1 := newTestModel()

	ar, aw := io.Pipe()
	br, bw := io.Pipe()

	c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
	c0.Start()
	c1 := NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
	c1.Start()
	c0.ClusterConfig(ClusterConfigMessage{})
	c1.ClusterConfig(ClusterConfigMessage{})

	c0.close(nil)

	<-c0.closed
	if !m0.isClosed() {
		t.Fatal("Connection should be closed")
	}

	// None of these should panic, some should return an error

	if c0.ping() {
		t.Error("Ping should not return true")
	}

	c0.Index("default", nil, 0, nil)
	c0.Index("default", nil, 0, nil)

	if _, err := c0.Request("default", "foo", 0, 0, nil, 0, nil); err == nil {
		t.Error("Request should return an error")
	}
}

func TestElementSizeExceededNested(t *testing.T) {
	m := ClusterConfigMessage{
		Folders: []Folder{
			{ID: "longstringlongstringlongstringinglongstringlongstringlonlongstringlongstringlon"},
		},
	}
	_, err := m.EncodeXDR(ioutil.Discard)
	if err == nil {
		t.Errorf("ID length %d > max 64, but no error", len(m.Folders[0].ID))
	}
}

func TestMarshalIndexMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 IndexMessage) bool {
		for i, f := range m1.Files {
			m1.Files[i].CachedSize = 0
			for j := range f.Blocks {
				f.Blocks[j].Offset = 0
				if len(f.Blocks[j].Hash) == 0 {
					f.Blocks[j].Hash = nil
				}
			}
		}

		return testMarshal(t, "index", &m1, &IndexMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalRequestMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 RequestMessage) bool {
		return testMarshal(t, "request", &m1, &RequestMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalResponseMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 ResponseMessage) bool {
		if len(m1.Data) == 0 {
			m1.Data = nil
		}
		return testMarshal(t, "response", &m1, &ResponseMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalClusterConfigMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 ClusterConfigMessage) bool {
		return testMarshal(t, "clusterconfig", &m1, &ClusterConfigMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

func TestMarshalCloseMessage(t *testing.T) {
	var quickCfg = &quick.Config{MaxCountScale: 10}
	if testing.Short() {
		quickCfg = nil
	}

	f := func(m1 CloseMessage) bool {
		return testMarshal(t, "close", &m1, &CloseMessage{})
	}

	if err := quick.Check(f, quickCfg); err != nil {
		t.Error(err)
	}
}

type message interface {
	EncodeXDR(io.Writer) (int, error)
	DecodeXDR(io.Reader) error
}

func testMarshal(t *testing.T, prefix string, m1, m2 message) bool {
	var buf bytes.Buffer

	failed := func(bc []byte) {
		bs, _ := json.MarshalIndent(m1, "", "  ")
		ioutil.WriteFile(prefix+"-1.txt", bs, 0644)
		bs, _ = json.MarshalIndent(m2, "", "  ")
		ioutil.WriteFile(prefix+"-2.txt", bs, 0644)
		if len(bc) > 0 {
			f, _ := os.Create(prefix + "-data.txt")
			fmt.Fprint(f, hex.Dump(bc))
			f.Close()
		}
	}

	_, err := m1.EncodeXDR(&buf)
	if err != nil && strings.Contains(err.Error(), "exceeds size") {
		return true
	}
	if err != nil {
		failed(nil)
		t.Fatal(err)
	}

	bc := make([]byte, len(buf.Bytes()))
	copy(bc, buf.Bytes())

	err = m2.DecodeXDR(&buf)
	if err != nil {
		failed(bc)
		t.Fatal(err)
	}

	ok := reflect.DeepEqual(m1, m2)
	if !ok {
		failed(bc)
	}
	return ok
}
<|endoftext|>


<commit_before>package bob

// Source: exercism/problem-specifications
// Commit: ca79943 Bob: Fix grammatical error in testdata (#1319)
// Problem Specifications Version: 1.4.0

var testCases = []struct {
	description string
	input       string
	expected    string
}{
	{
		"stating something",
		"Tom-ay-to, tom-aaaah-to.",
		"Whatever.",
	},
	{
		"shouting",
		"WATCH OUT!",
		"Whoa, chill out!",
	},
	{
		"shouting gibberish",
		"FCECDFCAAB",
		"Whoa, chill out!",
	},
	{
		"asking a question",
		"Does this cryogenic chamber make me look fat?",
		"Sure.",
	},
	{
		"asking a numeric question",
		"You are, what, like 15?",
		"Sure.",
	},
	{
		"asking gibberish",
		"fffbbcbeab?",
		"Sure.",
	},
	{
		"talking forcefully",
		"Let's go make out behind the gym!",
		"Whatever.",
	},
	{
		"using acronyms in regular speech",
		"It's OK if you don't want to go to the DMV.",
		"Whatever.",
	},
	{
		"forceful question",
		"WHAT THE HELL WERE YOU THINKING?",
		"Calm down, I know what I'm doing!",
	},
	{
		"shouting numbers",
		"1, 2, 3 GO!",
		"Whoa, chill out!",
	},
	{
		"no letters",
		"1, 2, 3",
		"Whatever.",
	},
	{
		"question with no letters",
		"4?",
		"Sure.",
	},
	{
		"shouting with special characters",
		"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
		"Whoa, chill out!",
	},
	{
		"shouting with no exclamation mark",
		"I HATE THE DMV",
		"Whoa, chill out!",
	},
	{
		"statement containing question mark",
		"Ending with ? means a question.",
		"Whatever.",
	},
	{
		"non-letters with question",
		":) ?",
		"Sure.",
	},
	{
		"prattling on",
		"Wait! Hang on. Are you going to be OK?",
		"Sure.",
	},
	{
		"silence",
		"",
		"Fine. Be that way!",
	},
	{
		"prolonged silence",
		"          ",
		"Fine. Be that way!",
	},
	{
		"alternate silence",
		"\t\t\t\t\t\t\t\t\t\t",
		"Fine. Be that way!",
	},
	{
		"multiple line question",
		"\nDoes this cryogenic chamber make me look fat?\nNo.",
		"Whatever.",
	},
	{
		"starting with whitespace",
		"         hmmmmmmm...",
		"Whatever.",
	},
	{
		"ending with whitespace",
		"Okay if like my  spacebar  quite a bit?   ",
		"Sure.",
	},
	{
		"other whitespace",
		"\n\r \t",
		"Fine. Be that way!",
	},
	{
		"non-question ending with whitespace",
		"This is a statement ending with whitespace      ",
		"Whatever.",
	},
}
<commit_msg>bob: update cases to reflect more inclusive language (#1317)<commit_after>package bob

// Source: exercism/problem-specifications
// Commit: 1904e91 Bob: Cleans up language on a couple of test cases
// Problem Specifications Version: 1.5.0

var testCases = []struct {
	description string
	input       string
	expected    string
}{
	{
		"stating something",
		"Tom-ay-to, tom-aaaah-to.",
		"Whatever.",
	},
	{
		"shouting",
		"WATCH OUT!",
		"Whoa, chill out!",
	},
	{
		"shouting gibberish",
		"FCECDFCAAB",
		"Whoa, chill out!",
	},
	{
		"asking a question",
		"Does this cryogenic chamber make me look fat?",
		"Sure.",
	},
	{
		"asking a numeric question",
		"You are, what, like 15?",
		"Sure.",
	},
	{
		"asking gibberish",
		"fffbbcbeab?",
		"Sure.",
	},
	{
		"talking forcefully",
		"Hi there!",
		"Whatever.",
	},
	{
		"using acronyms in regular speech",
		"It's OK if you don't want to go to the DMV.",
		"Whatever.",
	},
	{
		"forceful question",
		"WHAT'S GOING ON?",
		"Calm down, I know what I'm doing!",
	},
	{
		"shouting numbers",
		"1, 2, 3 GO!",
		"Whoa, chill out!",
	},
	{
		"no letters",
		"1, 2, 3",
		"Whatever.",
	},
	{
		"question with no letters",
		"4?",
		"Sure.",
	},
	{
		"shouting with special characters",
		"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
		"Whoa, chill out!",
	},
	{
		"shouting with no exclamation mark",
		"I HATE THE DMV",
		"Whoa, chill out!",
	},
	{
		"statement containing question mark",
		"Ending with ? means a question.",
		"Whatever.",
	},
	{
		"non-letters with question",
		":) ?",
		"Sure.",
	},
	{
		"prattling on",
		"Wait! Hang on. Are you going to be OK?",
		"Sure.",
	},
	{
		"silence",
		"",
		"Fine. Be that way!",
	},
	{
		"prolonged silence",
		"          ",
		"Fine. Be that way!",
	},
	{
		"alternate silence",
		"\t\t\t\t\t\t\t\t\t\t",
		"Fine. Be that way!",
	},
	{
		"multiple line question",
		"\nDoes this cryogenic chamber make me look fat?\nNo.",
		"Whatever.",
	},
	{
		"starting with whitespace",
		"         hmmmmmmm...",
		"Whatever.",
	},
	{
		"ending with whitespace",
		"Okay if like my  spacebar  quite a bit?   ",
		"Sure.",
	},
	{
		"other whitespace",
		"\n\r \t",
		"Fine. Be that way!",
	},
	{
		"non-question ending with whitespace",
		"This is a statement ending with whitespace      ",
		"Whatever.",
	},
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"log"

	_ "github.com/mattn/go-oci8"
)

func main() {
	db, err := sql.Open("oci8", "scott/tiger@XE")
	if err != nil {
		log.Fatal(err)
	}
	_, err = db.Exec(`
	CREATE OR REPLACE FUNCTION MY_SUM
	(
      P_NUM1 IN NUMBER,
      P_NUM2 IN NUMBER
    )
    RETURN NUMBER
    IS
      R_NUM NUMBER(2) DEFAULT 0;
    BEGIN
      FOR i IN 1..P_NUM2
	  LOOP
        R_NUM := R_NUM + P_NUM1;
      END LOOP;
      RETURN R_NUM;
    END;
	`)
	if err != nil {
		log.Fatal(err)
	}
	rows, err := db.Query("select SCOTT.MY_SUM(5,6) from dual")
	if err != nil {
		log.Fatal(err)
	}
	for rows.Next() {
		var i int
		err = rows.Scan(&i)
		if err != nil {
			log.Fatal(err)
		}
		println(i)
	}
}
<commit_msg>cosmetic change<commit_after>package main

import (
	"database/sql"
	"log"

	_ "github.com/mattn/go-oci8"
)

func main() {
	db, err := sql.Open("oci8", "scott/tiger@XE")
	if err != nil {
		log.Fatal(err)
	}
	_, err = db.Exec(`
    CREATE OR REPLACE FUNCTION MY_SUM
    (
      P_NUM1 IN NUMBER,
      P_NUM2 IN NUMBER
    )
    RETURN NUMBER
    IS
      R_NUM NUMBER(2) DEFAULT 0;
    BEGIN
      FOR i IN 1..P_NUM2
      LOOP
        R_NUM := R_NUM + P_NUM1;
      END LOOP;
      RETURN R_NUM;
    END;
    `)
	if err != nil {
		log.Fatal(err)
	}
	rows, err := db.Query("select SCOTT.MY_SUM(5,6) from dual")
	if err != nil {
		log.Fatal(err)
	}
	for rows.Next() {
		var i int
		err = rows.Scan(&i)
		if err != nil {
			log.Fatal(err)
		}
		println(i)
	}
}
<|endoftext|>


<commit_before>package elastigo

import (
	"fmt"
	"github.com/codahale/blake2"
	ds "github.com/jbenet/datastore.go"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
)

// Currently, elastigo does not allow connecting to multiple elasticsearch
// instances. The elastigo API uses global static variables (ugh).
// See https://github.com/mattbaird/elastigo/issues/22
//
// Thus, we use a global static variable (GlobalInstance), and return an
// error if NewDatastore is called twice with different addresses.
var GlobalInstance Address

type Address struct {
	Host string
	Port int
}

// Datastore uses a standard Go map for internal storage.
type Datastore struct {
	addr  Address
	index string

	// Elastic search does not allow slashes in their object ids,
	// so we hash the key. By default, we use the provided BlakeKeyHash
	KeyHash func(ds.Key) string
}

func NewDatastore(addr Address, index string) (*Datastore, error) {
	if GlobalInstance.Host != "" && GlobalInstance != addr {
		return nil, fmt.Errorf("elastigo only allows one client. See godoc.")
	}

	api.Domain = addr.Host
	if addr.Port > 0 {
		api.Port = fmt.Sprintf("%d", addr.Port)
	}

	GlobalInstance = addr
	return &Datastore{
		addr:    addr,
		index:   index,
		KeyHash: BlakeKeyHash,
	}, nil
}

// Returns the ElasticSearch index for given key. If the datastore specifies
// an index, use that. Else, key.Parent
func (d *Datastore) Index(key ds.Key) string {
	if len(d.index) > 0 {
		return d.index
	}
	return key.Parent().BaseNamespace()
}

// value should be JSON serializable.
func (d *Datastore) Put(key ds.Key, value interface{}) (err error) {
	id := d.KeyHash(key)
	res, err := core.Index(false, d.Index(key), key.Type(), id, value)
	if err != nil {
		return err
	}
	if !res.Ok {
		return fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return nil
}

func (d *Datastore) Get(key ds.Key) (value interface{}, err error) {
	id := d.KeyHash(key)
	res, err := core.Get(false, d.Index(key), key.Type(), id)
	if err != nil {
		return nil, err
	}
	if !res.Ok {
		return nil, fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return res.Source, nil
}

func (d *Datastore) Has(key ds.Key) (exists bool, err error) {
	id := d.KeyHash(key)
	return core.Exists(false, d.Index(key), key.Type(), id)
}

func (d *Datastore) Delete(key ds.Key) (err error) {
	id := d.KeyHash(key)
	res, err := core.Delete(false, d.Index(key), key.Type(), id, 0, "")
	if err != nil {
		return err
	}
	if !res.Ok {
		return fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return nil
}

// Hash a key and return the first 16 hex chars of its blake2b hash.
// basically: Blake2b(key).HexString[:16]
func BlakeKeyHash(key ds.Key) string {
	h := blake2.NewBlake2B()
	h.Write(key.Bytes())
	d := h.Sum(nil)
	return fmt.Sprintf("%x", d)[:16]
}
<commit_msg>elastigo: switched to use url address<commit_after>package elastigo

import (
	"fmt"
	"github.com/codahale/blake2"
	ds "github.com/jbenet/datastore.go"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"net/url"
	"strings"
)

// Currently, elastigo does not allow connecting to multiple elasticsearch
// instances. The elastigo API uses global static variables (ugh).
// See https://github.com/mattbaird/elastigo/issues/22
//
// Thus, we use a global static variable (GlobalInstance), and return an
// error if NewDatastore is called twice with different addresses.
var GlobalInstance string

// Datastore uses a standard Go map for internal storage.
type Datastore struct {
	url   string
	index string

	// Elastic search does not allow slashes in their object ids,
	// so we hash the key. By default, we use the provided BlakeKeyHash
	KeyHash func(ds.Key) string
}

func NewDatastore(urlstr string) (*Datastore, error) {
	if GlobalInstance != "" && GlobalInstance != urlstr {
		return nil, fmt.Errorf("elastigo only allows one client. See godoc.")
	}

	uf := "http://<host>:<port>/<index>"
	u, err := url.Parse(urlstr)
	if err != nil {
		return nil, fmt.Errorf("error parsing url: %s (%s)", urlstr, uf)
	}

	host := strings.Split(u.Host, ":")
	api.Domain = host[0]
	if len(host) > 1 {
		api.Port = host[1]
	}

	index := strings.Trim(u.Path, "/")
	if strings.Contains(index, "/") {
		e := "elastigo index cannot have slashes: %s (%s -> %s)"
		return nil, fmt.Errorf(e, index, urlstr, uf)
	}

	GlobalInstance = urlstr
	return &Datastore{
		url:     urlstr,
		index:   index,
		KeyHash: BlakeKeyHash,
	}, nil
}

// Returns the ElasticSearch index for given key. If the datastore specifies
// an index, use that. Else, key.Parent
func (d *Datastore) Index(key ds.Key) string {
	if len(d.index) > 0 {
		return d.index
	}
	return key.Parent().BaseNamespace()
}

// value should be JSON serializable.
func (d *Datastore) Put(key ds.Key, value interface{}) (err error) {
	id := d.KeyHash(key)
	res, err := core.Index(false, d.Index(key), key.Type(), id, value)
	if err != nil {
		return err
	}
	if !res.Ok {
		return fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return nil
}

func (d *Datastore) Get(key ds.Key) (value interface{}, err error) {
	id := d.KeyHash(key)
	res, err := core.Get(false, d.Index(key), key.Type(), id)
	if err != nil {
		return nil, err
	}
	if !res.Ok {
		return nil, fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return res.Source, nil
}

func (d *Datastore) Has(key ds.Key) (exists bool, err error) {
	id := d.KeyHash(key)
	return core.Exists(false, d.Index(key), key.Type(), id)
}

func (d *Datastore) Delete(key ds.Key) (err error) {
	id := d.KeyHash(key)
	res, err := core.Delete(false, d.Index(key), key.Type(), id, 0, "")
	if err != nil {
		return err
	}
	if !res.Ok {
		return fmt.Errorf("Elasticsearch response: NOT OK. %v", res)
	}
	return nil
}

// Hash a key and return the first 16 hex chars of its blake2b hash.
// basically: Blake2b(key).HexString[:16]
func BlakeKeyHash(key ds.Key) string {
	h := blake2.NewBlake2B()
	h.Write(key.Bytes())
	d := h.Sum(nil)
	return fmt.Sprintf("%x", d)[:16]
}
<|endoftext|>


<commit_before>package display

import (
	"fmt"
	"log"
	"time"

	"dwmb/request"
)

func MakeMessage(resp *request.Response) (string, time.Duration) {
	messageId := resp.Message
	log.Printf("message: %s\n", messageId)
	switch messageId {
	case "connecting":
		if resp.CardCode != "" {
			return fmt.Sprintf("Attach bike.\nRegister: %s", resp.CardCode), 30
		}
		return "Please attach\nyour bike :)", 30
	case "theft":
		return "RUN !", 15
	case "connected":
		return "Bike attached", 6
	case "cable":
		return "Don't touch me!", 6
	default:
		return "Unknown message", 6
	}
}
<commit_msg>fix all messages<commit_after>package display

import (
	"fmt"
	"log"
	"time"

	"dwmb/request"
)

func MakeMessage(resp *request.Response) (string, time.Duration) {
	messageId := resp.Message
	log.Printf("message: %s\n", messageId)
	switch messageId {
	case "connecting":
		if resp.CardCode != "" {
			return fmt.Sprintf("Attach bike.\nRegister: %s", resp.CardCode), 30
		}
		return "Please attach\nyour bike :)", 30
	case "theft":
		return "RUN !", 15
	case "connected":
		return "Bike attached", 6
	case "cable":
		return "Don't touch me!", 6
	case "disconnecting":
		return "You can detach\nyour bike!", 30
	case "disconnected":
		return "Goodbye ^-^", 6
	default:
		return "Unknown message", 6
	}
}
<|endoftext|>