<commit_before>package main

import (
	"errors"
	"fmt"
	ipamsapi "github.com/docker/libnetwork/ipams/remote/api"
	netlabel "github.com/docker/libnetwork/netlabel"
	ibclient "github.com/infobloxopen/infoblox-go-client"
	"log"
	"strconv"
	"strings"
)

type Container struct {
	NetworkContainer string // CIDR of Network Container
	ContainerObj     *ibclient.NetworkContainer
	exhausted        bool
}

type InfobloxAddressSpace struct {
	NetviewName  string // Network View Name
	PrefixLength uint   // Prefix Length
	Containers   []Container
}

type AddressSpaceScope int

const (
	GLOBAL AddressSpaceScope = iota
	LOCAL
)

type InfobloxDriver struct {
	objMgr              *ibclient.ObjectManager
	addressSpaceByScope map[AddressSpaceScope]*InfobloxAddressSpace
	addressSpaceByView  map[string]*InfobloxAddressSpace
}

func (ibDrv *InfobloxDriver) PluginActivate(r interface{}) (map[string]interface{}, error) {
	return map[string]interface{}{
		"Implements": []interface{}{
			"IpamDriver",
		}}, nil
}

func (ibDrv *InfobloxDriver) GetCapabilities(r interface{}) (map[string]interface{}, error) {
	return map[string]interface{}{"RequiresMACAddress": true}, nil
}

func (ibDrv *InfobloxDriver) GetDefaultAddressSpaces(r interface{}) (map[string]interface{}, error) {
	globalViewRef, localViewRef, err := ibDrv.objMgr.CreateDefaultNetviews(
		ibDrv.addressSpaceByScope[GLOBAL].NetviewName,
		ibDrv.addressSpaceByScope[LOCAL].NetviewName)

	return map[string]interface{}{"GlobalDefaultAddressSpace": globalViewRef, "LocalDefaultAddressSpace": localViewRef}, err
}

func getPrefixLength(cidr string) (prefixLength string) {
	parts := strings.Split(cidr, "/")
	return parts[1]
}

func (ibDrv *InfobloxDriver) RequestAddress(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.RequestAddressRequest)
	network := ibclient.BuildNetworkFromRef(v.PoolID)

	macAddr := v.Options[netlabel.MacAddress]
	if len(macAddr) == 0 {
		macAddr = ibclient.MACADDR_ZERO
		log.Printf("RequestAddressRequest contains empty MAC Address. '%s' will be used.\n", macAddr)
	}

	var fixedAddr *ibclient.FixedAddress
	if v.Address != "" {
		fixedAddr, _ = ibDrv.objMgr.GetFixedAddress(network.NetviewName, v.Address, "")

		if fixedAddr != nil {
			if fixedAddr.Mac == "" {
				fixedAddr.Mac = ibclient.MACADDR_ZERO
			}
			if fixedAddr.Mac != macAddr {
				log.Printf("Requested IP address '%s' is already used by a difference MAC address '%s' (%s)",
					v.Address, fixedAddr.Mac, macAddr)

				return nil, nil
			}
		}
	}

	if fixedAddr == nil {
		fixedAddr, _ = ibDrv.objMgr.AllocateIP(network.NetviewName, network.Cidr, v.Address, macAddr, "")
	}

	return map[string]interface{}{"Address": fmt.Sprintf("%s/%s", fixedAddr.IPAddress, getPrefixLength(network.Cidr))}, nil
}

func (ibDrv *InfobloxDriver) ReleaseAddress(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.ReleaseAddressRequest)
	log.Printf("Releasing Address '%s' from Pool '%s'\n", v.Address, v.PoolID)
	network := ibclient.BuildNetworkFromRef(v.PoolID)
	ref, _ := ibDrv.objMgr.ReleaseIP(network.NetviewName, v.Address, "")
	if ref == "" {
		log.Printf("***** IP Cannot be deleted '%s'! *******\n", v.Address)
	}

	return map[string]interface{}{}, nil
}

func (ibDrv *InfobloxDriver) requestSpecificNetwork(netview string, pool string, networkName string) (*ibclient.Network, error) {
	network, err := ibDrv.objMgr.GetNetwork(netview, pool, nil)
	if err != nil {
		return nil, err
	}
	if network != nil {
		if n, ok := network.Ea["Network Name"]; !ok || n != networkName {
			log.Printf("requestSpecificNetwork: network is already used '%s'", *network)
			return nil, nil
		}
	} else {
		networkByName, err := ibDrv.objMgr.GetNetwork(netview, "", ibclient.EA{"Network Name": networkName})
		if err != nil {
			return nil, err
		}
		if networkByName != nil {
			if networkByName.Cidr != pool {
				log.Printf("requestSpecificNetwork: network name has different Cidr '%s'", networkByName.Cidr)
				return nil, nil
			}
		}
	}

	if network == nil {
		network, err = ibDrv.objMgr.CreateNetwork(netview, pool, networkName)
		log.Printf("requestSpecificNetwork: CreateNetwork returns '%s', err='%s'", *network, err)
	}

	return network, err
}

func (ibDrv *InfobloxDriver) createNetworkContainer(netview string, pool string) (*ibclient.NetworkContainer, error) {
	container, err := ibDrv.objMgr.GetNetworkContainer(netview, pool)
	if container == nil {
		container, err = ibDrv.objMgr.CreateNetworkContainer(netview, pool)
	}

	return container, err
}

func nextAvailableContainer(addrSpace *InfobloxAddressSpace) *Container {
	for i, _ := range addrSpace.Containers {
		if !addrSpace.Containers[i].exhausted {
			return &addrSpace.Containers[i]
		}
	}

	return nil
}

func resetContainers(addrSpace *InfobloxAddressSpace) {
	for i, _ := range addrSpace.Containers {
		addrSpace.Containers[i].exhausted = false
	}
}

func (ibDrv *InfobloxDriver) allocateNetworkHelper(addrSpace *InfobloxAddressSpace, prefixLen uint, networkName string) (network *ibclient.Network, err error) {
	if prefixLen == 0 {
		prefixLen = addrSpace.PrefixLength
	}
	container := nextAvailableContainer(addrSpace)
	for container != nil {
		log.Printf("Allocating network from Container:'%s'", container.NetworkContainer)
		if container.ContainerObj == nil {
			var err error
			container.ContainerObj, err = ibDrv.createNetworkContainer(addrSpace.NetviewName, container.NetworkContainer)
			if err != nil {
				return nil, err
			}
		}
		network, err = ibDrv.objMgr.AllocateNetwork(addrSpace.NetviewName, container.NetworkContainer, prefixLen, networkName)
		if network != nil {
			break
		}
		container.exhausted = true
		container = nextAvailableContainer(addrSpace)
	}

	return network, nil
}

func (ibDrv *InfobloxDriver) allocateNetwork(netview string, prefixLen uint, networkName string) (network *ibclient.Network, err error) {
	addrSpace := ibDrv.addressSpaceByView[netview]

	network, err = ibDrv.allocateNetworkHelper(addrSpace, prefixLen, networkName)
	if network == nil {
		resetContainers(addrSpace)
		network, err = ibDrv.allocateNetworkHelper(addrSpace, prefixLen, networkName)
	}

	if network == nil {
		err = errors.New("Cannot allocate network in Address Space")
	}
	return
}

func (ibDrv *InfobloxDriver) RequestPool(r interface{}) (res map[string]interface{}, err error) {
	v := r.(*ipamsapi.RequestPoolRequest)
	log.Printf("RequestPoolRequest is '%v'\n", v)

	netviewName := ibclient.BuildNetworkViewFromRef(v.AddressSpace).Name

	var network *ibclient.Network
	var networkName string

	if opt, ok := v.Options["network-name"]; ok {
		networkName = opt
	}

	if len(v.Pool) > 0 {
		network, err = ibDrv.requestSpecificNetwork(netviewName, v.Pool, networkName)
	} else {
		var prefixLen uint
		var networkByName *ibclient.Network
		if networkName != "" {
			networkByName, err = ibDrv.objMgr.GetNetwork(netviewName, "", ibclient.EA{"Network Name": networkName})
			if err != nil {
				return
			}
		}
		if networkByName != nil {
			log.Printf("RequestNetwork: GetNetwork by name returns '%s'", *networkByName)
			network = networkByName
		} else {
			if opt, ok := v.Options["prefix-length"]; ok {
				if v, err := strconv.ParseUint(opt, 10, 8); err == nil {
					prefixLen = uint(v)
				}
			}
			network, err = ibDrv.allocateNetwork(netviewName, prefixLen, networkName)
		}
	}

	if network != nil {
		res = map[string]interface{}{"PoolID": network.Ref, "Pool": network.Cidr}
	}
	return
}

func (ibDrv *InfobloxDriver) ReleasePool(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.ReleasePoolRequest)

	if len(v.PoolID) > 0 {
		networkFromRef := ibclient.BuildNetworkFromRef(v.PoolID)
		network, err := ibDrv.objMgr.GetNetwork(networkFromRef.NetviewName, networkFromRef.Cidr, nil)
		if err != nil {
			return map[string]interface{}{}, err
		}

		// if network has a valid looking "Network Name" EA, assume that
		// it is shared with others - hence not deleted.
		if n, ok := network.Ea["Network Name"]; ok && n != "" {
			return map[string]interface{}{}, nil
		}

		ref, _ := ibDrv.objMgr.DeleteNetwork(v.PoolID, networkFromRef.NetviewName)
		if len(ref) > 0 {
			log.Printf("Network %s deleted from Infoblox\n", v.PoolID)
		}
	}

	return map[string]interface{}{}, nil
}

func makeContainers(containerList string) []Container {
	var containers []Container

	parts := strings.Split(containerList, ",")
	for _, p := range parts {
		containers = append(containers, Container{p, nil, false})
	}

	return containers
}

func NewInfobloxDriver(objMgr *ibclient.ObjectManager,
	globalNetview string, globalNetworkContainer string, globalPrefixLength uint,
	localNetview string, localNetworkContainer string, localPrefixLength uint) *InfobloxDriver {

	globalContainers := makeContainers(globalNetworkContainer)
	localContainers := makeContainers(localNetworkContainer)

	globalAddressSpace := &InfobloxAddressSpace{
		globalNetview, globalPrefixLength, globalContainers}
	localAddressSpace := &InfobloxAddressSpace{
		localNetview, localPrefixLength, localContainers}

	return &InfobloxDriver{
		objMgr: objMgr,
		addressSpaceByScope: map[AddressSpaceScope]*InfobloxAddressSpace{
			GLOBAL: globalAddressSpace,
			LOCAL:  localAddressSpace,
		},
		addressSpaceByView: map[string]*InfobloxAddressSpace{
			globalNetview: globalAddressSpace,
			localNetview:  localAddressSpace,
		},
	}
}
<commit_msg>Handle gateway IP allocation for shared pool<commit_after>package main

import (
	"errors"
	"fmt"
	ipamsapi "github.com/docker/libnetwork/ipams/remote/api"
	netlabel "github.com/docker/libnetwork/netlabel"
	ibclient "github.com/infobloxopen/infoblox-go-client"
	"log"
	"strconv"
	"strings"
)

type Container struct {
	NetworkContainer string // CIDR of Network Container
	ContainerObj     *ibclient.NetworkContainer
	exhausted        bool
}

