<commit_before>package mobilevikings

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

const defaultBaseURL = "https://api.mobilevikings.be/v3"

var usageAmount = regexp.MustCompile(`^([\d+]{1,})\.([\d+]{2})$`)

func newClient(accessToken string) *client {
	return &client{defaultBaseURL, accessToken, &http.Client{}}
}

type client struct {
	baseURL     string
	accessToken string
	client      *http.Client
}

type phoneNumbersResponse struct {
	Results []PhoneNumber `json:"results"`
}

type usageResponse struct {
	Results []Usage `json:"results"`
}

func (c *client) PhoneNumbers() ([]PhoneNumber, error) {
	response, err := c.doRequest("GET", "msisdns/")
	if err != nil {
		return nil, err
	}
	unmarshalled := &phoneNumbersResponse{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return nil, err
	}
	return unmarshalled.Results, nil
}

func (c *client) Insights(phoneNumber string) (*Insights, error) {
	response, err := c.doRequest("GET", fmt.Sprintf("msisdns/%s/insights/", phoneNumber))
	if err != nil {
		return &Insights{}, err
	}
	unmarshalled := &Insights{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return &Insights{}, err
	}
	return unmarshalled, nil
}

func (c *client) Usage(
	phoneNumber string,
	from time.Time,
	until time.Time,
) ([]Usage, error) {
	query := url.Values{}
	query.Set("from_date", from.Format("2006-01-02"))
	query.Set("until_date", until.Format("2006-01-02"))
	response, err := c.doRequest(
		"GET",
		fmt.Sprintf("msisdns/%s/usage/?%s", phoneNumber, query.Encode()),
	)
	if err != nil {
		return nil, err
	}
	unmarshalled := &usageResponse{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return nil, err
	}
	return unmarshalled.Results, nil
}

func (c *client) Topups(phoneNumber string, pageURL string) (TopupPage, error) {
	if pageURL == "" {
		pageURL = fmt.Sprintf("msisdns/%s/topups/", phoneNumber)
	}
	response, err := c.doRequest("GET", pageURL)
	if err != nil {
		return TopupPage{}, err
	}
	unmarshalled := TopupPage{}
	fmt.Println(string(response))
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return TopupPage{}, err
	}
	return unmarshalled, nil
}

func (c *client) doRequest(method string, path string) ([]byte, error) {
	fullUrl := strings.Join([]string{c.baseURL, path}, "/")
	request, err := http.NewRequest(method, fullUrl, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.accessToken))
	request.Header.Set("Accept", "application/json")
	response, err := c.client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}
<commit_msg>remove debug print<commit_after>package mobilevikings

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

const defaultBaseURL = "https://api.mobilevikings.be/v3"

var usageAmount = regexp.MustCompile(`^([\d+]{1,})\.([\d+]{2})$`)

func newClient(accessToken string) *client {
	return &client{defaultBaseURL, accessToken, &http.Client{}}
}

type client struct {
	baseURL     string
	accessToken string
	client      *http.Client
}

type phoneNumbersResponse struct {
	Results []PhoneNumber `json:"results"`
}

type usageResponse struct {
	Results []Usage `json:"results"`
}

func (c *client) PhoneNumbers() ([]PhoneNumber, error) {
	response, err := c.doRequest("GET", "msisdns/")
	if err != nil {
		return nil, err
	}
	unmarshalled := &phoneNumbersResponse{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return nil, err
	}
	return unmarshalled.Results, nil
}

func (c *client) Insights(phoneNumber string) (*Insights, error) {
	response, err := c.doRequest("GET", fmt.Sprintf("msisdns/%s/insights/", phoneNumber))
	if err != nil {
		return &Insights{}, err
	}
	unmarshalled := &Insights{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return &Insights{}, err
	}
	return unmarshalled, nil
}

func (c *client) Usage(
	phoneNumber string,
	from time.Time,
	until time.Time,
) ([]Usage, error) {
	query := url.Values{}
	query.Set("from_date", from.Format("2006-01-02"))
	query.Set("until_date", until.Format("2006-01-02"))
	response, err := c.doRequest(
		"GET",
		fmt.Sprintf("msisdns/%s/usage/?%s", phoneNumber, query.Encode()),
	)
	if err != nil {
		return nil, err
	}
	unmarshalled := &usageResponse{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return nil, err
	}
	return unmarshalled.Results, nil
}

func (c *client) Topups(phoneNumber string, pageURL string) (TopupPage, error) {
	if pageURL == "" {
		pageURL = fmt.Sprintf("msisdns/%s/topups/", phoneNumber)
	}
	response, err := c.doRequest("GET", pageURL)
	if err != nil {
		return TopupPage{}, err
	}
	unmarshalled := TopupPage{}
	if err := json.Unmarshal(response, &unmarshalled); err != nil {
		return TopupPage{}, err
	}
	return unmarshalled, nil
}

func (c *client) doRequest(method string, path string) ([]byte, error) {
	fullUrl := strings.Join([]string{c.baseURL, path}, "/")
	request, err := http.NewRequest(method, fullUrl, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.accessToken))
	request.Header.Set("Accept", "application/json")
	response, err := c.client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}
<|endoftext|>


<commit_before>package quic

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"github.com/lucas-clemente/quic-go/internal/wire"
	"github.com/lucas-clemente/quic-go/qerr"
)

type client struct {
	mutex sync.Mutex

	conn     connection
	hostname string

	handshakeChan <-chan handshakeEvent

	versionNegotiationChan           chan struct{} // the versionNegotiationChan is closed as soon as the server accepted the suggested version
	versionNegotiated                bool          // has version negotiation completed yet
	receivedVersionNegotiationPacket bool

	tlsConf *tls.Config
	config  *Config

	connectionID protocol.ConnectionID
	version      protocol.VersionNumber

	session packetHandler
}

var (
	// make it possible to mock connection ID generation in the tests
	generateConnectionID         = utils.GenerateConnectionID
	errCloseSessionForNewVersion = errors.New("closing session in order to recreate it with a new version")
)

// DialAddr establishes a new QUIC connection to a server.
// The hostname for SNI is taken from the given address.
func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error) {
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return nil, err
	}
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	return Dial(udpConn, udpAddr, addr, tlsConf, config)
}

// DialAddrNonFWSecure establishes a new QUIC connection to a server.
// The hostname for SNI is taken from the given address.
func DialAddrNonFWSecure(
	addr string,
	tlsConf *tls.Config,
	config *Config,
) (NonFWSession, error) {
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return nil, err
	}
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	return DialNonFWSecure(udpConn, udpAddr, addr, tlsConf, config)
}

// DialNonFWSecure establishes a new non-forward-secure QUIC connection to a server using a net.PacketConn.
// The host parameter is used for SNI.
func DialNonFWSecure(
	pconn net.PacketConn,
	remoteAddr net.Addr,
	host string,
	tlsConf *tls.Config,
	config *Config,
) (NonFWSession, error) {
	connID, err := generateConnectionID()
	if err != nil {
		return nil, err
	}

	var hostname string
	if tlsConf != nil {
		hostname = tlsConf.ServerName
	}

	if hostname == "" {
		hostname, _, err = net.SplitHostPort(host)
		if err != nil {
			return nil, err
		}
	}

	clientConfig := populateClientConfig(config)
	c := &client{
		conn:                   &conn{pconn: pconn, currentAddr: remoteAddr},
		connectionID:           connID,
		hostname:               hostname,
		tlsConf:                tlsConf,
		config:                 clientConfig,
		version:                clientConfig.Versions[0],
		versionNegotiationChan: make(chan struct{}),
	}

	utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %d", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)

	if err := c.establishSecureConnection(); err != nil {
		return nil, err
	}
	return c.session.(NonFWSession), nil
}

// Dial establishes a new QUIC connection to a server using a net.PacketConn.
// The host parameter is used for SNI.
func Dial(
	pconn net.PacketConn,
	remoteAddr net.Addr,
	host string,
	tlsConf *tls.Config,
	config *Config,
) (Session, error) {
	sess, err := DialNonFWSecure(pconn, remoteAddr, host, tlsConf, config)
	if err != nil {
		return nil, err
	}
	if err := sess.WaitUntilHandshakeComplete(); err != nil {
		return nil, err
	}
	return sess, nil
}

// populateClientConfig populates fields in the quic.Config with their default values, if none are set
// it may be called with nil
func populateClientConfig(config *Config) *Config {
	if config == nil {
		config = &Config{}
	}
	versions := config.Versions
	if len(versions) == 0 {
		versions = protocol.SupportedVersions
	}

	handshakeTimeout := protocol.DefaultHandshakeTimeout
	if config.HandshakeTimeout != 0 {
		handshakeTimeout = config.HandshakeTimeout
	}
	idleTimeout := protocol.DefaultIdleTimeout
	if config.IdleTimeout != 0 {
		idleTimeout = config.IdleTimeout
	}

	maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
	if maxReceiveStreamFlowControlWindow == 0 {
		maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowClient
	}
	maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
	if maxReceiveConnectionFlowControlWindow == 0 {
		maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
	}

	return &Config{
		Versions:                              versions,
		HandshakeTimeout:                      handshakeTimeout,
		IdleTimeout:                           idleTimeout,
		RequestConnectionIDTruncation:         config.RequestConnectionIDTruncation,
		MaxReceiveStreamFlowControlWindow:     maxReceiveStreamFlowControlWindow,
		MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
		KeepAlive: config.KeepAlive,
	}
}

// establishSecureConnection returns as soon as the connection is secure (as opposed to forward-secure)
func (c *client) establishSecureConnection() error {
	if err := c.createNewSession(nil); err != nil {
		return err
	}
	go c.listen()

	var runErr error
	errorChan := make(chan struct{})
	go func() {
		// session.run() returns as soon as the session is closed
		runErr = c.session.run()
		if runErr == errCloseSessionForNewVersion {
			// run the new session
			runErr = c.session.run()
		}
		close(errorChan)
		utils.Infof("Connection %x closed.", c.connectionID)
		c.conn.Close()
	}()

	// wait until the server accepts the QUIC version (or an error occurs)
	select {
	case <-errorChan:
		return runErr
	case <-c.versionNegotiationChan:
	}

	select {
	case <-errorChan:
		return runErr
	case ev := <-c.handshakeChan:
		if ev.err != nil {
			return ev.err
		}
		if c.version.UsesTLS() && ev.encLevel != protocol.EncryptionSecure {
			return fmt.Errorf("Client BUG: Expected encryption level to be secure, was %s", ev.encLevel)
		}
		return nil
	}
}

// Listen listens
func (c *client) listen() {
	var err error

	for {
		var n int
		var addr net.Addr
		data := getPacketBuffer()
		data = data[:protocol.MaxReceivePacketSize]
		// The packet size should not exceed protocol.MaxReceivePacketSize bytes
		// If it does, we only read a truncated packet, which will then end up undecryptable
		n, addr, err = c.conn.Read(data)
		if err != nil {
			if !strings.HasSuffix(err.Error(), "use of closed network connection") {
				c.session.Close(err)
			}
			break
		}
		data = data[:n]

		c.handlePacket(addr, data)
	}
}

func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
	rcvTime := time.Now()

	r := bytes.NewReader(packet)
	hdr, err := wire.ParsePublicHeader(r, protocol.PerspectiveServer, c.version)
	if err != nil {
		utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
		// drop this packet if we can't parse the Public Header
		return
	}
	// reject packets with truncated connection id if we didn't request truncation
	if hdr.TruncateConnectionID && !c.config.RequestConnectionIDTruncation {
		return
	}
	// reject packets with the wrong connection ID
	if !hdr.TruncateConnectionID && hdr.ConnectionID != c.connectionID {
		return
	}
	hdr.Raw = packet[:len(packet)-r.Len()]

	c.mutex.Lock()
	defer c.mutex.Unlock()

	if hdr.ResetFlag {
		cr := c.conn.RemoteAddr()
		// check if the remote address and the connection ID match
		// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
		if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID {
			utils.Infof("Received a spoofed Public Reset. Ignoring.")
			return
		}
		pr, err := wire.ParsePublicReset(r)
		if err != nil {
			utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.")
			return
		}
		utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber)
		c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.RejectedPacketNumber)))
		return
	}

	// ignore delayed / duplicated version negotiation packets
	if (c.receivedVersionNegotiationPacket || c.versionNegotiated) && hdr.VersionFlag {
		return
	}

	// this is the first packet after the client sent a packet with the VersionFlag set
	// if the server doesn't send a version negotiation packet, it supports the suggested version
	if !hdr.VersionFlag && !c.versionNegotiated {
		c.versionNegotiated = true
		close(c.versionNegotiationChan)
	}

	if hdr.VersionFlag {
		// version negotiation packets have no payload
		if err := c.handlePacketWithVersionFlag(hdr); err != nil {
			c.session.Close(err)
		}
		return
	}

	c.session.handlePacket(&receivedPacket{
		remoteAddr:   remoteAddr,
		publicHeader: hdr,
		data:         packet[len(packet)-r.Len():],
		rcvTime:      rcvTime,
	})
}

