<commit_before>package saml

import (
	"encoding/xml"
	"fmt"
)

func (s *ServiceProviderSettings) GetEntityDescriptor() (string, error) {
	d := EntityDescriptor{
		XMLName: xml.Name{
			Local: "md:EntityDescriptor",
		},
		DS:       "http://www.w3.org/2000/09/xmldsig#",
		XMLNS:    "urn:oasis:names:tc:SAML:2.0:metadata",
		MD:       "urn:oasis:names:tc:SAML:2.0:metadata",
		EntityId: s.AssertionConsumerServiceURL,

		Extensions: Extensions{
			XMLName: xml.Name{
				Local: "md:Extensions",
			},
			Alg:    "urn:oasis:names:tc:SAML:metadata:algsupport",
			MDAttr: "urn:oasis:names:tc:SAML:metadata:attribute",
			MDRPI:  "urn:oasis:names:tc:SAML:metadata:rpi",
		},
		SPSSODescriptor: SPSSODescriptor{
			ProtocolSupportEnumeration: "urn:oasis:names:tc:SAML:2.0:protocol",
			SigningKeyDescriptor: KeyDescriptor{
				XMLName: xml.Name{
					Local: "md:KeyDescriptor",
				},

				Use: "signing",
				KeyInfo: KeyInfo{
					XMLName: xml.Name{
						Local: "ds:KeyInfo",
					},
					X509Data: X509Data{
						XMLName: xml.Name{
							Local: "ds:X509Data",
						},
						X509Certificate: X509Certificate{
							XMLName: xml.Name{
								Local: "ds:X509Certificate",
							},
							Cert: s.PublicCert(),
						},
					},
				},
			},
			EncryptionKeyDescriptor: KeyDescriptor{
				XMLName: xml.Name{
					Local: "md:KeyDescriptor",
				},

				Use: "encryption",
				KeyInfo: KeyInfo{
					XMLName: xml.Name{
						Local: "ds:KeyInfo",
					},
					X509Data: X509Data{
						XMLName: xml.Name{
							Local: "ds:X509Data",
						},
						X509Certificate: X509Certificate{
							XMLName: xml.Name{
								Local: "ds:X509Certificate",
							},
							Cert: s.PublicCert(),
						},
					},
				},
			},
			// SingleLogoutService{
			// 	XMLName: xml.Name{
			// 		Local: "md:SingleLogoutService",
			// 	},
			// 	Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
			// 	Location: "---TODO---",
			// },
			AssertionConsumerServices: []AssertionConsumerService{
				{
					XMLName: xml.Name{
						Local: "md:AssertionConsumerService",
					},
					Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
					Location: s.AssertionConsumerServiceURL,
					Index:    "0",
				},
				{
					XMLName: xml.Name{
						Local: "md:AssertionConsumerService",
					},
					Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact",
					Location: s.AssertionConsumerServiceURL,
					Index:    "1",
				},
			},
		},
	}
	b, err := xml.MarshalIndent(d, "", "    ")
	if err != nil {
		return "", err
	}

	newMetadata := fmt.Sprintf("<?xml version='1.0' encoding='UTF-8'?>\n%s", b)
	return string(newMetadata), nil
}
<commit_msg>change the metadata entityid to use the metadata endpoint. i think this will make it easier. and distinguish between the entityid and the assertionconsumerserviceurl (for validation)<commit_after>package saml

import (
	"encoding/xml"
	"fmt"
)

func (s *ServiceProviderSettings) GetEntityDescriptor() (string, error) {
	d := EntityDescriptor{
		XMLName: xml.Name{
			Local: "md:EntityDescriptor",
		},
		DS:       "http://www.w3.org/2000/09/xmldsig#",
		XMLNS:    "urn:oasis:names:tc:SAML:2.0:metadata",
		MD:       "urn:oasis:names:tc:SAML:2.0:metadata",
		EntityId: s.IDPSSODescriptorURL,

		Extensions: Extensions{
			XMLName: xml.Name{
				Local: "md:Extensions",
			},
			Alg:    "urn:oasis:names:tc:SAML:metadata:algsupport",
			MDAttr: "urn:oasis:names:tc:SAML:metadata:attribute",
			MDRPI:  "urn:oasis:names:tc:SAML:metadata:rpi",
		},
		SPSSODescriptor: SPSSODescriptor{
			ProtocolSupportEnumeration: "urn:oasis:names:tc:SAML:2.0:protocol",
			SigningKeyDescriptor: KeyDescriptor{
				XMLName: xml.Name{
					Local: "md:KeyDescriptor",
				},

				Use: "signing",
				KeyInfo: KeyInfo{
					XMLName: xml.Name{
						Local: "ds:KeyInfo",
					},
					X509Data: X509Data{
						XMLName: xml.Name{
							Local: "ds:X509Data",
						},
						X509Certificate: X509Certificate{
							XMLName: xml.Name{
								Local: "ds:X509Certificate",
							},
							Cert: s.PublicCert(),
						},
					},
				},
			},
			EncryptionKeyDescriptor: KeyDescriptor{
				XMLName: xml.Name{
					Local: "md:KeyDescriptor",
				},

				Use: "encryption",
				KeyInfo: KeyInfo{
					XMLName: xml.Name{
						Local: "ds:KeyInfo",
					},
					X509Data: X509Data{
						XMLName: xml.Name{
							Local: "ds:X509Data",
						},
						X509Certificate: X509Certificate{
							XMLName: xml.Name{
								Local: "ds:X509Certificate",
							},
							Cert: s.PublicCert(),
						},
					},
				},
			},
			// SingleLogoutService{
			// 	XMLName: xml.Name{
			// 		Local: "md:SingleLogoutService",
			// 	},
			// 	Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
			// 	Location: "---TODO---",
			// },
			AssertionConsumerServices: []AssertionConsumerService{
				{
					XMLName: xml.Name{
						Local: "md:AssertionConsumerService",
					},
					Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
					Location: s.AssertionConsumerServiceURL,
					Index:    "0",
				},
				{
					XMLName: xml.Name{
						Local: "md:AssertionConsumerService",
					},
					Binding:  "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact",
					Location: s.AssertionConsumerServiceURL,
					Index:    "1",
				},
			},
		},
	}
	b, err := xml.MarshalIndent(d, "", "    ")
	if err != nil {
		return "", err
	}

	newMetadata := fmt.Sprintf("<?xml version='1.0' encoding='UTF-8'?>\n%s", b)
	return string(newMetadata), nil
}
<|endoftext|>


<commit_before>package ir

import (
	"fmt"

	"github.com/tisp-lang/tisp/src/lib/core"
)

// Switch represents a switch expression.
type Switch struct {
	patterns []core.Value
	values   []int
}

// NewSwitch creates a switch expression.
func NewSwitch(ps []core.Value, vs []int) Switch {
	if len(ps) != len(vs) {
		panic(fmt.Errorf(
			"A number of patterns (%d) doesn't match with a number of corresponding values (%d)",
			len(ps),
			len(vs)))
	} else if len(ps) == 0 {
		panic(fmt.Errorf("A number of patterns must be more than 0"))
	}

	return Switch{ps, vs}
}

func (s Switch) compileToDict() core.DictionaryType {
	ts := make([]*core.Thunk, 0, len(s.values))

	for _, v := range s.values {
		ts = append(ts, core.NewNumber(float64(v)))
	}

	return core.NewDictionary(s.patterns, ts).Eval().(core.DictionaryType)
}
<commit_msg>Add matched value to switch type<commit_after>package ir

import (
	"fmt"

	"github.com/tisp-lang/tisp/src/lib/core"
)

// Switch represents a switch expression.
type Switch struct {
	value    interface{}
	patterns []core.Value
	values   []int
}

// NewSwitch creates a switch expression.
func NewSwitch(ps []core.Value, vs []int) Switch {
	if len(ps) != len(vs) {
		panic(fmt.Errorf(
			"A number of patterns (%d) doesn't match with a number of corresponding values (%d)",
			len(ps),
			len(vs)))
	} else if len(ps) == 0 {
		panic(fmt.Errorf("A number of patterns must be more than 0"))
	}

	return Switch{ps, vs}
}

func (s Switch) compileToDict() core.DictionaryType {
	ts := make([]*core.Thunk, 0, len(s.values))

	for _, v := range s.values {
		ts = append(ts, core.NewNumber(float64(v)))
	}

	return core.NewDictionary(s.patterns, ts).Eval().(core.DictionaryType)
}
<|endoftext|>


<commit_before>// Package proxyproto implements Proxy Protocol (v1 and v2) parser and writer, as per specification:
// http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
package proxyproto

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"net"
	"time"
)

var (
	// Protocol
	SIGV1 = []byte{'\x50', '\x52', '\x4F', '\x58', '\x59'}
	SIGV2 = []byte{'\x0D', '\x0A', '\x0D', '\x0A', '\x00', '\x0D', '\x0A', '\x51', '\x55', '\x49', '\x54', '\x0A'}

	ErrCantReadProtocolVersionAndCommand    = errors.New("Can't read proxy protocol version and command")
	ErrCantReadAddressFamilyAndProtocol     = errors.New("Can't read address family or protocol")
	ErrCantReadLength                       = errors.New("Can't read length")
	ErrCantResolveSourceUnixAddress         = errors.New("Can't resolve source Unix address")
	ErrCantResolveDestinationUnixAddress    = errors.New("Can't resolve destination Unix address")
	ErrNoProxyProtocol                      = errors.New("Proxy protocol signature not present")
	ErrUnknownProxyProtocolVersion          = errors.New("Unknown proxy protocol version")
	ErrUnsupportedProtocolVersionAndCommand = errors.New("Unsupported proxy protocol version and command")
	ErrUnsupportedAddressFamilyAndProtocol  = errors.New("Unsupported address family and protocol")
	ErrInvalidLength                        = errors.New("Invalid length")
	ErrInvalidAddress                       = errors.New("Invalid address")
	ErrInvalidPortNumber                    = errors.New("Invalid port number")
	ErrSuperfluousProxyHeader               = errors.New("Upstream connection sent PROXY header but isn't allowed to send one")
)

// Header is the placeholder for proxy protocol header.
type Header struct {
	Version            byte
	Command            ProtocolVersionAndCommand
	TransportProtocol  AddressFamilyAndProtocol
	SourceAddress      net.IP
	DestinationAddress net.IP
	SourcePort         uint16
	DestinationPort    uint16
	rawTLVs            []byte
}

// RemoteAddr returns the address of the remote endpoint of the connection.
func (header *Header) RemoteAddr() net.Addr {
	return &net.TCPAddr{
		IP:   header.SourceAddress,
		Port: int(header.SourcePort),
	}
}

// LocalAddr returns the address of the local endpoint of the connection.
func (header *Header) LocalAddr() net.Addr {
	return &net.TCPAddr{
		IP:   header.DestinationAddress,
		Port: int(header.DestinationPort),
	}
}

// EqualTo returns true if headers are equivalent, false otherwise.
// Deprecated: use EqualsTo instead. This method will eventually be removed.
func (header *Header) EqualTo(otherHeader *Header) bool {
	return header.EqualsTo(otherHeader)
}

// EqualsTo returns true if headers are equivalent, false otherwise.
func (header *Header) EqualsTo(otherHeader *Header) bool {
	if otherHeader == nil {
		return false
	}
	if header.Command.IsLocal() {
		return true
	}
	// TLVs only exist for version 2
	if header.Version == 0x02 && !bytes.Equal(header.rawTLVs, otherHeader.rawTLVs) {
		return false
	}
	return header.Version == otherHeader.Version &&
		header.TransportProtocol == otherHeader.TransportProtocol &&
		header.SourceAddress.String() == otherHeader.SourceAddress.String() &&
		header.DestinationAddress.String() == otherHeader.DestinationAddress.String() &&
		header.SourcePort == otherHeader.SourcePort &&
		header.DestinationPort == otherHeader.DestinationPort
}

// WriteTo renders a proxy protocol header in a format and writes it to an io.Writer.
func (header *Header) WriteTo(w io.Writer) (int64, error) {
	buf, err := header.Format()
	if err != nil {
		return 0, err
	}

	return bytes.NewBuffer(buf).WriteTo(w)
}

// Format renders a proxy protocol header in a format to write over the wire.
func (header *Header) Format() ([]byte, error) {
	switch header.Version {
	case 1:
		return header.formatVersion1()
	case 2:
		return header.formatVersion2()
	default:
		return nil, ErrUnknownProxyProtocolVersion
	}
}

// TLVs returns the TLVs stored into this header, if they exist.  TLVs are optional for v2 of the protocol.
func (header *Header) TLVs() ([]TLV, error) {
	return SplitTLVs(header.rawTLVs)
}

// Read identifies the proxy protocol version and reads the remaining of
// the header, accordingly.
//
// If proxy protocol header signature is not present, the reader buffer remains untouched
// and is safe for reading outside of this code.
//
// If proxy protocol header signature is present but an error is raised while processing
// the remaining header, assume the reader buffer to be in a corrupt state.
// Also, this operation will block until enough bytes are available for peeking.
func Read(reader *bufio.Reader) (*Header, error) {
	// In order to improve speed for small non-PROXYed packets, take a peek at the first byte alone.
	if b1, err := reader.Peek(1); err == nil && (bytes.Equal(b1[:1], SIGV1[:1]) || bytes.Equal(b1[:1], SIGV2[:1])) {
		if signature, err := reader.Peek(5); err == nil && bytes.Equal(signature[:5], SIGV1) {
			return parseVersion1(reader)
		} else if signature, err := reader.Peek(12); err == nil && bytes.Equal(signature[:12], SIGV2) {
			return parseVersion2(reader)
		}
	}

	return nil, ErrNoProxyProtocol
}