type InfobloxAddressSpace struct {
	NetviewName  string // Network View Name
	PrefixLength uint   // Prefix Length
	Containers   []Container
}

type AddressSpaceScope int

const (
	GLOBAL AddressSpaceScope = iota
	LOCAL
)

type InfobloxDriver struct {
	objMgr              *ibclient.ObjectManager
	addressSpaceByScope map[AddressSpaceScope]*InfobloxAddressSpace
	addressSpaceByView  map[string]*InfobloxAddressSpace
}

func (ibDrv *InfobloxDriver) PluginActivate(r interface{}) (map[string]interface{}, error) {
	return map[string]interface{}{
		"Implements": []interface{}{
			"IpamDriver",
		}}, nil
}

func (ibDrv *InfobloxDriver) GetCapabilities(r interface{}) (map[string]interface{}, error) {
	return map[string]interface{}{"RequiresMACAddress": true}, nil
}

func (ibDrv *InfobloxDriver) GetDefaultAddressSpaces(r interface{}) (map[string]interface{}, error) {
	globalViewRef, localViewRef, err := ibDrv.objMgr.CreateDefaultNetviews(
		ibDrv.addressSpaceByScope[GLOBAL].NetviewName,
		ibDrv.addressSpaceByScope[LOCAL].NetviewName)

	return map[string]interface{}{"GlobalDefaultAddressSpace": globalViewRef, "LocalDefaultAddressSpace": localViewRef}, err
}

func getPrefixLength(cidr string) (prefixLength string) {
	parts := strings.Split(cidr, "/")
	return parts[1]
}

func (ibDrv *InfobloxDriver) RequestAddress(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.RequestAddressRequest)
	network := ibclient.BuildNetworkFromRef(v.PoolID)

	macAddr := v.Options[netlabel.MacAddress]
	if len(macAddr) == 0 {
		macAddr = ibclient.MACADDR_ZERO
		log.Printf("RequestAddressRequest contains empty MAC Address. '%s' will be used.\n", macAddr)
	}

	fixedAddr, _ := ibDrv.objMgr.GetFixedAddress(network.NetviewName, network.Cidr, "", macAddr)
	if fixedAddr != nil {
		if v.Address != "" {
			if fixedAddr.IPAddress != v.Address {
				log.Printf("Requested MAC address '%s' is already associated with a difference IP address '%s' (requested: '%s')",
					macAddr, fixedAddr.IPAddress, v.Address)

				return nil, nil
			}
		}
	}

	if fixedAddr == nil {
		fixedAddr, _ = ibDrv.objMgr.AllocateIP(network.NetviewName, network.Cidr, v.Address, macAddr, "")
	}

	return map[string]interface{}{"Address": fmt.Sprintf("%s/%s", fixedAddr.IPAddress, getPrefixLength(network.Cidr))}, nil
}

func (ibDrv *InfobloxDriver) ReleaseAddress(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.ReleaseAddressRequest)
	log.Printf("Releasing Address '%s' from Pool '%s'\n", v.Address, v.PoolID)
	network := ibclient.BuildNetworkFromRef(v.PoolID)
	ref, _ := ibDrv.objMgr.ReleaseIP(network.NetviewName, network.Cidr, v.Address, "")
	if ref == "" {
		log.Printf("***** IP Cannot be deleted '%s'! *******\n", v.Address)
	}

	return map[string]interface{}{}, nil
}

func (ibDrv *InfobloxDriver) requestSpecificNetwork(netview string, pool string, networkName string) (*ibclient.Network, error) {
	network, err := ibDrv.objMgr.GetNetwork(netview, pool, nil)
	if err != nil {
		return nil, err
	}
	if network != nil {
		if n, ok := network.Ea["Network Name"]; !ok || n != networkName {
			log.Printf("requestSpecificNetwork: network is already used '%s'", *network)
			return nil, nil
		}
	} else {
		networkByName, err := ibDrv.objMgr.GetNetwork(netview, "", ibclient.EA{"Network Name": networkName})
		if err != nil {
			return nil, err
		}
		if networkByName != nil {
			if networkByName.Cidr != pool {
				log.Printf("requestSpecificNetwork: network name has different Cidr '%s'", networkByName.Cidr)
				return nil, nil
			}
		}
	}

	if network == nil {
		network, err = ibDrv.objMgr.CreateNetwork(netview, pool, networkName)
		log.Printf("requestSpecificNetwork: CreateNetwork returns '%s', err='%s'", *network, err)
	}

	return network, err
}

func (ibDrv *InfobloxDriver) createNetworkContainer(netview string, pool string) (*ibclient.NetworkContainer, error) {
	container, err := ibDrv.objMgr.GetNetworkContainer(netview, pool)
	if container == nil {
		container, err = ibDrv.objMgr.CreateNetworkContainer(netview, pool)
	}

	return container, err
}

func nextAvailableContainer(addrSpace *InfobloxAddressSpace) *Container {
	for i, _ := range addrSpace.Containers {
		if !addrSpace.Containers[i].exhausted {
			return &addrSpace.Containers[i]
		}
	}

	return nil
}

func resetContainers(addrSpace *InfobloxAddressSpace) {
	for i, _ := range addrSpace.Containers {
		addrSpace.Containers[i].exhausted = false
	}
}

func (ibDrv *InfobloxDriver) allocateNetworkHelper(addrSpace *InfobloxAddressSpace, prefixLen uint, networkName string) (network *ibclient.Network, err error) {
	if prefixLen == 0 {
		prefixLen = addrSpace.PrefixLength
	}
	container := nextAvailableContainer(addrSpace)
	for container != nil {
		log.Printf("Allocating network from Container:'%s'", container.NetworkContainer)
		if container.ContainerObj == nil {
			var err error
			container.ContainerObj, err = ibDrv.createNetworkContainer(addrSpace.NetviewName, container.NetworkContainer)
			if err != nil {
				return nil, err
			}
		}
		network, err = ibDrv.objMgr.AllocateNetwork(addrSpace.NetviewName, container.NetworkContainer, prefixLen, networkName)
		if network != nil {
			break
		}
		container.exhausted = true
		container = nextAvailableContainer(addrSpace)
	}

	return network, nil
}

func (ibDrv *InfobloxDriver) allocateNetwork(netview string, prefixLen uint, networkName string) (network *ibclient.Network, err error) {
	addrSpace := ibDrv.addressSpaceByView[netview]

	network, err = ibDrv.allocateNetworkHelper(addrSpace, prefixLen, networkName)
	if network == nil {
		resetContainers(addrSpace)
		network, err = ibDrv.allocateNetworkHelper(addrSpace, prefixLen, networkName)
	}

	if network == nil {
		err = errors.New("Cannot allocate network in Address Space")
	}
	return
}

func (ibDrv *InfobloxDriver) RequestPool(r interface{}) (res map[string]interface{}, err error) {
	v := r.(*ipamsapi.RequestPoolRequest)
	log.Printf("RequestPoolRequest is '%v'\n", v)

	netviewName := ibclient.BuildNetworkViewFromRef(v.AddressSpace).Name

	var network *ibclient.Network
	var networkName string

	if opt, ok := v.Options["network-name"]; ok {
		networkName = opt
	}

	if len(v.Pool) > 0 {
		network, err = ibDrv.requestSpecificNetwork(netviewName, v.Pool, networkName)
	} else {
		var prefixLen uint
		var networkByName *ibclient.Network
		if networkName != "" {
			networkByName, err = ibDrv.objMgr.GetNetwork(netviewName, "", ibclient.EA{"Network Name": networkName})
			if err != nil {
				return
			}
		}
		if networkByName != nil {
			log.Printf("RequestNetwork: GetNetwork by name returns '%s'", *networkByName)
			network = networkByName
		} else {
			if opt, ok := v.Options["prefix-length"]; ok {
				if v, err := strconv.ParseUint(opt, 10, 8); err == nil {
					prefixLen = uint(v)
				}
			}
			network, err = ibDrv.allocateNetwork(netviewName, prefixLen, networkName)
		}
	}

	if network != nil {
		res = map[string]interface{}{"PoolID": network.Ref, "Pool": network.Cidr}
	}
	return
}

func (ibDrv *InfobloxDriver) ReleasePool(r interface{}) (map[string]interface{}, error) {
	v := r.(*ipamsapi.ReleasePoolRequest)

	if len(v.PoolID) > 0 {
		networkFromRef := ibclient.BuildNetworkFromRef(v.PoolID)
		network, err := ibDrv.objMgr.GetNetwork(networkFromRef.NetviewName, networkFromRef.Cidr, nil)
		if err != nil {
			return map[string]interface{}{}, err
		}

		// if network has a valid looking "Network Name" EA, assume that
		// it is shared with others - hence not deleted.
		if n, ok := network.Ea["Network Name"]; ok && n != "" {
			return map[string]interface{}{}, nil
		}

		ref, _ := ibDrv.objMgr.DeleteNetwork(v.PoolID, networkFromRef.NetviewName)
		if len(ref) > 0 {
			log.Printf("Network %s deleted from Infoblox\n", v.PoolID)
		}
	}

	return map[string]interface{}{}, nil
}

func makeContainers(containerList string) []Container {
	var containers []Container

	parts := strings.Split(containerList, ",")
	for _, p := range parts {
		containers = append(containers, Container{p, nil, false})
	}

	return containers
}