func (c *client) handlePacketWithVersionFlag(hdr *wire.PublicHeader) error {
	for _, v := range hdr.SupportedVersions {
		if v == c.version {
			// the version negotiation packet contains the version that we offered
			// this might be a packet sent by an attacker (or by a terribly broken server implementation)
			// ignore it
			return nil
		}
	}

	c.receivedVersionNegotiationPacket = true

	newVersion := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
	if newVersion == protocol.VersionUnsupported {
		return qerr.InvalidVersion
	}

	// switch to negotiated version
	c.version = newVersion
	var err error
	c.connectionID, err = utils.GenerateConnectionID()
	if err != nil {
		return err
	}
	utils.Infof("Switching to QUIC version %d. New connection ID: %x", newVersion, c.connectionID)

	// create a new session and close the old one
	// the new session must be created first to update client member variables
	oldSession := c.session
	defer oldSession.Close(errCloseSessionForNewVersion)
	return c.createNewSession(hdr.SupportedVersions)
}

func (c *client) createNewSession(negotiatedVersions []protocol.VersionNumber) error {
	var err error
	c.session, c.handshakeChan, err = newClientSession(
		c.conn,
		c.hostname,
		c.version,
		c.connectionID,
		c.tlsConf,
		c.config,
		negotiatedVersions,
	)
	return err
}
<commit_msg>fix encryption level bug check in the client<commit_after>package quic

import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"github.com/lucas-clemente/quic-go/internal/wire"
	"github.com/lucas-clemente/quic-go/qerr"
)

type client struct {
	mutex sync.Mutex

	conn     connection
	hostname string

	handshakeChan <-chan handshakeEvent

	versionNegotiationChan           chan struct{} // the versionNegotiationChan is closed as soon as the server accepted the suggested version
	versionNegotiated                bool          // has version negotiation completed yet
	receivedVersionNegotiationPacket bool

	tlsConf *tls.Config
	config  *Config

	connectionID protocol.ConnectionID
	version      protocol.VersionNumber

	session packetHandler
}

var (
	// make it possible to mock connection ID generation in the tests
	generateConnectionID         = utils.GenerateConnectionID
	errCloseSessionForNewVersion = errors.New("closing session in order to recreate it with a new version")
)

// DialAddr establishes a new QUIC connection to a server.
// The hostname for SNI is taken from the given address.
func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error) {
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return nil, err
	}
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	return Dial(udpConn, udpAddr, addr, tlsConf, config)
}

// DialAddrNonFWSecure establishes a new QUIC connection to a server.
// The hostname for SNI is taken from the given address.
func DialAddrNonFWSecure(
	addr string,
	tlsConf *tls.Config,
	config *Config,
) (NonFWSession, error) {
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return nil, err
	}
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
	if err != nil {
		return nil, err
	}
	return DialNonFWSecure(udpConn, udpAddr, addr, tlsConf, config)
}

// DialNonFWSecure establishes a new non-forward-secure QUIC connection to a server using a net.PacketConn.
// The host parameter is used for SNI.
func DialNonFWSecure(
	pconn net.PacketConn,
	remoteAddr net.Addr,
	host string,
	tlsConf *tls.Config,
	config *Config,
) (NonFWSession, error) {
	connID, err := generateConnectionID()
	if err != nil {
		return nil, err
	}

	var hostname string
	if tlsConf != nil {
		hostname = tlsConf.ServerName
	}

	if hostname == "" {
		hostname, _, err = net.SplitHostPort(host)
		if err != nil {
			return nil, err
		}
	}

	clientConfig := populateClientConfig(config)
	c := &client{
		conn:                   &conn{pconn: pconn, currentAddr: remoteAddr},
		connectionID:           connID,
		hostname:               hostname,
		tlsConf:                tlsConf,
		config:                 clientConfig,
		version:                clientConfig.Versions[0],
		versionNegotiationChan: make(chan struct{}),
	}

	utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %d", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)

	if err := c.establishSecureConnection(); err != nil {
		return nil, err
	}
	return c.session.(NonFWSession), nil
}

// Dial establishes a new QUIC connection to a server using a net.PacketConn.
// The host parameter is used for SNI.
func Dial(
	pconn net.PacketConn,
	remoteAddr net.Addr,
	host string,
	tlsConf *tls.Config,
	config *Config,
) (Session, error) {
	sess, err := DialNonFWSecure(pconn, remoteAddr, host, tlsConf, config)
	if err != nil {
		return nil, err
	}
	if err := sess.WaitUntilHandshakeComplete(); err != nil {
		return nil, err
	}
	return sess, nil
}

// populateClientConfig populates fields in the quic.Config with their default values, if none are set
// it may be called with nil
func populateClientConfig(config *Config) *Config {
	if config == nil {
		config = &Config{}
	}
	versions := config.Versions
	if len(versions) == 0 {
		versions = protocol.SupportedVersions
	}

	handshakeTimeout := protocol.DefaultHandshakeTimeout
	if config.HandshakeTimeout != 0 {
		handshakeTimeout = config.HandshakeTimeout
	}
	idleTimeout := protocol.DefaultIdleTimeout
	if config.IdleTimeout != 0 {
		idleTimeout = config.IdleTimeout
	}

	maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
	if maxReceiveStreamFlowControlWindow == 0 {
		maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowClient
	}
	maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
	if maxReceiveConnectionFlowControlWindow == 0 {
		maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
	}

	return &Config{
		Versions:                              versions,
		HandshakeTimeout:                      handshakeTimeout,
		IdleTimeout:                           idleTimeout,
		RequestConnectionIDTruncation:         config.RequestConnectionIDTruncation,
		MaxReceiveStreamFlowControlWindow:     maxReceiveStreamFlowControlWindow,
		MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
		KeepAlive: config.KeepAlive,
	}
}

// establishSecureConnection returns as soon as the connection is secure (as opposed to forward-secure)
func (c *client) establishSecureConnection() error {
	if err := c.createNewSession(nil); err != nil {
		return err
	}
	go c.listen()

	var runErr error
	errorChan := make(chan struct{})
	go func() {
		// session.run() returns as soon as the session is closed
		runErr = c.session.run()
		if runErr == errCloseSessionForNewVersion {
			// run the new session
			runErr = c.session.run()
		}
		close(errorChan)
		utils.Infof("Connection %x closed.", c.connectionID)
		c.conn.Close()
	}()

	// wait until the server accepts the QUIC version (or an error occurs)
	select {
	case <-errorChan:
		return runErr
	case <-c.versionNegotiationChan:
	}

	select {
	case <-errorChan:
		return runErr
	case ev := <-c.handshakeChan:
		if ev.err != nil {
			return ev.err
		}
		if !c.version.UsesTLS() && ev.encLevel != protocol.EncryptionSecure {
			return fmt.Errorf("Client BUG: Expected encryption level to be secure, was %s", ev.encLevel)
		}
		return nil
	}
}

// Listen listens
func (c *client) listen() {
	var err error

	for {
		var n int
		var addr net.Addr
		data := getPacketBuffer()
		data = data[:protocol.MaxReceivePacketSize]
		// The packet size should not exceed protocol.MaxReceivePacketSize bytes
		// If it does, we only read a truncated packet, which will then end up undecryptable
		n, addr, err = c.conn.Read(data)
		if err != nil {
			if !strings.HasSuffix(err.Error(), "use of closed network connection") {
				c.session.Close(err)
			}
			break
		}
		data = data[:n]

		c.handlePacket(addr, data)
	}
}

func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
	rcvTime := time.Now()

	r := bytes.NewReader(packet)
	hdr, err := wire.ParsePublicHeader(r, protocol.PerspectiveServer, c.version)
	if err != nil {
		utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
		// drop this packet if we can't parse the Public Header
		return
	}
	// reject packets with truncated connection id if we didn't request truncation
	if hdr.TruncateConnectionID && !c.config.RequestConnectionIDTruncation {
		return
	}
	// reject packets with the wrong connection ID
	if !hdr.TruncateConnectionID && hdr.ConnectionID != c.connectionID {
		return
	}
	hdr.Raw = packet[:len(packet)-r.Len()]

	c.mutex.Lock()
	defer c.mutex.Unlock()

	if hdr.ResetFlag {
		cr := c.conn.RemoteAddr()
		// check if the remote address and the connection ID match
		// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
		if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID {
			utils.Infof("Received a spoofed Public Reset. Ignoring.")
			return
		}
		pr, err := wire.ParsePublicReset(r)
		if err != nil {
			utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.")
			return
		}
		utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber)
		c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.RejectedPacketNumber)))
		return
	}

	// ignore delayed / duplicated version negotiation packets
	if (c.receivedVersionNegotiationPacket || c.versionNegotiated) && hdr.VersionFlag {
		return
	}

	// this is the first packet after the client sent a packet with the VersionFlag set
	// if the server doesn't send a version negotiation packet, it supports the suggested version
	if !hdr.VersionFlag && !c.versionNegotiated {
		c.versionNegotiated = true
		close(c.versionNegotiationChan)
	}

	if hdr.VersionFlag {
		// version negotiation packets have no payload
		if err := c.handlePacketWithVersionFlag(hdr); err != nil {
			c.session.Close(err)
		}
		return
	}

	c.session.handlePacket(&receivedPacket{
		remoteAddr:   remoteAddr,
		publicHeader: hdr,
		data:         packet[len(packet)-r.Len():],
		rcvTime:      rcvTime,
	})
}

func (c *client) handlePacketWithVersionFlag(hdr *wire.PublicHeader) error {
	for _, v := range hdr.SupportedVersions {
		if v == c.version {
			// the version negotiation packet contains the version that we offered
			// this might be a packet sent by an attacker (or by a terribly broken server implementation)
			// ignore it
			return nil
		}
	}

	c.receivedVersionNegotiationPacket = true

	newVersion := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
	if newVersion == protocol.VersionUnsupported {
		return qerr.InvalidVersion
	}

	// switch to negotiated version
	c.version = newVersion
	var err error
	c.connectionID, err = utils.GenerateConnectionID()
	if err != nil {
		return err
	}
	utils.Infof("Switching to QUIC version %d. New connection ID: %x", newVersion, c.connectionID)

	// create a new session and close the old one
	// the new session must be created first to update client member variables
	oldSession := c.session
	defer oldSession.Close(errCloseSessionForNewVersion)
	return c.createNewSession(hdr.SupportedVersions)
}

func (c *client) createNewSession(negotiatedVersions []protocol.VersionNumber) error {
	var err error
	c.session, c.handshakeChan, err = newClientSession(
		c.conn,
		c.hostname,
		c.version,
		c.connectionID,
		c.tlsConf,
		c.config,
		negotiatedVersions,
	)
	return err
}
<|endoftext|>


<commit_before>package pebbleclient

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"golang.org/x/net/context"
	"golang.org/x/net/context/ctxhttp"
)

const maxPartialBody = 64 * 1024

type options Options

func (o options) Merge(other *options) options {
	op := Options(*other)
	return options(Options(o).Merge(&op))
}

// HTTPClient is a client for the Central API.
type HTTPClient struct {
	options
	hc *http.Client
}

// New constructs a new client.
func NewHTTPClient(opts Options) (*HTTPClient, error) {
	if err := opts.validate(); err != nil {
		return nil, err
	}
	var newOpts options = *(*options)(opts.applyDefaults())
	return &HTTPClient{
		options: newOpts,
		hc:      newOpts.HTTPClient,
	}, nil
}