// ReadTimeout acts as Read but takes a timeout. If that timeout is reached, it's assumed
// there's no proxy protocol header.
func ReadTimeout(reader *bufio.Reader, timeout time.Duration) (*Header, error) {
	type header struct {
		h *Header
		e error
	}
	read := make(chan *header, 1)

	go func() {
		h := &header{}
		h.h, h.e = Read(reader)
		read <- h
	}()

	timer := time.NewTimer(timeout)
	select {
	case result := <-read:
		timer.Stop()
		return result.h, result.e
	case <-timer.C:
		return nil, ErrNoProxyProtocol
	}
}
<commit_msg>header: return err from reader.Peek()<commit_after>// Package proxyproto implements Proxy Protocol (v1 and v2) parser and writer, as per specification:
// http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
package proxyproto

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"net"
	"time"
)

var (
	// Protocol
	SIGV1 = []byte{'\x50', '\x52', '\x4F', '\x58', '\x59'}
	SIGV2 = []byte{'\x0D', '\x0A', '\x0D', '\x0A', '\x00', '\x0D', '\x0A', '\x51', '\x55', '\x49', '\x54', '\x0A'}

	ErrCantReadProtocolVersionAndCommand    = errors.New("Can't read proxy protocol version and command")
	ErrCantReadAddressFamilyAndProtocol     = errors.New("Can't read address family or protocol")
	ErrCantReadLength                       = errors.New("Can't read length")
	ErrCantResolveSourceUnixAddress         = errors.New("Can't resolve source Unix address")
	ErrCantResolveDestinationUnixAddress    = errors.New("Can't resolve destination Unix address")
	ErrNoProxyProtocol                      = errors.New("Proxy protocol signature not present")
	ErrUnknownProxyProtocolVersion          = errors.New("Unknown proxy protocol version")
	ErrUnsupportedProtocolVersionAndCommand = errors.New("Unsupported proxy protocol version and command")
	ErrUnsupportedAddressFamilyAndProtocol  = errors.New("Unsupported address family and protocol")
	ErrInvalidLength                        = errors.New("Invalid length")
	ErrInvalidAddress                       = errors.New("Invalid address")
	ErrInvalidPortNumber                    = errors.New("Invalid port number")
	ErrSuperfluousProxyHeader               = errors.New("Upstream connection sent PROXY header but isn't allowed to send one")
)

// Header is the placeholder for proxy protocol header.
type Header struct {
	Version            byte
	Command            ProtocolVersionAndCommand
	TransportProtocol  AddressFamilyAndProtocol
	SourceAddress      net.IP
	DestinationAddress net.IP
	SourcePort         uint16
	DestinationPort    uint16
	rawTLVs            []byte
}

// RemoteAddr returns the address of the remote endpoint of the connection.
func (header *Header) RemoteAddr() net.Addr {
	return &net.TCPAddr{
		IP:   header.SourceAddress,
		Port: int(header.SourcePort),
	}
}

// LocalAddr returns the address of the local endpoint of the connection.
func (header *Header) LocalAddr() net.Addr {
	return &net.TCPAddr{
		IP:   header.DestinationAddress,
		Port: int(header.DestinationPort),
	}
}

// EqualTo returns true if headers are equivalent, false otherwise.
// Deprecated: use EqualsTo instead. This method will eventually be removed.
func (header *Header) EqualTo(otherHeader *Header) bool {
	return header.EqualsTo(otherHeader)
}

// EqualsTo returns true if headers are equivalent, false otherwise.
func (header *Header) EqualsTo(otherHeader *Header) bool {
	if otherHeader == nil {
		return false
	}
	if header.Command.IsLocal() {
		return true
	}
	// TLVs only exist for version 2
	if header.Version == 0x02 && !bytes.Equal(header.rawTLVs, otherHeader.rawTLVs) {
		return false
	}
	return header.Version == otherHeader.Version &&
		header.TransportProtocol == otherHeader.TransportProtocol &&
		header.SourceAddress.String() == otherHeader.SourceAddress.String() &&
		header.DestinationAddress.String() == otherHeader.DestinationAddress.String() &&
		header.SourcePort == otherHeader.SourcePort &&
		header.DestinationPort == otherHeader.DestinationPort
}

// WriteTo renders a proxy protocol header in a format and writes it to an io.Writer.
func (header *Header) WriteTo(w io.Writer) (int64, error) {
	buf, err := header.Format()
	if err != nil {
		return 0, err
	}

	return bytes.NewBuffer(buf).WriteTo(w)
}

// Format renders a proxy protocol header in a format to write over the wire.
func (header *Header) Format() ([]byte, error) {
	switch header.Version {
	case 1:
		return header.formatVersion1()
	case 2:
		return header.formatVersion2()
	default:
		return nil, ErrUnknownProxyProtocolVersion
	}
}

// TLVs returns the TLVs stored into this header, if they exist.  TLVs are optional for v2 of the protocol.
func (header *Header) TLVs() ([]TLV, error) {
	return SplitTLVs(header.rawTLVs)
}

// Read identifies the proxy protocol version and reads the remaining of
// the header, accordingly.
//
// If proxy protocol header signature is not present, the reader buffer remains untouched
// and is safe for reading outside of this code.
//
// If proxy protocol header signature is present but an error is raised while processing
// the remaining header, assume the reader buffer to be in a corrupt state.
// Also, this operation will block until enough bytes are available for peeking.
func Read(reader *bufio.Reader) (*Header, error) {
	// In order to improve speed for small non-PROXYed packets, take a peek at the first byte alone.
	b1, err := reader.Peek(1)
	if err != nil {
		return nil, err
	}

	if bytes.Equal(b1[:1], SIGV1[:1]) || bytes.Equal(b1[:1], SIGV2[:1]) {
		if signature, err := reader.Peek(5); err == nil && bytes.Equal(signature[:5], SIGV1) {
			return parseVersion1(reader)
		} else if signature, err := reader.Peek(12); err == nil && bytes.Equal(signature[:12], SIGV2) {
			return parseVersion2(reader)
		}
	}

	return nil, ErrNoProxyProtocol
}

// ReadTimeout acts as Read but takes a timeout. If that timeout is reached, it's assumed
// there's no proxy protocol header.
func ReadTimeout(reader *bufio.Reader, timeout time.Duration) (*Header, error) {
	type header struct {
		h *Header
		e error
	}
	read := make(chan *header, 1)

	go func() {
		h := &header{}
		h.h, h.e = Read(reader)
		read <- h
	}()

	timer := time.NewTimer(timeout)
	select {
	case result := <-read:
		timer.Stop()
		return result.h, result.e
	case <-timer.C:
		return nil, ErrNoProxyProtocol
	}
}
<|endoftext|>


<commit_before>package fastly

import (
	"fmt"
	"net/http"
	"sort"
)

type HeaderType int

const (
	_                            = iota
	HeaderTypeRequest HeaderType = iota
	HeaderTypeFetch
	HeaderTypeCache
	HeaderTypeResponse
)

func (s *HeaderType) UnmarshalText(b []byte) error {
	switch string(b) {
	case "request":
		*s = HeaderTypeRequest
	case "fetch":
		*s = HeaderTypeFetch
	case "cache":
		*s = HeaderTypeCache
	case "response":
		*s = HeaderTypeResponse
	}
	return nil
}

func (s *HeaderType) MarshalText() ([]byte, error) {
	switch *s {
	case HeaderTypeRequest:
		return []byte("request"), nil
	case HeaderTypeFetch:
		return []byte("fetch"), nil
	case HeaderTypeCache:
		return []byte("cache"), nil
	case HeaderTypeResponse:
		return []byte("response"), nil
	}
	return nil, nil
}

type HeaderAction int

const (
	_                            = iota
	HeaderActionSet HeaderAction = iota
	HeaderActionAppend
	HeaderActionDelete
	HeaderActionRegex
	HeaderActionRegexRepeat
)

func (s *HeaderAction) UnmarshalText(b []byte) error {
	switch string(b) {
	case "set":
		*s = HeaderActionSet
	case "append":
		*s = HeaderActionAppend
	case "delete":
		*s = HeaderActionDelete
	case "regex":
		*s = HeaderActionRegex
	case "regex_repeat":
		*s = HeaderActionRegexRepeat
	}
	return nil
}

func (s *HeaderAction) MarshalText() ([]byte, error) {
	switch *s {
	case HeaderActionSet:
		return []byte("pass"), nil
	case HeaderActionAppend:
		return []byte("cache"), nil
	case HeaderActionDelete:
		return []byte("restart"), nil
	case HeaderActionRegex:
		return []byte("regex"), nil
	case HeaderActionRegexRepeat:
		return []byte("regex_repeat"), nil
	}
	return nil, nil
}

type HeaderConfig config

type Header struct {
	ServiceID string `json:"service_id,omitempty"`
	Version   uint   `json:"version,string,omitempty"`

	Name              string       `json:"name,omitempty"`
	Action            HeaderAction `json:"action,omitempty"`
	CacheCondition    string       `json:"cache_condition,omitempty"`
	IgnoreIfSet       Compatibool  `json:"ignore_if_set,omitempty"`
	Priority          uint         `json:"priority,string,omitempty"`
	Regex             string       `json:"regex,omitempty"`
	RequestCondition  string       `json:"request_condition,omitempty"`
	ResponseCondition string       `json:"response_condition,omitempty"`
	Source            string       `json:"src,omitempty"`
	Destination       string       `json:"dst,omitempty"`
	Substitution      string       `json:"substitution,omitempty"`
	Type              HeaderType   `json:"type,omitempty"`
}

// headersByName is a sortable list of headers.
type headersByName []*Header

// Len, Swap, and Less implement the sortable interface.
func (s headersByName) Len() int      { return len(s) }
func (s headersByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s headersByName) Less(i, j int) bool {
	return s[i].Name < s[j].Name
}

// List headers for a specific service and version.
func (c *HeaderConfig) List(serviceID string, version uint) ([]*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header", serviceID, version)

	req, err := c.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	headers := new([]*Header)
	resp, err := c.client.Do(req, headers)
	if err != nil {
		return nil, resp, err
	}

	sort.Stable(headersByName(*headers))

	return *headers, resp, nil
}

// Get fetches a specific header by name.
func (c *HeaderConfig) Get(serviceID string, version uint, name string) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	header := new(Header)
	resp, err := c.client.Do(req, header)
	if err != nil {
		return nil, resp, err
	}
	return header, resp, nil
}

// Create a new header.
func (c *HeaderConfig) Create(serviceID string, version uint, header *Header) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header", serviceID, version)

	req, err := c.client.NewJSONRequest("POST", u, header)
	if err != nil {
		return nil, nil, err
	}

	b := new(Header)
	resp, err := c.client.Do(req, b)
	if err != nil {
		return nil, resp, err
	}

	return b, resp, nil
}

// Update a header
func (c *HeaderConfig) Update(serviceID string, version uint, name string, header *Header) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewJSONRequest("PUT", u, header)
	if err != nil {
		return nil, nil, err
	}

	b := new(Header)
	resp, err := c.client.Do(req, b)
	if err != nil {
		return nil, resp, err
	}

	return b, resp, nil
}

// Delete a header
func (c *HeaderConfig) Delete(serviceID string, version uint, name string) (*http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, nil
}
<commit_msg>Fix header action marshalling.<commit_after>package fastly

import (
	"fmt"
	"net/http"
	"sort"
)

type HeaderType int

const (
	_                            = iota
	HeaderTypeRequest HeaderType = iota
	HeaderTypeFetch
	HeaderTypeCache
	HeaderTypeResponse
)

func (s *HeaderType) UnmarshalText(b []byte) error {
	switch string(b) {
	case "request":
		*s = HeaderTypeRequest
	case "fetch":
		*s = HeaderTypeFetch
	case "cache":
		*s = HeaderTypeCache
	case "response":
		*s = HeaderTypeResponse
	}
	return nil
}

func (s *HeaderType) MarshalText() ([]byte, error) {
	switch *s {
	case HeaderTypeRequest:
		return []byte("request"), nil
	case HeaderTypeFetch:
		return []byte("fetch"), nil
	case HeaderTypeCache:
		return []byte("cache"), nil
	case HeaderTypeResponse:
		return []byte("response"), nil
	}
	return nil, nil
}

type HeaderAction int

const (
	_                            = iota
	HeaderActionSet HeaderAction = iota
	HeaderActionAppend
	HeaderActionDelete
	HeaderActionRegex
	HeaderActionRegexRepeat
)

func (s *HeaderAction) UnmarshalText(b []byte) error {
	switch string(b) {
	case "set":
		*s = HeaderActionSet
	case "append":
		*s = HeaderActionAppend
	case "delete":
		*s = HeaderActionDelete
	case "regex":
		*s = HeaderActionRegex
	case "regex_repeat":
		*s = HeaderActionRegexRepeat
	}
	return nil
}

func (s *HeaderAction) MarshalText() ([]byte, error) {
	switch *s {
	case HeaderActionSet:
		return []byte("set"), nil
	case HeaderActionAppend:
		return []byte("append"), nil
	case HeaderActionDelete:
		return []byte("delete"), nil
	case HeaderActionRegex:
		return []byte("regex"), nil
	case HeaderActionRegexRepeat:
		return []byte("regex_repeat"), nil
	}
	return nil, nil
}

type HeaderConfig config