func NewInfobloxDriver(objMgr *ibclient.ObjectManager,
	globalNetview string, globalNetworkContainer string, globalPrefixLength uint,
	localNetview string, localNetworkContainer string, localPrefixLength uint) *InfobloxDriver {

	globalContainers := makeContainers(globalNetworkContainer)
	localContainers := makeContainers(localNetworkContainer)

	globalAddressSpace := &InfobloxAddressSpace{
		globalNetview, globalPrefixLength, globalContainers}
	localAddressSpace := &InfobloxAddressSpace{
		localNetview, localPrefixLength, localContainers}

	return &InfobloxDriver{
		objMgr: objMgr,
		addressSpaceByScope: map[AddressSpaceScope]*InfobloxAddressSpace{
			GLOBAL: globalAddressSpace,
			LOCAL:  localAddressSpace,
		},
		addressSpaceByView: map[string]*InfobloxAddressSpace{
			globalNetview: globalAddressSpace,
			localNetview:  localAddressSpace,
		},
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Apcera Inc. All rights reserved.

package nats

import (
	"bytes"
//	"fmt"
	"testing"
	"time"
)

func NewEConn(t *testing.T) *EncodedConn {
	ec, err := NewEncodedConn(newConnection(t), "default")
	if err != nil {
		t.Fatalf("Failed to create an encoded connection: %v\n", err)
	}
	return ec
}

func TestMarshalString(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testString := "Hello World!"

	ec.Subscribe("enc_string", func(s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		ch <- true
	})
	ec.Publish("enc_string", testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalBytes(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testBytes := []byte("Hello World!")

	ec.Subscribe("enc_bytes", func(b []byte) {
		if !bytes.Equal(b, testBytes) {
			t.Fatalf("Got test bytes of '%s', wanted '%s'\n", b, testBytes)
		}
		ch <- true
	})
	ec.Publish("enc_bytes", testBytes)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt32(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int32) {
		if n != int32(testN) {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt64(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int64) {
		if n != int64(testN) {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalFloat32(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := float32(22)

	ec.Subscribe("enc_float", func(n float32) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_float", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalFloat64(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := float64(22.22)

	ec.Subscribe("enc_float", func(n float64) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_float", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalBool(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	ec.Subscribe("enc_bool", func(b bool) {
		if b != false {
			t.Fatal("Boolean values did not match")
		}
		ch <- true
	})
	ec.Publish("enc_bool", false)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestExtendedSubscribeCB(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	subject := "cb_args"

	ec.Subscribe(subject, func(subj, s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		if subj != subject {
			t.Fatalf("Got subject of '%s', wanted '%s'\n", subj, subject)
		}
		ch <- true
	})
	ec.Publish(subject, testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestExtendedSubscribeCB2(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	oSubj  := "cb_args"
	oReply := "foobar"

	ec.Subscribe(oSubj, func(subj, reply, s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		if subj != oSubj {
			t.Fatalf("Got subject of '%s', wanted '%s'\n", subj, oSubj)
		}
		if reply != oReply {
			t.Fatalf("Got reply of '%s', wanted '%s'\n", reply, oReply)
		}
		ch <- true
	})
	ec.PublishRequest(oSubj, oReply, testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestEncRequest(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ec.Subscribe("help", func(subj, reply, req string) {
		ec.Publish(reply, "I can help!")
	})

	var resp string

	err := ec.Request("help", "help me", &resp, 100*time.Millisecond)
	if err != nil {
		t.Fatalf("Failed receiving proper response: %v\n", err)
	}
}

func TestEncRequestReceivesMsg(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ec.Subscribe("help", func(subj, reply, req string) {
		ec.Publish(reply, "I can help!")
	})

	var resp Msg

	err := ec.Request("help", "help me", &resp, 100*time.Millisecond)
	if err != nil {
		t.Fatalf("Failed receiving proper response: %v\n", err)
	}
}

func TestAsyncMarshalErr(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	subject := "err_marshall"

	ec.Subscribe(subject, func(subj, num int) {
		// This will never get called.
	})

	ec.Conn.Opts.AsynchErrorCB = func(c *Conn, s *Subscription, err error) {
		ch <- true
	}

	ec.Publish(subject, testString)
	if e := wait(ch); e != nil {
		t.Fatalf("Did not receive the message: %s", e)
	}
}<commit_msg>Removed fmt import<commit_after>// Copyright 2012 Apcera Inc. All rights reserved.

package nats

import (
	"bytes"
	"testing"
	"time"
)

func NewEConn(t *testing.T) *EncodedConn {
	ec, err := NewEncodedConn(newConnection(t), "default")
	if err != nil {
		t.Fatalf("Failed to create an encoded connection: %v\n", err)
	}
	return ec
}

func TestMarshalString(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testString := "Hello World!"

	ec.Subscribe("enc_string", func(s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		ch <- true
	})
	ec.Publish("enc_string", testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalBytes(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testBytes := []byte("Hello World!")

	ec.Subscribe("enc_bytes", func(b []byte) {
		if !bytes.Equal(b, testBytes) {
			t.Fatalf("Got test bytes of '%s', wanted '%s'\n", b, testBytes)
		}
		ch <- true
	})
	ec.Publish("enc_bytes", testBytes)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt32(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int32) {
		if n != int32(testN) {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalInt64(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := 22

	ec.Subscribe("enc_int", func(n int64) {
		if n != int64(testN) {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_int", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalFloat32(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := float32(22)

	ec.Subscribe("enc_float", func(n float32) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_float", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalFloat64(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	testN := float64(22.22)

	ec.Subscribe("enc_float", func(n float64) {
		if n != testN {
			t.Fatalf("Got test number of %d, wanted %d\n", n, testN)
		}
		ch <- true
	})
	ec.Publish("enc_float", testN)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestMarshalBool(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()
	ch := make(chan bool)

	ec.Subscribe("enc_bool", func(b bool) {
		if b != false {
			t.Fatal("Boolean values did not match")
		}
		ch <- true
	})
	ec.Publish("enc_bool", false)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestExtendedSubscribeCB(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	subject := "cb_args"

	ec.Subscribe(subject, func(subj, s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		if subj != subject {
			t.Fatalf("Got subject of '%s', wanted '%s'\n", subj, subject)
		}
		ch <- true
	})
	ec.Publish(subject, testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestExtendedSubscribeCB2(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	oSubj  := "cb_args"
	oReply := "foobar"

	ec.Subscribe(oSubj, func(subj, reply, s string) {
		if s != testString {
			t.Fatalf("Got test string of '%s', wanted '%s'\n", s, testString)
		}
		if subj != oSubj {
			t.Fatalf("Got subject of '%s', wanted '%s'\n", subj, oSubj)
		}
		if reply != oReply {
			t.Fatalf("Got reply of '%s', wanted '%s'\n", reply, oReply)
		}
		ch <- true
	})
	ec.PublishRequest(oSubj, oReply, testString)
	if e := wait(ch); e != nil {
		if ec.LastError() != nil {
			e = ec.LastError()
		}
		t.Fatalf("Did not receive the message: %s", e)
	}
}

func TestEncRequest(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ec.Subscribe("help", func(subj, reply, req string) {
		ec.Publish(reply, "I can help!")
	})

	var resp string

	err := ec.Request("help", "help me", &resp, 100*time.Millisecond)
	if err != nil {
		t.Fatalf("Failed receiving proper response: %v\n", err)
	}
}

func TestEncRequestReceivesMsg(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ec.Subscribe("help", func(subj, reply, req string) {
		ec.Publish(reply, "I can help!")
	})

	var resp Msg

	err := ec.Request("help", "help me", &resp, 100*time.Millisecond)
	if err != nil {
		t.Fatalf("Failed receiving proper response: %v\n", err)
	}
}

func TestAsyncMarshalErr(t *testing.T) {
	ec := NewEConn(t)
	defer ec.Close()

	ch := make(chan bool)

	testString := "Hello World!"
	subject := "err_marshall"

	ec.Subscribe(subject, func(subj, num int) {
		// This will never get called.
	})

	ec.Conn.Opts.AsynchErrorCB = func(c *Conn, s *Subscription, err error) {
		ch <- true
	}

	ec.Publish(subject, testString)
	if e := wait(ch); e != nil {
		t.Fatalf("Did not receive the message: %s", e)
	}
}<|endoftext|>


<commit_before>package exchange

import (
	"context"
	"encoding/json"
	"errors"

	"github.com/buger/jsonparser"
	"github.com/mxmCherry/openrtb"
	"github.com/prebid/prebid-server/adapters"
	"github.com/prebid/prebid-server/openrtb_ext"
	"github.com/prebid/prebid-server/pbs"
)

// AdaptLegacyAdapter turns a bidder.Adapter into an adaptedBidder.
//
// This is a temporary function which helps make the transition to OpenRTB smooth. Bidders which have not been
// updated yet can use this to be "OpenRTB-ish". They'll bid as well as they can, given the limitations of the
// legacy protocol
func adaptLegacyAdapter(adapter adapters.Adapter) adaptedBidder {
	return &adaptedAdapter{
		adapter: adapter,
	}
}

type adaptedAdapter struct {
	adapter adapters.Adapter
}

// requestBid attempts to bid on OpenRTB requests using the legacy protocol.
//
// This is not ideal. OpenRTB provides a superset of the legacy data structures.
// For requests which use those features, the best we can do is respond with "no bid".
func (bidder *adaptedAdapter) requestBid(ctx context.Context, request *openrtb.BidRequest, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbSeatBid, []error) {
	legacyRequest, legacyBidder, errs := bidder.toLegacyAdapterInputs(request, name)
	if legacyRequest == nil || legacyBidder == nil {
		return nil, errs
	}

	legacyBids, err := bidder.adapter.Call(ctx, legacyRequest, legacyBidder)
	if err != nil {
		errs = append(errs, err)
	}

	finalResponse, moreErrs := toNewResponse(legacyBids, legacyBidder, bidderTarg, name)
	return finalResponse, append(errs, moreErrs...)
}

// ----------------------------------------------------------------------------
// Request transformations.

// toLegacyAdapterInputs is a best-effort transformation of an OpenRTB BidRequest into the args needed to run a legacy Adapter.
// If the OpenRTB request is too complex, it fails with an error.
// If the error is nil, then the PBSRequest and PBSBidder are valid.
func (bidder *adaptedAdapter) toLegacyAdapterInputs(req *openrtb.BidRequest, name openrtb_ext.BidderName) (*pbs.PBSRequest, *pbs.PBSBidder, []error) {
	legacyReq, err := bidder.toLegacyRequest(req)
	if err != nil {
		return nil, nil, []error{err}
	}

	legacyBidder, errs := toLegacyBidder(req, name)
	if legacyBidder == nil {
		return nil, nil, errs
	}

	return legacyReq, legacyBidder, errs
}

func (bidder *adaptedAdapter) toLegacyRequest(req *openrtb.BidRequest) (*pbs.PBSRequest, error) {
	acctId, err := toAccountId(req)
	if err != nil {
		return nil, err
	}

	tId, err := toTransactionId(req)
	if err != nil {
		return nil, err
	}

	isSecure, err := toSecure(req)
	if err != nil {
		return nil, err
	}

	isDebug := false
	if req.Test == 1 {
		isDebug = true
	}

	url := ""
	domain := ""
	if req.Site != nil {
		url = req.Site.Page
		domain = req.Site.Domain
	}

	cookie := pbs.NewPBSCookie()
	if req.User != nil {
		if req.User.BuyerUID != "" {
			cookie.TrySync(bidder.adapter.FamilyName(), req.User.BuyerUID)
		}

		// This shouldn't be appnexus-specific... but this line does correctly invert the
		// logic from adapters/openrtb_util.go, which will preserve this questionable behavior in legacy adapters.
		if req.User.ID != "" {
			cookie.TrySync("adnxs", req.User.ID)
		}
	}

	return &pbs.PBSRequest{
		AccountID: acctId,
		Tid:       tId,
		// CacheMarkup is excluded because no legacy adapters read from it
		// SortBids is excluded because no legacy adapters read from it
		// MaxKeyLength is excluded because no legacy adapters read from it
		Secure:        isSecure,
		TimeoutMillis: req.TMax,
		// AdUnits is excluded because no legacy adapters read from it
		IsDebug: isDebug,
		App:     req.App,
		Device:  req.Device,
		// PBSUser is excluded because rubicon is the only adapter which reads from it, and they're supporting OpenRTB directly
		// SDK is excluded because that information doesn't exist in OpenRTB.
		// Bidders is excluded because no legacy adapters read from it
		User:   req.User,
		Cookie: cookie,
		Url:    url,
		Domain: domain,
		// Start is excluded because no legacy adapters read from it
	}, nil
}

func toAccountId(req *openrtb.BidRequest) (string, error) {
	if req.Site != nil && req.Site.Publisher != nil {
		return req.Site.Publisher.ID, nil
	}
	if req.App != nil && req.App.Publisher != nil {
		return req.App.Publisher.ID, nil
	}
	return "", errors.New("bidrequest.site.publisher.id or bidrequest.app.publisher.id required for legacy bidders.")
}

func toTransactionId(req *openrtb.BidRequest) (string, error) {
	if req.Source != nil {
		return req.Source.TID, nil
	}
	return "", errors.New("bidrequest.source.tid required for legacy bidders.")
}

func toSecure(req *openrtb.BidRequest) (secure int8, err error) {
	secure = -1
	for _, imp := range req.Imp {
		if imp.Secure != nil {
			thisVal := *imp.Secure
			if thisVal == 0 {
				if secure == 1 {
					err = errors.New("bidrequest.imp[i].secure must be consistent for legacy bidders. Mixing 0 and 1 are not allowed.")
					return
				}
				secure = 0
			} else if thisVal == 1 {
				if secure == 0 {
					err = errors.New("bidrequest.imp[i].secure must be consistent for legacy bidders. Mixing 0 and 1 are not allowed.")
					return
				}
				secure = 1
			}
		}
	}
	if secure == -1 {
		secure = 0
	}

	return
}

func toLegacyBidder(req *openrtb.BidRequest, name openrtb_ext.BidderName) (*pbs.PBSBidder, []error) {
	adUnits, errs := toPBSAdUnits(req)
	if len(adUnits) > 0 {
		return &pbs.PBSBidder{
			BidderCode: string(name),
			// AdUnitCode is excluded because no legacy adapters read from it
			// ResponseTime is excluded because no legacy adapters read from it
			// NumBids is excluded because no legacy adapters read from it
			// Error is excluded because no legacy adapters read from it
			// NoCookie is excluded because no legacy adapters read from it
			// NoBid is excluded because no legacy adapters read from it
			// UsersyncInfo is excluded because no legacy adapters read from it
			// Debug is excluded because legacy adapters only use it in nil-safe ways.
			//   They *do* write to it, though, so it may be read when unpacking the response.
			AdUnits: adUnits,
		}, errs
	} else {
		return nil, errs
	}
}

func toPBSAdUnits(req *openrtb.BidRequest) ([]pbs.PBSAdUnit, []error) {
	adUnits := make([]pbs.PBSAdUnit, len(req.Imp))
	var errs []error = nil
	nextAdUnit := 0
	for i := 0; i < len(req.Imp); i++ {
		err := initPBSAdUnit(&(req.Imp[i]), &(adUnits[nextAdUnit]))
		if err != nil {
			errs = append(errs, err)
		} else {
			nextAdUnit++
		}
	}
	return adUnits[:nextAdUnit], errs
}

func initPBSAdUnit(imp *openrtb.Imp, adUnit *pbs.PBSAdUnit) error {
	video := pbs.PBSVideo{}
	if imp.Video != nil {
		video.Mimes = imp.Video.MIMEs
		video.Minduration = imp.Video.MinDuration
		video.Maxduration = imp.Video.MaxDuration
		if imp.Video.StartDelay != nil {
			video.Startdelay = int64(*imp.Video.StartDelay)
		}
		if imp.Video.Skip != nil {
			video.Skippable = int(*imp.Video.Skip)
		}
		if len(imp.Video.PlaybackMethod) == 1 {
			video.PlaybackMethod = int8(imp.Video.PlaybackMethod[0])
		}
		if len(imp.Video.Protocols) > 0 {
			video.Protocols = make([]int8, len(imp.Video.Protocols))
			for i := 0; i < len(imp.Video.Protocols); i++ {
				video.Protocols[i] = int8(imp.Video.Protocols[i])
			}
		}
	}
	topFrame := int8(0)
	var sizes []openrtb.Format = nil
	if imp.Banner != nil {
		topFrame = imp.Banner.TopFrame
		sizes = imp.Banner.Format
	}

	params, _, _, err := jsonparser.Get(imp.Ext, "bidder")
	if err != nil {
		return err
	}

	mediaTypes := make([]pbs.MediaType, 0, 2)
	if imp.Banner != nil {
		mediaTypes = append(mediaTypes, pbs.MEDIA_TYPE_BANNER)
	}
	if imp.Video != nil {
		mediaTypes = append(mediaTypes, pbs.MEDIA_TYPE_VIDEO)
	}
	if len(mediaTypes) == 0 {
		return errors.New("legacy bidders can only bid on banner and video ad units")
	}

	adUnit.Sizes = sizes
	adUnit.TopFrame = topFrame
	adUnit.Code = imp.ID
	adUnit.BidID = imp.ID
	adUnit.Params = json.RawMessage(params)
	adUnit.Video = video
	adUnit.MediaTypes = mediaTypes
	adUnit.Instl = imp.Instl

	return nil
}

// ----------------------------------------------------------------------------
// Response transformations.

// toNewResponse is a best-effort transformation of legacy Bids into an OpenRTB response.
func toNewResponse(bids pbs.PBSBidSlice, bidder *pbs.PBSBidder, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbSeatBid, []error) {
	newBids, errs := transformBids(bids, bidderTarg, name)
	return &pbsOrtbSeatBid{
		bids:      newBids,
		httpCalls: transformDebugs(bidder.Debug),
	}, errs
}

func transformBids(legacyBids pbs.PBSBidSlice, bidderTarg *targetData, name openrtb_ext.BidderName) ([]*pbsOrtbBid, []error) {
	newBids := make([]*pbsOrtbBid, 0, len(legacyBids))
	var errs []error = nil
	for _, legacyBid := range legacyBids {
		if legacyBid != nil {
			newBid, err := transformBid(legacyBid, bidderTarg, name)
			if err == nil {
				newBids = append(newBids, newBid)
			} else {
				errs = append(errs, err)
			}
		}
	}
	return newBids, errs
}

func transformBid(legacyBid *pbs.PBSBid, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbBid, error) {
	newBid := transformBidToOrtb(legacyBid)

	newBidType, err := openrtb_ext.ParseBidType(legacyBid.CreativeMediaType)
	if err != nil {
		return nil, err
	}

	targets, err := bidderTarg.makePrebidTargets(name, newBid)
	if err != nil {
		return nil, err
	}

	return &pbsOrtbBid{
		bid:        newBid,
		bidType:    newBidType,
		bidTargets: targets,
	}, nil
}

func transformBidToOrtb(legacyBid *pbs.PBSBid) *openrtb.Bid {
	return &openrtb.Bid{
		ID:    legacyBid.BidID,
		ImpID: legacyBid.AdUnitCode,
		CrID:  legacyBid.Creative_id,
		// legacyBid.CreativeMediaType is handled by transformBid(), because it doesn't exist on the openrtb.Bid
		// legacyBid.BidderCode is handled by the exchange, which already knows which bidder we are.
		// legacyBid.BidHash is ignored, because it doesn't get sent in the response anyway
		Price:  legacyBid.Price,
		NURL:   legacyBid.NURL,
		AdM:    legacyBid.Adm,
		W:      legacyBid.Width,
		H:      legacyBid.Height,
		DealID: legacyBid.DealId,
		// TODO #216: Support CacheID here
		// TODO: #216: Support CacheURL here
		// ResponseTime is handled by the exchange, since it doesn't exist in the OpenRTB Bid
		// AdServerTargeting is handled by the exchange. Rubicon's adapter is the only one which writes to it,
		//   but that doesn't matter since they're supporting OpenRTB directly.
	}
}

func transformDebugs(legacyDebugs []*pbs.BidderDebug) []*openrtb_ext.ExtHttpCall {
	newDebug := make([]*openrtb_ext.ExtHttpCall, 0, len(legacyDebugs))
	for _, legacyDebug := range legacyDebugs {
		if legacyDebug != nil {
			newDebug = append(newDebug, transformDebug(legacyDebug))
		}
	}
	return newDebug
}

func transformDebug(legacyDebug *pbs.BidderDebug) *openrtb_ext.ExtHttpCall {
	return &openrtb_ext.ExtHttpCall{
		Uri:          legacyDebug.RequestURI,
		RequestBody:  legacyDebug.RequestBody,
		ResponseBody: legacyDebug.ResponseBody,
		Status:       legacyDebug.StatusCode,
	}
}
<commit_msg>Supported video sizes for legacy bidders. (#364)<commit_after>package exchange

import (
	"context"
	"encoding/json"
	"errors"

	"github.com/buger/jsonparser"
	"github.com/mxmCherry/openrtb"
	"github.com/prebid/prebid-server/adapters"
	"github.com/prebid/prebid-server/openrtb_ext"
	"github.com/prebid/prebid-server/pbs"
)

// AdaptLegacyAdapter turns a bidder.Adapter into an adaptedBidder.
//
// This is a temporary function which helps make the transition to OpenRTB smooth. Bidders which have not been
// updated yet can use this to be "OpenRTB-ish". They'll bid as well as they can, given the limitations of the
// legacy protocol
func adaptLegacyAdapter(adapter adapters.Adapter) adaptedBidder {
	return &adaptedAdapter{
		adapter: adapter,
	}
}

type adaptedAdapter struct {
	adapter adapters.Adapter
}

// requestBid attempts to bid on OpenRTB requests using the legacy protocol.
//
// This is not ideal. OpenRTB provides a superset of the legacy data structures.
// For requests which use those features, the best we can do is respond with "no bid".
func (bidder *adaptedAdapter) requestBid(ctx context.Context, request *openrtb.BidRequest, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbSeatBid, []error) {
	legacyRequest, legacyBidder, errs := bidder.toLegacyAdapterInputs(request, name)
	if legacyRequest == nil || legacyBidder == nil {
		return nil, errs
	}

	legacyBids, err := bidder.adapter.Call(ctx, legacyRequest, legacyBidder)
	if err != nil {
		errs = append(errs, err)
	}

	finalResponse, moreErrs := toNewResponse(legacyBids, legacyBidder, bidderTarg, name)
	return finalResponse, append(errs, moreErrs...)
}

// ----------------------------------------------------------------------------
// Request transformations.

// toLegacyAdapterInputs is a best-effort transformation of an OpenRTB BidRequest into the args needed to run a legacy Adapter.
// If the OpenRTB request is too complex, it fails with an error.
// If the error is nil, then the PBSRequest and PBSBidder are valid.
func (bidder *adaptedAdapter) toLegacyAdapterInputs(req *openrtb.BidRequest, name openrtb_ext.BidderName) (*pbs.PBSRequest, *pbs.PBSBidder, []error) {
	legacyReq, err := bidder.toLegacyRequest(req)
	if err != nil {
		return nil, nil, []error{err}
	}

	legacyBidder, errs := toLegacyBidder(req, name)
	if legacyBidder == nil {
		return nil, nil, errs
	}

	return legacyReq, legacyBidder, errs
}

func (bidder *adaptedAdapter) toLegacyRequest(req *openrtb.BidRequest) (*pbs.PBSRequest, error) {
	acctId, err := toAccountId(req)
	if err != nil {
		return nil, err
	}

	tId, err := toTransactionId(req)
	if err != nil {
		return nil, err
	}

	isSecure, err := toSecure(req)
	if err != nil {
		return nil, err
	}

	isDebug := false
	if req.Test == 1 {
		isDebug = true
	}

	url := ""
	domain := ""
	if req.Site != nil {
		url = req.Site.Page
		domain = req.Site.Domain
	}

	cookie := pbs.NewPBSCookie()
	if req.User != nil {
		if req.User.BuyerUID != "" {
			cookie.TrySync(bidder.adapter.FamilyName(), req.User.BuyerUID)
		}

		// This shouldn't be appnexus-specific... but this line does correctly invert the
		// logic from adapters/openrtb_util.go, which will preserve this questionable behavior in legacy adapters.
		if req.User.ID != "" {
			cookie.TrySync("adnxs", req.User.ID)
		}
	}

	return &pbs.PBSRequest{
		AccountID: acctId,
		Tid:       tId,
		// CacheMarkup is excluded because no legacy adapters read from it
		// SortBids is excluded because no legacy adapters read from it
		// MaxKeyLength is excluded because no legacy adapters read from it
		Secure:        isSecure,
		TimeoutMillis: req.TMax,
		// AdUnits is excluded because no legacy adapters read from it
		IsDebug: isDebug,
		App:     req.App,
		Device:  req.Device,
		// PBSUser is excluded because rubicon is the only adapter which reads from it, and they're supporting OpenRTB directly
		// SDK is excluded because that information doesn't exist in OpenRTB.
		// Bidders is excluded because no legacy adapters read from it
		User:   req.User,
		Cookie: cookie,
		Url:    url,
		Domain: domain,
		// Start is excluded because no legacy adapters read from it
	}, nil
}

func toAccountId(req *openrtb.BidRequest) (string, error) {
	if req.Site != nil && req.Site.Publisher != nil {
		return req.Site.Publisher.ID, nil
	}
	if req.App != nil && req.App.Publisher != nil {
		return req.App.Publisher.ID, nil
	}
	return "", errors.New("bidrequest.site.publisher.id or bidrequest.app.publisher.id required for legacy bidders.")
}

func toTransactionId(req *openrtb.BidRequest) (string, error) {
	if req.Source != nil {
		return req.Source.TID, nil
	}
	return "", errors.New("bidrequest.source.tid required for legacy bidders.")
}

func toSecure(req *openrtb.BidRequest) (secure int8, err error) {
	secure = -1
	for _, imp := range req.Imp {
		if imp.Secure != nil {
			thisVal := *imp.Secure
			if thisVal == 0 {
				if secure == 1 {
					err = errors.New("bidrequest.imp[i].secure must be consistent for legacy bidders. Mixing 0 and 1 are not allowed.")
					return
				}
				secure = 0
			} else if thisVal == 1 {
				if secure == 0 {
					err = errors.New("bidrequest.imp[i].secure must be consistent for legacy bidders. Mixing 0 and 1 are not allowed.")
					return
				}
				secure = 1
			}
		}
	}
	if secure == -1 {
		secure = 0
	}

	return
}

func toLegacyBidder(req *openrtb.BidRequest, name openrtb_ext.BidderName) (*pbs.PBSBidder, []error) {
	adUnits, errs := toPBSAdUnits(req)
	if len(adUnits) > 0 {
		return &pbs.PBSBidder{
			BidderCode: string(name),
			// AdUnitCode is excluded because no legacy adapters read from it
			// ResponseTime is excluded because no legacy adapters read from it
			// NumBids is excluded because no legacy adapters read from it
			// Error is excluded because no legacy adapters read from it
			// NoCookie is excluded because no legacy adapters read from it
			// NoBid is excluded because no legacy adapters read from it
			// UsersyncInfo is excluded because no legacy adapters read from it
			// Debug is excluded because legacy adapters only use it in nil-safe ways.
			//   They *do* write to it, though, so it may be read when unpacking the response.
			AdUnits: adUnits,
		}, errs
	} else {
		return nil, errs
	}
}

func toPBSAdUnits(req *openrtb.BidRequest) ([]pbs.PBSAdUnit, []error) {
	adUnits := make([]pbs.PBSAdUnit, len(req.Imp))
	var errs []error = nil
	nextAdUnit := 0
	for i := 0; i < len(req.Imp); i++ {
		err := initPBSAdUnit(&(req.Imp[i]), &(adUnits[nextAdUnit]))
		if err != nil {
			errs = append(errs, err)
		} else {
			nextAdUnit++
		}
	}
	return adUnits[:nextAdUnit], errs
}

func initPBSAdUnit(imp *openrtb.Imp, adUnit *pbs.PBSAdUnit) error {
	var sizes []openrtb.Format = nil

	video := pbs.PBSVideo{}
	if imp.Video != nil {
		video.Mimes = imp.Video.MIMEs
		video.Minduration = imp.Video.MinDuration
		video.Maxduration = imp.Video.MaxDuration
		if imp.Video.StartDelay != nil {
			video.Startdelay = int64(*imp.Video.StartDelay)
		}
		if imp.Video.Skip != nil {
			video.Skippable = int(*imp.Video.Skip)
		}
		if len(imp.Video.PlaybackMethod) == 1 {
			video.PlaybackMethod = int8(imp.Video.PlaybackMethod[0])
		}
		if len(imp.Video.Protocols) > 0 {
			video.Protocols = make([]int8, len(imp.Video.Protocols))
			for i := 0; i < len(imp.Video.Protocols); i++ {
				video.Protocols[i] = int8(imp.Video.Protocols[i])
			}
		}
		// Fixes #360
		if imp.Video.W != 0 && imp.Video.H != 0 {
			sizes = append(sizes, openrtb.Format{
				W: imp.Video.W,
				H: imp.Video.H,
			})
		}
	}
	topFrame := int8(0)
	if imp.Banner != nil {
		topFrame = imp.Banner.TopFrame
		sizes = append(sizes, imp.Banner.Format...)
	}

	params, _, _, err := jsonparser.Get(imp.Ext, "bidder")
	if err != nil {
		return err
	}

	mediaTypes := make([]pbs.MediaType, 0, 2)
	if imp.Banner != nil {
		mediaTypes = append(mediaTypes, pbs.MEDIA_TYPE_BANNER)
	}
	if imp.Video != nil {
		mediaTypes = append(mediaTypes, pbs.MEDIA_TYPE_VIDEO)
	}
	if len(mediaTypes) == 0 {
		return errors.New("legacy bidders can only bid on banner and video ad units")
	}

	adUnit.Sizes = sizes
	adUnit.TopFrame = topFrame
	adUnit.Code = imp.ID
	adUnit.BidID = imp.ID
	adUnit.Params = json.RawMessage(params)
	adUnit.Video = video
	adUnit.MediaTypes = mediaTypes
	adUnit.Instl = imp.Instl

	return nil
}

// ----------------------------------------------------------------------------
// Response transformations.

// toNewResponse is a best-effort transformation of legacy Bids into an OpenRTB response.
func toNewResponse(bids pbs.PBSBidSlice, bidder *pbs.PBSBidder, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbSeatBid, []error) {
	newBids, errs := transformBids(bids, bidderTarg, name)
	return &pbsOrtbSeatBid{
		bids:      newBids,
		httpCalls: transformDebugs(bidder.Debug),
	}, errs
}

func transformBids(legacyBids pbs.PBSBidSlice, bidderTarg *targetData, name openrtb_ext.BidderName) ([]*pbsOrtbBid, []error) {
	newBids := make([]*pbsOrtbBid, 0, len(legacyBids))
	var errs []error = nil
	for _, legacyBid := range legacyBids {
		if legacyBid != nil {
			newBid, err := transformBid(legacyBid, bidderTarg, name)
			if err == nil {
				newBids = append(newBids, newBid)
			} else {
				errs = append(errs, err)
			}
		}
	}
	return newBids, errs
}

func transformBid(legacyBid *pbs.PBSBid, bidderTarg *targetData, name openrtb_ext.BidderName) (*pbsOrtbBid, error) {
	newBid := transformBidToOrtb(legacyBid)

	newBidType, err := openrtb_ext.ParseBidType(legacyBid.CreativeMediaType)
	if err != nil {
		return nil, err
	}

	targets, err := bidderTarg.makePrebidTargets(name, newBid)
	if err != nil {
		return nil, err
	}

	return &pbsOrtbBid{
		bid:        newBid,
		bidType:    newBidType,
		bidTargets: targets,
	}, nil
}

func transformBidToOrtb(legacyBid *pbs.PBSBid) *openrtb.Bid {
	return &openrtb.Bid{
		ID:    legacyBid.BidID,
		ImpID: legacyBid.AdUnitCode,
		CrID:  legacyBid.Creative_id,
		// legacyBid.CreativeMediaType is handled by transformBid(), because it doesn't exist on the openrtb.Bid
		// legacyBid.BidderCode is handled by the exchange, which already knows which bidder we are.
		// legacyBid.BidHash is ignored, because it doesn't get sent in the response anyway
		Price:  legacyBid.Price,
		NURL:   legacyBid.NURL,
		AdM:    legacyBid.Adm,
		W:      legacyBid.Width,
		H:      legacyBid.Height,
		DealID: legacyBid.DealId,
		// TODO #216: Support CacheID here
		// TODO: #216: Support CacheURL here
		// ResponseTime is handled by the exchange, since it doesn't exist in the OpenRTB Bid
		// AdServerTargeting is handled by the exchange. Rubicon's adapter is the only one which writes to it,
		//   but that doesn't matter since they're supporting OpenRTB directly.
	}
}

func transformDebugs(legacyDebugs []*pbs.BidderDebug) []*openrtb_ext.ExtHttpCall {
	newDebug := make([]*openrtb_ext.ExtHttpCall, 0, len(legacyDebugs))
	for _, legacyDebug := range legacyDebugs {
		if legacyDebug != nil {
			newDebug = append(newDebug, transformDebug(legacyDebug))
		}
	}
	return newDebug
}

func transformDebug(legacyDebug *pbs.BidderDebug) *openrtb_ext.ExtHttpCall {
	return &openrtb_ext.ExtHttpCall{
		Uri:          legacyDebug.RequestURI,
		RequestBody:  legacyDebug.RequestBody,
		ResponseBody: legacyDebug.ResponseBody,
		Status:       legacyDebug.StatusCode,
	}
}
<|endoftext|>


<commit_before>package kdtree

import (
	"geo"
	"graph"
	"math"
	"math/rand"
	"testing"
	"time"
)

const (
	DataSetSize = 100000 // more important to the performance
	Repeats     = 10000
)

var nodeData = createData(DataSetSize, false)
var repeatsNodeData = createData(DataSetSize, true)

func createData(size int, repeats bool) []geo.Coordinate {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))

	nodeData := make([]geo.Coordinate, size)
	for i := 0; i < size; i++ {
		lat, lng := rnd.Float64(), rnd.Float64()
		nodeData[i] = geo.Coordinate{lat, lng}

		// insert coordinates that have the same lat/lng (ugly corner case)
		if repeats {
			if rnd.Intn(5) == 0 {
				up := i + 2 + rnd.Intn(100)
				for i++; i < up && i < size; i++ {
					nodeData[i] = geo.Coordinate{lat, rnd.Float64()}
				}
				i--
			}
			if rnd.Intn(5) == 0 {
				up := i + 2 + rnd.Intn(100)
				for i++; i < up && i < size; i++ {
					nodeData[i] = geo.Coordinate{rnd.Float64(), lng}
				}
				i--
			}
		}
	}
	return nodeData
}

func TestEncoding(t *testing.T) {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))
	maxNum := int64(math.Pow(2, TotalBits) - 1)
	data := make([]uint64, DataSetSize)
	for i, _ := range data {
		data[i] = uint64(rnd.Int63n(maxNum))
	}

	encodedSteps := make([]uint64, DataSetSize*TypeSize/TotalBits)

	g := make([]graph.Graph, 1)
	coordinates := make([]geo.Coordinate, 0)
	tree := KdTree{Graph: g[0], EncodedSteps: encodedSteps, Coordinates: coordinates}

	for i, _ := range data {
		//if i < 2 {
		tree.SetEncodedStep(i, data[i])
		//}
	}

	for i, _ := range data {
		if tree.EncodedStep(i) != data[i] {
			t.Fatalf("encoding didn't respect identity: expected %v but was %v at position %d\n", data[i], tree.EncodedStep(i), i)
		}
	}
}

func TestAppend(t *testing.T) {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))
	maxNum := int64(math.Pow(2, TotalBits) - 1)

	encodedSteps := make([]uint64, 0)
	g := make([]graph.Graph, 1)
	coordinates := make([]geo.Coordinate, 0)
	tree := KdTree{Graph: g[0], EncodedSteps: encodedSteps, Coordinates: coordinates}

	for i := 0; i < DataSetSize; i++ {
		s := uint64(rnd.Int63n(maxNum))
		tree.AppendEncodedStep(s)
		if tree.EncodedStepLen() != i+1 {
			t.Fatalf("wrong length: expected %d but was %d\n", i+1, tree.EncodedStepLen())
		}
		if tree.EncodedStep(i) != s {
			t.Fatalf("wrong content at position %d: expected %d but was %d\n", i, s, tree.EncodedStep(i))
		}
	}
}
<commit_msg>added test for k-d tree<commit_after>package kdtree

import (
	"geo"
	"graph"
	"math"
	"math/rand"
	"testing"
	"time"
)

const (
	DataSetSize = 100000 // more important to the performance
	Repeats     = 10000
)

var nodeData = createData(DataSetSize, false)
var repeatsNodeData = createData(DataSetSize, true)

func createData(size int, repeats bool) []geo.Coordinate {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))

	nodeData := make([]geo.Coordinate, size)
	for i := 0; i < size; i++ {
		lat, lng := rnd.Float64(), rnd.Float64()
		nodeData[i] = geo.Coordinate{lat, lng}

		// insert coordinates that have the same lat/lng (ugly corner case)
		if repeats {
			if rnd.Intn(5) == 0 {
				up := i + 2 + rnd.Intn(100)
				for i++; i < up && i < size; i++ {
					nodeData[i] = geo.Coordinate{lat, rnd.Float64()}
				}
				i--
			}
			if rnd.Intn(5) == 0 {
				up := i + 2 + rnd.Intn(100)
				for i++; i < up && i < size; i++ {
					nodeData[i] = geo.Coordinate{rnd.Float64(), lng}
				}
				i--
			}
		}
	}
	return nodeData
}

func TestEncoding(t *testing.T) {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))
	maxNum := int64(math.Pow(2, TotalBits) - 1)
	data := make([]uint64, DataSetSize)
	for i, _ := range data {
		data[i] = uint64(rnd.Int63n(maxNum))
	}

	encodedSteps := make([]uint64, DataSetSize*TypeSize/TotalBits)

	g := make([]graph.Graph, 1)
	coordinates := make([]geo.Coordinate, 0)
	tree := KdTree{Graph: g[0], EncodedSteps: encodedSteps, Coordinates: coordinates}

	for i, _ := range data {
		tree.SetEncodedStep(i, data[i])
	}

	for i, _ := range data {
		if tree.EncodedStep(i) != data[i] {
			t.Fatalf("encoding didn't respect identity: expected %v but was %v at position %d\n", data[i], tree.EncodedStep(i), i)
		}
	}
}

func TestAppend(t *testing.T) {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))
	maxNum := int64(math.Pow(2, TotalBits) - 1)

	encodedSteps := make([]uint64, 0)
	g := make([]graph.Graph, 1)
	coordinates := make([]geo.Coordinate, 0)
	tree := KdTree{Graph: g[0], EncodedSteps: encodedSteps, Coordinates: coordinates}

	for i := 0; i < DataSetSize; i++ {
		s := uint64(rnd.Int63n(maxNum))
		tree.AppendEncodedStep(s)
		if tree.EncodedStepLen() != i+1 {
			t.Fatalf("wrong length: expected %d but was %d\n", i+1, tree.EncodedStepLen())
		}
		if tree.EncodedStep(i) != s {
			t.Fatalf("wrong content at position %d: expected %d but was %d\n", i, s, tree.EncodedStep(i))
		}
	}
}

func TestAppend2(t *testing.T) {
	rnd := rand.New(rand.NewSource(time.Now().Unix()))
	maxNum := int64(math.Pow(2, TotalBits) - 1)
	data := make([]uint64, DataSetSize)
	for i, _ := range data {
		data[i] = uint64(rnd.Int63n(maxNum))
	}

	encodedSteps := make([]uint64, 0, DataSetSize*TypeSize/TotalBits)

	g := make([]graph.Graph, 1)
	coordinates := make([]geo.Coordinate, 0)
	tree := KdTree{Graph: g[0], EncodedSteps: encodedSteps, Coordinates: coordinates}

	for i, _ := range data {
		tree.AppendEncodedStep(data[i])
	}

	if tree.EncodedStepLen() != len(data) {
		t.Fatalf("wrong length: expected %d but was %d\n", len(data), tree.EncodedStepLen())
	}

	for i, _ := range data {
		if tree.EncodedStep(i) != data[i] {
			t.Fatalf("encoding didn't respect identity: expected %v but was %v at position %d\n", data[i], tree.EncodedStep(i), i)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp. 2018 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.
*/

package lib

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"math/big"
	"os"
	"testing"
	"time"

	"github.com/cloudflare/cfssl/certdb"
	"github.com/cloudflare/cfssl/log"
	"github.com/hyperledger/fabric-ca/lib/dbutil"
	"github.com/hyperledger/fabric-ca/lib/server"
	"github.com/hyperledger/fabric-ca/lib/spi"
	"github.com/hyperledger/fabric-ca/util"
	"github.com/jmoiron/sqlx"
	"github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
)

func TestGetCertificatesDB(t *testing.T) {
	os.RemoveAll("getCertDBTest")
	defer os.RemoveAll("getCertDBTest")
	log.Level = log.LevelDebug

	level := &dbutil.Levels{
		Affiliation: 1,
		Identity:    1,
		Certificate: 1,
	}
	srv := &Server{
		levels: level,
	}
	ca, err := newCA("getCertDBTest/config.yaml", &CAConfig{}, srv, false)
	util.FatalError(t, err, "Failed to get CA")

	populateCertificatesTable(t, ca)

	certReq := getCertReq("testCertificate1", "", "", false, false, nil, nil, nil, nil)
	rows, err := ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err := readRows(rows)
	assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName)

	certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, big.NewInt(1111), certs[0].SerialNumber)

	certReq = getCertReq("", "", "9876", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 2, len(certs))
	assert.Equal(t, []byte("9876"), certs[0].AuthorityKeyId)

	certReq = getCertReq("", "", "", true, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 5, len(certs))

	certReq = getCertReq("", "", "", false, true, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 6, len(certs))

	certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "dept1")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName)

	certReq = getCertReq("", "", "9876AB", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "testCertificate3", certs[0].Subject.CommonName)

	revokedStart := time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, &revokedStart, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "revoked1", certs[0].Subject.CommonName)

	revokedEnd := time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, &revokedEnd, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 2, len(certs))

	revokedStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)
	revokedEnd = time.Date(2017, time.August, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, &revokedStart, &revokedEnd, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "revoked2", certs[0].Subject.CommonName)

	expiredStart := time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 6, len(certs))

	expiredEnd := time.Date(2018, time.July, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, nil, nil, &expiredEnd)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 7, len(certs))

	expiredStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)
	expiredEnd = time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, &expiredEnd)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "expire1", certs[0].Subject.CommonName)
}

func readRows(rows *sqlx.Rows) ([]*x509.Certificate, error) {
	var certs []*x509.Certificate

	for rows.Next() {
		var cert certPEM
		err := rows.StructScan(&cert)
		if err != nil {
			return nil, errors.Errorf("Failed to get read row: %s", err)
		}

		block, rest := pem.Decode([]byte(cert.PEM))
		if block == nil || len(rest) > 0 {
			return nil, errors.New("Certificate decoding error")
		}
		certificate, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			return nil, err
		}

		certs = append(certs, certificate)
	}

	return certs, nil
}

func populateCertificatesTable(t *testing.T, ca *CA) {
	var err error

	dur, err := time.ParseDuration("+100h")
	util.FatalError(t, err, "Failed to parse duration '+100h'")
	futureTime := time.Now().Add(dur).UTC()

	ca.registry.InsertUser(&spi.UserInfo{
		Name:        "testCertificate1",
		Affiliation: "dept1",
	})
	// Active Certs
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1111",
		AKI:    "9876",
		Expiry: futureTime,
	}, "testCertificate1", ca)
	util.FatalError(t, err, "Failed to insert certificate with serial/AKI")

	ca.registry.InsertUser(&spi.UserInfo{
		Name:        "testCertificate2",
		Affiliation: "dept1",
	})
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1112",
		AKI:    "9876",
		Expiry: futureTime,
	}, "testCertificate2", ca)
	util.FatalError(t, err, "Failed to insert certificate with serial/AKI")

	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1132",
		AKI:    "9876ab",
		Expiry: futureTime,
	}, "testCertificate3", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")

	// Expired
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1121",
		AKI:    "98765",
		Expiry: time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC),
	}, "expire1", ca)
	util.FatalError(t, err, "Failed to insert certificate with expiration date")

	// Not Expired

	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1122",
		AKI:    "98765",
		Expiry: futureTime,
	}, "expire2", ca)
	util.FatalError(t, err, "Failed to insert certificate with expiration date")

	// Revoked
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial:    "1131",
		AKI:       "98765",
		Expiry:    futureTime,
		RevokedAt: time.Date(2018, time.February, 15, 0, 0, 0, 0, time.UTC),
	}, "revoked1", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")

	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial:    "1132",
		AKI:       "98765",
		Expiry:    futureTime,
		RevokedAt: time.Date(2017, time.February, 15, 0, 0, 0, 0, time.UTC),
	}, "revoked2", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")
}