// NewFromHTTPRequest constructs a new client that inherits the host name, protocol,
// session and request ID from an HTTP request. Any options specified will override inferred
// from the request.
func (client *HTTPClient) FromHTTPRequest(req *http.Request) (*HTTPClient, error) {
	opts := Options(client.options)

	var host string
	if hosts, ok := req.Header["X-Forwarded-Host"]; ok && len(hosts) > 0 {
		host = hosts[len(hosts)-1]
	} else {
		host = strings.SplitN(req.Host, ":", 2)[0]
	}
	opts.Host = host

	opts.Protocol = req.URL.Scheme

	if session := req.URL.Query().Get("session"); session != "" {
		opts.Session = session
	} else if cookie, err := req.Cookie("checkpoint.session"); err == nil {
		opts.Session = cookie.Value
	}

	if id := req.Header.Get("Request-Id"); id != "" {
		opts.RequestId = id
	}

	opts.HTTPClient = client.hc

	return NewHTTPClient(opts)
}

// GetOptions returns a copy of this client's options.
func (client *HTTPClient) GetOptions() Options {
	return Options(client.options)
}

func (client *HTTPClient) Options(opts Options) Client {
	newOpts := client.options.Merge((*options)(&opts))
	return &HTTPClient{
		options: newOpts,
		hc:      client.hc,
	}
}

func (client *HTTPClient) Get(path string, opts *RequestOptions, result interface{}) error {
	return client.Do(path, opts, http.MethodGet, nil, result)
}

func (client *HTTPClient) Head(path string, opts *RequestOptions) error {
	return client.Do(path, opts, http.MethodHead, nil, nil)
}

func (client *HTTPClient) Post(path string, opts *RequestOptions, body io.Reader, result interface{}) error {
	return client.Do(path, opts, http.MethodPost, body, result)
}

func (client *HTTPClient) Put(path string, opts *RequestOptions, body io.Reader, result interface{}) error {
	return client.Do(path, opts, http.MethodPut, body, result)
}

func (client *HTTPClient) Delete(path string, opts *RequestOptions, result interface{}) error {
	return client.Do(path, opts, http.MethodDelete, nil, result)
}

func (client *HTTPClient) Do(
	path string,
	opts *RequestOptions,
	method string,
	body io.Reader,
	result interface{}) error {
	if opts == nil {
		opts = &RequestOptions{}
	}

	req, err := http.NewRequest(method, client.formatEndpointUrl(path, opts.Params), body)
	if err != nil {
		return err
	}

	if client.Session != "" {
		req.AddCookie(&http.Cookie{
			Name:  "checkpoint.session",
			Value: client.Session,
		})
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")

	if client.options.RequestId != "" {
		req.Header.Set("Request-Id", client.options.RequestId)
	}

	ctx := client.Ctx
	if ctx == nil {
		ctx = context.Background()
	}

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

	respBody := resp.Body
	defer func() {
		if respBody != nil {
			// Drain remaining body to work around bug in Go < 1.7
			_, _ = io.Copy(ioutil.Discard, respBody)

			_ = respBody.Close()
		}
	}()

	if isNonSuccessStatus(resp.StatusCode) {
		return client.buildError(&RequestError{}, opts, resp)
	}

	if doesStatusCodeYieldBody(resp.StatusCode) && result != nil {
		return decodeResponseAsJSON(resp, respBody, result)
	}

	return nil
}

func (client *HTTPClient) buildError(
	error *RequestError,
	opts *RequestOptions,
	resp *http.Response) error {
	b, _ := ioutil.ReadAll(&io.LimitedReader{
		R: resp.Body,
		N: maxPartialBody,
	})
	error.PartialBody = b
	error.client = client
	error.Resp = resp
	error.Options = opts
	return error
}

func (client *HTTPClient) formatEndpointUrl(path string, params url.Values) string {
	if path[0:1] == "/" {
		path = path[1:]
	}
	result := url.URL{
		Scheme: client.Protocol,
		Host:   client.Host,
		Path: fmt.Sprintf("/api/%s/v%d/%s",
			client.ServiceName, client.ApiVersion, escapedPath(path)),
	}

	query := result.Query()
	if params != nil {
		for k, vs := range params {
			for _, v := range vs {
				query.Add(k, v)
			}
		}
	}
	result.RawQuery = query.Encode()

	return result.String()
}
<commit_msg>Go 1.5.x doesn't have http.Method*? Use strings.<commit_after>package pebbleclient

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"golang.org/x/net/context"
	"golang.org/x/net/context/ctxhttp"
)

const maxPartialBody = 64 * 1024

type options Options

func (o options) Merge(other *options) options {
	op := Options(*other)
	return options(Options(o).Merge(&op))
}

// HTTPClient is a client for the Central API.
type HTTPClient struct {
	options
	hc *http.Client
}

// New constructs a new client.
func NewHTTPClient(opts Options) (*HTTPClient, error) {
	if err := opts.validate(); err != nil {
		return nil, err
	}
	var newOpts options = *(*options)(opts.applyDefaults())
	return &HTTPClient{
		options: newOpts,
		hc:      newOpts.HTTPClient,
	}, nil
}

// NewFromHTTPRequest constructs a new client that inherits the host name, protocol,
// session and request ID from an HTTP request. Any options specified will override inferred
// from the request.
func (client *HTTPClient) FromHTTPRequest(req *http.Request) (*HTTPClient, error) {
	opts := Options(client.options)

	var host string
	if hosts, ok := req.Header["X-Forwarded-Host"]; ok && len(hosts) > 0 {
		host = hosts[len(hosts)-1]
	} else {
		host = strings.SplitN(req.Host, ":", 2)[0]
	}
	opts.Host = host

	opts.Protocol = req.URL.Scheme

	if session := req.URL.Query().Get("session"); session != "" {
		opts.Session = session
	} else if cookie, err := req.Cookie("checkpoint.session"); err == nil {
		opts.Session = cookie.Value
	}

	if id := req.Header.Get("Request-Id"); id != "" {
		opts.RequestId = id
	}

	opts.HTTPClient = client.hc

	return NewHTTPClient(opts)
}

// GetOptions returns a copy of this client's options.
func (client *HTTPClient) GetOptions() Options {
	return Options(client.options)
}

func (client *HTTPClient) Options(opts Options) Client {
	newOpts := client.options.Merge((*options)(&opts))
	return &HTTPClient{
		options: newOpts,
		hc:      client.hc,
	}
}

func (client *HTTPClient) Get(path string, opts *RequestOptions, result interface{}) error {
	return client.Do(path, opts, "GET", nil, result)
}

func (client *HTTPClient) Head(path string, opts *RequestOptions) error {
	return client.Do(path, opts, "HEAD", nil, nil)
}

func (client *HTTPClient) Post(path string, opts *RequestOptions, body io.Reader, result interface{}) error {
	return client.Do(path, opts, "POST", body, result)
}

func (client *HTTPClient) Put(path string, opts *RequestOptions, body io.Reader, result interface{}) error {
	return client.Do(path, opts, "PUT", body, result)
}

func (client *HTTPClient) Delete(path string, opts *RequestOptions, result interface{}) error {
	return client.Do(path, opts, "DELETE", nil, result)
}