type Header struct {
	ServiceID string `json:"service_id,omitempty"`
	Version   uint   `json:"version,string,omitempty"`

	Name              string       `json:"name,omitempty"`
	Action            HeaderAction `json:"action,omitempty"`
	CacheCondition    string       `json:"cache_condition,omitempty"`
	IgnoreIfSet       Compatibool  `json:"ignore_if_set,omitempty"`
	Priority          uint         `json:"priority,string,omitempty"`
	Regex             string       `json:"regex,omitempty"`
	RequestCondition  string       `json:"request_condition,omitempty"`
	ResponseCondition string       `json:"response_condition,omitempty"`
	Source            string       `json:"src,omitempty"`
	Destination       string       `json:"dst,omitempty"`
	Substitution      string       `json:"substitution,omitempty"`
	Type              HeaderType   `json:"type,omitempty"`
}

// headersByName is a sortable list of headers.
type headersByName []*Header

// Len, Swap, and Less implement the sortable interface.
func (s headersByName) Len() int      { return len(s) }
func (s headersByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s headersByName) Less(i, j int) bool {
	return s[i].Name < s[j].Name
}

// List headers for a specific service and version.
func (c *HeaderConfig) List(serviceID string, version uint) ([]*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header", serviceID, version)

	req, err := c.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	headers := new([]*Header)
	resp, err := c.client.Do(req, headers)
	if err != nil {
		return nil, resp, err
	}

	sort.Stable(headersByName(*headers))

	return *headers, resp, nil
}

// Get fetches a specific header by name.
func (c *HeaderConfig) Get(serviceID string, version uint, name string) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	header := new(Header)
	resp, err := c.client.Do(req, header)
	if err != nil {
		return nil, resp, err
	}
	return header, resp, nil
}

// Create a new header.
func (c *HeaderConfig) Create(serviceID string, version uint, header *Header) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header", serviceID, version)

	req, err := c.client.NewJSONRequest("POST", u, header)
	if err != nil {
		return nil, nil, err
	}

	b := new(Header)
	resp, err := c.client.Do(req, b)
	if err != nil {
		return nil, resp, err
	}

	return b, resp, nil
}

// Update a header
func (c *HeaderConfig) Update(serviceID string, version uint, name string, header *Header) (*Header, *http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewJSONRequest("PUT", u, header)
	if err != nil {
		return nil, nil, err
	}

	b := new(Header)
	resp, err := c.client.Do(req, b)
	if err != nil {
		return nil, resp, err
	}

	return b, resp, nil
}

// Delete a header
func (c *HeaderConfig) Delete(serviceID string, version uint, name string) (*http.Response, error) {
	u := fmt.Sprintf("/service/%s/version/%d/header/%s", serviceID, version, name)

	req, err := c.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, nil
}
<|endoftext|>


<commit_before>// vm: tabstop=2 shiftwidth=2

package main

import (
	"fmt"
	"bytes"
	"strings"
	"errors"
	"encoding/binary"
	"encoding/hex"
	"time"
	"crypto/rand"
	"code.google.com/p/go.crypto/nacl/box"
)

// timestamp creates a Mixmaster formatted timestamp, consisting of an intro
// string concatented to the number of days since Epoch (little Endian).
func timestamp() (stamp []byte) {
	d := uint16(time.Now().UTC().Unix() / 86400)
	days := make([]byte, 2)
	binary.LittleEndian.PutUint16(days, d)
	stamp = append([]byte("0000\x00"), days...)
	return
}

/*
Slot Header Format
[ Recipient key ID		 16 Bytes ]
[ Sender Public key		 32 Bytes ]
[ Xsalsa20 Nonce		 24 Bytes ]
[ Encrypted data		408 Bytes ] (392 + Overhead)
[ Random padding		 32 Bytes ]
*/

type slotHead struct {
	recipientKeyid []byte
	recipientPK []byte
	//sender_pubkey []byte
	//nonce []byte
	data []byte
}

func encodeHead(h slotHead) []byte {
	// Generate an ECC key pair
	sendpub, sendpriv, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	var nonce [24]byte
	copy(nonce[:], randbytes(24))
	buf := new(bytes.Buffer)
	buf.Write(h.recipientKeyid)
	buf.Write(sendpub[:])
	buf.Write(nonce[:])
	var pk [32]byte
	copy(pk[:], h.recipientPK)
	buf.Write(box.Seal(nil, h.data, &nonce, &pk, sendpriv))
	err = bufLenCheck(buf.Len(), 480)
	if err != nil {
		panic(err)
	}
	buf.Write(randbytes(headerBytes - buf.Len()))
	return buf.Bytes()
}

// decodeHead decodes a slot header
func decodeHead(b []byte, sec map[string][]byte) (data []byte, err error) {
	/*
	Decode functions should return their associated structs but, in this
	instance, the only field of value is the decrypted data.
	*/
	err = lenCheck(len(b), headerBytes)
	if err != nil {
		return
	}
	var keyid string
	keyid = hex.EncodeToString(b[0:16])
	sk, present := sec[keyid]
	if ! present {
		err = fmt.Errorf("%s: Keyid not found in secring", keyid)
		return
	}
	err = lenCheck(len(sk), 32)
	if err != nil {
		return
	}
	var sender_pk [32]byte
	copy(sender_pk[:], b[16:48])
	var recipient_sk [32]byte
	copy(recipient_sk[:], sk)
	var nonce [24]byte
	copy(nonce[:], b[48:72])
	var auth bool
	data, auth = box.Open(nil, b[72:72+408], &nonce, &sender_pk, &recipient_sk)
	if ! auth {
		err = errors.New("Authentication failed decrypting slot data")
		return
	}
	err = lenCheck(len(data), 392)
	return
}

/*
Encrypted Data
[ Packet ID		 16 Bytes ]
[ AES-CTR key		 32 Bytes ]
[ Packet type ID	  1 Byte  ]
[ Padded packet info	256 Bytes ]
[ Timestamp		  7 Bytes ]
[ Anti-tag digest	 64 Bytes ]
[ Padding		 16 Bytes ]
Total	392 Bytes
*/

type slotData struct {
	packetID []byte
	aesKey []byte
	packetType uint8
	packetInfo []byte
	timestamp []byte
	tagHash []byte
}

func encodeData(d slotData) (b []byte, err error) {
	err = lenCheck(len(d.packetID), 16)
	if err != nil {
		return
	}
	err = lenCheck(len(d.aesKey), 32)
	if err != nil {
		return
	}
	err = lenCheck(len(d.packetInfo), 256)
	if err != nil {
		return
	}
	err = lenCheck(len(d.tagHash), 64)
	if err != nil {
		return
	}
	buf := new(bytes.Buffer)
	buf.Write(d.packetID)
	buf.Write(d.aesKey)
	buf.WriteByte(d.packetType)
	buf.Write(d.packetInfo)
	buf.Write(d.timestamp)
	buf.Write(d.tagHash)
	err = bufLenCheck(buf.Len(), 376)
	if err != nil {
		return
	}
	buf.WriteString(strings.Repeat("\x00", 392 - buf.Len()))
	b = buf.Bytes()
	return
}

func decodeData(b []byte) (data slotData, err error) {
	err = lenCheck(len(b), 392)
	if err != nil {
		return
	}
	data.packetID = b[0:16]
	data.aesKey = b[16:48]
	data.packetType = uint8(b[48])
	data.packetInfo = b[49:305]
	//TODO Test timestamp
	data.tagHash = b[305:369]
	//Padding[369:392]
	return
}

/*
Final Hop
[ Chunk num		  1 Byte  ]
[ Num chunks		  1 Byte  ]
[ Message ID		 16 Bytes ]
[ AES-CTR IV		 16 Bytes ]
[ Body length		  4 Bytes ]
*/

type slotFinal struct {
	chunkNum uint8
	numChunks uint8
	messageID []byte
	aesIV []byte
	bodyBytes int
}

func encodeFinal(f slotFinal) []byte {
	buf := new(bytes.Buffer)
	buf.WriteByte(f.chunkNum)
	buf.WriteByte(f.numChunks)
	buf.Write(f.messageID)
	buf.Write(f.aesIV)
	tmp := make([]byte, 4)
	binary.LittleEndian.PutUint32(tmp, uint32(f.bodyBytes))
	buf.Write(tmp)
	err := bufLenCheck(buf.Len(), 38)
	if err != nil {
		panic(err)
	}
	buf.WriteString(strings.Repeat("\x00", 256 - buf.Len()))
	return buf.Bytes()
}

func decodeFinal(b []byte) (final slotFinal, err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	final.chunkNum = b[0]
	final.numChunks = b[1]
	final.messageID = b[2:18]
	final.aesIV = b[18:34]
	final.bodyBytes = int(binary.LittleEndian.Uint32(b[34:]))
	return
}

/*
Intermediate Hop
[ 11 * AES-CTR IVs		176 Bytes ]
[ Next hop address		 80 Bytes ]

IVs are 9 * header slots, payload and deterministic
*/

type slotIntermediate struct {
	aesIVs []byte
	nextHop string
}

func encodeIntermediate(inter slotIntermediate) []byte {
	var err error
	err = lenCheck(len(inter.aesIVs), (maxChainLength + 1) * 16)
	if err != nil {
		panic(err)
	}
	buf := new(bytes.Buffer)
	buf.Write(inter.aesIVs)
	buf.WriteString(inter.nextHop)
	err = bufLenCheck(buf.Len(), 256)
	if err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func decodeIntermediate(b []byte) (inter slotIntermediate, err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	inter.aesIVs = b[:176]
	inter.nextHop = strings.TrimRight(string(b[176:]), "\x00")
	return
}
<commit_msg>Correct a bug on tagHash length<commit_after>// vm: tabstop=2 shiftwidth=2

package main

import (
	"fmt"
	"bytes"
	"strings"
	"errors"
	"encoding/binary"
	"encoding/hex"
	"time"
	"crypto/rand"
	"code.google.com/p/go.crypto/nacl/box"
)

// timestamp creates a Mixmaster formatted timestamp, consisting of an intro
// string concatented to the number of days since Epoch (little Endian).
func timestamp() (stamp []byte) {
	d := uint16(time.Now().UTC().Unix() / 86400)
	days := make([]byte, 2)
	binary.LittleEndian.PutUint16(days, d)
	stamp = append([]byte("0000\x00"), days...)
	return
}

/*
Slot Header Format
[ Recipient key ID		 16 Bytes ]
[ Sender Public key		 32 Bytes ]
[ Xsalsa20 Nonce		 24 Bytes ]
[ Encrypted data		408 Bytes ] (392 + Overhead)
[ Random padding		 32 Bytes ]
*/

type slotHead struct {
	recipientKeyid []byte
	recipientPK []byte
	//sender_pubkey []byte
	//nonce []byte
	data []byte
}

func encodeHead(h slotHead) []byte {
	// Generate an ECC key pair
	sendpub, sendpriv, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	var nonce [24]byte
	copy(nonce[:], randbytes(24))
	buf := new(bytes.Buffer)
	buf.Write(h.recipientKeyid)
	buf.Write(sendpub[:])
	buf.Write(nonce[:])
	var pk [32]byte
	copy(pk[:], h.recipientPK)
	buf.Write(box.Seal(nil, h.data, &nonce, &pk, sendpriv))
	err = bufLenCheck(buf.Len(), 480)
	if err != nil {
		panic(err)
	}
	buf.Write(randbytes(headerBytes - buf.Len()))
	return buf.Bytes()
}

// decodeHead decodes a slot header
func decodeHead(b []byte, sec map[string][]byte) (data []byte, err error) {
	/*
	Decode functions should return their associated structs but, in this
	instance, the only field of value is the decrypted data.
	*/
	err = lenCheck(len(b), headerBytes)
	if err != nil {
		return
	}
	var keyid string
	keyid = hex.EncodeToString(b[0:16])
	sk, present := sec[keyid]
	if ! present {
		err = fmt.Errorf("%s: Keyid not found in secring", keyid)
		return
	}
	err = lenCheck(len(sk), 32)
	if err != nil {
		return
	}
	var sender_pk [32]byte
	copy(sender_pk[:], b[16:48])
	var recipient_sk [32]byte
	copy(recipient_sk[:], sk)
	var nonce [24]byte
	copy(nonce[:], b[48:72])
	var auth bool
	data, auth = box.Open(nil, b[72:72+408], &nonce, &sender_pk, &recipient_sk)
	if ! auth {
		err = errors.New("Authentication failed decrypting slot data")
		return
	}
	err = lenCheck(len(data), 392)
	return
}

/*
Encrypted Data
[ Packet ID		 16 Bytes ]
[ AES-CTR key		 32 Bytes ]
[ Packet type ID	  1 Byte  ]
[ Padded packet info	256 Bytes ]
[ Timestamp		  7 Bytes ]
[ Anti-tag digest	 64 Bytes ]
[ Padding		 16 Bytes ]
Total	392 Bytes
*/

type slotData struct {
	packetID []byte
	aesKey []byte
	packetType uint8
	packetInfo []byte
	timestamp []byte
	tagHash []byte
}

func encodeData(d slotData) (b []byte, err error) {
	err = lenCheck(len(d.packetID), 16)
	if err != nil {
		return
	}
	err = lenCheck(len(d.aesKey), 32)
	if err != nil {
		return
	}
	err = lenCheck(len(d.packetInfo), 256)
	if err != nil {
		return
	}
	err = lenCheck(len(d.tagHash), 64)
	if err != nil {
		return
	}
	buf := new(bytes.Buffer)
	buf.Write(d.packetID)
	buf.Write(d.aesKey)
	buf.WriteByte(d.packetType)
	buf.Write(d.packetInfo)
	buf.Write(d.timestamp)
	buf.Write(d.tagHash)
	err = bufLenCheck(buf.Len(), 376)
	if err != nil {
		return
	}
	buf.WriteString(strings.Repeat("\x00", 392 - buf.Len()))
	b = buf.Bytes()
	return
}

func decodeData(b []byte) (data slotData, err error) {
	err = lenCheck(len(b), 392)
	if err != nil {
		return
	}
	data.packetID = b[0:16]
	data.aesKey = b[16:48]
	data.packetType = uint8(b[48])
	data.packetInfo = b[49:305]
	data.timestamp = b[305:312]
	//TODO Test timestamp
	data.tagHash = b[312:376]
	//Padding[376:392]
	return
}

/*
Final Hop
[ Chunk num		  1 Byte  ]
[ Num chunks		  1 Byte  ]
[ Message ID		 16 Bytes ]
[ AES-CTR IV		 16 Bytes ]
[ Body length		  4 Bytes ]
*/

type slotFinal struct {
	chunkNum uint8
	numChunks uint8
	messageID []byte
	aesIV []byte
	bodyBytes int
}

func encodeFinal(f slotFinal) []byte {
	buf := new(bytes.Buffer)
	buf.WriteByte(f.chunkNum)
	buf.WriteByte(f.numChunks)
	buf.Write(f.messageID)
	buf.Write(f.aesIV)
	tmp := make([]byte, 4)
	binary.LittleEndian.PutUint32(tmp, uint32(f.bodyBytes))
	buf.Write(tmp)
	err := bufLenCheck(buf.Len(), 38)
	if err != nil {
		panic(err)
	}
	buf.WriteString(strings.Repeat("\x00", 256 - buf.Len()))
	return buf.Bytes()
}

func decodeFinal(b []byte) (final slotFinal, err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	final.chunkNum = b[0]
	final.numChunks = b[1]
	final.messageID = b[2:18]
	final.aesIV = b[18:34]
	final.bodyBytes = int(binary.LittleEndian.Uint32(b[34:]))
	return
}

/*
Intermediate Hop
[ 11 * AES-CTR IVs		176 Bytes ]
[ Next hop address		 80 Bytes ]

IVs are 9 * header slots, payload and deterministic
*/

type slotIntermediate struct {
	aesIVs []byte
	nextHop string
}

func encodeIntermediate(inter slotIntermediate) []byte {
	var err error
	err = lenCheck(len(inter.aesIVs), (maxChainLength + 1) * 16)
	if err != nil {
		panic(err)
	}
	buf := new(bytes.Buffer)
	buf.Write(inter.aesIVs)
	buf.WriteString(inter.nextHop)
	err = bufLenCheck(buf.Len(), 256)
	if err != nil {
		panic(err)
	}
	return buf.Bytes()
}

func decodeIntermediate(b []byte) (inter slotIntermediate, err error) {
	err = lenCheck(len(b), 256)
	if err != nil {
		return
	}
	inter.aesIVs = b[:176]
	inter.nextHop = strings.TrimRight(string(b[176:]), "\x00")
	return
}
<|endoftext|>


<commit_before>package ssdp

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/textproto"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/ipv4"
)