func testInsertCertificate(req *certdb.CertificateRecord, id string, ca *CA) error {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return errors.Errorf("Failed to generate private key: %s", err)
	}

	serial := new(big.Int)
	serial.SetString(req.Serial, 10) //base 10

	template := x509.Certificate{
		Subject: pkix.Name{
			CommonName: id,
		},
		SerialNumber:   serial,
		AuthorityKeyId: []byte(req.AKI),
		KeyUsage:       x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		log.Fatalf("Failed to create certificate: %s", err)
	}

	cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})

	var record = new(CertRecord)
	record.ID = id
	record.Serial = req.Serial
	record.AKI = req.AKI
	record.CALabel = req.CALabel
	record.Status = req.Status
	record.Reason = req.Reason
	record.Expiry = req.Expiry.UTC()
	record.RevokedAt = req.RevokedAt.UTC()
	record.PEM = string(cert)

	db := ca.GetDB()
	res, err := db.NamedExec(insertSQL, record)
	if err != nil {
		return errors.Wrap(err, "Failed to insert record into database")
	}

	numRowsAffected, err := res.RowsAffected()

	if numRowsAffected == 0 {
		return errors.New("Failed to insert the certificate record; no rows affected")
	}

	if numRowsAffected != 1 {
		return errors.Errorf("Expected to affect 1 entry in certificate database but affected %d",
			numRowsAffected)
	}

	return err
}