func (client *HTTPClient) Do(
	path string,
	opts *RequestOptions,
	method string,
	body io.Reader,
	result interface{}) error {
	if opts == nil {
		opts = &RequestOptions{}
	}

	req, err := http.NewRequest(method, client.formatEndpointUrl(path, opts.Params), body)
	if err != nil {
		return err
	}

	if client.Session != "" {
		req.AddCookie(&http.Cookie{
			Name:  "checkpoint.session",
			Value: client.Session,
		})
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")

	if client.options.RequestId != "" {
		req.Header.Set("Request-Id", client.options.RequestId)
	}

	ctx := client.Ctx
	if ctx == nil {
		ctx = context.Background()
	}

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

	respBody := resp.Body
	defer func() {
		if respBody != nil {
			// Drain remaining body to work around bug in Go < 1.7
			_, _ = io.Copy(ioutil.Discard, respBody)

			_ = respBody.Close()
		}
	}()

	if isNonSuccessStatus(resp.StatusCode) {
		return client.buildError(&RequestError{}, opts, resp)
	}

	if doesStatusCodeYieldBody(resp.StatusCode) && result != nil {
		return decodeResponseAsJSON(resp, respBody, result)
	}

	return nil
}

func (client *HTTPClient) buildError(
	error *RequestError,
	opts *RequestOptions,
	resp *http.Response) error {
	b, _ := ioutil.ReadAll(&io.LimitedReader{
		R: resp.Body,
		N: maxPartialBody,
	})
	error.PartialBody = b
	error.client = client
	error.Resp = resp
	error.Options = opts
	return error
}

func (client *HTTPClient) formatEndpointUrl(path string, params url.Values) string {
	if path[0:1] == "/" {
		path = path[1:]
	}
	result := url.URL{
		Scheme: client.Protocol,
		Host:   client.Host,
		Path: fmt.Sprintf("/api/%s/v%d/%s",
			client.ServiceName, client.ApiVersion, escapedPath(path)),
	}

	query := result.Query()
	if params != nil {
		for k, vs := range params {
			for _, v := range vs {
				query.Add(k, v)
			}
		}
	}
	result.RawQuery = query.Encode()

	return result.String()
}
<|endoftext|>


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

package firmata

import (
	"errors"
	"fmt"
	"io"
	"time"

	"github.com/tarm/serial"
)

// Arduino Firmata client for golang
type FirmataClient struct {
	serialDev string
	baud      int
	conn      io.ReadWriteCloser

	protocolVersion []byte
	firmwareVersion []int
	firmwareName    string

	analogMappingDone bool
	capabilityDone    bool

	digitalPinState [8]byte

	analogPinsChannelMap map[int]byte
	analogChannelPinsMap map[byte]int
	pinModes             []map[PinMode]interface{}

	valueChan  chan FirmataValue
	serialChan chan string
	spiChan    chan []byte
}

// NewClient creates a new FirmataClient and connects to the Arduino board
// over specified serial port. It blocks till a connection is
// succesfully established and pin mappings are retrieved.
func NewClient(dev string, baud int) (*FirmataClient, error) {
	c := &serial.Config{Name: dev, Baud: baud}
	conn, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	client := &FirmataClient{
		serialDev: dev,
		baud:      baud,
		conn:      conn,
		valueChan: make(chan FirmataValue),
	}

	inited := client.replyReader()
	conn.Write([]byte{byte(SystemReset)})

	for {
		select {
		case <-inited:
			return client, err
		case <-time.After(time.Second * 15):
			conn.Write([]byte{byte(SystemReset)})
		case <-time.After(time.Second * 30):
			conn.Close()
			break
		}
	}

	return nil, errors.New("cannot open connection to the device; timeout")
}

func (c *FirmataClient) Close() error {
	return c.conn.Close()
}

// SetPinMode sets the pin mode.
func (c *FirmataClient) SetPinMode(pin uint8, mode PinMode) error {
	if c.pinModes[pin][mode] == nil {
		return fmt.Errorf("pin mode = %v not supported by pin %v", mode, pin)
	}
	return c.sendCommand([]byte{byte(SetPinMode), (pin & 0x7F), byte(mode)})
}

// Specified if a digital Pin should be watched for input.
// Values will be streamed back over a channel which can be retrieved by the GetValues() call
func (c *FirmataClient) EnableDigitalInput(pin uint, val bool) error {
	if pin < 0 || pin > uint(len(c.pinModes)) {
		return fmt.Errorf("invalid pin number: %v", pin)
	}
	port := (pin / 8) & 0x7F
	pin = pin % 8

	if val {
		cmd := []byte{byte(EnableDigitalInput) | byte(port), 0x01}
		return c.sendCommand(cmd)
	}
	cmd := []byte{byte(EnableDigitalInput) | byte(port), 0x00}
	return c.sendCommand(cmd)
}

// Set the value of a digital pin
func (c *FirmataClient) DigitalWrite(pin uint8, val bool) error {
	if pin < 0 || pin > uint8(len(c.pinModes)) && c.pinModes[pin][Output] != nil {
		return fmt.Errorf("invalid pin number: %v", pin)
	}
	port := (pin / 8) & 0x7F
	portData := &c.digitalPinState[port]
	pin = pin % 8
	if val {
		(*portData) = (*portData) | (1 << pin)
	} else {
		(*portData) = (*portData) & ^(1 << pin)
	}
	data := to7Bit(*(portData))
	cmd := []byte{byte(DigitalMessage) | byte(port), data[0], data[1]}
	return c.sendCommand(cmd)
}

// Specified if a analog Pin should be watched for input.
// Values will be streamed back over a channel which can be retrieved by the Values() call.
func (c *FirmataClient) EnableAnalogInput(pin uint, val bool) error {
	if pin < 0 || pin > uint(len(c.pinModes)) && c.pinModes[pin][Analog] != nil {
		return fmt.Errorf("invalid pin number: %v\n", pin)
	}
	ch := byte(c.analogPinsChannelMap[int(pin)])
	if val {
		cmd := []byte{byte(EnableAnalogInput) | ch, 0x01}
		return c.sendCommand(cmd)
	}
	cmd := []byte{byte(EnableAnalogInput) | ch, 0x00}
	return c.sendCommand(cmd)
}

func (c *FirmataClient) AnalogWrite(pin uint, pinData byte) error {
	if pin < 0 || pin > uint(len(c.pinModes)) && c.pinModes[pin][Analog] != nil {
		return fmt.Errorf("invalid pin number %v\n", pin)
	}
	data := to7Bit(pinData)
	cmd := []byte{byte(AnalogMessage) | byte(pin), data[0], data[1]}
	return c.sendCommand(cmd)
}

func (c *FirmataClient) sendCommand(cmd []byte) error {
	// TODO(jbd): Do not concat.
	bStr := ""
	for _, b := range cmd {
		bStr = bStr + fmt.Sprintf(" %#2x", b)
	}
	_, err := c.conn.Write(cmd)
	return err
}

func (c *FirmataClient) SetAnalogSamplingInterval(ms byte) error {
	data := to7Bit(ms)
	return c.sendSysEx(SamplingInterval, data[0], data[1])
}

func (c *FirmataClient) Values() <-chan FirmataValue {
	return c.valueChan
}
<commit_msg>Rename field.<commit_after>// Copyright 2014 Krishna Raman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package firmata

import (
	"errors"
	"fmt"
	"io"
	"time"

	"github.com/tarm/serial"
)

// Arduino Firmata client for golang
type FirmataClient struct {
	dev  string
	baud int
	conn io.ReadWriteCloser

	protocolVersion []byte
	firmwareVersion []int
	firmwareName    string

	analogMappingDone bool
	capabilityDone    bool

	digitalPinState [8]byte

	analogPinsChannelMap map[int]byte
	analogChannelPinsMap map[byte]int
	pinModes             []map[PinMode]interface{}

	valueChan  chan FirmataValue
	serialChan chan string
	spiChan    chan []byte
}

// NewClient creates a new FirmataClient and connects to the Arduino board
// over specified serial port. It blocks till a connection is
// succesfully established and pin mappings are retrieved.
func NewClient(dev string, baud int) (*FirmataClient, error) {
	c := &serial.Config{Name: dev, Baud: baud}
	conn, err := serial.OpenPort(c)
	if err != nil {
		return nil, err
	}

	client := &FirmataClient{
		dev:       dev,
		baud:      baud,
		conn:      conn,
		valueChan: make(chan FirmataValue),
	}

	inited := client.replyReader()
	conn.Write([]byte{byte(SystemReset)})

	for {
		select {
		case <-inited:
			return client, err
		case <-time.After(time.Second * 15):
			conn.Write([]byte{byte(SystemReset)})
		case <-time.After(time.Second * 30):
			conn.Close()
			break
		}
	}

	return nil, errors.New("cannot open connection to the device; timeout")
}

func (c *FirmataClient) Close() error {
	return c.conn.Close()
}

// SetPinMode sets the pin mode.
func (c *FirmataClient) SetPinMode(pin uint8, mode PinMode) error {
	if c.pinModes[pin][mode] == nil {
		return fmt.Errorf("pin mode = %v not supported by pin %v", mode, pin)
	}
	return c.sendCommand([]byte{byte(SetPinMode), (pin & 0x7F), byte(mode)})
}

// Specified if a digital Pin should be watched for input.
// Values will be streamed back over a channel which can be retrieved by the GetValues() call
func (c *FirmataClient) EnableDigitalInput(pin uint, val bool) error {
	if pin < 0 || pin > uint(len(c.pinModes)) {
		return fmt.Errorf("invalid pin number: %v", pin)
	}
	port := (pin / 8) & 0x7F
	pin = pin % 8

	if val {
		cmd := []byte{byte(EnableDigitalInput) | byte(port), 0x01}
		return c.sendCommand(cmd)
	}
	cmd := []byte{byte(EnableDigitalInput) | byte(port), 0x00}
	return c.sendCommand(cmd)
}

// Set the value of a digital pin
func (c *FirmataClient) DigitalWrite(pin uint8, val bool) error {
	if pin < 0 || pin > uint8(len(c.pinModes)) && c.pinModes[pin][Output] != nil {
		return fmt.Errorf("invalid pin number: %v", pin)
	}
	port := (pin / 8) & 0x7F
	portData := &c.digitalPinState[port]
	pin = pin % 8
	if val {
		(*portData) = (*portData) | (1 << pin)
	} else {
		(*portData) = (*portData) & ^(1 << pin)
	}
	data := to7Bit(*(portData))
	cmd := []byte{byte(DigitalMessage) | byte(port), data[0], data[1]}
	return c.sendCommand(cmd)
}

// Specified if a analog Pin should be watched for input.
// Values will be streamed back over a channel which can be retrieved by the Values() call.
func (c *FirmataClient) EnableAnalogInput(pin uint, val bool) error {
	if pin < 0 || pin > uint(len(c.pinModes)) && c.pinModes[pin][Analog] != nil {
		return fmt.Errorf("invalid pin number: %v\n", pin)
	}
	ch := byte(c.analogPinsChannelMap[int(pin)])
	if val {
		cmd := []byte{byte(EnableAnalogInput) | ch, 0x01}
		return c.sendCommand(cmd)
	}
	cmd := []byte{byte(EnableAnalogInput) | ch, 0x00}
	return c.sendCommand(cmd)
}

func (c *FirmataClient) AnalogWrite(pin uint, pinData byte) error {
	if pin < 0 || pin > uint(len(c.pinModes)) && c.pinModes[pin][Analog] != nil {
		return fmt.Errorf("invalid pin number %v\n", pin)
	}
	data := to7Bit(pinData)
	cmd := []byte{byte(AnalogMessage) | byte(pin), data[0], data[1]}
	return c.sendCommand(cmd)
}

func (c *FirmataClient) sendCommand(cmd []byte) error {
	// TODO(jbd): Do not concat.
	bStr := ""
	for _, b := range cmd {
		bStr = bStr + fmt.Sprintf(" %#2x", b)
	}
	_, err := c.conn.Write(cmd)
	return err
}

func (c *FirmataClient) SetAnalogSamplingInterval(ms byte) error {
	data := to7Bit(ms)
	return c.sendSysEx(SamplingInterval, data[0], data[1])
}

func (c *FirmataClient) Values() <-chan FirmataValue {
	return c.valueChan
}
<|endoftext|>


<commit_before>package gohttp

import (
	"bytes"
	"crypto/tls"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Request struct {
	*http.Request
}

func (self *Request) SetHeader(k, v string) *Request {
	self.Header.Add(k, v)
	return self
}

func (self *Request) SetHeaders(kv map[string]string) *Request {
	for k, v := range kv {
		self.SetHeader(k, v)
	}
	return self
}

type Response struct {
	*http.Response
}

func (self *Response) Code() int {
	return self.StatusCode
}

func (self *Response) Bytes() ([]byte, error) {
	return ioutil.ReadAll(self.Body)
}

func (self *Response) String() string {
	if resp, err := self.Bytes(); err != nil {
		return ""
	} else {
		return string(resp)
	}

}

func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
	req, err := http.NewRequest(method, urlStr, body)
	return &Request{req}, err
}

type Client struct {
	method     string
	url        string
	path       string
	query      string
	fragment   string
	cookies    map[string]string
	headers    map[string]string
	body       interface{}
	proxy      string
	timeout    int
	retries    int
	verifySsl  bool //true:强制使用https,false:不校验https证书
	keepAlived bool
	transport  http.Transport
}

func NewClient() *Client {
	return &Client{
		method:     "GET",
		cookies:    make(map[string]string),
		headers:    make(map[string]string),
		verifySsl:  false,
		keepAlived: true,
	}
}

//构造request body [interface{} -> io.Reader]
func parseBody(v interface{}) (io.Reader, error) {
	if v == nil {
		return nil, nil
	}
	bts, err := ToBytes(v)
	if err != nil {
		return nil, err
	}
	body := bytes.NewBuffer(bts)
	return body, nil
}

func (self *Client) newRequest() (*http.Request, error) {
	u, err := self.newURL()
	if err != nil {
		return nil, err
	}

	body, err := parseBody(self.body)
	if err != nil {
		return nil, err
	}

	req, err := NewRequest(self.method, u.String(), body)
	for k, v := range self.headers {
		req.Header.Set(k, v)
	}
	for k, v := range self.cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}
	return req.Request, err
}

func (self *Client) setClient() (*http.Client, error) {
	if self.proxy != "" {
		proxy, err := url.Parse(self.proxy)
		if err != nil {
			return nil, err
		}
		self.transport.Proxy = http.ProxyURL(proxy)
	}
	self.transport.DisableKeepAlives = !self.keepAlived
	self.transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: !self.verifySsl}
	client := &http.Client{Transport: &self.transport}
	client.Timeout = time.Duration(self.timeout) * time.Second
	return client, nil
}

func (self *Client) Reset() *Client {
	self.method = "GET"
	self.url = ""
	self.path = ""
	self.query = ""
	self.fragment = ""
	self.cookies = make(map[string]string)
	self.headers = make(map[string]string)
	self.body = nil
	self.proxy = ""
	self.timeout = 0
	self.retries = 0
	self.verifySsl = false
	self.keepAlived = true
	self.transport = http.Transport{}
	return self
}

func (self *Client) doReq(method string) (*Response, error) {
	self.method = method
	req, err := self.newRequest()
	if err != nil {
		return nil, err
	}

	client, err := self.setClient()
	if err != nil {
		return nil, err
	}

	resp, err := client.Do(req)
	return &Response{resp}, err
}

// 长连接,Default is true
func (self *Client) KeepAlived(used bool) *Client {
	self.keepAlived = used
	return self
}

// 强制使用HTTPS,Default is false
func (self *Client) VerifySSL(used bool) *Client {
	self.verifySsl = used
	return self
}

func (self *Client) URL(urlstr string) *Client {
	self.url = urlstr
	return self
}

func (self *Client) Path(path string) *Client {
	self.path = path
	return self
}

func (self *Client) Query(kv map[string]string) *Client {
	query := []string{}
	for k, v := range kv {
		s := k + "=" + url.QueryEscape(v)
		query = append(query, s)
	}
	self.query = strings.Join(query, "&")
	return self
}

func (self *Client) Proxy(proxy string) *Client {
	self.proxy = proxy
	return self
}

func (self *Client) Timeout(timeout int) *Client {
	self.timeout = timeout
	return self
}

func (self *Client) Cookie(k, v string) *Client {
	self.cookies[k] = v
	return self
}

func (self *Client) Header(k, v string) *Client {
	self.headers[k] = v
	return self
}

func (self *Client) Headers(kv map[string]string) *Client {
	for k, v := range kv {
		self.Header(k, v)
	}
	return self
}

func (self *Client) Body(body interface{}) *Client {
	self.body = body
	return self
}

func (self *Client) Retries(count int) *Client {
	self.retries = count
	return self
}

func (self *Client) newURL() (*url.URL, error) {
	u, err := url.Parse(self.url)
	if err != nil {
		return u, err
	}
	if self.path != "" {
		u.Path = self.path
	}
	if self.query != "" {
		u.RawQuery = self.query
	}
	return u, err
}

func (self *Client) URLString() string {
	url, _ := self.newURL()
	return url.String()
}

func (self *Client) Get() (*Response, error)  { return self.doReq("GET") }
func (self *Client) Post() (*Response, error) { return self.doReq("POST") }
func (self *Client) Head() (*Response, error) { return self.doReq("HEAD") }
func (self *Client) Put() (*Response, error)  { return self.doReq("PUT") }
<commit_msg>Update client.go<commit_after>package gohttp