const (
	AddrString = "239.255.255.250:1900"
	rootDevice = "upnp:rootdevice"
	aliveNTS   = "ssdp:alive"
	byebyeNTS  = "ssdp:byebye"
)

var NetAddr *net.UDPAddr

func init() {
	var err error
	NetAddr, err = net.ResolveUDPAddr("udp4", AddrString)
	if err != nil {
		log.Panicf("Could not resolve %s: %s", AddrString, err)
	}
}

type badStringError struct {
	what string
	str  string
}

func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }

func ReadRequest(b *bufio.Reader) (req *http.Request, err error) {
	tp := textproto.NewReader(b)
	var s string
	if s, err = tp.ReadLine(); err != nil {
		return nil, err
	}
	defer func() {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	var f []string
	// TODO a split that only allows N values?
	if f = strings.SplitN(s, " ", 3); len(f) < 3 {
		return nil, &badStringError{"malformed request line", s}
	}
	if f[1] != "*" {
		return nil, &badStringError{"bad URL request", f[1]}
	}
	req = &http.Request{
		Method: f[0],
	}
	var ok bool
	if req.ProtoMajor, req.ProtoMinor, ok = http.ParseHTTPVersion(strings.TrimSpace(f[2])); !ok {
		return nil, &badStringError{"malformed HTTP version", f[2]}
	}

	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return nil, err
	}
	req.Header = http.Header(mimeHeader)
	return
}

type Server struct {
	conn           *net.UDPConn
	Interface      net.Interface
	Server         string
	Services       []string
	Devices        []string
	Location       func(net.IP) string
	UUID           string
	NotifyInterval time.Duration
	closed         chan struct{}
}

func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) {
	ret, err = net.ListenMulticastUDP("udp", &ifi, NetAddr)
	if err != nil {
		return
	}
	p := ipv4.NewPacketConn(ret)
	if err := p.SetMulticastTTL(2); err != nil {
		log.Println(err)
	}
	if err := p.SetMulticastLoopback(true); err != nil {
		log.Println(err)
	}
	return
}

func (me *Server) serve() {
	for {
		size := me.Interface.MTU
		if size > 65536 {
			size = 65536
		} else if size <= 0 { // fix for windows with mtu 4gb
			size = 65536
		}
		b := make([]byte, size)
		n, addr, err := me.conn.ReadFromUDP(b)
		select {
		case <-me.closed:
			return
		default:
		}
		if err != nil {
			log.Printf("error reading from UDP socket: %s", err)
			break
		}
		go me.handle(b[:n], addr)
	}
}

func (me *Server) Init() (err error) {
	me.closed = make(chan struct{})
	me.conn, err = makeConn(me.Interface)
	return
}

func (me *Server) Close() {
	close(me.closed)
	me.sendByeBye()
	me.conn.Close()
}

func (me *Server) Serve() (err error) {
	go me.serve()
	for {
		addrs, err := me.Interface.Addrs()
		if err != nil {
			return err
		}
		for _, addr := range addrs {
			ip := func() net.IP {
				switch val := addr.(type) {
				case *net.IPNet:
					return val.IP
				case *net.IPAddr:
					return val.IP
				}
				panic(fmt.Sprint("unexpected addr type:", addr))
			}()
			if ip.IsLinkLocalUnicast() {
				// These addresses seem to confuse VLC. Possibly there's supposed to be a zone
				// included in the address, but I don't see one.
				continue
			}
			extraHdrs := [][2]string{
				{"CACHE-CONTROL", fmt.Sprintf("max-age=%d", 5*me.NotifyInterval/2/time.Second)},
				{"LOCATION", me.Location(ip)},
			}
			me.notifyAll(aliveNTS, extraHdrs)
		}
		time.Sleep(me.NotifyInterval)
	}
}

func (me *Server) usnFromTarget(target string) string {
	if target == me.UUID {
		return target
	}
	return me.UUID + "::" + target
}

func (me *Server) makeNotifyMessage(target, nts string, extraHdrs [][2]string) []byte {
	lines := [...][2]string{
		{"HOST", AddrString},
		{"NT", target},
		{"NTS", nts},
		{"SERVER", me.Server},
		{"USN", me.usnFromTarget(target)},
	}
	buf := &bytes.Buffer{}
	fmt.Fprint(buf, "NOTIFY * HTTP/1.1\r\n")
	writeHdr := func(keyValue [2]string) {
		fmt.Fprintf(buf, "%s: %s\r\n", keyValue[0], keyValue[1])
	}
	for _, pair := range lines {
		writeHdr(pair)
	}
	for _, pair := range extraHdrs {
		writeHdr(pair)
	}
	fmt.Fprint(buf, "\r\n")
	return buf.Bytes()
}

func (me *Server) send(buf []byte, addr *net.UDPAddr) {
	if n, err := me.conn.WriteToUDP(buf, addr); err != nil {
		log.Printf("error writing to UDP socket: %s", err)
	} else if n != len(buf) {
		log.Printf("short write: %d/%d bytes", n, len(buf))
	}
}

func (me *Server) delayedSend(delay time.Duration, buf []byte, addr *net.UDPAddr) {
	go func() {
		select {
		case <-time.After(delay):
			me.send(buf, addr)
		case <-me.closed:
		}
	}()
}

func (me *Server) log(args ...interface{}) {
	args = append([]interface{}{me.Interface.Name + ":"}, args...)
	log.Print(args...)
}

func (me *Server) sendByeBye() {
	for _, type_ := range me.allTypes() {
		buf := me.makeNotifyMessage(type_, byebyeNTS, nil)
		me.send(buf, NetAddr)
	}
}

func (me *Server) notifyAll(nts string, extraHdrs [][2]string) {
	for _, type_ := range me.allTypes() {
		buf := me.makeNotifyMessage(type_, nts, extraHdrs)
		delay := time.Duration(rand.Int63n(int64(100 * time.Millisecond)))
		me.delayedSend(delay, buf, NetAddr)
	}
}

func (me *Server) allTypes() (ret []string) {
	for _, a := range [][]string{
		{rootDevice, me.UUID},
		me.Devices,
		me.Services,
	} {
		ret = append(ret, a...)
	}
	return
}

func (me *Server) handle(buf []byte, sender *net.UDPAddr) {
	req, err := ReadRequest(bufio.NewReader(bytes.NewReader(buf)))
	if err != nil {
		log.Println(err)
		return
	}
	if req.Method != "M-SEARCH" || req.Header.Get("man") != `"ssdp:discover"` {
		return
	}
	var mx uint
	if req.Header.Get("Host") == AddrString {
		mxHeader := req.Header.Get("mx")
		i, err := strconv.ParseUint(mxHeader, 0, 0)
		if err != nil {
			log.Printf("Invalid mx header %q: %s", mxHeader, err)
			return
		}
		mx = uint(i)
	} else {
		mx = 1
	}
	types := func(st string) []string {
		if st == "ssdp:all" {
			return me.allTypes()
		}
		for _, t := range me.allTypes() {
			if t == st {
				return []string{t}
			}
		}
		return nil
	}(req.Header.Get("st"))
	for _, ip := range func() (ret []net.IP) {
		addrs, err := me.Interface.Addrs()
		if err != nil {
			panic(err)
		}
		for _, addr := range addrs {
			if ip, ok := func() (net.IP, bool) {
				switch data := addr.(type) {
				case *net.IPNet:
					if data.Contains(sender.IP) {
						return data.IP, true
					}
					return nil, false
				case *net.IPAddr:
					return data.IP, true
				}
				panic(addr)
			}(); ok {
				ret = append(ret, ip)
			}
		}
		return
	}() {
		for _, type_ := range types {
			resp := me.makeResponse(ip, type_, req)
			delay := time.Duration(rand.Int63n(int64(time.Second) * int64(mx)))
			me.delayedSend(delay, resp, sender)
		}
	}
}

func (me *Server) makeResponse(ip net.IP, targ string, req *http.Request) (ret []byte) {
	resp := &http.Response{
		StatusCode: 200,
		ProtoMajor: 1,
		ProtoMinor: 1,
		Header:     make(http.Header),
		Request:    req,
	}
	for _, pair := range [...][2]string{
		{"CACHE-CONTROL", fmt.Sprintf("max-age=%d", 5*me.NotifyInterval/2/time.Second)},
		{"EXT", ""},
		{"LOCATION", me.Location(ip)},
		{"SERVER", me.Server},
		{"ST", targ},
		{"USN", me.usnFromTarget(targ)},
	} {
		resp.Header.Set(pair[0], pair[1])
	}
	buf := &bytes.Buffer{}
	if err := resp.Write(buf); err != nil {
		panic(err)
	}
	return buf.Bytes()
}
<commit_msg>Don't loopback multicast<commit_after>package ssdp

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net"
	"net/http"
	"net/textproto"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/ipv4"
)

const (
	AddrString = "239.255.255.250:1900"
	rootDevice = "upnp:rootdevice"
	aliveNTS   = "ssdp:alive"
	byebyeNTS  = "ssdp:byebye"
)

var NetAddr *net.UDPAddr

func init() {
	var err error
	NetAddr, err = net.ResolveUDPAddr("udp4", AddrString)
	if err != nil {
		log.Panicf("Could not resolve %s: %s", AddrString, err)
	}
}

type badStringError struct {
	what string
	str  string
}

func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }

func ReadRequest(b *bufio.Reader) (req *http.Request, err error) {
	tp := textproto.NewReader(b)
	var s string
	if s, err = tp.ReadLine(); err != nil {
		return nil, err
	}
	defer func() {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
	}()

	var f []string
	// TODO a split that only allows N values?
	if f = strings.SplitN(s, " ", 3); len(f) < 3 {
		return nil, &badStringError{"malformed request line", s}
	}
	if f[1] != "*" {
		return nil, &badStringError{"bad URL request", f[1]}
	}
	req = &http.Request{
		Method: f[0],
	}
	var ok bool
	if req.ProtoMajor, req.ProtoMinor, ok = http.ParseHTTPVersion(strings.TrimSpace(f[2])); !ok {
		return nil, &badStringError{"malformed HTTP version", f[2]}
	}

	mimeHeader, err := tp.ReadMIMEHeader()
	if err != nil {
		return nil, err
	}
	req.Header = http.Header(mimeHeader)
	return
}

type Server struct {
	conn           *net.UDPConn
	Interface      net.Interface
	Server         string
	Services       []string
	Devices        []string
	Location       func(net.IP) string
	UUID           string
	NotifyInterval time.Duration
	closed         chan struct{}
}