func getCertReq(id, serial, aki string, notrevoked, notexpired bool, revokedTimeStart, revokedTimeEnd, expiredTimeStart, expiredTimeEnd *time.Time) *server.CertificateRequestImpl {
	return &server.CertificateRequestImpl{
		ID:               id,
		SerialNumber:     serial,
		Aki:              aki,
		Notexpired:       notexpired,
		Notrevoked:       notrevoked,
		ExpiredTimeStart: expiredTimeStart,
		ExpiredTimeEnd:   expiredTimeEnd,
		RevokedTimeStart: revokedTimeStart,
		RevokedTimeEnd:   revokedTimeEnd,
	}
}
<commit_msg>[FAB-10906] Fix failing TestGetCertificatesDB<commit_after>/*
Copyright IBM Corp. 2018 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.
*/

package lib

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"math/big"
	"os"
	"testing"
	"time"

	"github.com/cloudflare/cfssl/certdb"
	"github.com/cloudflare/cfssl/log"
	"github.com/hyperledger/fabric-ca/lib/dbutil"
	"github.com/hyperledger/fabric-ca/lib/server"
	"github.com/hyperledger/fabric-ca/lib/spi"
	"github.com/hyperledger/fabric-ca/util"
	"github.com/jmoiron/sqlx"
	"github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
)