import (
	"bytes"
	"crypto/tls"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

type Request struct {
	*http.Request
}

func (req *Request) SetHeader(k, v string) *Request {
	req.Header.Add(k, v)
	return req
}

func (req *Request) SetHeaders(kv map[string]string) *Request {
	for k, v := range kv {
		req.SetHeader(k, v)
	}
	return req
}

type Response struct {
	*http.Response
}

func (resp *Response) Code() int {
	return resp.StatusCode
}

func (resp *Response) Bytes() ([]byte, error) {
	return ioutil.ReadAll(resp.Body)
}

func (resp *Response) String() string {
	if response, err := resp.Bytes(); err != nil {
		return ""
	} else {
		return string(response)
	}

}

func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
	req, err := http.NewRequest(method, urlStr, body)
	return &Request{req}, err
}

type Client struct {
	method     string
	url        string
	path       string
	query      string
	fragment   string
	cookies    map[string]string
	headers    map[string]string
	body       interface{}
	proxy      string
	timeout    int
	retries    int
	verifySsl  bool //true:强制使用https,false:不校验https证书
	keepAlived bool
	transport  http.Transport
}

func NewClient() *Client {
	return &Client{
		method:     "GET",
		cookies:    make(map[string]string),
		headers:    make(map[string]string),
		verifySsl:  false,
		keepAlived: true,
	}
}

//构造request body [interface{} -> io.Reader]
func parseBody(v interface{}) (io.Reader, error) {
	if v == nil {
		return nil, nil
	}
	bts, err := ToBytes(v)
	if err != nil {
		return nil, err
	}
	body := bytes.NewBuffer(bts)
	return body, nil
}

func (c *Client) newRequest() (*http.Request, error) {
	u, err := c.newURL()
	if err != nil {
		return nil, err
	}

	body, err := parseBody(c.body)
	if err != nil {
		return nil, err
	}

	req, err := NewRequest(c.method, u.String(), body)
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}
	for k, v := range c.cookies {
		req.AddCookie(&http.Cookie{Name: k, Value: v})
	}
	return req.Request, err
}

func (c *Client) setClient() (*http.Client, error) {
	if c.proxy != "" {
		proxy, err := url.Parse(c.proxy)
		if err != nil {
			return nil, err
		}
		c.transport.Proxy = http.ProxyURL(proxy)
	}
	c.transport.DisableKeepAlives = !c.keepAlived
	c.transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: !c.verifySsl}
	client := &http.Client{Transport: &c.transport}
	client.Timeout = time.Duration(c.timeout) * time.Second
	return client, nil
}

func (c *Client) Reset() *Client {
	c.method = "GET"
	c.url = ""
	c.path = ""
	c.query = ""
	c.fragment = ""
	c.cookies = make(map[string]string)
	c.headers = make(map[string]string)
	c.body = nil
	c.proxy = ""
	c.timeout = 0
	c.retries = 0
	c.verifySsl = false
	c.keepAlived = true
	c.transport = http.Transport{}
	return c
}

func (c *Client) doReq(method string) (*Response, error) {
	c.method = method
	req, err := c.newRequest()
	if err != nil {
		return nil, err
	}

	client, err := c.setClient()
	if err != nil {
		return nil, err
	}

	resp, err := client.Do(req)
	return &Response{resp}, err
}

// 长连接,Default is true
func (c *Client) KeepAlived(used bool) *Client {
	c.keepAlived = used
	return c
}

// 强制使用HTTPS,Default is false
func (c *Client) VerifySSL(used bool) *Client {
	c.verifySsl = used
	return c
}

func (c *Client) URL(urlstr string) *Client {
	c.url = urlstr
	return c
}

func (c *Client) Path(path string) *Client {
	c.path = path
	return c
}

func (c *Client) Query(kv map[string]string) *Client {
	query := []string{}
	for k, v := range kv {
		s := k + "=" + url.QueryEscape(v)
		query = append(query, s)
	}
	c.query = strings.Join(query, "&")
	return c
}

func (c *Client) Proxy(proxy string) *Client {
	c.proxy = proxy
	return c
}

func (c *Client) Timeout(timeout int) *Client {
	c.timeout = timeout
	return c
}

func (c *Client) Cookie(k, v string) *Client {
	c.cookies[k] = v
	return c
}

func (c *Client) Header(k, v string) *Client {
	c.headers[k] = v
	return c
}

func (c *Client) Headers(kv map[string]string) *Client {
	for k, v := range kv {
		c.Header(k, v)
	}
	return c
}

func (c *Client) Body(body interface{}) *Client {
	c.body = body
	return c
}

func (c *Client) Retries(count int) *Client {
	c.retries = count
	return c
}

func (c *Client) newURL() (*url.URL, error) {
	u, err := url.Parse(c.url)
	if err != nil {
		return u, err
	}
	if c.path != "" {
		u.Path = c.path
	}
	if c.query != "" {
		u.RawQuery = c.query
	}
	return u, err
}

func (c *Client) URLString() string {
	url, _ := c.newURL()
	return url.String()
}

func (c *Client) Get() (*Response, error)  { return c.doReq("GET") }
func (c *Client) Post() (*Response, error) { return c.doReq("POST") }
func (c *Client) Head() (*Response, error) { return c.doReq("HEAD") }
func (c *Client) Put() (*Response, error)  { return c.doReq("PUT") }
<|endoftext|>


<commit_before>package gift

import (
	"image"
	"image/draw"
	"math"
)

func prepareLut(lutSize int, fn func(float32) float32) []float32 {
	lut := make([]float32, lutSize)
	q := 1 / float32(lutSize-1)
	for v := 0; v < lutSize; v++ {
		u := float32(v) * q
		lut[v] = fn(u)
	}
	return lut
}

func getFromLut(lut []float32, u float32) float32 {
	v := int(u*float32(len(lut)-1) + 0.5)
	return lut[v]
}

type colorchanFilter struct {
	fn  func(float32) float32
	lut bool
}

func (p *colorchanFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) {
	dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
	return
}

func (p *colorchanFilter) Draw(dst draw.Image, src image.Image, options *Options) {
	if options == nil {
		options = &defaultOptions
	}

	srcb := src.Bounds()
	dstb := dst.Bounds()
	pixGetter := newPixelGetter(src)
	pixSetter := newPixelSetter(dst)

	var useLut bool
	var lut []float32

	useLut = false
	if p.lut {
		var lutSize int

		it := pixGetter.imgType
		if it == itNRGBA || it == itRGBA || it == itGray || it == itYCbCr {
			lutSize = 0xff + 1
		} else {
			lutSize = 0xffff + 1
		}

		numCalculations := srcb.Dx() * srcb.Dy() * 3
		if numCalculations > lutSize*2 {
			useLut = true
			lut = prepareLut(lutSize, p.fn)
		}
	}

	parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(pmin, pmax int) {
		for y := pmin; y < pmax; y++ {
			for x := srcb.Min.X; x < srcb.Max.X; x++ {
				px := pixGetter.getPixel(x, y)
				if useLut {
					px.R = getFromLut(lut, px.R)
					px.G = getFromLut(lut, px.G)
					px.B = getFromLut(lut, px.B)
				} else {
					px.R = p.fn(px.R)
					px.G = p.fn(px.G)
					px.B = p.fn(px.B)
				}
				pixSetter.setPixel(dstb.Min.X+x-srcb.Min.X, dstb.Min.Y+y-srcb.Min.Y, px)
			}
		}
	})
}

// Invert creates a filter that negates the colors of an image.
func Invert() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			return 1.0 - x
		},
		lut: false,
	}
}

// ColorspaceSRGBToLinear creates a filter that converts the colors of an image from sRGB to linear RGB.
func ColorspaceSRGBToLinear() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			if x <= 0.04045 {
				return x / 12.92
			} else {
				return float32(math.Pow(float64((x+0.055)/1.055), 2.4))
			}
		},
		lut: true,
	}
}

// ColorspaceLinearToSRGB creates a filter that converts the colors of an image from linear RGB to sRGB.
func ColorspaceLinearToSRGB() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			if x <= 0.0031308 {
				return x * 12.92
			} else {
				return float32(1.055*math.Pow(float64(x), 1.0/2.4) - 0.055)
			}
		},
		lut: true,
	}
}

// Gamma creates a filter that performs a gamma correction on an image.
// The gamma parameter must be positive. Gamma = 1.0 gives the original image.
// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
func Gamma(gamma float32) Filter {
	e := 1.0 / maxf32(gamma, 1.0e-5)
	return &colorchanFilter{
		fn: func(x float32) float32 {
			return powf32(x, e)
		},
		lut: true,
	}
}

func sigmoid(a, b, x float32) float32 {
	return 1 / (1 + expf32(b*(a-x)))
}

// Sigmoid creates a filter that changes the contrast of an image using a sigmoidal function and returns the adjusted image.
// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
//
// Example:
//
//	g := gift.New(
//		gift.Sigmoid(0.5, 3.0),
//	)
//	dst := image.NewRGBA(src.Bounds())
//	g.Draw(dst, src)
//
func Sigmoid(midpoint, factor float32) Filter {
	a := minf32(maxf32(midpoint, 0.0), 1.0)
	b := absf32(factor)
	sig0 := sigmoid(a, b, 0)
	sig1 := sigmoid(a, b, 1)
	e := float32(1.0e-5)

	return &colorchanFilter{
		fn: func(x float32) float32 {
			if factor == 0 {
				return x
			} else if factor > 0 {
				sig := sigmoid(a, b, x)
				return (sig - sig0) / (sig1 - sig0)
			} else {
				arg := minf32(maxf32((sig1-sig0)*x+sig0, e), 1.0-e)
				return a - logf32(1.0/arg-1.0)/b
			}
		},
		lut: true,
	}
}

// Contrast creates a filter that changes the contrast of an image.
// The percentage parameter must be in range (-100, 100). The percentage = 0 gives the original image.
// The percentage = -100 gives solid grey image. The percentage = 100 gives an overcontrasted image.
func Contrast(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}

	p := 1 + minf32(maxf32(percentage, -100.0), 100.0)/100.0

	return &colorchanFilter{
		fn: func(x float32) float32 {
			if 0 <= p && p <= 1 {
				return 0.5 + (x-0.5)*p
			} else if 1 < p && p < 2 {
				return 0.5 + (x-0.5)*(1/(2.0-p))
			} else {
				if x < 0.5 {
					return 0.0
				} else {
					return 1.0
				}
			}
		},
		lut: false,
	}
}

// Brightness creates a filter that changes the brightness of an image.
// The percentage parameter must be in range (-100, 100). The percentage = 0 gives the original image.
// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.
func Brightness(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}

	shift := minf32(maxf32(percentage, -100.0), 100.0) / 100.0

	return &colorchanFilter{
		fn: func(x float32) float32 {
			return x + shift
		},
		lut: false,
	}
}

type colorFilter struct {
	fn func(pixel) pixel
}

func (p *colorFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) {
	dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
	return
}

func (p *colorFilter) Draw(dst draw.Image, src image.Image, options *Options) {
	if options == nil {
		options = &defaultOptions
	}

	srcb := src.Bounds()
	dstb := dst.Bounds()
	pixGetter := newPixelGetter(src)
	pixSetter := newPixelSetter(dst)

	parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(pmin, pmax int) {
		for y := pmin; y < pmax; y++ {
			for x := srcb.Min.X; x < srcb.Max.X; x++ {
				px := pixGetter.getPixel(x, y)
				pixSetter.setPixel(dstb.Min.X+x-srcb.Min.X, dstb.Min.Y+y-srcb.Min.Y, p.fn(px))
			}
		}
	})
}

// Grayscale creates a filter that produces a grayscale version of an image.
func Grayscale() Filter {
	return &colorFilter{
		fn: func(px pixel) pixel {
			y := 0.299*px.R + 0.587*px.G + 0.114*px.B
			return pixel{y, y, y, px.A}
		},
	}
}

// Sepia creates a filter that produces a sepia-toned version of an image.
func Sepia() Filter {
	return &colorFilter{
		fn: func(px pixel) pixel {
			r := 0.393*px.R + 0.769*px.G + 0.189*px.B
			g := 0.349*px.R + 0.686*px.G + 0.168*px.B
			b := 0.272*px.R + 0.534*px.G + 0.131*px.B
			return pixel{r, g, b, px.A}
		},
	}
}

func convertHSLToRGB(h, s, l float32) (float32, float32, float32) {
	if s == 0.0 {
		return l, l, l
	}

	_v := func(p, q, t float32) float32 {
		if t < 0.0 {
			t += 1.0
		}
		if t > 1.0 {
			t -= 1.0
		}
		if t < 1.0/6.0 {
			return p + (q-p)*6.0*t
		}
		if t < 1.0/2.0 {
			return q
		}
		if t < 2.0/3.0 {
			return p + (q-p)*(2.0/3.0-t)*6.0
		}
		return p
	}

	var p, q float32
	if l < 0.5 {
		q = l * (1.0 + s)
	} else {
		q = l + s - l*s
	}
	p = 2.0*l - q

	r := _v(p, q, h+1.0/3.0)
	g := _v(p, q, h)
	b := _v(p, q, h-1.0/3.0)

	return r, g, b
}