func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) {
	ret, err = net.ListenMulticastUDP("udp", &ifi, NetAddr)
	if err != nil {
		return
	}
	p := ipv4.NewPacketConn(ret)
	if err := p.SetMulticastTTL(2); err != nil {
		log.Println(err)
	}
	// if err := p.SetMulticastLoopback(true); err != nil {
	// 	log.Println(err)
	// }
	return
}

func (me *Server) serve() {
	for {
		size := me.Interface.MTU
		if size > 65536 {
			size = 65536
		} else if size <= 0 { // fix for windows with mtu 4gb
			size = 65536
		}
		b := make([]byte, size)
		n, addr, err := me.conn.ReadFromUDP(b)
		select {
		case <-me.closed:
			return
		default:
		}
		if err != nil {
			log.Printf("error reading from UDP socket: %s", err)
			break
		}
		go me.handle(b[:n], addr)
	}
}

func (me *Server) Init() (err error) {
	me.closed = make(chan struct{})
	me.conn, err = makeConn(me.Interface)
	return
}

func (me *Server) Close() {
	close(me.closed)
	me.sendByeBye()
	me.conn.Close()
}

func (me *Server) Serve() (err error) {
	go me.serve()
	for {
		addrs, err := me.Interface.Addrs()
		if err != nil {
			return err
		}
		for _, addr := range addrs {
			ip := func() net.IP {
				switch val := addr.(type) {
				case *net.IPNet:
					return val.IP
				case *net.IPAddr:
					return val.IP
				}
				panic(fmt.Sprint("unexpected addr type:", addr))
			}()
			if ip.IsLinkLocalUnicast() {
				// These addresses seem to confuse VLC. Possibly there's supposed to be a zone
				// included in the address, but I don't see one.
				continue
			}
			extraHdrs := [][2]string{
				{"CACHE-CONTROL", fmt.Sprintf("max-age=%d", 5*me.NotifyInterval/2/time.Second)},
				{"LOCATION", me.Location(ip)},
			}
			me.notifyAll(aliveNTS, extraHdrs)
		}
		time.Sleep(me.NotifyInterval)
	}
}

func (me *Server) usnFromTarget(target string) string {
	if target == me.UUID {
		return target
	}
	return me.UUID + "::" + target
}

func (me *Server) makeNotifyMessage(target, nts string, extraHdrs [][2]string) []byte {
	lines := [...][2]string{
		{"HOST", AddrString},
		{"NT", target},
		{"NTS", nts},
		{"SERVER", me.Server},
		{"USN", me.usnFromTarget(target)},
	}
	buf := &bytes.Buffer{}
	fmt.Fprint(buf, "NOTIFY * HTTP/1.1\r\n")
	writeHdr := func(keyValue [2]string) {
		fmt.Fprintf(buf, "%s: %s\r\n", keyValue[0], keyValue[1])
	}
	for _, pair := range lines {
		writeHdr(pair)
	}
	for _, pair := range extraHdrs {
		writeHdr(pair)
	}
	fmt.Fprint(buf, "\r\n")
	return buf.Bytes()
}

func (me *Server) send(buf []byte, addr *net.UDPAddr) {
	if n, err := me.conn.WriteToUDP(buf, addr); err != nil {
		log.Printf("error writing to UDP socket: %s", err)
	} else if n != len(buf) {
		log.Printf("short write: %d/%d bytes", n, len(buf))
	}
}

func (me *Server) delayedSend(delay time.Duration, buf []byte, addr *net.UDPAddr) {
	go func() {
		select {
		case <-time.After(delay):
			me.send(buf, addr)
		case <-me.closed:
		}
	}()
}

func (me *Server) log(args ...interface{}) {
	args = append([]interface{}{me.Interface.Name + ":"}, args...)
	log.Print(args...)
}

func (me *Server) sendByeBye() {
	for _, type_ := range me.allTypes() {
		buf := me.makeNotifyMessage(type_, byebyeNTS, nil)
		me.send(buf, NetAddr)
	}
}

func (me *Server) notifyAll(nts string, extraHdrs [][2]string) {
	for _, type_ := range me.allTypes() {
		buf := me.makeNotifyMessage(type_, nts, extraHdrs)
		delay := time.Duration(rand.Int63n(int64(100 * time.Millisecond)))
		me.delayedSend(delay, buf, NetAddr)
	}
}

func (me *Server) allTypes() (ret []string) {
	for _, a := range [][]string{
		{rootDevice, me.UUID},
		me.Devices,
		me.Services,
	} {
		ret = append(ret, a...)
	}
	return
}

func (me *Server) handle(buf []byte, sender *net.UDPAddr) {
	req, err := ReadRequest(bufio.NewReader(bytes.NewReader(buf)))
	if err != nil {
		log.Println(err)
		return
	}
	if req.Method != "M-SEARCH" || req.Header.Get("man") != `"ssdp:discover"` {
		return
	}
	var mx uint
	if req.Header.Get("Host") == AddrString {
		mxHeader := req.Header.Get("mx")
		i, err := strconv.ParseUint(mxHeader, 0, 0)
		if err != nil {
			log.Printf("Invalid mx header %q: %s", mxHeader, err)
			return
		}
		mx = uint(i)
	} else {
		mx = 1
	}
	types := func(st string) []string {
		if st == "ssdp:all" {
			return me.allTypes()
		}
		for _, t := range me.allTypes() {
			if t == st {
				return []string{t}
			}
		}
		return nil
	}(req.Header.Get("st"))
	for _, ip := range func() (ret []net.IP) {
		addrs, err := me.Interface.Addrs()
		if err != nil {
			panic(err)
		}
		for _, addr := range addrs {
			if ip, ok := func() (net.IP, bool) {
				switch data := addr.(type) {
				case *net.IPNet:
					if data.Contains(sender.IP) {
						return data.IP, true
					}
					return nil, false
				case *net.IPAddr:
					return data.IP, true
				}
				panic(addr)
			}(); ok {
				ret = append(ret, ip)
			}
		}
		return
	}() {
		for _, type_ := range types {
			resp := me.makeResponse(ip, type_, req)
			delay := time.Duration(rand.Int63n(int64(time.Second) * int64(mx)))
			me.delayedSend(delay, resp, sender)
		}
	}
}

func (me *Server) makeResponse(ip net.IP, targ string, req *http.Request) (ret []byte) {
	resp := &http.Response{
		StatusCode: 200,
		ProtoMajor: 1,
		ProtoMinor: 1,
		Header:     make(http.Header),
		Request:    req,
	}
	for _, pair := range [...][2]string{
		{"CACHE-CONTROL", fmt.Sprintf("max-age=%d", 5*me.NotifyInterval/2/time.Second)},
		{"EXT", ""},
		{"LOCATION", me.Location(ip)},
		{"SERVER", me.Server},
		{"ST", targ},
		{"USN", me.usnFromTarget(targ)},
	} {
		resp.Header.Set(pair[0], pair[1])
	}
	buf := &bytes.Buffer{}
	if err := resp.Write(buf); err != nil {
		panic(err)
	}
	return buf.Bytes()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	// . "github.com/eaciit/hdc/hive"
	. "github.com/hdc/yanda15/hdc/hive"
)

var h *Hive
var q string

type Sample7 struct {
	Code        string `tag_name:"code"`
	Description string `tag_name:"description"`
	Total_emp   string `tag_name:"total_emp"`
	Salary      string `tag_name:"salary"`
}

func main() {
	h = HiveConfig("192.168.0.223:10000", "default", "developer", "b1gD@T@", "")
	q = "select * from sample_07 limit 5;"
	//for now this function just provide  csv type
	TestParseOutput()
	//Exec Query and Process with DoSomething Function PerLine
	TestExecPerLine()
	// Exec Query and wait until all line fetched
	TestExec()
}

func DoSomething(res string) {
	tmp := Sample7{}
	h.ParseOutput(res, &tmp)
	fmt.Println(tmp)
}

func TestExec() {
	res, e := h.Exec(q)

	if e != nil {
		fmt.Printf("error: \n%v\n", e)
	} else {
		fmt.Println(res)
	}
}

func TestExecPerLine() {
	e := h.ExecLine(q, DoSomething)

	if e != nil {
		fmt.Printf("error: \n%v\n", e)
	}
}

func TestParseOutput() {
	h.Header = []string{"code", "description", "total_emp", "salary"}
	h.OutputType = "csv"
	//h = SetHeader([]string{"code", "description", "total_emp", "salary"})
	res := "00-0000,All Occupations,134354250,40690"
	tmp := Sample7{}
	h.ParseOutput(res, &tmp)
	fmt.Println(tmp)
}
<commit_msg>commit for test parse out<commit_after>package main

import (
	"fmt"
	// . "github.com/eaciit/hdc/hive"
	. "github.com/eaciit/hdc/hive"
)

var h *Hive
var q string

type Sample7 struct {
	Code        string `tag_name:"code"`
	Description string `tag_name:"description"`
	Total_emp   string `tag_name:"total_emp"`
	Salary      string `tag_name:"salary"`
}

func main() {
	h = HiveConfig("192.168.0.223:10000", "default", "developer", "b1gD@T@", "")
	q = "select * from sample_07 limit 5;"
	//for now this function just provide  csv type
	TestParseOutput()
	//Exec Query and Process with DoSomething Function PerLine
	TestExecPerLine()
	// Exec Query and wait until all line fetched
	TestExec()
}

func DoSomething(res string) {
	tmp := Sample7{}
	h.ParseOutput(res, &tmp)
	fmt.Println(tmp)
}

func TestExec() {
	res, e := h.Exec(q)

	if e != nil {
		fmt.Printf("error: \n%v\n", e)
	} else {
		fmt.Println(res)
	}
}

func TestExecPerLine() {
	e := h.ExecLine(q, DoSomething)

	if e != nil {
		fmt.Printf("error: \n%v\n", e)
	}
}

func TestParseOutput() {
	h.Header = []string{"code", "description", "total_emp", "salary"}
	h.OutputType = "csv"
	//h = SetHeader([]string{"code", "description", "total_emp", "salary"})
	res := "00-0000,All Occupations,134354250,40690"
	tmp := Sample7{}
	h.ParseOutput(res, &tmp)
	fmt.Println(tmp)
}
<|endoftext|>


<commit_before>package test

import (
	// "github.com/ipfs/go-ipfs/thirdparty/testutil"
	"github.com/OpenBazaar/multiwallet"
	"github.com/OpenBazaar/multiwallet/config"
	"github.com/OpenBazaar/openbazaar-go/core"
	"github.com/OpenBazaar/openbazaar-go/ipfs"
	"github.com/OpenBazaar/openbazaar-go/net"
	"github.com/OpenBazaar/openbazaar-go/net/service"
	"github.com/OpenBazaar/spvwallet"
	wi "github.com/OpenBazaar/wallet-interface"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcutil/hdkeychain"
	"github.com/ipfs/go-ipfs/core/mock"
	"github.com/tyler-smith/go-bip39"
	"gx/ipfs/QmZoWKhxUmZ2seW4BzX6fJkNR8hh9PsGModr7q171yq2SS/go-libp2p-peer"
	"gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
	inet "net"
)

// NewNode creates a new *core.OpenBazaarNode prepared for testing
func NewNode() (*core.OpenBazaarNode, error) {
	// Create test repo
	repository, err := NewRepository()
	if err != nil {
		return nil, err
	}

	repository.Reset()
	if err != nil {
		return nil, err
	}

	// Create test ipfs node
	ipfsNode, err := coremock.NewMockNode()
	if err != nil {
		return nil, err
	}

	seed := bip39.NewSeed(GetPassword(), "Secret Passphrase")
	privKey, err := ipfs.IdentityKeyFromSeed(seed, 256)
	if err != nil {
		return nil, err
	}

	sk, err := crypto.UnmarshalPrivateKey(privKey)
	if err != nil {
		return nil, err
	}

	id, err := peer.IDFromPublicKey(sk.GetPublic())
	if err != nil {
		return nil, err
	}

	ipfsNode.Identity = id

	// Create test wallet
	mnemonic, err := repository.DB.Config().GetMnemonic()
	if err != nil {
		return nil, err
	}
	mPrivKey, err := hdkeychain.NewMaster(seed, &chaincfg.RegressionNetParams)
	if err != nil {
		return nil, err
	}
	tp, err := inet.ResolveTCPAddr("tcp4", "127.0.0.1:8333")
	if err != nil {
		return nil, err
	}
	spvwalletConfig := &spvwallet.Config{
		Mnemonic:    mnemonic,
		Params:      &chaincfg.RegressionNetParams,
		MaxFee:      50000,
		LowFee:      8000,
		MediumFee:   16000,
		HighFee:     24000,
		RepoPath:    repository.Path,
		DB:          repository.DB,
		UserAgent:   "OpenBazaar",
		TrustedPeer: tp,
		Proxy:       nil,
		Logger:      NewLogger(),
	}

	coins := make(map[wi.CoinType]bool)
	coins[wi.Bitcoin] = true
	coins[wi.BitcoinCash] = true
	coins[wi.Zcash] = true
	coins[wi.Litecoin] = true

	walletConf := config.NewDefaultConfig(coins, &chaincfg.RegressionNetParams)
	walletConf.Mnemonic = mnemonic
	mw, err := multiwallet.NewMultiWallet(walletConf)
	if err != nil {
		return nil, err
	}

	wallet, err := spvwallet.NewSPVWallet(spvwalletConfig)
	if err != nil {
		return nil, err
	}

	// Put it all together in an OpenBazaarNode
	node := &core.OpenBazaarNode{
		RepoPath:         GetRepoPath(),
		IpfsNode:         ipfsNode,
		Datastore:        repository.DB,
		Wallet:           wallet,
		Multiwallet:      mw,
		BanManager:       net.NewBanManager([]peer.ID{}),
		MasterPrivateKey: mPrivKey,
	}

	node.Service = service.New(node, repository.DB)

	return node, nil
}
<commit_msg>Remove wallet from test node<commit_after>package test