func TestGetCertificatesDB(t *testing.T) {
	os.RemoveAll("getCertDBTest")
	defer os.RemoveAll("getCertDBTest")
	log.Level = log.LevelDebug

	level := &dbutil.Levels{
		Affiliation: 1,
		Identity:    1,
		Certificate: 1,
	}
	srv := &Server{
		levels: level,
	}
	ca, err := newCA("getCertDBTest/config.yaml", &CAConfig{}, srv, false)
	util.FatalError(t, err, "Failed to get CA")

	populateCertificatesTable(t, ca)

	certReq := getCertReq("testCertificate1", "", "", false, false, nil, nil, nil, nil)
	rows, err := ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err := readRows(rows)
	assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName)

	certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, big.NewInt(1111), certs[0].SerialNumber)

	certReq = getCertReq("", "", "9876", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 2, len(certs))
	assert.Equal(t, []byte("9876"), certs[0].AuthorityKeyId)

	certReq = getCertReq("", "", "", true, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 5, len(certs))

	certReq = getCertReq("", "", "", false, true, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 6, len(certs))

	certReq = getCertReq("", "1111", "", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "dept1")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "testCertificate1", certs[0].Subject.CommonName)

	certReq = getCertReq("", "", "9876AB", false, false, nil, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "testCertificate3", certs[0].Subject.CommonName)

	revokedStart := time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, &revokedStart, nil, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "revoked1", certs[0].Subject.CommonName)

	revokedEnd := time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, &revokedEnd, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 2, len(certs))

	revokedStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)
	revokedEnd = time.Date(2017, time.August, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, &revokedStart, &revokedEnd, nil, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "revoked2", certs[0].Subject.CommonName)

	expiredStart := time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, nil)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 6, len(certs))

	dur, err := time.ParseDuration("+100h")
	expiredEnd := time.Now().Add(dur).UTC()
	certReq = getCertReq("", "", "", false, false, nil, nil, nil, &expiredEnd)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 7, len(certs))

	expiredStart = time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC)
	expiredEnd = time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC)
	certReq = getCertReq("", "", "", false, false, nil, nil, &expiredStart, &expiredEnd)
	rows, err = ca.certDBAccessor.GetCertificates(certReq, "")
	assert.NoError(t, err, "Failed to get certificates from database")
	certs, err = readRows(rows)
	assert.Equal(t, 1, len(certs))
	assert.Equal(t, "expire1", certs[0].Subject.CommonName)
}