func convertRGBToHSL(r, g, b float32) (float32, float32, float32) {
	max := maxf32(r, maxf32(g, b))
	min := minf32(r, minf32(g, b))

	l := (max + min) / 2.0

	if max == min {
		return 0.0, 0.0, l
	}

	var h, s float32
	d := max - min
	if l > 0.5 {
		s = d / (2.0 - max - min)
	} else {
		s = d / (max + min)
	}

	if r == max {
		h = (g - b) / d
		if g < b {
			h += 6.0
		}
	} else if g == max {
		h = (b-r)/d + 2.0
	} else {
		h = (r-g)/d + 4.0
	}
	h /= 6.0

	return h, s, l
}

// Hue creates a filter that rotates the hue of an image.
// The shift parameter must be in range (-180, 180). The shift = 0 gives the original image.
func Hue(shift float32) Filter {
	if shift == 0 {
		return &copyimageFilter{}
	}
	p := minf32(maxf32(shift, -180.0), 180.0) / 360.0
	if p < 0.0 {
		p += 1.0
	}
	return &colorFilter{
		fn: func(px pixel) pixel {
			h, s, l := convertRGBToHSL(px.R, px.G, px.B)
			h = h + p
			if h > 1.0 {
				h -= 1.0
			}
			r, g, b := convertHSLToRGB(h, s, l)
			return pixel{r, g, b, px.A}
		},
	}
}

// Saturation creates a filter that changes the saturation of an image.
// The percentage parameter must be in range (-100, 500). The percentage = 0 gives the original image.
func Saturation(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}
	p := 1 + minf32(maxf32(percentage, -100.0), 500.0)/100.0

	return &colorFilter{
		fn: func(px pixel) pixel {
			h, s, l := convertRGBToHSL(px.R, px.G, px.B)
			s *= p
			if s > 1 {
				s = 1
			}
			r, g, b := convertHSLToRGB(h, s, l)
			return pixel{r, g, b, px.A}
		},
	}
}
<commit_msg>Sepia takes a parameter for amount<commit_after>package gift

import (
	"image"
	"image/draw"
	"math"
)

func prepareLut(lutSize int, fn func(float32) float32) []float32 {
	lut := make([]float32, lutSize)
	q := 1 / float32(lutSize-1)
	for v := 0; v < lutSize; v++ {
		u := float32(v) * q
		lut[v] = fn(u)
	}
	return lut
}

func getFromLut(lut []float32, u float32) float32 {
	v := int(u*float32(len(lut)-1) + 0.5)
	return lut[v]
}

type colorchanFilter struct {
	fn  func(float32) float32
	lut bool
}

func (p *colorchanFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) {
	dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
	return
}

func (p *colorchanFilter) Draw(dst draw.Image, src image.Image, options *Options) {
	if options == nil {
		options = &defaultOptions
	}

	srcb := src.Bounds()
	dstb := dst.Bounds()
	pixGetter := newPixelGetter(src)
	pixSetter := newPixelSetter(dst)

	var useLut bool
	var lut []float32

	useLut = false
	if p.lut {
		var lutSize int

		it := pixGetter.imgType
		if it == itNRGBA || it == itRGBA || it == itGray || it == itYCbCr {
			lutSize = 0xff + 1
		} else {
			lutSize = 0xffff + 1
		}

		numCalculations := srcb.Dx() * srcb.Dy() * 3
		if numCalculations > lutSize*2 {
			useLut = true
			lut = prepareLut(lutSize, p.fn)
		}
	}

	parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(pmin, pmax int) {
		for y := pmin; y < pmax; y++ {
			for x := srcb.Min.X; x < srcb.Max.X; x++ {
				px := pixGetter.getPixel(x, y)
				if useLut {
					px.R = getFromLut(lut, px.R)
					px.G = getFromLut(lut, px.G)
					px.B = getFromLut(lut, px.B)
				} else {
					px.R = p.fn(px.R)
					px.G = p.fn(px.G)
					px.B = p.fn(px.B)
				}
				pixSetter.setPixel(dstb.Min.X+x-srcb.Min.X, dstb.Min.Y+y-srcb.Min.Y, px)
			}
		}
	})
}

// Invert creates a filter that negates the colors of an image.
func Invert() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			return 1.0 - x
		},
		lut: false,
	}
}

// ColorspaceSRGBToLinear creates a filter that converts the colors of an image from sRGB to linear RGB.
func ColorspaceSRGBToLinear() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			if x <= 0.04045 {
				return x / 12.92
			} else {
				return float32(math.Pow(float64((x+0.055)/1.055), 2.4))
			}
		},
		lut: true,
	}
}

// ColorspaceLinearToSRGB creates a filter that converts the colors of an image from linear RGB to sRGB.
func ColorspaceLinearToSRGB() Filter {
	return &colorchanFilter{
		fn: func(x float32) float32 {
			if x <= 0.0031308 {
				return x * 12.92
			} else {
				return float32(1.055*math.Pow(float64(x), 1.0/2.4) - 0.055)
			}
		},
		lut: true,
	}
}

// Gamma creates a filter that performs a gamma correction on an image.
// The gamma parameter must be positive. Gamma = 1.0 gives the original image.
// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
func Gamma(gamma float32) Filter {
	e := 1.0 / maxf32(gamma, 1.0e-5)
	return &colorchanFilter{
		fn: func(x float32) float32 {
			return powf32(x, e)
		},
		lut: true,
	}
}

func sigmoid(a, b, x float32) float32 {
	return 1 / (1 + expf32(b*(a-x)))
}

// Sigmoid creates a filter that changes the contrast of an image using a sigmoidal function and returns the adjusted image.
// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
//
// Example:
//
//	g := gift.New(
//		gift.Sigmoid(0.5, 3.0),
//	)
//	dst := image.NewRGBA(src.Bounds())
//	g.Draw(dst, src)
//
func Sigmoid(midpoint, factor float32) Filter {
	a := minf32(maxf32(midpoint, 0.0), 1.0)
	b := absf32(factor)
	sig0 := sigmoid(a, b, 0)
	sig1 := sigmoid(a, b, 1)
	e := float32(1.0e-5)

	return &colorchanFilter{
		fn: func(x float32) float32 {
			if factor == 0 {
				return x
			} else if factor > 0 {
				sig := sigmoid(a, b, x)
				return (sig - sig0) / (sig1 - sig0)
			} else {
				arg := minf32(maxf32((sig1-sig0)*x+sig0, e), 1.0-e)
				return a - logf32(1.0/arg-1.0)/b
			}
		},
		lut: true,
	}
}

// Contrast creates a filter that changes the contrast of an image.
// The percentage parameter must be in range (-100, 100). The percentage = 0 gives the original image.
// The percentage = -100 gives solid grey image. The percentage = 100 gives an overcontrasted image.
func Contrast(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}

	p := 1 + minf32(maxf32(percentage, -100.0), 100.0)/100.0

	return &colorchanFilter{
		fn: func(x float32) float32 {
			if 0 <= p && p <= 1 {
				return 0.5 + (x-0.5)*p
			} else if 1 < p && p < 2 {
				return 0.5 + (x-0.5)*(1/(2.0-p))
			} else {
				if x < 0.5 {
					return 0.0
				} else {
					return 1.0
				}
			}
		},
		lut: false,
	}
}

// Brightness creates a filter that changes the brightness of an image.
// The percentage parameter must be in range (-100, 100). The percentage = 0 gives the original image.
// The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.
func Brightness(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}

	shift := minf32(maxf32(percentage, -100.0), 100.0) / 100.0

	return &colorchanFilter{
		fn: func(x float32) float32 {
			return x + shift
		},
		lut: false,
	}
}

type colorFilter struct {
	fn func(pixel) pixel
}

func (p *colorFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) {
	dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
	return
}

func (p *colorFilter) Draw(dst draw.Image, src image.Image, options *Options) {
	if options == nil {
		options = &defaultOptions
	}

	srcb := src.Bounds()
	dstb := dst.Bounds()
	pixGetter := newPixelGetter(src)
	pixSetter := newPixelSetter(dst)

	parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(pmin, pmax int) {
		for y := pmin; y < pmax; y++ {
			for x := srcb.Min.X; x < srcb.Max.X; x++ {
				px := pixGetter.getPixel(x, y)
				pixSetter.setPixel(dstb.Min.X+x-srcb.Min.X, dstb.Min.Y+y-srcb.Min.Y, p.fn(px))
			}
		}
	})
}

// Grayscale creates a filter that produces a grayscale version of an image.
func Grayscale() Filter {
	return &colorFilter{
		fn: func(px pixel) pixel {
			y := 0.299*px.R + 0.587*px.G + 0.114*px.B
			return pixel{y, y, y, px.A}
		},
	}
}

// Sepia creates a filter that changes the tint of an image and returns the adjusted image.
// It takes a parameter for how much the image should be adjusted, typically in the range (0, 100)
//
// Example:
//
//	g := gift.New(
//		gift.Sepia(100),
//	)
//	dst := image.NewRGBA(src.Bounds())
//	g.Draw(dst, src)
//
func Sepia(adjust int) Filter {
	return &colorFilter{
		fn: func(px pixel) pixel {
			adjustAmount := float32(adjust) / 100.0
			calculatedR := (px.R * (1.0 - (0.607 * adjustAmount))) +
				(px.G * (0.769 * adjustAmount)) +
				(px.B * (0.189 * adjustAmount))
			calculatedG := (px.R * (0.349 * adjustAmount)) +
				(px.G * (1.0 - (0.314 * adjustAmount))) +
				(px.B * (0.168 * adjustAmount))
			calculatedB := (px.R * (0.349 * adjustAmount)) +
				(px.G * (1.0 - (0.314 * adjustAmount))) +
				(px.B * (float32(0.168) * adjustAmount))
			r := float32(math.Min(255.0, float64(calculatedR)))
			g := float32(math.Min(255.0, float64(calculatedG)))
			b := float32(math.Min(255.0, float64(calculatedB)))
			return pixel{r, g, b, px.A}
		},
	}
}

func convertHSLToRGB(h, s, l float32) (float32, float32, float32) {
	if s == 0.0 {
		return l, l, l
	}

	_v := func(p, q, t float32) float32 {
		if t < 0.0 {
			t += 1.0
		}
		if t > 1.0 {
			t -= 1.0
		}
		if t < 1.0/6.0 {
			return p + (q-p)*6.0*t
		}
		if t < 1.0/2.0 {
			return q
		}
		if t < 2.0/3.0 {
			return p + (q-p)*(2.0/3.0-t)*6.0
		}
		return p
	}

	var p, q float32
	if l < 0.5 {
		q = l * (1.0 + s)
	} else {
		q = l + s - l*s
	}
	p = 2.0*l - q

	r := _v(p, q, h+1.0/3.0)
	g := _v(p, q, h)
	b := _v(p, q, h-1.0/3.0)

	return r, g, b
}

func convertRGBToHSL(r, g, b float32) (float32, float32, float32) {
	max := maxf32(r, maxf32(g, b))
	min := minf32(r, minf32(g, b))

	l := (max + min) / 2.0

	if max == min {
		return 0.0, 0.0, l
	}

	var h, s float32
	d := max - min
	if l > 0.5 {
		s = d / (2.0 - max - min)
	} else {
		s = d / (max + min)
	}

	if r == max {
		h = (g - b) / d
		if g < b {
			h += 6.0
		}
	} else if g == max {
		h = (b-r)/d + 2.0
	} else {
		h = (r-g)/d + 4.0
	}
	h /= 6.0

	return h, s, l
}

// Hue creates a filter that rotates the hue of an image.
// The shift parameter must be in range (-180, 180). The shift = 0 gives the original image.
func Hue(shift float32) Filter {
	if shift == 0 {
		return &copyimageFilter{}
	}
	p := minf32(maxf32(shift, -180.0), 180.0) / 360.0
	if p < 0.0 {
		p += 1.0
	}
	return &colorFilter{
		fn: func(px pixel) pixel {
			h, s, l := convertRGBToHSL(px.R, px.G, px.B)
			h = h + p
			if h > 1.0 {
				h -= 1.0
			}
			r, g, b := convertHSLToRGB(h, s, l)
			return pixel{r, g, b, px.A}
		},
	}
}