import (
	// "github.com/ipfs/go-ipfs/thirdparty/testutil"
	"github.com/OpenBazaar/multiwallet"
	"github.com/OpenBazaar/multiwallet/config"
	"github.com/OpenBazaar/openbazaar-go/core"
	"github.com/OpenBazaar/openbazaar-go/ipfs"
	"github.com/OpenBazaar/openbazaar-go/net"
	"github.com/OpenBazaar/openbazaar-go/net/service"
	wi "github.com/OpenBazaar/wallet-interface"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcutil/hdkeychain"
	"github.com/ipfs/go-ipfs/core/mock"
	"github.com/tyler-smith/go-bip39"
	"gx/ipfs/QmZoWKhxUmZ2seW4BzX6fJkNR8hh9PsGModr7q171yq2SS/go-libp2p-peer"
	"gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
)

// NewNode creates a new *core.OpenBazaarNode prepared for testing
func NewNode() (*core.OpenBazaarNode, error) {
	// Create test repo
	repository, err := NewRepository()
	if err != nil {
		return nil, err
	}

	repository.Reset()
	if err != nil {
		return nil, err
	}

	// Create test ipfs node
	ipfsNode, err := coremock.NewMockNode()
	if err != nil {
		return nil, err
	}

	seed := bip39.NewSeed(GetPassword(), "Secret Passphrase")
	privKey, err := ipfs.IdentityKeyFromSeed(seed, 256)
	if err != nil {
		return nil, err
	}

	sk, err := crypto.UnmarshalPrivateKey(privKey)
	if err != nil {
		return nil, err
	}

	id, err := peer.IDFromPublicKey(sk.GetPublic())
	if err != nil {
		return nil, err
	}

	ipfsNode.Identity = id

	// Create test wallet
	mnemonic, err := repository.DB.Config().GetMnemonic()
	if err != nil {
		return nil, err
	}
	mPrivKey, err := hdkeychain.NewMaster(seed, &chaincfg.RegressionNetParams)
	if err != nil {
		return nil, err
	}

	coins := make(map[wi.CoinType]bool)
	coins[wi.Bitcoin] = true
	coins[wi.BitcoinCash] = true
	coins[wi.Zcash] = true
	coins[wi.Litecoin] = true

	walletConf := config.NewDefaultConfig(coins, &chaincfg.RegressionNetParams)
	walletConf.Mnemonic = mnemonic
	mw, err := multiwallet.NewMultiWallet(walletConf)
	if err != nil {
		return nil, err
	}

	// Put it all together in an OpenBazaarNode
	node := &core.OpenBazaarNode{
		RepoPath:         GetRepoPath(),
		IpfsNode:         ipfsNode,
		Datastore:        repository.DB,
		Multiwallet:      mw,
		BanManager:       net.NewBanManager([]peer.ID{}),
		MasterPrivateKey: mPrivKey,
	}

	node.Service = service.New(node, repository.DB)

	return node, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Blake Gentry. All rights reserved. Use of
// this source code is governed by an MIT license that can be
// found in the LICENSE file.

package heroku

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"reflect"
	"runtime"
	"strings"

	"code.google.com/p/go-uuid/uuid"
)

const (
	Version          = "0.8.0"
	DefaultAPIURL    = "https://api.heroku.com"
	DefaultUserAgent = "heroku-go/" + Version + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
)

// A Client is a Heroku API client. Its zero value is a usable client that uses
// default settings for the Heroku API. The Client has an internal HTTP client
// (HTTP) which defaults to http.DefaultClient.
//
// As with all http.Clients, this Client's Transport has internal state (cached
// HTTP connections), so Clients should be reused instead of created as needed.
// Clients are safe for use by multiple goroutines.
type Client struct {
	// HTTP is the Client's internal http.Client, handling HTTP requests to the
	// Heroku API.
	HTTP *http.Client

	// The URL of the Heroku API to communicate with. Defaults to
	// "https://api.heroku.com".
	URL string

	// Username is the HTTP basic auth username for API calls made by this Client.
	Username string

	// Password is the HTTP basic auth password for API calls made by this Client.
	Password string

	// UserAgent to be provided in API requests. Set to DefaultUserAgent if not
	// specified.
	UserAgent string

	// Debug mode can be used to dump the full request and response to stdout.
	Debug bool

	// AdditionalHeaders are extra headers to add to each HTTP request sent by
	// this Client.
	AdditionalHeaders http.Header
}

func (c *Client) Get(v interface{}, path string) error {
	return c.APIReq(v, "GET", path, nil)
}

func (c *Client) Patch(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "PATCH", path, body)
}

func (c *Client) Post(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "POST", path, body)
}

func (c *Client) Put(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "PUT", path, body)
}

func (c *Client) Delete(path string) error {
	return c.APIReq(nil, "DELETE", path, nil)
}

// Generates an HTTP request for the Heroku API, but does not
// perform the request. The request's Accept header field will be
// set to:
//
//   Accept: application/vnd.heroku+json; version=3
//
// The Request-Id header will be set to a random UUID. The User-Agent header
// will be set to the Client's UserAgent, or DefaultUserAgent if UserAgent is
// not set.
//
// The type of body determines how to encode the request:
//
//   nil         no body
//   io.Reader   body is sent verbatim
//   else        body is encoded as application/json
func (c *Client) NewRequest(method, path string, body interface{}) (*http.Request, error) {
	var ctype string
	var rbody io.Reader

	switch t := body.(type) {
	case nil:
	case string:
		rbody = bytes.NewBufferString(t)
	case io.Reader:
		rbody = t
	default:
		v := reflect.ValueOf(body)
		if !v.IsValid() {
			break
		}
		if v.Type().Kind() == reflect.Ptr {
			v = reflect.Indirect(v)
			if !v.IsValid() {
				break
			}
		}

		j, err := json.Marshal(body)
		if err != nil {
			log.Fatal(err)
		}
		rbody = bytes.NewReader(j)
		ctype = "application/json"
	}
	apiURL := strings.TrimRight(c.URL, "/")
	if apiURL == "" {
		apiURL = DefaultAPIURL
	}
	req, err := http.NewRequest(method, apiURL+path, rbody)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", "application/vnd.heroku+json; version=3")
	req.Header.Set("Request-Id", uuid.New())
	useragent := c.UserAgent
	if useragent == "" {
		useragent = DefaultUserAgent
	}
	req.Header.Set("User-Agent", useragent)
	if ctype != "" {
		req.Header.Set("Content-Type", ctype)
	}
	req.SetBasicAuth(c.Username, c.Password)
	for k, v := range c.AdditionalHeaders {
		req.Header[k] = v
	}
	return req, nil
}

// Sends a Heroku API request and decodes the response into v. As
// described in NewRequest(), the type of body determines how to
// encode the request body. As described in DoReq(), the type of
// v determines how to handle the response body.
func (c *Client) APIReq(v interface{}, meth, path string, body interface{}) error {
	req, err := c.NewRequest(meth, path, body)
	if err != nil {
		return err
	}
	return c.DoReq(req, v)
}

// Submits an HTTP request, checks its response, and deserializes
// the response into v. The type of v determines how to handle
// the response body:
//
//   nil        body is discarded
//   io.Writer  body is copied directly into v
//   else       body is decoded into v as json
//
func (c *Client) DoReq(req *http.Request, v interface{}) error {
	if c.Debug {
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			log.Println(err)
		} else {
			os.Stderr.Write(dump)
			os.Stderr.Write([]byte{'\n', '\n'})
		}
	}

	httpClient := c.HTTP
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	res, err := httpClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if c.Debug {
		dump, err := httputil.DumpResponse(res, true)
		if err != nil {
			log.Println(err)
		} else {
			os.Stderr.Write(dump)
			os.Stderr.Write([]byte{'\n'})
		}
	}
	if err = checkResp(res); err != nil {
		return err
	}
	switch t := v.(type) {
	case nil:
	case io.Writer:
		_, err = io.Copy(t, res.Body)
	default:
		err = json.NewDecoder(res.Body).Decode(v)
	}
	return err
}

// An Error represents a Heroku API error.
type Error struct {
	error
	Id  string
	URL string
}

type errorResp struct {
	Message string
	Id      string
	URL     string `json:"url"`
}

func checkResp(res *http.Response) error {
	if res.StatusCode/100 != 2 { // 200, 201, 202, etc
		var e errorResp
		err := json.NewDecoder(res.Body).Decode(&e)
		if err != nil {
			return errors.New("Unexpected error: " + res.Status)
		}
		return Error{error: errors.New(e.Message), Id: e.Id, URL: e.URL}
	}
	if msg := res.Header.Get("X-Heroku-Warning"); msg != "" {
		fmt.Fprintln(os.Stderr, strings.TrimSpace(msg))
	}
	return nil
}

type ListRange struct {
	Field      string
	Max        int
	Descending bool
	FirstId    string
	LastId     string
}

func (lr *ListRange) SetHeader(req *http.Request) {
	var hdrval string
	if lr.Field != "" {
		hdrval += lr.Field + " "
	}
	hdrval += lr.FirstId + ".." + lr.LastId
	if lr.Max != 0 {
		hdrval += fmt.Sprintf("; max=%d", lr.Max)
		if lr.Descending {
			hdrval += ", "
		}
	}

	if lr.Descending {
		hdrval += ", order=desc"
	}

	req.Header.Set("Range", hdrval)
	return
}
<commit_msg>version 0.9.0<commit_after>// Copyright (c) 2013 Blake Gentry. All rights reserved. Use of
// this source code is governed by an MIT license that can be
// found in the LICENSE file.

package heroku

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"reflect"
	"runtime"
	"strings"

	"code.google.com/p/go-uuid/uuid"
)

const (
	Version          = "0.9.0"
	DefaultAPIURL    = "https://api.heroku.com"
	DefaultUserAgent = "heroku-go/" + Version + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
)

// A Client is a Heroku API client. Its zero value is a usable client that uses
// default settings for the Heroku API. The Client has an internal HTTP client
// (HTTP) which defaults to http.DefaultClient.
//
// As with all http.Clients, this Client's Transport has internal state (cached
// HTTP connections), so Clients should be reused instead of created as needed.
// Clients are safe for use by multiple goroutines.
type Client struct {
	// HTTP is the Client's internal http.Client, handling HTTP requests to the
	// Heroku API.
	HTTP *http.Client

	// The URL of the Heroku API to communicate with. Defaults to
	// "https://api.heroku.com".
	URL string

	// Username is the HTTP basic auth username for API calls made by this Client.
	Username string

	// Password is the HTTP basic auth password for API calls made by this Client.
	Password string

	// UserAgent to be provided in API requests. Set to DefaultUserAgent if not
	// specified.
	UserAgent string

	// Debug mode can be used to dump the full request and response to stdout.
	Debug bool

	// AdditionalHeaders are extra headers to add to each HTTP request sent by
	// this Client.
	AdditionalHeaders http.Header
}

func (c *Client) Get(v interface{}, path string) error {
	return c.APIReq(v, "GET", path, nil)
}

func (c *Client) Patch(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "PATCH", path, body)
}

func (c *Client) Post(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "POST", path, body)
}

func (c *Client) Put(v interface{}, path string, body interface{}) error {
	return c.APIReq(v, "PUT", path, body)
}

func (c *Client) Delete(path string) error {
	return c.APIReq(nil, "DELETE", path, nil)
}

// Generates an HTTP request for the Heroku API, but does not
// perform the request. The request's Accept header field will be
// set to:
//
//   Accept: application/vnd.heroku+json; version=3
//
// The Request-Id header will be set to a random UUID. The User-Agent header
// will be set to the Client's UserAgent, or DefaultUserAgent if UserAgent is
// not set.
//
// The type of body determines how to encode the request:
//
//   nil         no body
//   io.Reader   body is sent verbatim
//   else        body is encoded as application/json
func (c *Client) NewRequest(method, path string, body interface{}) (*http.Request, error) {
	var ctype string
	var rbody io.Reader

	switch t := body.(type) {
	case nil:
	case string:
		rbody = bytes.NewBufferString(t)
	case io.Reader:
		rbody = t
	default:
		v := reflect.ValueOf(body)
		if !v.IsValid() {
			break
		}
		if v.Type().Kind() == reflect.Ptr {
			v = reflect.Indirect(v)
			if !v.IsValid() {
				break
			}
		}

		j, err := json.Marshal(body)
		if err != nil {
			log.Fatal(err)
		}
		rbody = bytes.NewReader(j)
		ctype = "application/json"
	}
	apiURL := strings.TrimRight(c.URL, "/")
	if apiURL == "" {
		apiURL = DefaultAPIURL
	}
	req, err := http.NewRequest(method, apiURL+path, rbody)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", "application/vnd.heroku+json; version=3")
	req.Header.Set("Request-Id", uuid.New())
	useragent := c.UserAgent
	if useragent == "" {
		useragent = DefaultUserAgent
	}
	req.Header.Set("User-Agent", useragent)
	if ctype != "" {
		req.Header.Set("Content-Type", ctype)
	}
	req.SetBasicAuth(c.Username, c.Password)
	for k, v := range c.AdditionalHeaders {
		req.Header[k] = v
	}
	return req, nil
}