func readRows(rows *sqlx.Rows) ([]*x509.Certificate, error) {
	var certs []*x509.Certificate

	for rows.Next() {
		var cert certPEM
		err := rows.StructScan(&cert)
		if err != nil {
			return nil, errors.Errorf("Failed to get read row: %s", err)
		}

		block, rest := pem.Decode([]byte(cert.PEM))
		if block == nil || len(rest) > 0 {
			return nil, errors.New("Certificate decoding error")
		}
		certificate, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			return nil, err
		}

		certs = append(certs, certificate)
	}

	return certs, nil
}

func populateCertificatesTable(t *testing.T, ca *CA) {
	var err error

	dur, err := time.ParseDuration("+100h")
	util.FatalError(t, err, "Failed to parse duration '+100h'")
	futureTime := time.Now().Add(dur).UTC()

	ca.registry.InsertUser(&spi.UserInfo{
		Name:        "testCertificate1",
		Affiliation: "dept1",
	})
	// Active Certs
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1111",
		AKI:    "9876",
		Expiry: futureTime,
	}, "testCertificate1", ca)
	util.FatalError(t, err, "Failed to insert certificate with serial/AKI")

	ca.registry.InsertUser(&spi.UserInfo{
		Name:        "testCertificate2",
		Affiliation: "dept1",
	})
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1112",
		AKI:    "9876",
		Expiry: futureTime,
	}, "testCertificate2", ca)
	util.FatalError(t, err, "Failed to insert certificate with serial/AKI")

	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1132",
		AKI:    "9876ab",
		Expiry: futureTime,
	}, "testCertificate3", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")

	// Expired
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1121",
		AKI:    "98765",
		Expiry: time.Date(2018, time.March, 1, 0, 0, 0, 0, time.UTC),
	}, "expire1", ca)
	util.FatalError(t, err, "Failed to insert certificate with expiration date")

	// Not Expired
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial: "1122",
		AKI:    "98765",
		Expiry: futureTime,
	}, "expire2", ca)
	util.FatalError(t, err, "Failed to insert certificate with expiration date")

	// Revoked
	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial:    "1131",
		AKI:       "98765",
		Expiry:    futureTime,
		RevokedAt: time.Date(2018, time.February, 15, 0, 0, 0, 0, time.UTC),
	}, "revoked1", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")

	err = testInsertCertificate(&certdb.CertificateRecord{
		Serial:    "1132",
		AKI:       "98765",
		Expiry:    futureTime,
		RevokedAt: time.Date(2017, time.February, 15, 0, 0, 0, 0, time.UTC),
	}, "revoked2", ca)
	util.FatalError(t, err, "Failed to insert certificate with revocation date")
}

func testInsertCertificate(req *certdb.CertificateRecord, id string, ca *CA) error {
	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		return errors.Errorf("Failed to generate private key: %s", err)
	}

	serial := new(big.Int)
	serial.SetString(req.Serial, 10) //base 10

	template := x509.Certificate{
		Subject: pkix.Name{
			CommonName: id,
		},
		SerialNumber:   serial,
		AuthorityKeyId: []byte(req.AKI),
		KeyUsage:       x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		log.Fatalf("Failed to create certificate: %s", err)
	}

	cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})

	var record = new(CertRecord)
	record.ID = id
	record.Serial = req.Serial
	record.AKI = req.AKI
	record.CALabel = req.CALabel
	record.Status = req.Status
	record.Reason = req.Reason
	record.Expiry = req.Expiry.UTC()
	record.RevokedAt = req.RevokedAt.UTC()
	record.PEM = string(cert)

	db := ca.GetDB()
	res, err := db.NamedExec(insertSQL, record)
	if err != nil {
		return errors.Wrap(err, "Failed to insert record into database")
	}

	numRowsAffected, err := res.RowsAffected()

	if numRowsAffected == 0 {
		return errors.New("Failed to insert the certificate record; no rows affected")
	}

	if numRowsAffected != 1 {
		return errors.Errorf("Expected to affect 1 entry in certificate database but affected %d",
			numRowsAffected)
	}

	return err
}

func getCertReq(id, serial, aki string, notrevoked, notexpired bool, revokedTimeStart, revokedTimeEnd, expiredTimeStart, expiredTimeEnd *time.Time) *server.CertificateRequestImpl {
	return &server.CertificateRequestImpl{
		ID:               id,
		SerialNumber:     serial,
		Aki:              aki,
		Notexpired:       notexpired,
		Notrevoked:       notrevoked,
		ExpiredTimeStart: expiredTimeStart,
		ExpiredTimeEnd:   expiredTimeEnd,
		RevokedTimeStart: revokedTimeStart,
		RevokedTimeEnd:   revokedTimeEnd,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
	"github.com/layeh/gumble/gumble_ffmpeg"
	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumbleutil"
	"flag"
)

func main() {
	var sounds_dir = flag.String("sounds", "sounds", "directory where soundboard files are located")
	var volume = flag.Float64("volume", 0.25, "soundboard volume from 0 to 1")
	var stream *gumble_ffmpeg.Stream
	soundboard := make(map[string]string)

	// Populate soundboard with files in $pwd/sounds/
	files, err := ioutil.ReadDir(*sounds_dir)
	if err != nil  {
		fmt.Println(err)
		return
	}
	for _, f := range files {
		key := f.Name()
		value, _ := filepath.Abs(filepath.Join(*sounds_dir, key))
		soundboard[key] = value
	}

	gumbleutil.Main(func(client *gumble.Client) {
		stream, _ = gumble_ffmpeg.New(client)
		stream.Volume = float32(*volume)
		client.Attach(gumbleutil.AutoBitrate)
	}, gumbleutil.Listener{
		Connect: func(e *gumble.ConnectEvent) {
			fmt.Printf("Connected!\n")
		},
		TextMessage: func(e *gumble.TextMessageEvent) {
			if e.Sender == nil {
				return
			}
			if (e.Message == "stop") {
				stream.Stop()
			}
			for key, value := range soundboard {
				if strings.Index(key, e.Message) == 0 {
					stream.Stop()
					stream.Play(value)
				}
			}
		},
	})

}

<commit_msg>added file extension checking<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
	"github.com/layeh/gumble/gumble_ffmpeg"
	"github.com/layeh/gumble/gumble"
	"github.com/layeh/gumble/gumbleutil"
	"flag"
)

func main() {
	var sounds_dir = flag.String("sounds", "sounds", "directory where soundboard files are located")
	var volume = flag.Float64("volume", 0.25, "soundboard volume from 0 to 1")
	var stream *gumble_ffmpeg.Stream
	soundboard := make(map[string]string)

	// Populate soundboard with files in $pwd/sounds/
	files, err := ioutil.ReadDir(*sounds_dir)
	if err != nil  {
		fmt.Println(err)
		return
	}
	for _, f := range files {
		key := f.Name()
		if filepath.Ext(key) == "mp3" || filepath.Ext(key) == "ogg" {
			value, _ := filepath.Abs(filepath.Join(*sounds_dir, key))
			soundboard[key] = value
		}
	}

	gumbleutil.Main(func(client *gumble.Client) {
		stream, _ = gumble_ffmpeg.New(client)
		stream.Volume = float32(*volume)
		client.Attach(gumbleutil.AutoBitrate)
	}, gumbleutil.Listener{
		Connect: func(e *gumble.ConnectEvent) {
			fmt.Printf("Connected!\n")
		},
		TextMessage: func(e *gumble.TextMessageEvent) {
			if e.Sender == nil {
				return
			}
			if (e.Message == "stop") {
				stream.Stop()
			}
			for key, value := range soundboard {
				if strings.Index(key, e.Message) == 0 {
					stream.Stop()
					stream.Play(value)
				}
			}
		},
	})

}

<|endoftext|>


<commit_before>package checkmgr

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/circonus-labs/circonus-gometrics/api"
)