// Saturation creates a filter that changes the saturation of an image.
// The percentage parameter must be in range (-100, 500). The percentage = 0 gives the original image.
func Saturation(percentage float32) Filter {
	if percentage == 0 {
		return &copyimageFilter{}
	}
	p := 1 + minf32(maxf32(percentage, -100.0), 500.0)/100.0

	return &colorFilter{
		fn: func(px pixel) pixel {
			h, s, l := convertRGBToHSL(px.R, px.G, px.B)
			s *= p
			if s > 1 {
				s = 1
			}
			r, g, b := convertHSLToRGB(h, s, l)
			return pixel{r, g, b, px.A}
		},
	}
}
<|endoftext|>


<commit_before>package mdt

import (
	"fmt"
	"github.com/mattn/go-runewidth"
	"strings"
)

type columner interface {
	length() int
	toMarkdown(length int) string
}

type column struct {
	content string
}

func newColumn(s string) column {
	return column{
		content: strings.TrimSpace(s),
	}
}

func (c column) length() int {
	return runewidth.StringWidth(c.content)
}

func (c column) toMarkdown(length int) string {
	format := fmt.Sprintf(" %%- %ds ", length-c.length()+1)
	return fmt.Sprintf(format, c.content)
}

type align int

const (
	left align = iota
	center
	right
	none
)

type divColumn struct {
	column
	align align
}

func newDivColumn(s string) divColumn {
	s = strings.TrimSpace(s)
	align := none
	switch {
	case strings.HasPrefix(s, ":") && strings.HasSuffix(s, ":"):
		align = center
	case strings.HasPrefix(s, ":"):
		align = left
	case strings.HasSuffix(s, ":"):
		align = right
	}
	return divColumn{
		column: newColumn(strings.Trim(s, ":")),
		align:  align,
	}
}

func (d divColumn) toMarkdown(length int) string {
	prefix := " "
	suffix := " "
	switch d.align {
	case left:
		prefix = ":"
	case center:
		prefix = ":"
		suffix = ":"
	case right:
		suffix = ":"
	}
	return fmt.Sprintf("%s%s%s", prefix, strings.Repeat("-", length), suffix)
}
<commit_msg>fix toMarkdown()<commit_after>package mdt

import (
	"fmt"
	"github.com/mattn/go-runewidth"
	"strings"
)

type columner interface {
	length() int
	toMarkdown(length int) string
}

type column struct {
	content string
}

func newColumn(s string) column {
	return column{
		content: strings.TrimSpace(s),
	}
}

func (c column) length() int {
	return runewidth.StringWidth(c.content)
}

func (c column) toMarkdown(length int) string {
	return " " + c.content + strings.Repeat(" ", length-c.length()) + " "
}

type align int

const (
	left align = iota
	center
	right
	none
)

type divColumn struct {
	column
	align align
}

func newDivColumn(s string) divColumn {
	s = strings.TrimSpace(s)
	align := none
	switch {
	case strings.HasPrefix(s, ":") && strings.HasSuffix(s, ":"):
		align = center
	case strings.HasPrefix(s, ":"):
		align = left
	case strings.HasSuffix(s, ":"):
		align = right
	}
	return divColumn{
		column: newColumn(strings.Trim(s, ":")),
		align:  align,
	}
}

func (d divColumn) toMarkdown(length int) string {
	prefix := " "
	suffix := " "
	switch d.align {
	case left:
		prefix = ":"
	case center:
		prefix = ":"
		suffix = ":"
	case right:
		suffix = ":"
	}
	return fmt.Sprintf("%s%s%s", prefix, strings.Repeat("-", length), suffix)
}
<|endoftext|>


<commit_before>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/mitchellh/go-homedir"
	"github.com/op/go-logging"
	"golang.org/x/net/proxy"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"time"
)

type Config struct {
	// Network parameters. Set mainnet, testnet, or regtest using this.
	Params *chaincfg.Params

	// Bip39 mnemonic string. If empty a new mnemonic will be created.
	Mnemonic string

	// The date the wallet was created.
	// If before the earliest checkpoint the chain will be synced using the earliest checkpoint.
	CreationDate time.Time

	// The user-agent that shall be visible to peers
	UserAgent string

	// Location of the data directory
	RepoPath string

	// An implementation of the Datastore interface
	DB Datastore

	// If you wish to connect to a single trusted peer set this. Otherwise leave nil.
	TrustedPeer net.Addr

	// A Tor proxy can be set here causing the wallet will use Tor
	Proxy proxy.Dialer

	// The default fee-per-byte for each level
	LowFee    uint64
	MediumFee uint64
	HighFee   uint64

	// The highest allowable fee-per-byte
	MaxFee uint64

	// External API to query to look up fees. If this field is nil then the default fees will be used.
	// If the API is unreachable then the default fees will likewise be used. If the API returns a fee
	// greater than MaxFee then the MaxFee will be used in place. The API response must be formatted as
	// { "fastestFee": 40, "halfHourFee": 20, "hourFee": 10 }
	FeeAPI url.URL

	// A logger. You can write the logs to file or stdout or however else you want.
	Logger logging.Backend
}

func NewDefaultConfig() *Config {
	repoPath, _ := homedir.Expand(filepath.Join("~", ".bitcoincash"))
	_, ferr := os.Stat(repoPath)
	if os.IsNotExist(ferr) {
		os.Mkdir(repoPath, os.ModePerm)
	}
	feeApi, _ := url.Parse("https://bitcoinfees.21.co/api/v1/fees/recommended")
	return &Config{
		Params:    &chaincfg.MainNetParams,
		UserAgent: "spvwallet",
		RepoPath:  repoPath,
		LowFee:    140,
		MediumFee: 160,
		HighFee:   180,
		MaxFee:    2000,
		FeeAPI:    *feeApi,
		Logger:    logging.NewLogBackend(os.Stdout, "", 0),
	}
}
<commit_msg>Update default repo path<commit_after>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/mitchellh/go-homedir"
	"github.com/op/go-logging"
	"golang.org/x/net/proxy"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"time"
	"runtime"
)

type Config struct {
	// Network parameters. Set mainnet, testnet, or regtest using this.
	Params *chaincfg.Params

	// Bip39 mnemonic string. If empty a new mnemonic will be created.
	Mnemonic string

	// The date the wallet was created.
	// If before the earliest checkpoint the chain will be synced using the earliest checkpoint.
	CreationDate time.Time

	// The user-agent that shall be visible to peers
	UserAgent string

	// Location of the data directory
	RepoPath string

	// An implementation of the Datastore interface
	DB Datastore

	// If you wish to connect to a single trusted peer set this. Otherwise leave nil.
	TrustedPeer net.Addr

	// A Tor proxy can be set here causing the wallet will use Tor
	Proxy proxy.Dialer

	// The default fee-per-byte for each level
	LowFee    uint64
	MediumFee uint64
	HighFee   uint64

	// The highest allowable fee-per-byte
	MaxFee uint64

	// External API to query to look up fees. If this field is nil then the default fees will be used.
	// If the API is unreachable then the default fees will likewise be used. If the API returns a fee
	// greater than MaxFee then the MaxFee will be used in place. The API response must be formatted as
	// { "fastestFee": 40, "halfHourFee": 20, "hourFee": 10 }
	FeeAPI url.URL

	// A logger. You can write the logs to file or stdout or however else you want.
	Logger logging.Backend
}

func NewDefaultConfig() *Config {
	repoPath, _ := getRepoPath()
	_, ferr := os.Stat(repoPath)
	if os.IsNotExist(ferr) {
		os.Mkdir(repoPath, os.ModePerm)
	}
	feeApi, _ := url.Parse("https://bitcoinfees.21.co/api/v1/fees/recommended")
	return &Config{
		Params:    &chaincfg.MainNetParams,
		UserAgent: "spvwallet",
		RepoPath:  repoPath,
		LowFee:    140,
		MediumFee: 160,
		HighFee:   180,
		MaxFee:    2000,
		FeeAPI:    *feeApi,
		Logger:    logging.NewLogBackend(os.Stdout, "", 0),
	}
}

func getRepoPath() (string, error) {
	// Set default base path and directory name
	path := "~"
	directoryName := "BitcoinCash"

	// Override OS-specific names
	switch runtime.GOOS {
	case "linux":
		directoryName = ".bitcoincash"
	case "darwin":
		path = "~/Library/Application Support"
	}

	// Join the path and directory name, then expand the home path
	fullPath, err := homedir.Expand(filepath.Join(path, directoryName))
	if err != nil {
		return "", err
	}

	// Return the shortest lexical representation of the path
	return filepath.Clean(fullPath), nil
}<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/mitchellh/osext"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/packer/plugin"
	"io"
	"log"
	"os/exec"
	"path/filepath"
)

// This is the default, built-in configuration that ships with
// Packer.
const defaultConfig = `
{
	"plugin_min_port": 10000,
	"plugin_max_port": 25000,

	"builders": {
		"amazon-ebs": "packer-builder-amazon-ebs",
		"amazon-chroot": "packer-builder-amazon-chroot",
		"amazon-instance": "packer-builder-amazon-instance",
		"digitalocean": "packer-builder-digitalocean",
		"docker": "packer-builder-docker",
		"googlecompute": "packer-builder-googlecompute",
		"openstack": "packer-builder-openstack",
		"qemu": "packer-builder-qemu",
		"virtualbox-iso": "packer-builder-virtualbox-iso",
		"virtualbox-ovf": "packer-builder-virtualbox-ovf",
		"vmware-iso": "packer-builder-vmware-iso",
		"vmware-vmx": "packer-builder-vmware-vmx"
	},

	"commands": {
		"build": "packer-command-build",
		"fix": "packer-command-fix",
		"inspect": "packer-command-inspect",
		"validate": "packer-command-validate"
	},

	"post-processors": {
		"vagrant": "packer-post-processor-vagrant",
		"vsphere": "packer-post-processor-vsphere",
    "docker-push": "packer-post-processor-docker-push",
    "docker-import": "packer-post-processor-docker-import"
	},

	"provisioners": {
		"ansible-local": "packer-provisioner-ansible-local",
		"chef-solo": "packer-provisioner-chef-solo",
		"file": "packer-provisioner-file",
		"puppet-masterless": "packer-provisioner-puppet-masterless",
		"shell": "packer-provisioner-shell",
		"salt-masterless": "packer-provisioner-salt-masterless"
	}
}
`

type config struct {
	PluginMinPort uint
	PluginMaxPort uint

	Builders       map[string]string
	Commands       map[string]string
	PostProcessors map[string]string `json:"post-processors"`
	Provisioners   map[string]string
}

// Decodes configuration in JSON format from the given io.Reader into
// the config object pointed to.
func decodeConfig(r io.Reader, c *config) error {
	decoder := json.NewDecoder(r)
	return decoder.Decode(c)
}

// Returns an array of defined command names.
func (c *config) CommandNames() (result []string) {
	result = make([]string, 0, len(c.Commands))
	for name := range c.Commands {
		result = append(result, name)
	}
	return
}