// Sends a Heroku API request and decodes the response into v. As
// described in NewRequest(), the type of body determines how to
// encode the request body. As described in DoReq(), the type of
// v determines how to handle the response body.
func (c *Client) APIReq(v interface{}, meth, path string, body interface{}) error {
	req, err := c.NewRequest(meth, path, body)
	if err != nil {
		return err
	}
	return c.DoReq(req, v)
}

// Submits an HTTP request, checks its response, and deserializes
// the response into v. The type of v determines how to handle
// the response body:
//
//   nil        body is discarded
//   io.Writer  body is copied directly into v
//   else       body is decoded into v as json
//
func (c *Client) DoReq(req *http.Request, v interface{}) error {
	if c.Debug {
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			log.Println(err)
		} else {
			os.Stderr.Write(dump)
			os.Stderr.Write([]byte{'\n', '\n'})
		}
	}

	httpClient := c.HTTP
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	res, err := httpClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if c.Debug {
		dump, err := httputil.DumpResponse(res, true)
		if err != nil {
			log.Println(err)
		} else {
			os.Stderr.Write(dump)
			os.Stderr.Write([]byte{'\n'})
		}
	}
	if err = checkResp(res); err != nil {
		return err
	}
	switch t := v.(type) {
	case nil:
	case io.Writer:
		_, err = io.Copy(t, res.Body)
	default:
		err = json.NewDecoder(res.Body).Decode(v)
	}
	return err
}

// An Error represents a Heroku API error.
type Error struct {
	error
	Id  string
	URL string
}

type errorResp struct {
	Message string
	Id      string
	URL     string `json:"url"`
}

func checkResp(res *http.Response) error {
	if res.StatusCode/100 != 2 { // 200, 201, 202, etc
		var e errorResp
		err := json.NewDecoder(res.Body).Decode(&e)
		if err != nil {
			return errors.New("Unexpected error: " + res.Status)
		}
		return Error{error: errors.New(e.Message), Id: e.Id, URL: e.URL}
	}
	if msg := res.Header.Get("X-Heroku-Warning"); msg != "" {
		fmt.Fprintln(os.Stderr, strings.TrimSpace(msg))
	}
	return nil
}

type ListRange struct {
	Field      string
	Max        int
	Descending bool
	FirstId    string
	LastId     string
}

func (lr *ListRange) SetHeader(req *http.Request) {
	var hdrval string
	if lr.Field != "" {
		hdrval += lr.Field + " "
	}
	hdrval += lr.FirstId + ".." + lr.LastId
	if lr.Max != 0 {
		hdrval += fmt.Sprintf("; max=%d", lr.Max)
		if lr.Descending {
			hdrval += ", "
		}
	}

	if lr.Descending {
		hdrval += ", order=desc"
	}

	req.Header.Set("Range", hdrval)
	return
}
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
    "database/sql/driver"
    )

type firebirdsqlStmt struct {
    wp *wireProtocol
    stmtHandle int32
}

func (stmt *firebirdsqlStmt) Close() (err error) {
    return
}

func (stmt *firebirdsqlStmt) NumInput() int {
    return 0
}

func (stmt *firebirdsqlStmt) Exec(args []driver.Value) (driver.Result, error) {
    var err error
    return nil, err
}

func (stmt *firebirdsqlStmt) Query(args []driver.Value) (driver.Rows, error) {
    var err error
    return nil, err
}

func newFirebirdsqlStmt(wp *wireProtocol, query string) (*firebirdsqlStmt, error) {
    var err error
    stmt := new(firebirdsqlStmt)
    return stmt, err
}
<commit_msg>opAllocateStatement()<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
    "database/sql/driver"
    )

type firebirdsqlStmt struct {
    wp *wireProtocol
    stmtHandle int32
}

func (stmt *firebirdsqlStmt) Close() (err error) {
    return
}

func (stmt *firebirdsqlStmt) NumInput() int {
    return 0
}

func (stmt *firebirdsqlStmt) Exec(args []driver.Value) (driver.Result, error) {
    var err error
    return nil, err
}

func (stmt *firebirdsqlStmt) Query(args []driver.Value) (driver.Rows, error) {
    var err error
    return nil, err
}

func newFirebirdsqlStmt(wp *wireProtocol, query string) (*firebirdsqlStmt, error) {
    var err error
    stmt := new(firebirdsqlStmt)
    wp.opAllocateStatement()

    stmt.stmtHandle, _, _, err = tx.wp.opResponse()
    return stmt, err
}
<|endoftext|>


<commit_before>package vbox

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
)

var VBoxManage = "VBoxManage"

func createVBoxError(output []string, e error) error {
	vboxErrorPrefix := "VBoxManage: error: "
	for i := range output {
		if strings.HasPrefix(output[i], vboxErrorPrefix) {
			return fmt.Errorf(strings.TrimPrefix(output[i], vboxErrorPrefix))
		}
	}
	return e
}

func downloadFile(baseUrl, filename string) (target string, e error) {
	target = filepath.Join(os.TempDir(), filename)

	if _, e = os.Stat(target); !os.IsNotExist(e) {
		return "", fmt.Errorf("target %q already exists", target)
	}

	out, e := os.Create(target)
	if e != nil {
		log.Printf("failed to create %q", target)
		return "", e
	}
	defer out.Close()

	url := baseUrl + "/" + filename

	resp, e := http.Get(url)
	if e != nil || resp.StatusCode != 200 {
		if resp == nil {
			return "", e
		}
		return "", fmt.Errorf("request for %q failed: %s", url, resp.Status)
	}
	defer resp.Body.Close()

	log.Print("downloading template ...")
	_, e = io.Copy(out, resp.Body)
	log.Print(" ... done")

	return target, nil
}

func ImportTemplateVM(filename, vm string) error {
	switch _, err := os.Stat(filename); {
	case os.IsNotExist(err):
		return fmt.Errorf("file %s does not exist", filename)
	case err != nil:
		return err
	}

	if vmList, err := ListAllVMs(); err != nil {
		return err
	} else {
		for i := range vmList {
			if vmList[i].Name == vm {
				return fmt.Errorf("vm %q already exists!", vm)
			}
		}
	}

	log.Print("importing vm ...")
	_, err := run("import", filename, "--vsys", "0", "--vmname", vm)
	log.Print(" ... done")
	return err

}

func DownloadTemplateVM(sourceURL, filename, vm string) (e error) {
	vmList, e := ListAllVMs()
	if e != nil {
		return e
	}

	for i := range vmList {
		if vmList[i].Name == vm {
			return fmt.Errorf("vm %q already exists!", vm)
		}
	}

	target, e := downloadFile(sourceURL, filename)
	if e != nil {
		return e
	}
	defer os.Remove(target)

	log.Print("importing vm ...")
	_, e = run("import", target, "--vsys", "0", "--vmname", vm)
	log.Print(" ... done")
	return e
}

func run(action string, args ...string) (output []string, e error) {
	args = append([]string{action}, args...)
	cmd := exec.Command(VBoxManage, args...)

	out, e := cmd.CombinedOutput()
	if out != nil {
		output = strings.Split(string(out), "\n")
		if e != nil {
			return output, createVBoxError(output, e)
		}
	}
	return output, e
}

func ListAllVMs() ([]*VM, error) {
	return listVMs(true)
}

func ListRunningVMs() ([]*VM, error) {
	return listVMs(false)
}

func listVMs(all bool) (vms []*VM, e error) {
	listType := "vms"
	if !all {
		listType = "runningvms"
	}

	var output []string
	if output, e = run("list", listType); e != nil {
		return nil, e
	}

	vms = make([]*VM, 0, len(output))

	for i := range output {
		if len(output[i]) == 0 {
			continue
		}

		parts := strings.Fields(output[i])
		if len(parts) != 2 {
			return nil, fmt.Errorf("failed to parse line: %s", output[i])
		}
		vm := &VM{Name: strings.Trim(parts[0], "\""), Uuid: parts[1]}
		if e = vm.load(); e != nil {
			return nil, e
		}
		vms = append(vms, vm)
	}
	return vms, nil
}

func parsePropertyLine(line string) (name string, value string) {
	parts := strings.Split(line, ", ")

	name = strings.TrimPrefix(parts[0], "Name: ")
	value = strings.TrimPrefix(parts[1], "value: ")

	return name, value
}

func GetVMProperties(vm string) (properties map[string]string, e error) {
	var output []string
	if output, e = run("guestproperty", "enumerate", vm); e != nil {
		return nil, e
	}

	properties = map[string]string{}
	for _, line := range output {
		if len(line) == 0 {
			continue
		}

		name, value := parsePropertyLine(line)
		properties[name] = value
	}

	return properties, nil
}

func (vm *VM) load() (e error) {
	var output []string
	if output, e = run("showvminfo", "--machinereadable", vm.Name); e != nil {
		return e
	}

	values := map[string]string{}

	for _, line := range output {
		if len(line) == 0 {
			continue
		}
		parts := strings.Split(line, "=")
		values[parts[0]] = strings.Trim(parts[1], "\"")
	}

	if vm.Cpus, e = strconv.Atoi(values["cpus"]); e != nil {
		return e
	}

	if vm.Memory, e = strconv.Atoi(values["memory"]); e != nil {
		return e
	}

	vm.Status = values["VMState"]

	for i := 0; i < 4; i++ {
		vm.BootOrder[i] = values[fmt.Sprintf("boot%d", i+1)]
	}

	for i := 0; i < 8; i++ {
		if ntype, found := values[fmt.Sprintf("nic%d", i+1)]; found {
			if ntype == "none" {
				continue
			}
			nic := &VNet{
				Id:    i + 1,
				NType: ntype,
			}
			nic.Mac = values[fmt.Sprintf("macaddress%d", nic.Id)]
			if ntype == "hostonly" {
				nic.Name = values[fmt.Sprintf("hostonlyadapter%d", nic.Id)]
			}
			vm.Nics = append(vm.Nics, nic)
		}
	}

	if vm.SFolders == nil {
		vm.SFolders = map[string]string{}
	}
	for i := 1; ; i++ {
		sfMap, found := values[fmt.Sprintf("SharedFolderNameMachineMapping%d", i)]

		if !found {
			break
		}

		vm.SFolders[sfMap] = values[fmt.Sprintf("SharedFolderPathMachineMapping%d", i)]
	}

	return nil
}

func CloneVM(name string, template string, snapshot string) (e error) {
	if _, e = run("clonevm", template, "--name", name, "--snapshot", snapshot, "--options", "link", "--register"); e != nil {
		return e
	}

	return e
}

type VM struct {
	Name      string
	Uuid      string
	Status    string
	BootOrder [4]string
	Memory    int
	Cpus      int
	Nics      []*VNet
	SFolders  map[string]string
}

type VNet struct {
	Id    int
	NType string
	Name  string
	Mac   string
}

func LoadVM(name string) (vm *VM, e error) {
	vm = &VM{Name: name}
	return vm, vm.load()
}

func StartVM(name string, withGui bool) (e error) {
	vmtype := "headless"
	if withGui {
		vmtype = "gui"
	}
	_, e = run("startvm", name, "--type", vmtype)
	return e
}

func SaveVM(name string) (e error) {
	_, e = run("controlvm", name, "savestate")
	return e
}

func StopVM(name string) (e error) {
	_, e = run("controlvm", name, "poweroff")
	return e
}

func ShutdownVM(name string) (e error) {
	_, e = run("controlvm", name, "acpipowerbutton")
	return e
}

func isVMRunning(name string) (bool, error) {
	vms, e := ListRunningVMs()
	if e != nil {
		return false, e
	}

	for i := range vms {
		if vms[i].Name == name {
			return true, nil
		}
	}
	return false, nil
}

func isVM(name string) (bool, error) {
	vms, e := ListAllVMs()
	if e != nil {
		return false, e
	}

	for i := range vms {
		if vms[i].Name == name {
			return true, nil
		}
	}
	return false, nil
}

func getProperty(vm string, property string) (value string, e error) {
	result, e := run("guestproperty", "get", vm, property)
	if e != nil {
		return "", e
	}

	if result[0] == "No value set!" {
		return "", nil
	}

	if strings.HasPrefix(result[0], "Value: ") {
		return strings.TrimPrefix(result[0], "Value: "), nil
	}

	return "", fmt.Errorf("failed to retrieve property")
}

func waitForProperty(vm string, property string, timeout int) (value string, e error) {
	result, e := run("guestproperty", "wait", vm, property, "--timeout", strconv.Itoa(1000*timeout))
	if e != nil {
		return "", e
	} else if strings.HasPrefix(result[0], "VBoxManage: error: Time out or interruption while waiting for a notification.") {
		return "", fmt.Errorf("Machine not reachable.")
	}

	_, ip := parsePropertyLine(result[0])
	return ip, nil
}

func GetIP(vm string, iface int, timeout int) (ip string, e error) {
	var valid, running bool
	if valid, e = isVM(vm); e != nil {
		return "", e
	} else if !valid {
		return "", fmt.Errorf("VM %q does not exist", vm)
	}

	if running, e = isVMRunning(vm); e != nil {
		return "", e
	} else if !running {
		return "", fmt.Errorf("VM %q not running", vm)
	}

	property := fmt.Sprintf("/VirtualBox/GuestInfo/Net/%d/V4/IP", iface)

	ip, e = getProperty(vm, property)
	if e != nil {
		return "", e
	} else if ip == "" {
		ip, e = waitForProperty(vm, property, timeout)
		if e != nil {
			return "", e
		}
	}
	return ip, nil
}

func DeleteVM(name string) (e error) {
	_, e = run("unregistervm", name, "--delete")
	return e
}