// Initialize CirconusMetrics instance. Attempt to find a check otherwise create one.
// use cases:
//
// check [bundle] by submission url
// check [bundle] by *check* id (note, not check_bundle id)
// check [bundle] by search
// create check [bundle]
func (cm *CheckManager) initializeTrapUrl() error {
	if cm.trapUrl != "" {
		return nil
	}

	cm.trapmu.Lock()
	defer cm.trapmu.Unlock()

	if cm.checkSubmissionUrl != "" {
		if !cm.enabled {
			cm.trapUrl = cm.checkSubmissionUrl
			cm.trapLastUpdate = time.Now()
			return nil
		}
	}

	if !cm.enabled {
		return errors.New("Unable to initialize trap, check manager is disabled.")
	}

	var err error
	var check *api.Check
	var checkBundle *api.CheckBundle
	var broker *api.Broker

	if cm.checkSubmissionUrl != "" {
		check, err := cm.apih.FetchCheckBySubmissionUrl(cm.checkSubmissionUrl)
		if err != nil {
			return err
		}
		// extract check id from check object returned from looking up using submission url
		// set m.CheckId to the id
		// set m.SubmissionUrl to "" to prevent trying to search on it going forward
		// use case: if the broker is changed in the UI metrics would stop flowing
		// unless the new submission url can be fetched with the API (which is no
		// longer possible using the original submission url)
		id, err := strconv.Atoi(strings.Replace(check.Cid, "/check/", "", -1))
		if err == nil {
			cm.checkId = id
			cm.checkSubmissionUrl = ""
		} else {
			cm.Log.Printf(
				"[WARN] SubmissionUrl check to Check ID: unable to convert %s to int %q\n",
				check.Cid, err)
		}
	} else if cm.checkId > 0 {
		check, err = cm.apih.FetchCheckById(cm.checkId)
		if err != nil {
			return err
		}
	} else {
		searchCriteria := fmt.Sprintf(
			"(active:1)(host:\"%s\")(type:\"%s\")(tags:%s)",
			cm.checkInstanceId, cm.checkType, cm.checkSearchTag)
		checkBundle, err = cm.checkBundleSearch(searchCriteria)
		if err != nil {
			return err
		}

		if checkBundle == nil {
			// err==nil && checkBundle==nil is "no check bundles matched"
			// an error *should* be returned for any other invalid scenario
			checkBundle, broker, err = cm.createNewCheck()
			if err != nil {
				return err
			}
		}
	}

	if checkBundle == nil {
		if check != nil {
			checkBundle, err = cm.apih.FetchCheckBundleByCid(check.CheckBundleCid)
			if err != nil {
				return err
			}
		} else {
			return fmt.Errorf("[ERROR] Unable to retrieve, find, or create check.")
		}
	}

	if broker == nil {
		broker, err = cm.apih.FetchBrokerByCid(checkBundle.Brokers[0])
		if err != nil {
			return err
		}
	}

	// retain to facilitate metric management (adding new metrics specifically)
	cm.checkBundle = checkBundle
	cm.inventoryMetrics()

	// url to which metrics should be PUT
	cm.trapUrl = checkBundle.Config.SubmissionUrl

	// used when sending as "ServerName" get around certs not having IP SANS
	// (cert created with server name as CN but IP used in trap url)
	cn, err := cm.getBrokerCN(broker, cm.trapUrl)
	if err != nil {
		return err
	}
	cm.trapCN = cn

	cm.trapLastUpdate = time.Now()

	return nil
}

// Search for a check bundle given a predetermined set of criteria
func (cm *CheckManager) checkBundleSearch(criteria string) (*api.CheckBundle, error) {
	checkBundles, err := cm.apih.SearchCheckBundles(criteria)
	if err != nil {
		return nil, err
	}

	if len(checkBundles) == 0 {
		return nil, nil // trigger creation of a new check
	}

	numActive := 0
	checkId := -1

	for idx, check := range checkBundles {
		if check.Status == "active" {
			numActive++
			checkId = idx
		}
	}

	if numActive > 1 {
		return nil, fmt.Errorf("[ERROR] Multiple possibilities multiple check bundles match criteria %s\n", criteria)
	}

	return &checkBundles[checkId], nil
}

// Create a new check to receive metrics
func (cm *CheckManager) createNewCheck() (*api.CheckBundle, *api.Broker, error) {
	checkSecret := cm.checkSecret
	if checkSecret == "" {
		secret, err := cm.makeSecret()
		if err != nil {
			secret = "myS3cr3t"
		}
		checkSecret = secret
	}

	broker, brokerErr := cm.getBroker()
	if brokerErr != nil {
		return nil, nil, brokerErr
	}

	config := api.CheckBundle{
		Brokers:     []string{broker.Cid},
		Config:      api.CheckBundleConfig{AsyncMetrics: true, Secret: checkSecret},
		DisplayName: cm.checkDisplayName,
		Metrics:     []api.CheckBundleMetric{},
		MetricLimit: 0,
		Notes:       "",
		Period:      60,
		Status:      "active",
		Tags:        append([]string{cm.checkSearchTag}, cm.checkTags...),
		Target:      cm.checkInstanceId,
		Timeout:     10,
		Type:        cm.checkType,
	}

	checkBundle, err := cm.apih.CreateCheckBundle(config)
	if err != nil {
		return nil, nil, err
	}

	return checkBundle, broker, nil
}

// Create a dynamic secret to use with a new check
func (cm *CheckManager) makeSecret() (string, error) {
	hash := sha256.New()
	x := make([]byte, 2048)
	if _, err := rand.Read(x); err != nil {
		return "", err
	}
	hash.Write(x)
	return hex.EncodeToString(hash.Sum(nil))[0:16], nil
}
<commit_msg>var name, change to err<commit_after>package checkmgr

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/circonus-labs/circonus-gometrics/api"
)

// Initialize CirconusMetrics instance. Attempt to find a check otherwise create one.
// use cases:
//
// check [bundle] by submission url
// check [bundle] by *check* id (note, not check_bundle id)
// check [bundle] by search
// create check [bundle]
func (cm *CheckManager) initializeTrapUrl() error {
	if cm.trapUrl != "" {
		return nil
	}

	cm.trapmu.Lock()
	defer cm.trapmu.Unlock()

	if cm.checkSubmissionUrl != "" {
		if !cm.enabled {
			cm.trapUrl = cm.checkSubmissionUrl
			cm.trapLastUpdate = time.Now()
			return nil
		}
	}

	if !cm.enabled {
		return errors.New("Unable to initialize trap, check manager is disabled.")
	}

	var err error
	var check *api.Check
	var checkBundle *api.CheckBundle
	var broker *api.Broker

	if cm.checkSubmissionUrl != "" {
		check, err := cm.apih.FetchCheckBySubmissionUrl(cm.checkSubmissionUrl)
		if err != nil {
			return err
		}
		// extract check id from check object returned from looking up using submission url
		// set m.CheckId to the id
		// set m.SubmissionUrl to "" to prevent trying to search on it going forward
		// use case: if the broker is changed in the UI metrics would stop flowing
		// unless the new submission url can be fetched with the API (which is no
		// longer possible using the original submission url)
		id, err := strconv.Atoi(strings.Replace(check.Cid, "/check/", "", -1))
		if err == nil {
			cm.checkId = id
			cm.checkSubmissionUrl = ""
		} else {
			cm.Log.Printf(
				"[WARN] SubmissionUrl check to Check ID: unable to convert %s to int %q\n",
				check.Cid, err)
		}
	} else if cm.checkId > 0 {
		check, err = cm.apih.FetchCheckById(cm.checkId)
		if err != nil {
			return err
		}
	} else {
		searchCriteria := fmt.Sprintf(
			"(active:1)(host:\"%s\")(type:\"%s\")(tags:%s)",
			cm.checkInstanceId, cm.checkType, cm.checkSearchTag)
		checkBundle, err = cm.checkBundleSearch(searchCriteria)
		if err != nil {
			return err
		}

		if checkBundle == nil {
			// err==nil && checkBundle==nil is "no check bundles matched"
			// an error *should* be returned for any other invalid scenario
			checkBundle, broker, err = cm.createNewCheck()
			if err != nil {
				return err
			}
		}
	}

	if checkBundle == nil {
		if check != nil {
			checkBundle, err = cm.apih.FetchCheckBundleByCid(check.CheckBundleCid)
			if err != nil {
				return err
			}
		} else {
			return fmt.Errorf("[ERROR] Unable to retrieve, find, or create check.")
		}
	}

	if broker == nil {
		broker, err = cm.apih.FetchBrokerByCid(checkBundle.Brokers[0])
		if err != nil {
			return err
		}
	}

	// retain to facilitate metric management (adding new metrics specifically)
	cm.checkBundle = checkBundle
	cm.inventoryMetrics()

	// url to which metrics should be PUT
	cm.trapUrl = checkBundle.Config.SubmissionUrl

	// used when sending as "ServerName" get around certs not having IP SANS
	// (cert created with server name as CN but IP used in trap url)
	cn, err := cm.getBrokerCN(broker, cm.trapUrl)
	if err != nil {
		return err
	}
	cm.trapCN = cn

	cm.trapLastUpdate = time.Now()

	return nil
}

// Search for a check bundle given a predetermined set of criteria
func (cm *CheckManager) checkBundleSearch(criteria string) (*api.CheckBundle, error) {
	checkBundles, err := cm.apih.SearchCheckBundles(criteria)
	if err != nil {
		return nil, err
	}

	if len(checkBundles) == 0 {
		return nil, nil // trigger creation of a new check
	}

	numActive := 0
	checkId := -1

	for idx, check := range checkBundles {
		if check.Status == "active" {
			numActive++
			checkId = idx
		}
	}

	if numActive > 1 {
		return nil, fmt.Errorf("[ERROR] Multiple possibilities multiple check bundles match criteria %s\n", criteria)
	}

	return &checkBundles[checkId], nil
}

// Create a new check to receive metrics
func (cm *CheckManager) createNewCheck() (*api.CheckBundle, *api.Broker, error) {
	checkSecret := cm.checkSecret
	if checkSecret == "" {
		secret, err := cm.makeSecret()
		if err != nil {
			secret = "myS3cr3t"
		}
		checkSecret = secret
	}

	broker, err := cm.getBroker()
	if err != nil {
		return nil, nil, err
	}

	config := api.CheckBundle{
		Brokers:     []string{broker.Cid},
		Config:      api.CheckBundleConfig{AsyncMetrics: true, Secret: checkSecret},
		DisplayName: cm.checkDisplayName,
		Metrics:     []api.CheckBundleMetric{},
		MetricLimit: 0,
		Notes:       "",
		Period:      60,
		Status:      "active",
		Tags:        append([]string{cm.checkSearchTag}, cm.checkTags...),
		Target:      cm.checkInstanceId,
		Timeout:     10,
		Type:        cm.checkType,
	}

	checkBundle, err := cm.apih.CreateCheckBundle(config)
	if err != nil {
		return nil, nil, err
	}

	return checkBundle, broker, nil
}

// Create a dynamic secret to use with a new check
func (cm *CheckManager) makeSecret() (string, error) {
	hash := sha256.New()
	x := make([]byte, 2048)
	if _, err := rand.Read(x); err != nil {
		return "", err
	}
	hash.Write(x)
	return hex.EncodeToString(hash.Sum(nil))[0:16], nil
}
<|endoftext|>