// This is a proper packer.BuilderFunc that can be used to load packer.Builder
// implementations from the defined plugins.
func (c *config) LoadBuilder(name string) (packer.Builder, error) {
	log.Printf("Loading builder: %s\n", name)
	bin, ok := c.Builders[name]
	if !ok {
		log.Printf("Builder not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Builder()
}

// This is a proper packer.CommandFunc that can be used to load packer.Command
// implementations from the defined plugins.
func (c *config) LoadCommand(name string) (packer.Command, error) {
	log.Printf("Loading command: %s\n", name)
	bin, ok := c.Commands[name]
	if !ok {
		log.Printf("Command not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Command()
}

// This is a proper implementation of packer.HookFunc that can be used
// to load packer.Hook implementations from the defined plugins.
func (c *config) LoadHook(name string) (packer.Hook, error) {
	log.Printf("Loading hook: %s\n", name)
	return c.pluginClient(name).Hook()
}

// This is a proper packer.PostProcessorFunc that can be used to load
// packer.PostProcessor implementations from defined plugins.
func (c *config) LoadPostProcessor(name string) (packer.PostProcessor, error) {
	log.Printf("Loading post-processor: %s", name)
	bin, ok := c.PostProcessors[name]
	if !ok {
		log.Printf("Post-processor not found: %s", name)
		return nil, nil
	}

	return c.pluginClient(bin).PostProcessor()
}

// This is a proper packer.ProvisionerFunc that can be used to load
// packer.Provisioner implementations from defined plugins.
func (c *config) LoadProvisioner(name string) (packer.Provisioner, error) {
	log.Printf("Loading provisioner: %s\n", name)
	bin, ok := c.Provisioners[name]
	if !ok {
		log.Printf("Provisioner not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Provisioner()
}

func (c *config) pluginClient(path string) *plugin.Client {
	originalPath := path

	// First attempt to find the executable by consulting the PATH.
	path, err := exec.LookPath(path)
	if err != nil {
		// If that doesn't work, look for it in the same directory
		// as the `packer` executable (us).
		log.Printf("Plugin could not be found. Checking same directory as executable.")
		exePath, err := osext.Executable()
		if err != nil {
			log.Printf("Couldn't get current exe path: %s", err)
		} else {
			log.Printf("Current exe path: %s", exePath)
			path = filepath.Join(filepath.Dir(exePath), filepath.Base(originalPath))
		}
	}

	// If everything failed, just use the original path and let the error
	// bubble through.
	if path == "" {
		path = originalPath
	}

	log.Printf("Creating plugin client for path: %s", path)
	var config plugin.ClientConfig
	config.Cmd = exec.Command(path)
	config.Managed = true
	config.MinPort = c.PluginMinPort
	config.MaxPort = c.PluginMaxPort
	return plugin.NewClient(&config)
}
<commit_msg>Add chef client provisioner to default list<commit_after>package main

import (
	"encoding/json"
	"github.com/mitchellh/osext"
	"github.com/mitchellh/packer/packer"
	"github.com/mitchellh/packer/packer/plugin"
	"io"
	"log"
	"os/exec"
	"path/filepath"
)

// This is the default, built-in configuration that ships with
// Packer.
const defaultConfig = `
{
	"plugin_min_port": 10000,
	"plugin_max_port": 25000,

	"builders": {
		"amazon-ebs": "packer-builder-amazon-ebs",
		"amazon-chroot": "packer-builder-amazon-chroot",
		"amazon-instance": "packer-builder-amazon-instance",
		"digitalocean": "packer-builder-digitalocean",
		"docker": "packer-builder-docker",
		"googlecompute": "packer-builder-googlecompute",
		"openstack": "packer-builder-openstack",
		"qemu": "packer-builder-qemu",
		"virtualbox-iso": "packer-builder-virtualbox-iso",
		"virtualbox-ovf": "packer-builder-virtualbox-ovf",
		"vmware-iso": "packer-builder-vmware-iso",
		"vmware-vmx": "packer-builder-vmware-vmx"
	},

	"commands": {
		"build": "packer-command-build",
		"fix": "packer-command-fix",
		"inspect": "packer-command-inspect",
		"validate": "packer-command-validate"
	},

	"post-processors": {
		"vagrant": "packer-post-processor-vagrant",
		"vsphere": "packer-post-processor-vsphere",
		"docker-push": "packer-post-processor-docker-push",
		"docker-import": "packer-post-processor-docker-import"
	},

	"provisioners": {
		"ansible-local": "packer-provisioner-ansible-local",
		"chef-client": "packer-provisioner-chef-client",
		"chef-solo": "packer-provisioner-chef-solo",
		"file": "packer-provisioner-file",
		"puppet-masterless": "packer-provisioner-puppet-masterless",
		"shell": "packer-provisioner-shell",
		"salt-masterless": "packer-provisioner-salt-masterless"
	}
}
`

type config struct {
	PluginMinPort uint
	PluginMaxPort uint

	Builders       map[string]string
	Commands       map[string]string
	PostProcessors map[string]string `json:"post-processors"`
	Provisioners   map[string]string
}

// Decodes configuration in JSON format from the given io.Reader into
// the config object pointed to.
func decodeConfig(r io.Reader, c *config) error {
	decoder := json.NewDecoder(r)
	return decoder.Decode(c)
}

// Returns an array of defined command names.
func (c *config) CommandNames() (result []string) {
	result = make([]string, 0, len(c.Commands))
	for name := range c.Commands {
		result = append(result, name)
	}
	return
}

// This is a proper packer.BuilderFunc that can be used to load packer.Builder
// implementations from the defined plugins.
func (c *config) LoadBuilder(name string) (packer.Builder, error) {
	log.Printf("Loading builder: %s\n", name)
	bin, ok := c.Builders[name]
	if !ok {
		log.Printf("Builder not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Builder()
}

// This is a proper packer.CommandFunc that can be used to load packer.Command
// implementations from the defined plugins.
func (c *config) LoadCommand(name string) (packer.Command, error) {
	log.Printf("Loading command: %s\n", name)
	bin, ok := c.Commands[name]
	if !ok {
		log.Printf("Command not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Command()
}

// This is a proper implementation of packer.HookFunc that can be used
// to load packer.Hook implementations from the defined plugins.
func (c *config) LoadHook(name string) (packer.Hook, error) {
	log.Printf("Loading hook: %s\n", name)
	return c.pluginClient(name).Hook()
}

// This is a proper packer.PostProcessorFunc that can be used to load
// packer.PostProcessor implementations from defined plugins.
func (c *config) LoadPostProcessor(name string) (packer.PostProcessor, error) {
	log.Printf("Loading post-processor: %s", name)
	bin, ok := c.PostProcessors[name]
	if !ok {
		log.Printf("Post-processor not found: %s", name)
		return nil, nil
	}

	return c.pluginClient(bin).PostProcessor()
}

// This is a proper packer.ProvisionerFunc that can be used to load
// packer.Provisioner implementations from defined plugins.
func (c *config) LoadProvisioner(name string) (packer.Provisioner, error) {
	log.Printf("Loading provisioner: %s\n", name)
	bin, ok := c.Provisioners[name]
	if !ok {
		log.Printf("Provisioner not found: %s\n", name)
		return nil, nil
	}

	return c.pluginClient(bin).Provisioner()
}

func (c *config) pluginClient(path string) *plugin.Client {
	originalPath := path

	// First attempt to find the executable by consulting the PATH.
	path, err := exec.LookPath(path)
	if err != nil {
		// If that doesn't work, look for it in the same directory
		// as the `packer` executable (us).
		log.Printf("Plugin could not be found. Checking same directory as executable.")
		exePath, err := osext.Executable()
		if err != nil {
			log.Printf("Couldn't get current exe path: %s", err)
		} else {
			log.Printf("Current exe path: %s", exePath)
			path = filepath.Join(filepath.Dir(exePath), filepath.Base(originalPath))
		}
	}

	// If everything failed, just use the original path and let the error
	// bubble through.
	if path == "" {
		path = originalPath
	}

	log.Printf("Creating plugin client for path: %s", path)
	var config plugin.ClientConfig
	config.Cmd = exec.Command(path)
	config.Managed = true
	config.MinPort = c.PluginMinPort
	config.MaxPort = c.PluginMaxPort
	return plugin.NewClient(&config)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
)

const (
	// Name is the user facing name for this binary. Internally we call it
	// klientctl to avoid confusion.
	Name = "kd"

	// KlientName is the user facing name for klient.
	KlientName = "KD Daemon"

	// KlientAddress is url of locally running klient to connect to send
	// user commands.
	KlientAddress = "http://127.0.0.1:56789/kite"

	// KiteHome is full path to the kite key that we will use to authenticate
	// to the given klient.
	KiteHome = "/etc/kite"

	// KlientDirectory is full path to directory that holds klient.
	KlientDirectory = "/opt/kite/klient"

	// KlientctlDirectory is full path to directory that holds klientctl.
	KlientctlDirectory = "/usr/local/bin"

	// KlientctlBinName is the bin named that will be stored in the KlientctlDirectory.
	KlientctlBinName = "kd"

	// KontrolURL is the url to connect to authenticate local klient and get
	// list of machines.
	KontrolURL = "https://koding.com/kontrol/kite"

	// Version is the current version of klientctl. This number is used
	// by CheckUpdate to determine if current version is behind or equal to latest
	// version on S3 bucket.
	Version = 20

	osName = runtime.GOOS

	// S3UpdateLocation is publically accessible url to check for new updates.
	S3UpdateLocation = "https://koding-kd.s3.amazonaws.com/latest-version.txt"

	// S3KlientPath is publically accessible url for latest version of klient.
	// Each OS has its own version of binary, identifiable by OS suffix.
	S3KlientPath = "https://koding-kd.s3.amazonaws.com/klient-" + osName

	// S3KlientctlPath is publically accessible url for latest version of
	// klientctl. Each OS has its own version of binary, identifiable by suffix.
	S3KlientctlPath = "https://koding-kd.s3.amazonaws.com/klientctl-" + osName

	// SSHDefaultKeyDir is the default directory that stores users ssh key pairs.
	SSHDefaultKeyDir = ".ssh"

	// SSHDefaultKeyName is the default name of the ssh key pair.
	SSHDefaultKeyName = "kd-ssh-key"
)

var (
	// KiteVersion is the version identifier used to connect to Kontrol.
	KiteVersion = fmt.Sprintf("0.0.%d", Version)

	// ConfigFolder is folder where config and other related info are stored.
	ConfigFolder string
)

func init() {
	var err error
	if ConfigFolder, err = createFolderAtHome(".config", "koding"); err != nil {
		panic(err)
	}
}

func createFolderAtHome(cf ...string) (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}

	args := []string{usr.HomeDir}
	args = append(args, cf...)

	folderName := filepath.Join(args...)
	if err := os.MkdirAll(folderName, 0755); err != nil {
		return "", err
	}

	return folderName, nil
}
<commit_msg>config: Version incrememnt.<commit_after>package main

import (
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
)

const (
	// Name is the user facing name for this binary. Internally we call it
	// klientctl to avoid confusion.
	Name = "kd"

	// KlientName is the user facing name for klient.
	KlientName = "KD Daemon"

	// KlientAddress is url of locally running klient to connect to send
	// user commands.
	KlientAddress = "http://127.0.0.1:56789/kite"

	// KiteHome is full path to the kite key that we will use to authenticate
	// to the given klient.
	KiteHome = "/etc/kite"

	// KlientDirectory is full path to directory that holds klient.
	KlientDirectory = "/opt/kite/klient"

	// KlientctlDirectory is full path to directory that holds klientctl.
	KlientctlDirectory = "/usr/local/bin"

	// KlientctlBinName is the bin named that will be stored in the KlientctlDirectory.
	KlientctlBinName = "kd"

	// KontrolURL is the url to connect to authenticate local klient and get
	// list of machines.
	KontrolURL = "https://koding.com/kontrol/kite"

	// Version is the current version of klientctl. This number is used
	// by CheckUpdate to determine if current version is behind or equal to latest
	// version on S3 bucket.
	Version = 21

	osName = runtime.GOOS

	// S3UpdateLocation is publically accessible url to check for new updates.
	S3UpdateLocation = "https://koding-kd.s3.amazonaws.com/latest-version.txt"

	// S3KlientPath is publically accessible url for latest version of klient.
	// Each OS has its own version of binary, identifiable by OS suffix.
	S3KlientPath = "https://koding-kd.s3.amazonaws.com/klient-" + osName

	// S3KlientctlPath is publically accessible url for latest version of
	// klientctl. Each OS has its own version of binary, identifiable by suffix.
	S3KlientctlPath = "https://koding-kd.s3.amazonaws.com/klientctl-" + osName

	// SSHDefaultKeyDir is the default directory that stores users ssh key pairs.
	SSHDefaultKeyDir = ".ssh"

	// SSHDefaultKeyName is the default name of the ssh key pair.
	SSHDefaultKeyName = "kd-ssh-key"
)

var (
	// KiteVersion is the version identifier used to connect to Kontrol.
	KiteVersion = fmt.Sprintf("0.0.%d", Version)

	// ConfigFolder is folder where config and other related info are stored.
	ConfigFolder string
)

func init() {
	var err error
	if ConfigFolder, err = createFolderAtHome(".config", "koding"); err != nil {
		panic(err)
	}
}

func createFolderAtHome(cf ...string) (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}

	args := []string{usr.HomeDir}
	args = append(args, cf...)

	folderName := filepath.Join(args...)
	if err := os.MkdirAll(folderName, 0755); err != nil {
		return "", err
	}

	return folderName, nil
}
<|endoftext|>