func (vm *VM) Save() (e error) {
	args := []string{vm.Name}
	args = append(args, "--memory", strconv.Itoa(vm.Memory))
	args = append(args, "--cpus", strconv.Itoa(vm.Cpus))

	for i := 0; i < 4; i++ {
		args = append(args, "--boot"+strconv.Itoa(i+1), vm.BootOrder[i])
	}

	for _, nic := range vm.Nics {
		args = append(args, "--nic"+strconv.Itoa(nic.Id), nic.NType)
		if nic.NType == "hostonly" {
			args = append(args, "--hostonlyadapter"+strconv.Itoa(nic.Id), nic.Name)
		}
	}

	_, e = run("modifyvm", args...)

	return e
}

func ShareFolder(name, tname, folder string) (e error) {
	if _, e = os.Stat(folder); os.IsNotExist(e) {
		return fmt.Errorf("folder %q does not exist!", folder)
	}

	_, e = run("sharedfolder", "add", name, "--name", tname, "--hostpath", folder, "--automount")
	return e
}

func UnshareFolder(name, tname string) (e error) {
	_, e = run("sharedfolder", "remove", name, "--name", tname)
	return e
}

func (vm *VM) String() string {
	s := ""
	s += fmt.Sprintf("VM %q\n", vm.Name)
	s += fmt.Sprintf("cpus:          %d\n", vm.Cpus)
	s += fmt.Sprintf("memory:        %d MB\n", vm.Memory)
	s += fmt.Sprintf("boot order:    %s\n", strings.Join(vm.BootOrder[:], ","))
	for _, nic := range vm.Nics {
		networkName := ""
		if nic.NType == "hostonly" {
			networkName = " [->" + nic.Name + "]"
		}
		s += fmt.Sprintf("nic [%d]:       %s %s%s\n", nic.Id, nic.NType, nic.Mac, networkName)
	}
	for k, v := range vm.SFolders {
		s += fmt.Sprintf("shared folder: %s [->%s]\n", v, k)
	}
	return s
}
<commit_msg>[vbox] made delete vm shutdown first<commit_after>package vbox

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

var VBoxManage = "VBoxManage"

func createVBoxError(output []string, e error) error {
	vboxErrorPrefix := "VBoxManage: error: "
	for i := range output {
		if strings.HasPrefix(output[i], vboxErrorPrefix) {
			return fmt.Errorf(strings.TrimPrefix(output[i], vboxErrorPrefix))
		}
	}
	return e
}

func downloadFile(baseUrl, filename string) (target string, e error) {
	target = filepath.Join(os.TempDir(), filename)

	if _, e = os.Stat(target); !os.IsNotExist(e) {
		return "", fmt.Errorf("target %q already exists", target)
	}

	out, e := os.Create(target)
	if e != nil {
		log.Printf("failed to create %q", target)
		return "", e
	}
	defer out.Close()

	url := baseUrl + "/" + filename

	resp, e := http.Get(url)
	if e != nil || resp.StatusCode != 200 {
		if resp == nil {
			return "", e
		}
		return "", fmt.Errorf("request for %q failed: %s", url, resp.Status)
	}
	defer resp.Body.Close()

	log.Print("downloading template ...")
	_, e = io.Copy(out, resp.Body)
	log.Print(" ... done")

	return target, nil
}

func ImportTemplateVM(filename, vm string) error {
	switch _, err := os.Stat(filename); {
	case os.IsNotExist(err):
		return fmt.Errorf("file %s does not exist", filename)
	case err != nil:
		return err
	}

	if vmList, err := ListAllVMs(); err != nil {
		return err
	} else {
		for i := range vmList {
			if vmList[i].Name == vm {
				return fmt.Errorf("vm %q already exists!", vm)
			}
		}
	}

	log.Print("importing vm ...")
	_, err := run("import", filename, "--vsys", "0", "--vmname", vm)
	log.Print(" ... done")
	return err

}

func DownloadTemplateVM(sourceURL, filename, vm string) (e error) {
	vmList, e := ListAllVMs()
	if e != nil {
		return e
	}

	for i := range vmList {
		if vmList[i].Name == vm {
			return fmt.Errorf("vm %q already exists!", vm)
		}
	}

	target, e := downloadFile(sourceURL, filename)
	if e != nil {
		return e
	}
	defer os.Remove(target)

	log.Print("importing vm ...")
	_, e = run("import", target, "--vsys", "0", "--vmname", vm)
	log.Print(" ... done")
	return e
}

func run(action string, args ...string) (output []string, e error) {
	args = append([]string{action}, args...)
	cmd := exec.Command(VBoxManage, args...)

	out, e := cmd.CombinedOutput()
	if out != nil {
		output = strings.Split(string(out), "\n")
		if e != nil {
			return output, createVBoxError(output, e)
		}
	}
	return output, e
}

func ListAllVMs() ([]*VM, error) {
	return listVMs(true)
}

func ListRunningVMs() ([]*VM, error) {
	return listVMs(false)
}

func listVMs(all bool) (vms []*VM, e error) {
	listType := "vms"
	if !all {
		listType = "runningvms"
	}

	var output []string
	if output, e = run("list", listType); e != nil {
		return nil, e
	}

	vms = make([]*VM, 0, len(output))

	for i := range output {
		if len(output[i]) == 0 {
			continue
		}

		parts := strings.Fields(output[i])
		if len(parts) != 2 {
			return nil, fmt.Errorf("failed to parse line: %s", output[i])
		}
		vm := &VM{Name: strings.Trim(parts[0], "\""), Uuid: parts[1]}
		if e = vm.load(); e != nil {
			return nil, e
		}
		vms = append(vms, vm)
	}
	return vms, nil
}

func parsePropertyLine(line string) (name string, value string) {
	parts := strings.Split(line, ", ")

	name = strings.TrimPrefix(parts[0], "Name: ")
	value = strings.TrimPrefix(parts[1], "value: ")

	return name, value
}

func GetVMProperties(vm string) (properties map[string]string, e error) {
	var output []string
	if output, e = run("guestproperty", "enumerate", vm); e != nil {
		return nil, e
	}

	properties = map[string]string{}
	for _, line := range output {
		if len(line) == 0 {
			continue
		}

		name, value := parsePropertyLine(line)
		properties[name] = value
	}

	return properties, nil
}

func (vm *VM) load() (e error) {
	var output []string
	if output, e = run("showvminfo", "--machinereadable", vm.Name); e != nil {
		return e
	}

	values := map[string]string{}

	for _, line := range output {
		if len(line) == 0 {
			continue
		}
		parts := strings.Split(line, "=")
		values[parts[0]] = strings.Trim(parts[1], "\"")
	}

	if vm.Cpus, e = strconv.Atoi(values["cpus"]); e != nil {
		return e
	}

	if vm.Memory, e = strconv.Atoi(values["memory"]); e != nil {
		return e
	}

	vm.Status = values["VMState"]

	for i := 0; i < 4; i++ {
		vm.BootOrder[i] = values[fmt.Sprintf("boot%d", i+1)]
	}

	for i := 0; i < 8; i++ {
		if ntype, found := values[fmt.Sprintf("nic%d", i+1)]; found {
			if ntype == "none" {
				continue
			}
			nic := &VNet{
				Id:    i + 1,
				NType: ntype,
			}
			nic.Mac = values[fmt.Sprintf("macaddress%d", nic.Id)]
			if ntype == "hostonly" {
				nic.Name = values[fmt.Sprintf("hostonlyadapter%d", nic.Id)]
			}
			vm.Nics = append(vm.Nics, nic)
		}
	}

	if vm.SFolders == nil {
		vm.SFolders = map[string]string{}
	}
	for i := 1; ; i++ {
		sfMap, found := values[fmt.Sprintf("SharedFolderNameMachineMapping%d", i)]

		if !found {
			break
		}

		vm.SFolders[sfMap] = values[fmt.Sprintf("SharedFolderPathMachineMapping%d", i)]
	}

	return nil
}

func CloneVM(name string, template string, snapshot string) (e error) {
	if _, e = run("clonevm", template, "--name", name, "--snapshot", snapshot, "--options", "link", "--register"); e != nil {
		return e
	}

	return e
}

type VM struct {
	Name      string
	Uuid      string
	Status    string
	BootOrder [4]string
	Memory    int
	Cpus      int
	Nics      []*VNet
	SFolders  map[string]string
}

type VNet struct {
	Id    int
	NType string
	Name  string
	Mac   string
}

func LoadVM(name string) (vm *VM, e error) {
	vm = &VM{Name: name}
	return vm, vm.load()
}

func StartVM(name string, withGui bool) (e error) {
	vmtype := "headless"
	if withGui {
		vmtype = "gui"
	}
	_, e = run("startvm", name, "--type", vmtype)
	return e
}

func SaveVM(name string) (e error) {
	_, e = run("controlvm", name, "savestate")
	return e
}

func StopVM(name string) (e error) {
	_, e = run("controlvm", name, "poweroff")
	return e
}

func ShutdownVM(name string) (e error) {
	_, e = run("controlvm", name, "acpipowerbutton")
	return e
}

func isVMRunning(name string) (bool, error) {
	vms, e := ListRunningVMs()
	if e != nil {
		return false, e
	}

	for i := range vms {
		if vms[i].Name == name {
			return true, nil
		}
	}
	return false, nil
}

func isVM(name string) (bool, error) {
	vms, e := ListAllVMs()
	if e != nil {
		return false, e
	}

	for i := range vms {
		if vms[i].Name == name {
			return true, nil
		}
	}
	return false, nil
}

func getProperty(vm string, property string) (value string, e error) {
	result, e := run("guestproperty", "get", vm, property)
	if e != nil {
		return "", e
	}

	if result[0] == "No value set!" {
		return "", nil
	}

	if strings.HasPrefix(result[0], "Value: ") {
		return strings.TrimPrefix(result[0], "Value: "), nil
	}

	return "", fmt.Errorf("failed to retrieve property")
}

func waitForProperty(vm string, property string, timeout int) (value string, e error) {
	result, e := run("guestproperty", "wait", vm, property, "--timeout", strconv.Itoa(1000*timeout))
	if e != nil {
		return "", e
	} else if strings.HasPrefix(result[0], "VBoxManage: error: Time out or interruption while waiting for a notification.") {
		return "", fmt.Errorf("Machine not reachable.")
	}

	_, ip := parsePropertyLine(result[0])
	return ip, nil
}

func GetIP(vm string, iface int, timeout int) (ip string, e error) {
	var valid, running bool
	if valid, e = isVM(vm); e != nil {
		return "", e
	} else if !valid {
		return "", fmt.Errorf("VM %q does not exist", vm)
	}

	if running, e = isVMRunning(vm); e != nil {
		return "", e
	} else if !running {
		return "", fmt.Errorf("VM %q not running", vm)
	}

	property := fmt.Sprintf("/VirtualBox/GuestInfo/Net/%d/V4/IP", iface)

	ip, e = getProperty(vm, property)
	if e != nil {
		return "", e
	} else if ip == "" {
		ip, e = waitForProperty(vm, property, timeout)
		if e != nil {
			return "", e
		}
	}
	return ip, nil
}

func DeleteVM(name string) (e error) {
	err := func() error {
		if running, err := isVMRunning(name); err != nil {
			return err
		} else if running {
			_ = ShutdownVM(name)
			for i := 0; i < 20; i++ { // wait for 10 seconds
				running, _ := isVMRunning(name)
				if !running {
					return nil
				}
				time.Sleep(500 * time.Millisecond)
			}
			return fmt.Errorf("failed to shutdown vm")
		}
		return nil
	}()
	if err != nil {
		return err
	}

	_, e = run("unregistervm", name, "--delete")
	return e
}

func (vm *VM) Save() (e error) {
	args := []string{vm.Name}
	args = append(args, "--memory", strconv.Itoa(vm.Memory))
	args = append(args, "--cpus", strconv.Itoa(vm.Cpus))

	for i := 0; i < 4; i++ {
		args = append(args, "--boot"+strconv.Itoa(i+1), vm.BootOrder[i])
	}

	for _, nic := range vm.Nics {
		args = append(args, "--nic"+strconv.Itoa(nic.Id), nic.NType)
		if nic.NType == "hostonly" {
			args = append(args, "--hostonlyadapter"+strconv.Itoa(nic.Id), nic.Name)
		}
	}

	_, e = run("modifyvm", args...)

	return e
}

func ShareFolder(name, tname, folder string) (e error) {
	if _, e = os.Stat(folder); os.IsNotExist(e) {
		return fmt.Errorf("folder %q does not exist!", folder)
	}

	_, e = run("sharedfolder", "add", name, "--name", tname, "--hostpath", folder, "--automount")
	return e
}

func UnshareFolder(name, tname string) (e error) {
	_, e = run("sharedfolder", "remove", name, "--name", tname)
	return e
}

func (vm *VM) String() string {
	s := ""
	s += fmt.Sprintf("VM %q\n", vm.Name)
	s += fmt.Sprintf("cpus:          %d\n", vm.Cpus)
	s += fmt.Sprintf("memory:        %d MB\n", vm.Memory)
	s += fmt.Sprintf("boot order:    %s\n", strings.Join(vm.BootOrder[:], ","))
	for _, nic := range vm.Nics {
		networkName := ""
		if nic.NType == "hostonly" {
			networkName = " [->" + nic.Name + "]"
		}
		s += fmt.Sprintf("nic [%d]:       %s %s%s\n", nic.Id, nic.NType, nic.Mac, networkName)
	}
	for k, v := range vm.SFolders {
		s += fmt.Sprintf("shared folder: %s [->%s]\n", v, k)
	}
	return s
}
<|endoftext|>