<commit_before>package dhcp6

import (
	"net"

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

var (
	// AllRelayAgentsAndServersAddr is the multicast address group which is
	// used to communicate with neighboring (on-link) DHCP servers and relay
	// agents, as defined in IETF RFC 3315, Section 5.1.  All DHCP servers
	// and relay agents are members of this multicast group.
	AllRelayAgentsAndServersAddr = &net.IPAddr{
		IP: net.ParseIP("ff02::1:2"),
	}

	// AllServersAddr is the multicast address group which is used by a
	// DHCP relay agent to communicate with DHCP servers, if the relay agent
	// wishes to send messages to all servers, or does not know the unicast
	// address of a server.  All DHCP servers are members of this multicast
	// group.
	AllServersAddr = &net.IPAddr{
		IP: net.ParseIP("ff05::1:3"),
	}
)

// Server represents a DHCP server, and is used to configure a DHCP server's
// behavior.
type Server struct {
	// Iface is the name of the network interface on which this server should
	// listen.  Traffic from any other network interface will be filtered out
	// and ignored by the server.
	Iface string

	// Handler is the handler to use while serving DHCP requests.  If this
	// value is nil, DefaultServeMux will be used in place of Handler.
	Handler Handler

	// MulticastGroups designates which IPv6 multicast groups this server
	// will join on start-up.  Because the default configuration acts as a
	// DHCP server, most servers will typically join both
	// AllRelayAgentsAndServersAddr, and AllServersAddr. If configuring a
	// DHCP relay agent, only the former value should be used.
	MulticastGroups []*net.IPAddr

	// ServerID is the the server's DUID, which uniquely identifies this
	// server to clients.  If no DUID is specified, a DUID-LL will be
	// generated using Iface's hardware type and address.  If possible,
	// servers with persistent storage available should generate a DUID-LLT
	// and store it for future use.
	ServerID DUID

	// ifIndex stores the index of Iface, which is used to filter out traffic
	// bound for other interfaces on this machine.
	ifIndex int
}

// ListenAndServe listens for UDP6 connections on port [::]:567 of the
// specified interface, using the default Server configuration and specified
// handler to handle DHCPv6 connections.  If the handler is nil,
// DefaultServeMux is used instead.
//
// Any traffic which reaches the Server, and is not bound for the specified
// network interface, will be filtered out and ignored.
//
// In this configuration, the server acts as a DHCP server, but NOT as a
// DHCP relay agent.  For more information on DHCP relay agents, see
// IETF RFC 3315, Section 20.
func ListenAndServe(iface string, handler Handler) error {
	return (&Server{
		Iface:   iface,
		Handler: handler,
		MulticastGroups: []*net.IPAddr{
			AllRelayAgentsAndServersAddr,
			AllServersAddr,
		},
	}).ListenAndServe()
}

// ListenAndServe listens on the UDP6 [::]:547 using the interface defined in
// s.Iface.  Traffic from any other interface will be filtered out and ignored.
// Serve is called to handle serving DHCP traffic once ListenAndServe opens a
// UDP6 packet connection, and joins the multicast groups defined in
// s.MulticastGroups.
func (s *Server) ListenAndServe() error {
	// Check for valid interface
	iface, err := net.InterfaceByName(s.Iface)
	if err != nil {
		return err
	}

	// If no DUID was set for server previously, generate a DUID-LL
	// now using the interface's hardware type and address
	if s.ServerID == nil {
		// BUG(mdlayher): see if hardware type can be easily determined for
		// an interface.  For now, default to Ethernet (10mb) as defined here:
		// http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml.
		const ethernet10Mb = 1
		s.ServerID = NewDUIDLL(ethernet10Mb, iface.HardwareAddr)
	}

	// Open UDP6 packet connection listener on designated DHCPv6 port
	conn, err := net.ListenPacket("udp6", "[::]:547")
	if err != nil {
		return err
	}

	// Set up IPv6 packet connection, and on return, handle leaving multicast
	// groups and closing connection
	p := ipv6.NewPacketConn(conn)
	defer func() {
		for _, g := range s.MulticastGroups {
			_ = p.LeaveGroup(iface, g)
		}

		_ = conn.Close()
	}()

	// Filter any traffic which does not indicate the interface
	// defined by s.Iface.
	if err := p.SetControlMessage(ipv6.FlagInterface, true); err != nil {
		return err
	}

	// Join appropriate multicast groups
	for _, g := range s.MulticastGroups {
		if err := p.JoinGroup(iface, g); err != nil {
			return err
		}
	}

	// Begin serving connections
	s.ifIndex = iface.Index
	return s.Serve(p)
}

// Serve accepts incoming connections on ipv6.PacketConn p, creating a
// new goroutine for each.  The service goroutine reads requests, generates
// the appropriate Request and Responser values, then calls s.Handler to handle
// the request.
func (s *Server) Serve(p *ipv6.PacketConn) error {
	defer p.Close()

	// Loop and read requests until exit
	buf := make([]byte, 1500)
	for {
		n, cm, addr, err := p.ReadFrom(buf)
		if err != nil {
			// BUG(mdlayher): determine if error can be temporary
			return err
		}

		// Filter any traffic with a control message indicating an incorrect
		// interface index
		if cm != nil && cm.IfIndex != s.ifIndex {
			continue
		}

		// Create conn struct with data specific to this connection
		uc, err := s.newConn(p, addr.(*net.UDPAddr), n, buf)
		if err != nil {
			continue
		}

		// Serve conn and continue looping for more connections
		go uc.serve()
	}
}

// conn represents an in-flight DHCP connection, and contains information about
// the connection and server.
type conn struct {
	remoteAddr *net.UDPAddr
	server     *Server
	conn       *ipv6.PacketConn
	buf        []byte
}

// newConn creates a new conn using information received in a single DHCP
// connection.  newConn makes a copy of the input buffer for use in handling
// a single connection.
// BUG(mdlayher): consider using a sync.Pool with many buffers available to avoid
// allocating a new one on each connection
func (s *Server) newConn(p *ipv6.PacketConn, addr *net.UDPAddr, n int, buf []byte) (*conn, error) {
	c := &conn{
		remoteAddr: addr,
		server:     s,
		conn:       p,
		buf:        make([]byte, n, n),
	}
	copy(c.buf, buf[:n])

	return c, nil
}

// response represents a DHCP response, and implements Responser so that
// outbound packets can be appropriately sent.
type response struct {
	remoteAddr *net.UDPAddr
	conn       *ipv6.PacketConn
	req        *Request
}

// Write implements Responser, and writes a packet directly to the address
// indicated in the response.
func (r *response) Write(p []byte) (int, error) {
	return r.conn.WriteTo(p, nil, r.remoteAddr)
}

// serve handles serving an individual DHCP connection, and is invoked in a
// goroutine.
func (c *conn) serve() {
	// Parse Packet data from raw buffer
	p := Packet(c.buf)

	// Set up Request with information from a Packet, providing a nicer
	// API for callers to implement their own DHCP request handlers
	r := newServerRequest(p, c.remoteAddr)

	// Set up response to send responses back to the original requester
	w := &response{
		remoteAddr: c.remoteAddr,
		conn:       c.conn,
		req:        r,
	}

	// If set, invoke DHCP handler using request and response
	// Default to DefaultServeMux if handler is not available
	handler := c.server.Handler
	if handler == nil {
		handler = DefaultServeMux
	}

	handler.ServeDHCP(w, r)
}
<commit_msg>server: add serveConn interface to allow connection to be swapped out for tests<commit_after>package dhcp6

import (
	"net"

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

var (
	// AllRelayAgentsAndServersAddr is the multicast address group which is
	// used to communicate with neighboring (on-link) DHCP servers and relay
	// agents, as defined in IETF RFC 3315, Section 5.1.  All DHCP servers
	// and relay agents are members of this multicast group.
	AllRelayAgentsAndServersAddr = &net.IPAddr{
		IP: net.ParseIP("ff02::1:2"),
	}

	// AllServersAddr is the multicast address group which is used by a
	// DHCP relay agent to communicate with DHCP servers, if the relay agent
	// wishes to send messages to all servers, or does not know the unicast
	// address of a server.  All DHCP servers are members of this multicast
	// group.
	AllServersAddr = &net.IPAddr{
		IP: net.ParseIP("ff05::1:3"),
	}
)

// Server represents a DHCP server, and is used to configure a DHCP server's
// behavior.
type Server struct {
	// Iface is the name of the network interface on which this server should
	// listen.  Traffic from any other network interface will be filtered out
	// and ignored by the server.
	Iface string

	// Handler is the handler to use while serving DHCP requests.  If this
	// value is nil, DefaultServeMux will be used in place of Handler.
	Handler Handler

	// MulticastGroups designates which IPv6 multicast groups this server
	// will join on start-up.  Because the default configuration acts as a
	// DHCP server, most servers will typically join both
	// AllRelayAgentsAndServersAddr, and AllServersAddr. If configuring a
	// DHCP relay agent, only the former value should be used.
	MulticastGroups []*net.IPAddr

	// ServerID is the the server's DUID, which uniquely identifies this
	// server to clients.  If no DUID is specified, a DUID-LL will be
	// generated using Iface's hardware type and address.  If possible,
	// servers with persistent storage available should generate a DUID-LLT
	// and store it for future use.
	ServerID DUID

	// ifIndex stores the index of Iface, which is used to filter out traffic
	// bound for other interfaces on this machine.
	ifIndex int
}

// ListenAndServe listens for UDP6 connections on port [::]:567 of the
// specified interface, using the default Server configuration and specified
// handler to handle DHCPv6 connections.  If the handler is nil,
// DefaultServeMux is used instead.
//
// Any traffic which reaches the Server, and is not bound for the specified
// network interface, will be filtered out and ignored.
//
// In this configuration, the server acts as a DHCP server, but NOT as a
// DHCP relay agent.  For more information on DHCP relay agents, see
// IETF RFC 3315, Section 20.
func ListenAndServe(iface string, handler Handler) error {
	return (&Server{
		Iface:   iface,
		Handler: handler,
		MulticastGroups: []*net.IPAddr{
			AllRelayAgentsAndServersAddr,
			AllServersAddr,
		},
	}).ListenAndServe()
}

// ListenAndServe listens on the UDP6 [::]:547 using the interface defined in
// s.Iface.  Traffic from any other interface will be filtered out and ignored.
// Serve is called to handle serving DHCP traffic once ListenAndServe opens a
// UDP6 packet connection, and joins the multicast groups defined in
// s.MulticastGroups.
func (s *Server) ListenAndServe() error {
	// Check for valid interface
	iface, err := net.InterfaceByName(s.Iface)
	if err != nil {
		return err
	}

	// If no DUID was set for server previously, generate a DUID-LL
	// now using the interface's hardware type and address
	if s.ServerID == nil {
		// BUG(mdlayher): see if hardware type can be easily determined for
		// an interface.  For now, default to Ethernet (10mb) as defined here:
		// http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml.
		const ethernet10Mb = 1
		s.ServerID = NewDUIDLL(ethernet10Mb, iface.HardwareAddr)
	}

	// Open UDP6 packet connection listener on designated DHCPv6 port
	conn, err := net.ListenPacket("udp6", "[::]:547")
	if err != nil {
		return err
	}

	// Set up IPv6 packet connection, and on return, handle leaving multicast
	// groups and closing connection
	p := ipv6.NewPacketConn(conn)
	defer func() {
		for _, g := range s.MulticastGroups {
			_ = p.LeaveGroup(iface, g)
		}

		_ = conn.Close()
	}()

	// Filter any traffic which does not indicate the interface
	// defined by s.Iface.
	if err := p.SetControlMessage(ipv6.FlagInterface, true); err != nil {
		return err
	}

	// Join appropriate multicast groups
	for _, g := range s.MulticastGroups {
		if err := p.JoinGroup(iface, g); err != nil {
			return err
		}
	}

	// Begin serving connections
	s.ifIndex = iface.Index
	return s.Serve(p)
}

// Serve accepts incoming connections on ipv6.PacketConn p, creating a
// new goroutine for each.  The service goroutine reads requests, generates
// the appropriate Request and Responser values, then calls s.Handler to handle
// the request.
func (s *Server) Serve(p *ipv6.PacketConn) error {
	defer p.Close()

	// Loop and read requests until exit
	buf := make([]byte, 1500)
	for {
		n, cm, addr, err := p.ReadFrom(buf)
		if err != nil {
			// BUG(mdlayher): determine if error can be temporary
			return err
		}

		// Filter any traffic with a control message indicating an incorrect
		// interface index
		if cm != nil && cm.IfIndex != s.ifIndex {
			continue
		}

		// Create conn struct with data specific to this connection
		uc, err := s.newConn(p, addr.(*net.UDPAddr), n, buf)
		if err != nil {
			continue
		}

		// Serve conn and continue looping for more connections
		go uc.serve()
	}
}

// serveConn is an internal type which allows a packet connection to be swapped
// out for testing, without opening a network connection.
type serveConn interface {
	WriteTo([]byte, *ipv6.ControlMessage, net.Addr) (int, error)
}

// conn represents an in-flight DHCP connection, and contains information about
// the connection and server.
type conn struct {
	remoteAddr *net.UDPAddr
	server     *Server
	conn       serveConn
	buf        []byte
}

// newConn creates a new conn using information received in a single DHCP
// connection.  newConn makes a copy of the input buffer for use in handling
// a single connection.
// BUG(mdlayher): consider using a sync.Pool with many buffers available to avoid
// allocating a new one on each connection
func (s *Server) newConn(p serveConn, addr *net.UDPAddr, n int, buf []byte) (*conn, error) {
	c := &conn{
		remoteAddr: addr,
		server:     s,
		conn:       p,
		buf:        make([]byte, n, n),
	}
	copy(c.buf, buf[:n])

	return c, nil
}

// response represents a DHCP response, and implements Responser so that
// outbound packets can be appropriately sent.
type response struct {
	remoteAddr *net.UDPAddr
	conn       serveConn
	req        *Request
}

// Write implements Responser, and writes a packet directly to the address
// indicated in the response.
func (r *response) Write(p []byte) (int, error) {
	return r.conn.WriteTo(p, nil, r.remoteAddr)
}

// serve handles serving an individual DHCP connection, and is invoked in a
// goroutine.
func (c *conn) serve() {
	// Parse Packet data from raw buffer
	p := Packet(c.buf)

	// Set up Request with information from a Packet, providing a nicer
	// API for callers to implement their own DHCP request handlers
	r := newServerRequest(p, c.remoteAddr)

	// Set up response to send responses back to the original requester
	w := &response{
		remoteAddr: c.remoteAddr,
		conn:       c.conn,
		req:        r,
	}

	// If set, invoke DHCP handler using request and response
	// Default to DefaultServeMux if handler is not available
	handler := c.server.Handler
	if handler == nil {
		handler = DefaultServeMux
	}

	handler.ServeDHCP(w, r)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/igm/sockjs-go/sockjs"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

func main() {
	http.Handle("/echo/", sockjs.NewHandler("/echo", sockjs.DefaultOptions, echoHandler))
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./public"))))
	http.HandleFunc("/", Index)

	port := os.Getenv("PORT")
	if port == "" {
		port = "3001"
	}

	log.Println("Server started")
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func echoHandler(session sockjs.Session) {
	log.Println("Client connected")
	for {
		if msg, err := session.Recv(); err == nil {
			log.Println("Msg rec'd: " + msg)
			session.Send(msg)
			continue
		}
		log.Println("Client disconnected")
		break
	}
}

func Index(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path != "/" {
		http.NotFound(w, req)
		return
	}
	contents, err := ioutil.ReadFile("public/index.html")
	if err != nil {
		log.Fatal(err)
	}
	w.Write(contents)
}
<commit_msg>pubsub<commit_after>package main

import (
	"github.com/igm/pubsub"
	"github.com/igm/sockjs-go/sockjs"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

var chat pubsub.Publisher

func main() {
	http.Handle("/echo/", sockjs.NewHandler("/echo", sockjs.DefaultOptions, echoHandler))
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./public"))))
	http.HandleFunc("/", Index)

	port := os.Getenv("PORT")
	if port == "" {
		port = "3001"
	}

	log.Println("Server started")
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func echoHandler(session sockjs.Session) {
	log.Println("Client connected")
	closedSession := make(chan struct{})
	chat.Publish("[info] chatter joined")
	defer chat.Publish("[info] chatter left")
	go func() {
		reader, _ := chat.SubChannel(nil)
		for {
			select {
			case <-closedSession:
				return
			case msg := <-reader:
				if err := session.Send(msg.(string)); err != nil {
					return
				}
			}
		}
	}()
	for {
		if msg, err := session.Recv(); err == nil {
			log.Println("Msg rec'd: " + msg)
			chat.Publish(msg)
			continue
		}
		log.Println("Client disconnected")
		break
	}
	close(closedSession)
	log.Println("Session closed")
}

func Index(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path != "/" {
		http.NotFound(w, req)
		return
	}
	contents, err := ioutil.ReadFile("public/index.html")
	if err != nil {
		log.Fatal(err)
	}
	w.Write(contents)
}
<|endoftext|>


<commit_before>// Copyright 2016 Jacob Taylor jacob.taylor@gmail.com
// License: Apache2
package main

import (
    "fmt"
    "net"
    "./utils"
    "bufio"
    "encoding/binary"
    "time"
    "os"
)

func send_export_list_item(output *bufio.Writer, export_name string) {
    data := make([]byte, 1024)
    length := len(export_name)
    offset := 0

    // length of export name
    binary.BigEndian.PutUint32(data[offset:], uint32(length))  // length of string
    offset += 4

    // export name
    copy(data[offset:], export_name)
    offset += length

    reply_type := uint32(2)     // reply_type: NBD_REP_SERVER
    send_message(output, reply_type, uint32(offset), data)
}

func send_ack(output *bufio.Writer) {
    send_message(output, utils.NBD_COMMAND_ACK, 0, nil)
}

func export_name(output *bufio.Writer, conn net.Conn, payload_size int, payload []byte) {
    fmt.Printf("have request to bind to: %s\n", string(payload[:payload_size]))

    defer conn.Close()

    // attempt to open the file read only
    file, err := os.Open("/Users/jacob/work/nbd/sample_disks/happyu")
    utils.ErrorCheck(err)
    //defer file.Close()

    data := make([]byte, 1024)
    count, err := file.Read(data)
    utils.ErrorCheck(err)

    if count > 100 {
        count = 100
    }

    // send export information
    // size u64
    // flags u16
    // Zeros (124 bytes)?
    buffer := make([]byte, 256)
    offset := 0

    binary.BigEndian.PutUint64(buffer[offset:], 52428800)  // size
    offset += 8

    binary.BigEndian.PutUint16(buffer[offset:], 0)  // flags
    offset += 2

    //offset += 124       // zero pad

    len, err := output.Write(buffer[:offset])
    output.Flush()
    utils.ErrorCheck(err)
    fmt.Printf("Wrote %d chars: %v\n", len, buffer[:offset])

    fmt.Printf("File descriptor:\n%+v\n", *file)
    fmt.Printf("First 100 bytes: \n%v\n", data[:count])

    // send a reply with the handle
    //S: 32 bits, 0x67446698, magic (NBD_REPLY_MAGIC)
    //S: 32 bits, error (MAY be zero)
    //S: 64 bits, handle
    //S: (length bytes of data if the request is of type NBD_CMD_READ)
    //offset = 0
    //binary.BigEndian.PutUint32(buffer[offset:], utils.NBD_REPLY_MAGIC)
    //offset += 4
    //
    //binary.BigEndian.PutUint32(buffer[offset:], 0) // error
    //offset += 4
    //
    //binary.BigEndian.PutUint64(buffer[offset:], 8000) // handle
    //offset += 8
    //
    //fmt.Printf("Writing out data: %v\n", buffer[:offset])
    //len, err = output.Write(buffer[:offset])
    //output.Flush()
    //utils.ErrorCheck(err)
    fmt.Printf("Done sending data\n")

    buffer = make([]byte, 512*1024)
    for {

        offset := 0
        waiting_for := 24       // wait for at least the minimum payload size

        for offset < waiting_for {
            length, err := conn.Read(buffer[offset:])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, buffer)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }

        //magic := binary.BigEndian.Uint32(buffer)
        command := binary.BigEndian.Uint32(buffer[4:8])
        handle := binary.BigEndian.Uint64(buffer[8:16])
        from := binary.BigEndian.Uint64(buffer[16:24])
        length := binary.BigEndian.Uint64(buffer[16:24])

        switch command {
        case utils.NBD_COMMAND_READ:
            fmt.Printf("We have a request to read handle: %v, from: %v, length: %v\n", handle, from, length)
            continue
        case utils.NBD_COMMAND_WRITE:
            fmt.Printf("We have a request to write handle: %v, from: %v, length: %v\n", handle, from, length)
            continue
        case utils.NBD_COMMAND_DISCONNECT:
            fmt.Printf("We have received a request to disconnect\n")
            // close the file and return
            return
        }
    }

    //
    //
    //// Fetch the data until we get the initial options
    //data := make([]byte, 1024)
    //offset := 0
    //waiting_for := 16       // wait for at least the minimum payload size
    //
    //for offset < waiting_for {
    //    length, err := conn.Read(data[offset:])
    //    offset += length
    //    utils.ErrorCheck(err)
    //    utils.LogData("Reading instruction", offset, data)
    //    if offset < waiting_for {
    //        time.Sleep(5 * time.Millisecond)
    //    }
    //}
    //
    //// Skip the first 8 characters (options)
    //command := binary.BigEndian.Uint32(data[12:])
    //payload_size := int(binary.BigEndian.Uint32(data[16:]))
    //
    //
    //    syscall.Read(nbd.socket, buf[0:28])
    //
		//x.magic = binary.BigEndian.Uint32(buf)
		//x.typus = binary.BigEndian.Uint32(buf[4:8])
		//x.handle = binary.BigEndian.Uint64(buf[8:16])
		//x.from = binary.BigEndian.Uint64(buf[16:24])
		//x.len = binary.BigEndian.Uint32(buf[24:28])
    //
    //
    //
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Fetch the data until we get the initial options
    //time.Sleep(300 * time.Millisecond)
    //
    //fmt.Printf("about to read\n")
    //for ; ;  {
    //    var zero_time time.Time
    //    conn.SetReadDeadline(zero_time)
    //    short_data := make([]byte, 1)
    //    conn.Read(short_data)
    //    fmt.Printf("read byte: %v\n", short_data)
    //    time.Sleep(300 * time.Millisecond)
    //
    //}
    //
    //
    ////conn2, err = listener.Accept()
    ////utils.ErrorCheck(err)
    //
    //data = make([]byte, 1024)
    //offset = 0
    //waiting_for := 16       // wait for at least the minimum payload size
    //
    //for offset < waiting_for {
    //    fmt.Printf("1: offset: %d, data: %v\n", offset, data)
    //    length, err := conn.Read(data[offset:])
    //    offset += length
    //    fmt.Printf("3: offset: %d, err: %v, data: %v\n", offset, err, data)
    //    //utils.ErrorCheck(err)
    //    fmt.Printf("4: offset: %d, data: %v\n", offset, data)
    //    utils.LogData("Reading instruction", offset, data)
    //    fmt.Printf("5: offset: %d, data: %v\n", offset, data)
    //    if offset < waiting_for {
    //    fmt.Printf("6: offset: %d, data: %v\n", offset, data)
    //        time.Sleep(1000 * time.Millisecond)
    //    }
    //}
    fmt.Printf("done reading\n")
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function

}

func send_export_list(output *bufio.Writer) {
    export_name_list := []string{"happy_export", "very_happy_export", "third_export"}

    for index := range export_name_list {
        send_export_list_item(output, export_name_list[index])
    }

    send_ack(output)
}

func send_message(output *bufio.Writer, reply_type uint32, length uint32, data []byte ) {
    endian := binary.BigEndian
    buffer := make([]byte, 1024)
    offset := 0

    endian.PutUint64(buffer[offset:], utils.NBD_SERVER_SEND_REPLY_MAGIC)
    offset += 8

    endian.PutUint32(buffer[offset:], uint32(3))  // Flags (3 = supports list)
    offset += 4

    endian.PutUint32(buffer[offset:], reply_type)  // reply_type: NBD_REP_SERVER
    offset += 4

    endian.PutUint32(buffer[offset:], length)  // length of package
    offset += 4

    if data != nil {
        copy(buffer[offset:], data[0:length])
        offset += int(length)
    }

    data_to_send := buffer[:offset]
    output.Write(data_to_send)
    output.Flush()

    utils.LogData("Just sent:", offset, data_to_send)
}

func main() {
    listener, err := net.Listen("tcp", "192.168.214.1:8000")
    utils.ErrorCheck(err)

    fmt.Printf("Hello World, we have %v\n", listener)
    reply_magic := make([]byte, 4)
    binary.BigEndian.PutUint32(reply_magic, utils.NBD_REPLY_MAGIC)

    for {
        conn, err := listener.Accept()
        utils.ErrorCheck(err)

        fmt.Printf("We have a new connection from: %s\n", conn.RemoteAddr())
        output := bufio.NewWriter(conn)

        output.WriteString("NBDMAGIC")      // init password
        output.Flush()
        output.WriteString("IHAVEOPT")      // Magic
        output.Flush()
        output.Write([]byte{0, 3})          // Flags (3 = supports list)
        output.Flush()

        // Fetch the data until we get the initial options
        data := make([]byte, 1024)
        offset := 0
        waiting_for := 16       // wait for at least the minimum payload size

        for offset < waiting_for {
            length, err := conn.Read(data[offset:])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, data)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }

        // Skip the first 8 characters (options)
        command := binary.BigEndian.Uint32(data[12:])
        payload_size := int(binary.BigEndian.Uint32(data[16:]))

        fmt.Sprintf("command is: %d\npayload_size is: %d\n", command, payload_size)
        waiting_for += int(payload_size)
        for offset < waiting_for {
            length, err := conn.Read(data[offset:])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, data)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }
        payload := make([]byte, payload_size)

        if payload_size > 0{
            copy(payload, data[20:])
        }

        utils.LogData("Payload is:", payload_size, payload)
        fmt.Printf("command is: %v\n", command)

        // At this point, we have the command, payload size, and payload.
        switch command {
        case utils.NBD_COMMAND_LIST:
            send_export_list(output)
            conn.Close()
            break
        case utils.NBD_COMMAND_EXPORT_NAME:
            go export_name(output, conn, payload_size, payload)
            break
        }
    }

}
<commit_msg>adding file name support. adding debug statements. fixing file offset code.<commit_after>// Copyright 2016 Jacob Taylor jacob.taylor@gmail.com
// License: Apache2
package main

import (
    "fmt"
    "net"
    "./utils"
    "bufio"
    "encoding/binary"
    "time"
    "os"
    "bytes"
)

func send_export_list_item(output *bufio.Writer, export_name string) {
    data := make([]byte, 1024)
    length := len(export_name)
    offset := 0

    // length of export name
    binary.BigEndian.PutUint32(data[offset:], uint32(length))  // length of string
    offset += 4

    // export name
    copy(data[offset:], export_name)
    offset += length

    reply_type := uint32(2)     // reply_type: NBD_REP_SERVER
    send_message(output, reply_type, uint32(offset), data)
}

func send_ack(output *bufio.Writer) {
    send_message(output, utils.NBD_COMMAND_ACK, 0, nil)
}

func export_name(output *bufio.Writer, conn net.Conn, payload_size int, payload []byte) {
    fmt.Printf("have request to bind to: %s\n", string(payload[:payload_size]))

    defer conn.Close()

    var filename bytes.Buffer
    filename.WriteString("/Users/jacob/work/nbd/sample_disks/")
    filename.WriteString(string(payload[:payload_size]))
    fmt.Println("Opening file: %s", filename.String())

    // attempt to open the file read only
    file, err := os.Open(filename.String())
    utils.ErrorCheck(err)
    //defer file.Close()

    data := make([]byte, 1024)
    count, err := file.Read(data)
    utils.ErrorCheck(err)

    if count > 100 {
        count = 100
    }

    // send export information
    // size u64
    // flags u16
    // Zeros (124 bytes)?
    buffer := make([]byte, 256)
    offset := 0

    binary.BigEndian.PutUint64(buffer[offset:], 52428800)  // size
    offset += 8

    binary.BigEndian.PutUint16(buffer[offset:], 0)  // flags
    offset += 2

    //offset += 124       // zero pad

    len, err := output.Write(buffer[:offset])
    output.Flush()
    utils.ErrorCheck(err)
    fmt.Printf("Wrote %d chars: %v\n", len, buffer[:offset])

    fmt.Printf("File descriptor:\n%+v\n", *file)
    fmt.Printf("First 100 bytes: \n%v\n", data[:count])

    // send a reply with the handle
    //S: 32 bits, 0x67446698, magic (NBD_REPLY_MAGIC)
    //S: 32 bits, error (MAY be zero)
    //S: 64 bits, handle
    //S: (length bytes of data if the request is of type NBD_CMD_READ)
    //offset = 0
    //binary.BigEndian.PutUint32(buffer[offset:], utils.NBD_REPLY_MAGIC)
    //offset += 4
    //
    //binary.BigEndian.PutUint32(buffer[offset:], 0) // error
    //offset += 4
    //
    //binary.BigEndian.PutUint64(buffer[offset:], 8000) // handle
    //offset += 8
    //
    //fmt.Printf("Writing out data: %v\n", buffer[:offset])
    //len, err = output.Write(buffer[:offset])
    //output.Flush()
    //utils.ErrorCheck(err)
    fmt.Printf("Done sending data\n")

    buffer = make([]byte, 512*1024)
    file_position := uint64(0)
    conn_reader := bufio.NewReader(conn)
    for {

        offset := 0
        waiting_for := 28       // wait for at least the minimum payload size

        for offset < waiting_for {
            length, err := conn_reader.Read(buffer[offset:waiting_for])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, buffer)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }

        //magic := binary.BigEndian.Uint32(buffer)
        command := binary.BigEndian.Uint32(buffer[4:8])
        handle := binary.BigEndian.Uint64(buffer[8:16])
        from := binary.BigEndian.Uint64(buffer[16:24])
        length := binary.BigEndian.Uint32(buffer[24:28])

        switch command {
        case utils.NBD_COMMAND_READ:
            fmt.Printf("We have a request to read handle: %v, from: %v, length: %v, file_position: %v\n", handle, from, length, file_position)
            if file_position != from {
                fmt.Printf("Seeking to %v\n", int64(from))
                file.Seek(int64(from), 0)     // seek to the requested position relative to the start of the file
                file_position = from
            }
            len, err = file.Read(buffer[28:28+length])
            file_position += uint64(length)
            fmt.Printf("new file position is: %v\n", file_position)
            utils.ErrorCheck(err)

            binary.BigEndian.PutUint32(buffer[:4], utils.NBD_REPLY_MAGIC)
            binary.BigEndian.PutUint32(buffer[4:8], 0)                      // error bits

            utils.LogData("About to reply with", int(28+length), buffer)
            conn.Write(buffer[:28+length])

            continue
        case utils.NBD_COMMAND_WRITE:
            fmt.Printf("We have a request to write handle: %v, from: %v, length: %v\n", handle, from, length)
            continue
        case utils.NBD_COMMAND_DISCONNECT:
            fmt.Printf("We have received a request to disconnect\n")
            // close the file and return
            return
        }
    }

    //
    //
    //// Fetch the data until we get the initial options
    //data := make([]byte, 1024)
    //offset := 0
    //waiting_for := 16       // wait for at least the minimum payload size
    //
    //for offset < waiting_for {
    //    length, err := conn.Read(data[offset:])
    //    offset += length
    //    utils.ErrorCheck(err)
    //    utils.LogData("Reading instruction", offset, data)
    //    if offset < waiting_for {
    //        time.Sleep(5 * time.Millisecond)
    //    }
    //}
    //
    //// Skip the first 8 characters (options)
    //command := binary.BigEndian.Uint32(data[12:])
    //payload_size := int(binary.BigEndian.Uint32(data[16:]))
    //
    //
    //    syscall.Read(nbd.socket, buf[0:28])
    //
		//x.magic = binary.BigEndian.Uint32(buf)
		//x.typus = binary.BigEndian.Uint32(buf[4:8])
		//x.handle = binary.BigEndian.Uint64(buf[8:16])
		//x.from = binary.BigEndian.Uint64(buf[16:24])
		//x.len = binary.BigEndian.Uint32(buf[24:28])
    //
    //
    //
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Duplicated code. move this to helper function
    //// Fetch the data until we get the initial options
    //time.Sleep(300 * time.Millisecond)
    //
    //fmt.Printf("about to read\n")
    //for ; ;  {
    //    var zero_time time.Time
    //    conn.SetReadDeadline(zero_time)
    //    short_data := make([]byte, 1)
    //    conn.Read(short_data)
    //    fmt.Printf("read byte: %v\n", short_data)
    //    time.Sleep(300 * time.Millisecond)
    //
    //}
    //
    //
    ////conn2, err = listener.Accept()
    ////utils.ErrorCheck(err)
    //
    //data = make([]byte, 1024)
    //offset = 0
    //waiting_for := 16       // wait for at least the minimum payload size
    //
    //for offset < waiting_for {
    //    fmt.Printf("1: offset: %d, data: %v\n", offset, data)
    //    length, err := conn.Read(data[offset:])
    //    offset += length
    //    fmt.Printf("3: offset: %d, err: %v, data: %v\n", offset, err, data)
    //    //utils.ErrorCheck(err)
    //    fmt.Printf("4: offset: %d, data: %v\n", offset, data)
    //    utils.LogData("Reading instruction", offset, data)
    //    fmt.Printf("5: offset: %d, data: %v\n", offset, data)
    //    if offset < waiting_for {
    //    fmt.Printf("6: offset: %d, data: %v\n", offset, data)
    //        time.Sleep(1000 * time.Millisecond)
    //    }
    //}
    fmt.Printf("done reading\n")
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function
    // Duplicated code. move this to helper function

}

func send_export_list(output *bufio.Writer) {
    export_name_list := []string{"happy_export", "very_happy_export", "third_export"}

    for index := range export_name_list {
        send_export_list_item(output, export_name_list[index])
    }

    send_ack(output)
}

func send_message(output *bufio.Writer, reply_type uint32, length uint32, data []byte ) {
    endian := binary.BigEndian
    buffer := make([]byte, 1024)
    offset := 0

    endian.PutUint64(buffer[offset:], utils.NBD_SERVER_SEND_REPLY_MAGIC)
    offset += 8

    endian.PutUint32(buffer[offset:], uint32(3))  // Flags (3 = supports list)
    offset += 4

    endian.PutUint32(buffer[offset:], reply_type)  // reply_type: NBD_REP_SERVER
    offset += 4

    endian.PutUint32(buffer[offset:], length)  // length of package
    offset += 4

    if data != nil {
        copy(buffer[offset:], data[0:length])
        offset += int(length)
    }

    data_to_send := buffer[:offset]
    output.Write(data_to_send)
    output.Flush()

    utils.LogData("Just sent:", offset, data_to_send)
}

func main() {
    listener, err := net.Listen("tcp", "192.168.214.1:8000")
    utils.ErrorCheck(err)

    fmt.Printf("Hello World, we have %v\n", listener)
    reply_magic := make([]byte, 4)
    binary.BigEndian.PutUint32(reply_magic, utils.NBD_REPLY_MAGIC)

    for {
        conn, err := listener.Accept()
        utils.ErrorCheck(err)

        fmt.Printf("We have a new connection from: %s\n", conn.RemoteAddr())
        output := bufio.NewWriter(conn)

        output.WriteString("NBDMAGIC")      // init password
        output.Flush()
        output.WriteString("IHAVEOPT")      // Magic
        output.Flush()
        output.Write([]byte{0, 3})          // Flags (3 = supports list)
        output.Flush()

        // Fetch the data until we get the initial options
        data := make([]byte, 1024)
        offset := 0
        waiting_for := 16       // wait for at least the minimum payload size

        for offset < waiting_for {
            length, err := conn.Read(data[offset:])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, data)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }

        // Skip the first 8 characters (options)
        command := binary.BigEndian.Uint32(data[12:])
        payload_size := int(binary.BigEndian.Uint32(data[16:]))

        fmt.Sprintf("command is: %d\npayload_size is: %d\n", command, payload_size)
        waiting_for += int(payload_size)
        for offset < waiting_for {
            length, err := conn.Read(data[offset:])
            offset += length
            utils.ErrorCheck(err)
            utils.LogData("Reading instruction", offset, data)
            if offset < waiting_for {
                time.Sleep(5 * time.Millisecond)
            }
        }
        payload := make([]byte, payload_size)

        if payload_size > 0{
            copy(payload, data[20:])
        }

        utils.LogData("Payload is:", payload_size, payload)
        fmt.Printf("command is: %v\n", command)

        // At this point, we have the command, payload size, and payload.
        switch command {
        case utils.NBD_COMMAND_LIST:
            send_export_list(output)
            conn.Close()
            break
        case utils.NBD_COMMAND_EXPORT_NAME:
            go export_name(output, conn, payload_size, payload)
            break
        }
    }

}
<|endoftext|>


<commit_before>package main

import (
    "io"
    "os"
    "log"
    "net/http"
    "html/template"
    "github.com/gorilla/mux"
    "github.com/mitchellh/go-homedir"

)

type FList struct {
    Files []os.FileInfo
}

func Run(){

    r := mux.NewRouter()

    r.HandleFunc("/", DefaultHandler).Methods("GET")
    r.HandleFunc("/", PathHandler).Methods("POST")

    http.Handle("/", r)
    http.ListenAndServe(":8080", nil)
}

func DefaultHandler(res http.ResponseWriter, req *http.Request){
    path, err := homedir.Dir()
    checkErr(err)

    dir, err := os.Open(path)
    checkErr(err)

    fi, err := dir.Readdir(100)
    checkErr(err)

    t, err := template.ParseFiles("index.html")
    checkErr(err)

    fobj := &FList{Files: fi}

    err = t.Execute(res, fobj)
    checkErr(err)
}

func PathHandler(res http.ResponseWriter, req *http.Request){
    newpath := req.FormValue("path")
    w := io.Writer(res)
    io.WriteString(w, newpath)
}

func checkErr(err error){
    if err != nil {
        log.Fatal(err)
    }
}
    <commit_msg>Refactored filelisting.Reused from DH to PH<commit_after>package main

import (
    "os"
    "log"
    "net/http"
    "html/template"
    "github.com/gorilla/mux"
    "github.com/mitchellh/go-homedir"

)

type FList struct {
    Files []os.FileInfo
}

func Run(){

    r := mux.NewRouter()

    r.HandleFunc("/", DefaultHandler).Methods("GET")
    r.HandleFunc("/", PathHandler).Methods("POST")

    http.Handle("/", r)
    http.ListenAndServe(":8080", nil)
}

func DefaultHandler(res http.ResponseWriter, req *http.Request){
    path, err := homedir.Dir()
    log.Println(path)
    checkErr(err)

    fobj := CreateFList(path)

    t, err := template.ParseFiles("index.html")
    checkErr(err)

    err = t.Execute(res, fobj)
    checkErr(err)
}

func PathHandler(res http.ResponseWriter, req *http.Request){
    path := req.FormValue("path")
    log.Println(path)
    fobj := CreateFList(path)

    t, err := template.ParseFiles("index.html")
    checkErr(err)

    err = t.Execute(res, fobj)
    checkErr(err)
}

func checkErr(err error){
    if err != nil {
        log.Fatal(err)
    }
}

func CreateFList(path string) *FList {
    dir, err := os.Open(path)
    checkErr(err)

    fi, err := dir.Readdir(100)
    checkErr(err)

    fobj := &FList{Files: fi}

    return fobj
}

    <|endoftext|>


<commit_before>package main

// #include <stddef.h>
// extern char _binary_assets_zip_start[];
// extern char _binary_assets_zip_end[];
// int resource_size() {return _binary_assets_zip_end - _binary_assets_zip_start;}
// char* resource() {return _binary_assets_zip_start;}
// #cgo LDFLAGS: -L . -lassets
import "C"
import "unsafe"

import (
    "net/http"
    "fmt"
    "bytes"
    "io/ioutil"
    "archive/zip"
    "log"
    "github.com/gorilla/mux"
)

type cache map[string] []byte

var fileCache cache

// Pick up assets from the C library
func extractAssets() []byte {
    size := C.resource_size();
    fmt.Println(size)
    bytes := C.GoBytes(unsafe.Pointer(C.resource()), C.resource_size())
    return bytes
}

func readArchive(rawArchive []byte) cache  {
    fcache := make(map[string] []byte)

    // r, err := zip.OpenReader(archive)
    r, err := makeZipReader(rawArchive)
    if err != nil {
            log.Fatal(err)
    }
    // defer r.Close()

    for _, f := range r.File {
        log.Printf("Found file: %s", f.Name)
        rc, err := f.Open()
        if err != nil {
            log.Println("cannot open")
            log.Fatal(err)
        }
        defer rc.Close()

        // _, err = io.Copy(os.Stdout, rc)
        content, err := ioutil.ReadAll(rc)
        if err != nil {
            log.Println("cannot read file")
            log.Fatal(err)
        }
        fcache[f.Name] = content
    }
    return fcache
}

func makeZipReader(buffer []byte) (*zip.Reader, error) {
    reader := bytes.NewReader(buffer)
    r, err := zip.NewReader(reader, int64(len(buffer)))
    if err != nil {
        return nil, err
    }
    return r, nil
}

func assetHandler(writer http.ResponseWriter, request *http.Request) {
    path :=request.URL.Path[1:]
    // log.Printf("Path: %s\n", path)
    content, found := fileCache[path]
    if found {
        writer.Write(content)
    } else {
        fmt.Fprintf(writer, "Not found")
    }
}

func main() {
    rawAssets := extractAssets();

    //fileCache = readArchive("assets.zip")
    fileCache = readArchive(rawAssets);

    r := mux.NewRouter()
    r.HandleFunc("/assets/{path:.*}", assetHandler)
    http.ListenAndServe(":3000", r)
}
<commit_msg>Added Content-Type to HTTP headers<commit_after>package main

// #include <stddef.h>
// extern char _binary_assets_zip_start[];
// extern char _binary_assets_zip_end[];
// int resource_size() {return _binary_assets_zip_end - _binary_assets_zip_start;}
// char* resource() {return _binary_assets_zip_start;}
// #cgo LDFLAGS: -L . -lassets
import "C"

import (
    "net/http"
    "path/filepath"
    "fmt"
    "bytes"
    "io/ioutil"
    "archive/zip"
    "log"
    "mime"
    "unsafe"
    "github.com/gorilla/mux"
)

type cache map[string] []byte

var fileCache cache

// Pick up assets from the C library
func extractAssets() []byte {
    size := C.resource_size();
    fmt.Println(size)
    bytes := C.GoBytes(unsafe.Pointer(C.resource()), C.resource_size())
    return bytes
}

func readArchive(rawArchive []byte) cache  {
    fcache := make(cache)

    // r, err := zip.OpenReader(archive)
    r, err := makeZipReader(rawArchive)
    if err != nil {
            log.Fatal(err)
    }
    // defer r.Close()

    for _, f := range r.File {
        log.Printf("Found file: %s", f.Name)
        rc, err := f.Open()
        if err != nil {
            log.Println("cannot open")
            log.Fatal(err)
        }
        defer rc.Close()

        // _, err = io.Copy(os.Stdout, rc)
        content, err := ioutil.ReadAll(rc)
        if err != nil {
            log.Println("cannot read file")
            log.Fatal(err)
        }
        fcache[f.Name] = content
    }
    return fcache
}

func makeZipReader(buffer []byte) (*zip.Reader, error) {
    reader := bytes.NewReader(buffer)
    r, err := zip.NewReader(reader, int64(len(buffer)))
    if err != nil {
        return nil, err
    }
    return r, nil
}

func assetHandler(writer http.ResponseWriter, request *http.Request) {
    path :=request.URL.Path[1:]
    // log.Printf("Path: %s\n", path)
    content, found := fileCache[path]
    ext := filepath.Ext(path)
    mime := mime.TypeByExtension(ext)
    writer.Header().Set("Content-Type", mime)
    if found {
        writer.Write(content)
    } else {
        fmt.Fprintf(writer, "Not found")
    }
}

func main() {
    rawAssets := extractAssets();

    //fileCache = readArchive("assets.zip")
    fileCache = readArchive(rawAssets);

    r := mux.NewRouter()
    r.HandleFunc("/assets/{path:.*}", assetHandler)
    http.ListenAndServe(":3000", r)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"net/url"
	"time"

	"github.com/jangie/goloadbalancers/bestof"
	"github.com/jangie/goloadbalancers/jsq"
	"github.com/jangie/goloadbalancers/random"
	"github.com/jangie/goloadbalancers/util"
	"github.com/vulcand/oxy/forward"
	"github.com/vulcand/oxy/roundrobin"
)

//Test harness
type testHarness struct {
	next http.Handler
	port int
}

func (t *testHarness) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "/" {
		fmt.Fprintf(w, "This is a dumb server which is meant to be used with the node file testServer.js.\n - Run the node server (which will hold onto :8080)\n - Add pointers into your hosts file for 127.0.0.1 testa, testb, testc\n - Hit localhost:%d/simulateServers, and see which server you get balanced to", t.port)
	} else {
		t.next.ServeHTTP(w, req)
	}
}

func getBestOfHarness(balancees []string, fwd http.Handler) *testHarness {
	var bal = bestof.NewChoiceOfBalancer(
		balancees,
		bestof.ChoiceOfBalancerOptions{
			Choices:         2,
			RandomGenerator: util.GoRandom{},
		},
		fwd,
	)
	var tbestof = testHarness{
		next: bal,
		port: 8090,
	}
	return &tbestof
}

func getRandomHarness(balancees []string, fwd http.Handler) *testHarness {
	var random = random.NewRandomBalancer(balancees,
		random.RandomBalancerOptions{
			RandomGenerator: util.GoRandom{},
		},
		fwd,
	)
	var trandom = testHarness{
		next: random,
		port: 8091,
	}
	return &trandom
}

func getRoundRobinHarness(balancees []string, fwd http.Handler) *testHarness {
	var rr, _ = roundrobin.New(fwd)
	var trr = testHarness{
		next: rr,
		port: 8095,
	}
	for _, u := range balancees {
		var purl, _ = url.Parse(u)
		rr.UpsertServer(purl)
	}
	return &trr
}

func getDynamicRoundRobinHarness(balancees []string, fwd http.Handler) *testHarness {
	var rr, _ = roundrobin.New(fwd)
	rebalancer, _ := roundrobin.NewRebalancer(rr)
	for _, u := range balancees {
		var purl, _ = url.Parse(u)
		rr.UpsertServer(purl, roundrobin.Weight(5))
	}
	var tdrr = testHarness{
		next: rebalancer,
		port: 8096,
	}
	return &tdrr
}

func getJSQHarness(balancees []string, fwd http.Handler) *testHarness {
	var jsq = jsq.NewJoinShortestQueueBalancer(balancees,
		jsq.JoinShortestQueueBalancerOptions{},
		fwd,
	)
	var tjsq = testHarness{
		next: jsq,
		port: 8092,
	}
	return &tjsq
}

func main() {
	var fwd, _ = forward.New()
	var balancees = []string{"http://testa:8080", "http://testb:8080", "http://testc:8080"}

	go http.ListenAndServe(":8090", getBestOfHarness(balancees, fwd))
	go http.ListenAndServe(":8091", getRandomHarness(balancees, fwd))
	go http.ListenAndServe(":8092", getJSQHarness(balancees, fwd))

	go http.ListenAndServe(":8095", getRoundRobinHarness(balancees, fwd))
	go http.ListenAndServe(":8096", getDynamicRoundRobinHarness(balancees, fwd))
	fmt.Print("Listening on:\n - http://localhost:8090 [bestof lb]\n - http://localhost:8091 [random lb]\n - http://localhost:8092 [jsq lb]\n - http://localhost:8095 [vulcand/oxy (external) roundrobin]\n - http://localhost:8096 [vulcand/oxy (external) dynamic roundrobin]\n")
	for true == true {
		time.Sleep(1000)
	}
}
<commit_msg>ha. sleep not a great thing to use. will have to determine a better thing.<commit_after>package main

import (
	"fmt"
	"net/http"
	"net/url"

	"github.com/jangie/goloadbalancers/bestof"
	"github.com/jangie/goloadbalancers/jsq"
	"github.com/jangie/goloadbalancers/random"
	"github.com/jangie/goloadbalancers/util"
	"github.com/vulcand/oxy/forward"
	"github.com/vulcand/oxy/roundrobin"
)

//Test harness
type testHarness struct {
	next http.Handler
	port int
}

func (t *testHarness) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "/" {
		fmt.Fprintf(w, "This is a dumb server which is meant to be used with the node file testServer.js.\n - Run the node server (which will hold onto :8080)\n - Add pointers into your hosts file for 127.0.0.1 testa, testb, testc\n - Hit localhost:%d/simulateServers, and see which server you get balanced to", t.port)
	} else {
		t.next.ServeHTTP(w, req)
	}
}

func getBestOfHarness(balancees []string, fwd http.Handler) *testHarness {
	var bal = bestof.NewChoiceOfBalancer(
		balancees,
		bestof.ChoiceOfBalancerOptions{
			Choices:         2,
			RandomGenerator: util.GoRandom{},
		},
		fwd,
	)
	var tbestof = testHarness{
		next: bal,
		port: 8090,
	}
	return &tbestof
}

func getRandomHarness(balancees []string, fwd http.Handler) *testHarness {
	var random = random.NewRandomBalancer(balancees,
		random.RandomBalancerOptions{
			RandomGenerator: util.GoRandom{},
		},
		fwd,
	)
	var trandom = testHarness{
		next: random,
		port: 8091,
	}
	return &trandom
}

func getRoundRobinHarness(balancees []string, fwd http.Handler) *testHarness {
	var rr, _ = roundrobin.New(fwd)
	var trr = testHarness{
		next: rr,
		port: 8095,
	}
	for _, u := range balancees {
		var purl, _ = url.Parse(u)
		rr.UpsertServer(purl)
	}
	return &trr
}

func getDynamicRoundRobinHarness(balancees []string, fwd http.Handler) *testHarness {
	var rr, _ = roundrobin.New(fwd)
	rebalancer, _ := roundrobin.NewRebalancer(rr)
	for _, u := range balancees {
		var purl, _ = url.Parse(u)
		rr.UpsertServer(purl, roundrobin.Weight(5))
	}
	var tdrr = testHarness{
		next: rebalancer,
		port: 8096,
	}
	return &tdrr
}

func getJSQHarness(balancees []string, fwd http.Handler) *testHarness {
	var jsq = jsq.NewJoinShortestQueueBalancer(balancees,
		jsq.JoinShortestQueueBalancerOptions{},
		fwd,
	)
	var tjsq = testHarness{
		next: jsq,
		port: 8092,
	}
	return &tjsq
}

func main() {
	var fwd, _ = forward.New()
	var balancees = []string{"http://testa:8080", "http://testb:8080", "http://testc:8080"}

	go http.ListenAndServe(":8090", getBestOfHarness(balancees, fwd))
	go http.ListenAndServe(":8091", getRandomHarness(balancees, fwd))
	go http.ListenAndServe(":8092", getJSQHarness(balancees, fwd))

	go http.ListenAndServe(":8095", getRoundRobinHarness(balancees, fwd))
	fmt.Print("Listening on:\n - http://localhost:8090 [bestof lb]\n - http://localhost:8091 [random lb]\n - http://localhost:8092 [jsq lb]\n - http://localhost:8095 [vulcand/oxy (external) roundrobin]\n - http://localhost:8096 [vulcand/oxy (external) dynamic roundrobin]\n")
	http.ListenAndServe(":8096", getDynamicRoundRobinHarness(balancees, fwd))

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"path/filepath"
	"time"

	"github.com/PuerkitoBio/ghost/handlers"
)

var (
	// Favicon path and cache duration
	faviconPath  = filepath.Join(PublicDir, "favicon.ico")
	faviconCache = 2 * 24 * time.Hour
)

// Start serving the blog.
func run() {
	h := handlers.FaviconHandler(
		handlers.PanicHandler(
			handlers.LogHandler(
				handlers.GZIPHandler(
					http.FileServer(http.Dir(PublicDir)),
					nil),
				handlers.NewLogOptions(nil, handlers.Lshort)),
			nil),
		faviconPath,
		faviconCache)

	// Assign the combined handler to the server.
	http.Handle("/", h)

	// Start it up.
	log.Printf("trofaf server listening on port %d", Options.Port)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", Options.Port), nil); err != nil {
		log.Fatal("FATAL ", err)
	}
}
<commit_msg>use default log format instead of short<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"path/filepath"
	"time"

	"github.com/PuerkitoBio/ghost/handlers"
)

var (
	// Favicon path and cache duration
	faviconPath  = filepath.Join(PublicDir, "favicon.ico")
	faviconCache = 2 * 24 * time.Hour
)

// Start serving the blog.
func run() {
	h := handlers.FaviconHandler(
		handlers.PanicHandler(
			handlers.LogHandler(
				handlers.GZIPHandler(
					http.FileServer(http.Dir(PublicDir)),
					nil),
				handlers.NewLogOptions(nil, handlers.Ldefault)),
			nil),
		faviconPath,
		faviconCache)

	// Assign the combined handler to the server.
	http.Handle("/", h)

	// Start it up.
	log.Printf("trofaf server listening on port %d", Options.Port)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", Options.Port), nil); err != nil {
		log.Fatal("FATAL ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/wjessop/go-piglow"

	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

// from go-piglow
var colorToLEDs = map[string][3]int8{
	"white":  [3]int8{12, 9, 10},
	"blue":   [3]int8{14, 4, 11},
	"green":  [3]int8{3, 5, 13},
	"yellow": [3]int8{2, 8, 15},
	"orange": [3]int8{1, 7, 16},
	"red":    [3]int8{0, 6, 17},
}

var colorOrder = [6]string{
	"white",
	"blue",
	"green",
	"yellow",
	"orange",
	"red",
}

var animations = map[string]func(*Blinky){
	"shimmer: turn random LEDs to random brightnesses":       func(b *Blinky) { shimmer(b) },
	"pulse: pulse all LEDs up and down":                      func(b *Blinky) { pulse(b) },
	"bounce: bounce a single LED up and down all arms":       func(b *Blinky) { bounce(b, false) },
	"bounce2: bounce a single LED each arm in turn":          func(b *Blinky) { bounce(b, true) },
	"cycle: turn all LEDs on and then off in bands":          func(b *Blinky) { cycle(b) },
	"arms: light each arm in turn and then turn of each arm": func(b *Blinky) { arms(b, false) },
	"arms2: light each arm in turn by itself":                func(b *Blinky) { arms(b, true) },
}

var animationsColor = map[string]func(*Blinky, string){
	"<color>spin: spin through the LEDs of the specified color":  func(b *Blinky, color string) { spin(b, color, false) },
	"<color>spin2: spin through the LEDs of the specified color": func(b *Blinky, color string) { spin(b, color, true) },
	"<color>: turn the specified color LED on":                   func(b *Blinky, color string) { solid(b, color) },
}

type Blinky struct {
	p    *piglow.Piglow
	quit chan bool
	done chan bool
}

func main() {
	var commandChan = make(chan string)

	// start up command dispatcher
	go dispatcher(commandChan)

	var webqueue string
	if webqueue = os.Getenv("WEBQUEUE"); len(webqueue) > 0 {
		log.Println("WEBQUEUE env variable found, polling", webqueue)
		for {
			res, err := http.Get(webqueue)
			if err != nil {
				log.Fatalln("Error:", err)
			}

			body, err := ioutil.ReadAll(res.Body)
			res.Body.Close()
			if err != nil {
				log.Fatal(err)
			}

			if res.StatusCode == 200 {
				// send command over to dispatcher
				commandChan <- strings.TrimSpace(string(body))
			}
		}
	} else {
		var animation = flag.String("a", "cycle", "specify an animation to run (default: cycle)")
		var list = flag.Bool("l", false, "list available animations")
		flag.Parse()

		if *list {
			fmt.Println("\nAvailable animations:")
			for desc, _ := range animations {
				fmt.Println("  ", desc)
			}
			for desc, _ := range animationsColor {
				fmt.Println("  ", desc)
			}

			fmt.Println("\nAvailable colors:")
			for _, color := range colorOrder {
				fmt.Println("  ", color)
			}

			fmt.Println("")
		} else {
			commandChan <- *animation

			var sleepForever = make(chan int)
			<-sleepForever
		}
	}

}

func dispatcher(in chan string) {
	var p *piglow.Piglow
	var err error

	var quit = make(chan bool)
	var done = make(chan bool)
	var running = false

	// Create a new Piglow
	p, err = piglow.NewPiglow()
	if err != nil {
		log.Fatal("Couldn't create a Piglow: ", err)
	}

	var blinky = &Blinky{p, quit, done}

	// clear the LEDs
	p.SetAll(0)
	err = p.Apply()
	if err != nil { // Apply the changes
		log.Fatal("Couldn't apply changes: ", err)
	}

	for {
		command := <-in

		log.Println("Starting animation:", command)

		// if animation is already running, stop it
		// and wait for it to finish
		if running {
			quit <- true
			<-done
		}

		// clear all LEDs
		p.SetAll(0)
		err = p.Apply()

		running = false

		if !running {
		ANIM:
			for key, value := range animations {
				if strings.HasPrefix(key, command+":") {
					running = true
					go value(blinky)
					break ANIM
				}
			}
		}

		if !running {
		ANIMCOLOR:
			for key, value := range animationsColor {
				if strings.Contains(key, "<color>") {
					for _, color := range colorOrder {
						if strings.HasPrefix(key, strings.Replace(command, color, "<color>", -1)+":") {
							running = true
							go value(blinky, color)
							break ANIMCOLOR
						}
					}
				}
			}
		}

		if !running {
			log.Println("Can't understand animation", command)
		}
	}
}

// animate each arm on and then each arm off
func arms(blinky *Blinky, reset bool) {

	var tentacle = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if tentacle == 3 {
			tentacle = 0

			if !reset {
				if value == 4 {
					value = 0
				} else {
					value = 4
				}
			}
		}

		if reset {
			p.SetAll(0)
			p.Apply()
		}
		p.SetTentacle(tentacle, uint8(value))
		p.Apply()

		// next tentacle
		tentacle += 1
	})
}

// spin through a particular color
func spin(blinky *Blinky, color string, reset bool) {

	leds := colorToLEDs[color]
	var index = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if index == 3 {
			index = 0

			if !reset {
				if value == 4 {
					value = 0
				} else {
					value = 4
				}
			}
		}

		if reset {
			p.SetAll(0)
			p.Apply()
		}
		p.SetLED(int8(leds[index]), uint8(value))
		p.Apply()

		// next index
		index += 1
	})
}

// cycle leds from the center
func cycle(blinky *Blinky) {

	var index = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if index == len(colorOrder) {
			index = 0

			if value == 4 {
				value = 0
			} else {
				value = 4
			}
		}

		for _, led := range colorToLEDs[colorOrder[index]] {
			p.SetLED(led, uint8(value))
		}
		p.Apply()

		// next index
		index += 1
	})
}

// pulse all LEDs
func pulse(blinky *Blinky) {

	var step = 2
	var max = 30
	var value = 2
	var brighten = true

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {

		if value == max {
			brighten = false
		}
		if value == 2 {
			brighten = true
		}

		p.SetAll(uint8(value))
		p.Apply()

		if brighten {
			value += step
		} else {
			value -= step
		}
	})
}

// shimmer all LEDs
func shimmer(blinky *Blinky) {

	var min = 2
	var max = 10

	var init = func(p *piglow.Piglow) {
		p.SetAll(uint8(min))
		p.Apply()
	}

	var animate = func(p *piglow.Piglow) {
		p.SetLED(int8(rand.Intn(18)), uint8(rand.Intn(max-min)+min))
		p.Apply()
	}

	animateWithInit(blinky, time.Second/10, init, animate)
}

// bounce a single led along the arm(s)
func bounce(blinky *Blinky, singleArm bool) {

	var index = 0
	var value = 4
	var arm = 0
	var outward = true

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {

		if index == (len(colorOrder) - 1) {
			outward = false
		}
		if index == 0 {
			outward = true

			// advance arm if in single arm mode
			if singleArm {
				arm += 1
				if arm == 3 {
					arm = 0
				}
			}
		}

		p.SetAll(0)
		p.Apply()
		for i, led := range colorToLEDs[colorOrder[index]] {
			if !singleArm || arm == i {
				p.SetLED(led, uint8(value))
			}
		}
		p.Apply()

		// next index
		if outward {
			index += 1
		} else {
			index -= 1
		}
	})
}

// This function handles the common case of a simple animation with no cleanup
func animate(blinky *Blinky, timeout time.Duration, callback func(*piglow.Piglow)) {
	for {
		select {
		case <-blinky.quit:
			blinky.done <- true
			return
		default:
			callback(blinky.p)
			time.Sleep(timeout)
		}
	}
}

// animateWithInit is for animations that need initialization
func animateWithInit(blinky *Blinky, timeout time.Duration, init func(*piglow.Piglow), animation func(*piglow.Piglow)) {

	init(blinky.p)

	animate(blinky, timeout, animation)
}

// turn on all LEDs of a certain color
func solid(blinky *Blinky, color string) {

	var init = func(p *piglow.Piglow) {
		switch color {
		case "green":
			p.SetGreen(8)
		case "blue":
			p.SetBlue(8)
		case "white":
			p.SetWhite(8)
		case "yellow":
			p.SetYellow(8)
		case "orange":
			p.SetOrange(8)
		case "red":
			p.SetRed(8)
		case "clear":
		case "all":
			p.SetAll(8)
		default:
			p.SetLED(int8(len(color)%17), 8)
		}
		p.Apply()
	}

	// wait for the end, aka no animation
	animateWithInit(blinky, time.Second/10, init, func(p *piglow.Piglow) {})
}
<commit_msg>faster timeout for shimmer<commit_after>package main

import (
	"github.com/wjessop/go-piglow"

	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

// from go-piglow
var colorToLEDs = map[string][3]int8{
	"white":  [3]int8{12, 9, 10},
	"blue":   [3]int8{14, 4, 11},
	"green":  [3]int8{3, 5, 13},
	"yellow": [3]int8{2, 8, 15},
	"orange": [3]int8{1, 7, 16},
	"red":    [3]int8{0, 6, 17},
}

var colorOrder = [6]string{
	"white",
	"blue",
	"green",
	"yellow",
	"orange",
	"red",
}

var animations = map[string]func(*Blinky){
	"shimmer: turn random LEDs to random brightnesses":       func(b *Blinky) { shimmer(b) },
	"pulse: pulse all LEDs up and down":                      func(b *Blinky) { pulse(b) },
	"bounce: bounce a single LED up and down all arms":       func(b *Blinky) { bounce(b, false) },
	"bounce2: bounce a single LED each arm in turn":          func(b *Blinky) { bounce(b, true) },
	"cycle: turn all LEDs on and then off in bands":          func(b *Blinky) { cycle(b) },
	"arms: light each arm in turn and then turn of each arm": func(b *Blinky) { arms(b, false) },
	"arms2: light each arm in turn by itself":                func(b *Blinky) { arms(b, true) },
}

var animationsColor = map[string]func(*Blinky, string){
	"<color>spin: spin through the LEDs of the specified color":  func(b *Blinky, color string) { spin(b, color, false) },
	"<color>spin2: spin through the LEDs of the specified color": func(b *Blinky, color string) { spin(b, color, true) },
	"<color>: turn the specified color LED on":                   func(b *Blinky, color string) { solid(b, color) },
}

type Blinky struct {
	p    *piglow.Piglow
	quit chan bool
	done chan bool
}

func main() {
	var commandChan = make(chan string)

	// start up command dispatcher
	go dispatcher(commandChan)

	var webqueue string
	if webqueue = os.Getenv("WEBQUEUE"); len(webqueue) > 0 {
		log.Println("WEBQUEUE env variable found, polling", webqueue)
		for {
			res, err := http.Get(webqueue)
			if err != nil {
				log.Fatalln("Error:", err)
			}

			body, err := ioutil.ReadAll(res.Body)
			res.Body.Close()
			if err != nil {
				log.Fatal(err)
			}

			if res.StatusCode == 200 {
				// send command over to dispatcher
				commandChan <- strings.TrimSpace(string(body))
			}
		}
	} else {
		var animation = flag.String("a", "cycle", "specify an animation to run (default: cycle)")
		var list = flag.Bool("l", false, "list available animations")
		flag.Parse()

		if *list {
			fmt.Println("\nAvailable animations:")
			for desc, _ := range animations {
				fmt.Println("  ", desc)
			}
			for desc, _ := range animationsColor {
				fmt.Println("  ", desc)
			}

			fmt.Println("\nAvailable colors:")
			for _, color := range colorOrder {
				fmt.Println("  ", color)
			}

			fmt.Println("")
		} else {
			commandChan <- *animation

			var sleepForever = make(chan int)
			<-sleepForever
		}
	}

}

func dispatcher(in chan string) {
	var p *piglow.Piglow
	var err error

	var quit = make(chan bool)
	var done = make(chan bool)
	var running = false

	// Create a new Piglow
	p, err = piglow.NewPiglow()
	if err != nil {
		log.Fatal("Couldn't create a Piglow: ", err)
	}

	var blinky = &Blinky{p, quit, done}

	// clear the LEDs
	p.SetAll(0)
	err = p.Apply()
	if err != nil { // Apply the changes
		log.Fatal("Couldn't apply changes: ", err)
	}

	for {
		command := <-in

		log.Println("Starting animation:", command)

		// if animation is already running, stop it
		// and wait for it to finish
		if running {
			quit <- true
			<-done
		}

		// clear all LEDs
		p.SetAll(0)
		err = p.Apply()

		running = false

		if !running {
		ANIM:
			for key, value := range animations {
				if strings.HasPrefix(key, command+":") {
					running = true
					go value(blinky)
					break ANIM
				}
			}
		}

		if !running {
		ANIMCOLOR:
			for key, value := range animationsColor {
				if strings.Contains(key, "<color>") {
					for _, color := range colorOrder {
						if strings.HasPrefix(key, strings.Replace(command, color, "<color>", -1)+":") {
							running = true
							go value(blinky, color)
							break ANIMCOLOR
						}
					}
				}
			}
		}

		if !running {
			log.Println("Can't understand animation", command)
		}
	}
}

// animate each arm on and then each arm off
func arms(blinky *Blinky, reset bool) {

	var tentacle = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if tentacle == 3 {
			tentacle = 0

			if !reset {
				if value == 4 {
					value = 0
				} else {
					value = 4
				}
			}
		}

		if reset {
			p.SetAll(0)
			p.Apply()
		}
		p.SetTentacle(tentacle, uint8(value))
		p.Apply()

		// next tentacle
		tentacle += 1
	})
}

// spin through a particular color
func spin(blinky *Blinky, color string, reset bool) {

	leds := colorToLEDs[color]
	var index = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if index == 3 {
			index = 0

			if !reset {
				if value == 4 {
					value = 0
				} else {
					value = 4
				}
			}
		}

		if reset {
			p.SetAll(0)
			p.Apply()
		}
		p.SetLED(int8(leds[index]), uint8(value))
		p.Apply()

		// next index
		index += 1
	})
}

// cycle leds from the center
func cycle(blinky *Blinky) {

	var index = 0
	var value = 4

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {
		if index == len(colorOrder) {
			index = 0

			if value == 4 {
				value = 0
			} else {
				value = 4
			}
		}

		for _, led := range colorToLEDs[colorOrder[index]] {
			p.SetLED(led, uint8(value))
		}
		p.Apply()

		// next index
		index += 1
	})
}

// pulse all LEDs
func pulse(blinky *Blinky) {

	var step = 2
	var max = 30
	var value = 2
	var brighten = true

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {

		if value == max {
			brighten = false
		}
		if value == 2 {
			brighten = true
		}

		p.SetAll(uint8(value))
		p.Apply()

		if brighten {
			value += step
		} else {
			value -= step
		}
	})
}

// shimmer all LEDs
func shimmer(blinky *Blinky) {

	var min = 2
	var max = 10

	var init = func(p *piglow.Piglow) {
		p.SetAll(uint8(min))
		p.Apply()
	}

	var animate = func(p *piglow.Piglow) {
		p.SetLED(int8(rand.Intn(18)), uint8(rand.Intn(max-min)+min))
		p.Apply()
	}

	animateWithInit(blinky, time.Second/50, init, animate)
}

// bounce a single led along the arm(s)
func bounce(blinky *Blinky, singleArm bool) {

	var index = 0
	var value = 4
	var arm = 0
	var outward = true

	animate(blinky, time.Second/10, func(p *piglow.Piglow) {

		if index == (len(colorOrder) - 1) {
			outward = false
		}
		if index == 0 {
			outward = true

			// advance arm if in single arm mode
			if singleArm {
				arm += 1
				if arm == 3 {
					arm = 0
				}
			}
		}

		p.SetAll(0)
		p.Apply()
		for i, led := range colorToLEDs[colorOrder[index]] {
			if !singleArm || arm == i {
				p.SetLED(led, uint8(value))
			}
		}
		p.Apply()

		// next index
		if outward {
			index += 1
		} else {
			index -= 1
		}
	})
}

// This function handles the common case of a simple animation with no cleanup
func animate(blinky *Blinky, timeout time.Duration, callback func(*piglow.Piglow)) {
	for {
		select {
		case <-blinky.quit:
			blinky.done <- true
			return
		default:
			callback(blinky.p)
			time.Sleep(timeout)
		}
	}
}

// animateWithInit is for animations that need initialization
func animateWithInit(blinky *Blinky, timeout time.Duration, init func(*piglow.Piglow), animation func(*piglow.Piglow)) {

	init(blinky.p)

	animate(blinky, timeout, animation)
}

// turn on all LEDs of a certain color
func solid(blinky *Blinky, color string) {

	var init = func(p *piglow.Piglow) {
		switch color {
		case "green":
			p.SetGreen(8)
		case "blue":
			p.SetBlue(8)
		case "white":
			p.SetWhite(8)
		case "yellow":
			p.SetYellow(8)
		case "orange":
			p.SetOrange(8)
		case "red":
			p.SetRed(8)
		case "clear":
		case "all":
			p.SetAll(8)
		default:
			p.SetLED(int8(len(color)%17), 8)
		}
		p.Apply()
	}

	// wait for the end, aka no animation
	animateWithInit(blinky, time.Second/10, init, func(p *piglow.Piglow) {})
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ViBiOh/dashboard/docker"
	"log"
	"net/http"
	"runtime"
)

const port = `1080`

const restPrefix = `/`
const websocketPrefix = `/ws/`
const host = `DOCKER_HOST`
const version = `DOCKER_VERSION`

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	http.Handle(websocketPrefix, http.StripPrefix(websocketPrefix, docker.WebsocketHandler{}))
	http.Handle(restPrefix, http.StripPrefix(restPrefix, docker.Handler{}))

	log.Print(`Starting server on port ` + port)
	log.Fatal(http.ListenAndServe(`:`+port, nil))
}
<commit_msg>Removing obsolete variables<commit_after>package main

import (
	"github.com/ViBiOh/dashboard/docker"
	"log"
	"net/http"
	"runtime"
)

const port = `1080`

const restPrefix = `/`
const websocketPrefix = `/ws/`

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	http.Handle(websocketPrefix, http.StripPrefix(websocketPrefix, docker.WebsocketHandler{}))
	http.Handle(restPrefix, http.StripPrefix(restPrefix, docker.Handler{}))

	log.Print(`Starting server on port ` + port)
	log.Fatal(http.ListenAndServe(`:`+port, nil))
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "github.com/orc/db"
    "database/sql"
    "github.com/orc/resources"
    "github.com/orc/router"
    "github.com/orc/mvc/controllers"
    "log"
    "net/http"
    "os"
)

var err error

func main() {
    log.Println("Server started.")

    db.DB, err = sql.Open("postgres", os.Getenv("DATABASE_URL"))
    defer db.DB.Close()

    if err != nil {
        log.Println("Error db connection: ", err.Error())
        os.Exit(1)
    }

    log.Println("DB CONNECTED")

    testData := flag.Bool("test-data", false, "to load test data")
    flag.Parse()

    new(controllers.BaseController).IndexController().Init(*testData)
    resources.LoadAdmin()
    resources.LoadParamTypes()

    if *testData == true {
        resources.Load()
    }

    // base := new(controllers.BaseController)
    // base.Index().LoadContestsFromCats()

    http.Handle("/", new(router.FastCGIServer))
    http.HandleFunc("/handler/wellcometoprofile/", controllers.WellcomeToProfile)
    http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./static/js"))))
    http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./static/css"))))
    http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("./static/img"))))

    port := os.Getenv("PORT")
    if port == "" {
        port = "5000"
    }

    if err := http.ListenAndServe(":" + port, nil); err != nil {
        log.Println("Error listening: ", err.Error())
        os.Exit(1)
    }
}
<commit_msg>server.go: fix path for method controllers.WellcomeToProfile<commit_after>package main

import (
    "flag"
    "github.com/orc/db"
    "database/sql"
    "github.com/orc/resources"
    "github.com/orc/router"
    "github.com/orc/mvc/controllers"
    "log"
    "net/http"
    "os"
)

var err error

func main() {
    log.Println("Server started.")

    db.DB, err = sql.Open("postgres", os.Getenv("DATABASE_URL"))
    defer db.DB.Close()

    if err != nil {
        log.Println("Error db connection: ", err.Error())
        os.Exit(1)
    }

    log.Println("DB CONNECTED")

    testData := flag.Bool("test-data", false, "to load test data")
    flag.Parse()

    new(controllers.BaseController).IndexController().Init(*testData)
    resources.LoadAdmin()
    resources.LoadParamTypes()

    if *testData == true {
        resources.Load()
    }

    // base := new(controllers.BaseController)
    // base.Index().LoadContestsFromCats()

    http.Handle("/", new(router.FastCGIServer))
    http.HandleFunc("/wellcometoprofile/", controllers.WellcomeToProfile)
    http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./static/js"))))
    http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./static/css"))))
    http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("./static/img"))))

    port := os.Getenv("PORT")
    if port == "" {
        port = "5000"
    }

    if err := http.ListenAndServe(":" + port, nil); err != nil {
        log.Println("Error listening: ", err.Error())
        os.Exit(1)
    }
}
<|endoftext|>


<commit_before>package main

import (
  "encoding/json"
  "fmt"
  "github.com/codegangsta/negroni"
  "github.com/gorilla/mux"
  "net/http"
)

type Hacker struct {
  Name    string
  Hobbies []string
}

func main() {
  // classic provides Recovery, Logging, Static default middleware
  n := negroni.Classic()

  router := mux.NewRouter()
  router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Hello World!")
  })

  router.HandleFunc("/json/{hacker}", hacker_handler)

  // router goes last
  n.UseHandler(router)
  n.Run(":3000")
}

// learned from: http://www.alexedwards.net/blog/golang-response-snippets#json
func hacker_handler(w http.ResponseWriter, r *http.Request) {
  vars := mux.Vars(r) // from the request
  hacker := vars["hacker"]
  my_little_json := Hacker{hacker, []string{"music", "programming"}}

  js, err := json.Marshal(my_little_json)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }

  w.Header().Set("Content-Type", "application/json")
  w.Write(js)
}
<commit_msg>could renames<commit_after>package main

import (
  "encoding/json"
  "fmt"
  "github.com/codegangsta/negroni"
  "github.com/gorilla/mux"
  "net/http"
)

type Hacker struct {
  Name    string
  Hobbies []string
}

func main() {
  // classic provides Recovery, Logging, Static default middleware
  n := negroni.Classic()

  router := mux.NewRouter()
  router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Hello World!")
  })

  // GET /hackers/chase
  router.HandleFunc("/hackers/{hacker}", hacker_handler)

  // router goes last
  n.UseHandler(router)
  n.Run(":3000")
}

// learned from: http://www.alexedwards.net/blog/golang-response-snippets#json
func hacker_handler(w http.ResponseWriter, r *http.Request) {
  vars := mux.Vars(r) // from the request
  hacker := vars["hacker"]
  my_little_json := Hacker{hacker, []string{"music", "programming"}}

  js, err := json.Marshal(my_little_json)
  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }

  w.Header().Set("Content-Type", "application/json")
  w.Write(js)
}
<|endoftext|>


<commit_before>package registry

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/Sirupsen/logrus"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/registry/api/v2"
	"github.com/docker/docker/pkg/httputils"
)

const DockerDigestHeader = "Docker-Content-Digest"

func getV2Builder(e *Endpoint) *v2.URLBuilder {
	if e.URLBuilder == nil {
		e.URLBuilder = v2.NewURLBuilder(e.URL)
	}
	return e.URLBuilder
}

func (r *Session) V2RegistryEndpoint(index *IndexInfo) (ep *Endpoint, err error) {
	// TODO check if should use Mirror
	if index.Official {
		ep, err = newEndpoint(REGISTRYSERVER, true, nil)
		if err != nil {
			return
		}
		err = validateEndpoint(ep)
		if err != nil {
			return
		}
	} else if r.indexEndpoint.String() == index.GetAuthConfigKey() {
		ep = r.indexEndpoint
	} else {
		ep, err = NewEndpoint(index, nil)
		if err != nil {
			return
		}
	}

	ep.URLBuilder = v2.NewURLBuilder(ep.URL)
	return
}

// GetV2Authorization gets the authorization needed to the given image
// If readonly access is requested, then only the authorization may
// only be used for Get operations.
func (r *Session) GetV2Authorization(ep *Endpoint, imageName string, readOnly bool) (auth *RequestAuthorization, err error) {
	scopes := []string{"pull"}
	if !readOnly {
		scopes = append(scopes, "push")
	}

	logrus.Debugf("Getting authorization for %s %s", imageName, scopes)
	return NewRequestAuthorization(r.GetAuthConfig(true), ep, "repository", imageName, scopes), nil
}

//
// 1) Check if TarSum of each layer exists /v2/
//  1.a) if 200, continue
//  1.b) if 300, then push the
//  1.c) if anything else, err
// 2) PUT the created/signed manifest
//
func (r *Session) GetV2ImageManifest(ep *Endpoint, imageName, tagName string, auth *RequestAuthorization) ([]byte, string, error) {
	routeURL, err := getV2Builder(ep).BuildManifestURL(imageName, tagName)
	if err != nil {
		return nil, "", err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, "", err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, "", err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, "", errLoginRequired
		} else if res.StatusCode == 404 {
			return nil, "", ErrDoesNotExist
		}
		return nil, "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch for %s:%s", res.StatusCode, imageName, tagName), res)
	}

	manifestBytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, "", fmt.Errorf("Error while reading the http response: %s", err)
	}

	return manifestBytes, res.Header.Get(DockerDigestHeader), nil
}

// - Succeeded to head image blob (already exists)
// - Failed with no error (continue to Push the Blob)
// - Failed with error
func (r *Session) HeadV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, auth *RequestAuthorization) (bool, error) {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return false, err
	}

	method := "HEAD"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return false, err
	}
	if err := auth.Authorize(req); err != nil {
		return false, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return false, err
	}
	res.Body.Close() // close early, since we're not needing a body on this call .. yet?
	switch {
	case res.StatusCode >= 200 && res.StatusCode < 400:
		// return something indicating no push needed
		return true, nil
	case res.StatusCode == 401:
		return false, errLoginRequired
	case res.StatusCode == 404:
		// return something indicating blob push needed
		return false, nil
	}

	return false, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying head request for %s - %s", res.StatusCode, imageName, dgst), res)
}

func (r *Session) GetV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, blobWrtr io.Writer, auth *RequestAuthorization) error {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return err
	}
	if err := auth.Authorize(req); err != nil {
		return err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return errLoginRequired
		}
		return httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob", res.StatusCode, imageName), res)
	}

	_, err = io.Copy(blobWrtr, res.Body)
	return err
}

func (r *Session) GetV2ImageBlobReader(ep *Endpoint, imageName string, dgst digest.Digest, auth *RequestAuthorization) (io.ReadCloser, int64, error) {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return nil, 0, err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, 0, err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, 0, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, 0, err
	}
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, 0, errLoginRequired
		}
		return nil, 0, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob - %s", res.StatusCode, imageName, dgst), res)
	}
	lenStr := res.Header.Get("Content-Length")
	l, err := strconv.ParseInt(lenStr, 10, 64)
	if err != nil {
		return nil, 0, err
	}

	return res.Body, l, err
}

// Push the image to the server for storage.
// 'layer' is an uncompressed reader of the blob to be pushed.
// The server will generate it's own checksum calculation.
func (r *Session) PutV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, blobRdr io.Reader, auth *RequestAuthorization) error {
	location, err := r.initiateBlobUpload(ep, imageName, auth)
	if err != nil {
		return err
	}

	method := "PUT"
	logrus.Debugf("[registry] Calling %q %s", method, location)
	req, err := http.NewRequest(method, location, ioutil.NopCloser(blobRdr))
	if err != nil {
		return err
	}
	queryParams := req.URL.Query()
	queryParams.Add("digest", dgst.String())
	req.URL.RawQuery = queryParams.Encode()
	if err := auth.Authorize(req); err != nil {
		return err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != 201 {
		if res.StatusCode == 401 {
			return errLoginRequired
		}
		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob - %s", res.StatusCode, imageName, dgst), res)
	}

	return nil
}

// initiateBlobUpload gets the blob upload location for the given image name.
func (r *Session) initiateBlobUpload(ep *Endpoint, imageName string, auth *RequestAuthorization) (location string, err error) {
	routeURL, err := getV2Builder(ep).BuildBlobUploadURL(imageName)
	if err != nil {
		return "", err
	}

	logrus.Debugf("[registry] Calling %q %s", "POST", routeURL)
	req, err := http.NewRequest("POST", routeURL, nil)
	if err != nil {
		return "", err
	}

	if err := auth.Authorize(req); err != nil {
		return "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return "", err
	}

	if res.StatusCode != http.StatusAccepted {
		if res.StatusCode == http.StatusUnauthorized {
			return "", errLoginRequired
		}
		if res.StatusCode == http.StatusNotFound {
			return "", ErrDoesNotExist
		}

		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return "", err
		}

		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: unexpected %d response status trying to initiate upload of %s", res.StatusCode, imageName), res)
	}

	if location = res.Header.Get("Location"); location == "" {
		return "", fmt.Errorf("registry did not return a Location header for resumable blob upload for image %s", imageName)
	}

	return
}

// Finally Push the (signed) manifest of the blobs we've just pushed
func (r *Session) PutV2ImageManifest(ep *Endpoint, imageName, tagName string, signedManifest, rawManifest []byte, auth *RequestAuthorization) (digest.Digest, error) {
	routeURL, err := getV2Builder(ep).BuildManifestURL(imageName, tagName)
	if err != nil {
		return "", err
	}

	method := "PUT"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, bytes.NewReader(signedManifest))
	if err != nil {
		return "", err
	}
	if err := auth.Authorize(req); err != nil {
		return "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()

	// All 2xx and 3xx responses can be accepted for a put.
	if res.StatusCode >= 400 {
		if res.StatusCode == 401 {
			return "", errLoginRequired
		}
		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return "", err
		}
		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s:%s manifest", res.StatusCode, imageName, tagName), res)
	}

	hdrDigest, err := digest.ParseDigest(res.Header.Get(DockerDigestHeader))
	if err != nil {
		return "", fmt.Errorf("invalid manifest digest from registry: %s", err)
	}

	dgstVerifier, err := digest.NewDigestVerifier(hdrDigest)
	if err != nil {
		return "", fmt.Errorf("invalid manifest digest from registry: %s", err)
	}

	dgstVerifier.Write(rawManifest)

	if !dgstVerifier.Verified() {
		computedDigest, _ := digest.FromBytes(rawManifest)
		return "", fmt.Errorf("unable to verify manifest digest: registry has %q, computed %q", hdrDigest, computedDigest)
	}

	return hdrDigest, nil
}

type remoteTags struct {
	Name string   `json:"name"`
	Tags []string `json:"tags"`
}

// Given a repository name, returns a json array of string tags
func (r *Session) GetV2RemoteTags(ep *Endpoint, imageName string, auth *RequestAuthorization) ([]string, error) {
	routeURL, err := getV2Builder(ep).BuildTagsURL(imageName)
	if err != nil {
		return nil, err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, errLoginRequired
		} else if res.StatusCode == 404 {
			return nil, ErrDoesNotExist
		}
		return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch for %s", res.StatusCode, imageName), res)
	}

	var remote remoteTags
	if err := json.NewDecoder(res.Body).Decode(&remote); err != nil {
		return nil, fmt.Errorf("Error while decoding the http response: %s", err)
	}
	return remote.Tags, nil
}
<commit_msg>Fix wording in comment<commit_after>package registry

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/Sirupsen/logrus"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/registry/api/v2"
	"github.com/docker/docker/pkg/httputils"
)

const DockerDigestHeader = "Docker-Content-Digest"

func getV2Builder(e *Endpoint) *v2.URLBuilder {
	if e.URLBuilder == nil {
		e.URLBuilder = v2.NewURLBuilder(e.URL)
	}
	return e.URLBuilder
}

func (r *Session) V2RegistryEndpoint(index *IndexInfo) (ep *Endpoint, err error) {
	// TODO check if should use Mirror
	if index.Official {
		ep, err = newEndpoint(REGISTRYSERVER, true, nil)
		if err != nil {
			return
		}
		err = validateEndpoint(ep)
		if err != nil {
			return
		}
	} else if r.indexEndpoint.String() == index.GetAuthConfigKey() {
		ep = r.indexEndpoint
	} else {
		ep, err = NewEndpoint(index, nil)
		if err != nil {
			return
		}
	}

	ep.URLBuilder = v2.NewURLBuilder(ep.URL)
	return
}

// GetV2Authorization gets the authorization needed to the given image
// If readonly access is requested, then the authorization may
// only be used for Get operations.
func (r *Session) GetV2Authorization(ep *Endpoint, imageName string, readOnly bool) (auth *RequestAuthorization, err error) {
	scopes := []string{"pull"}
	if !readOnly {
		scopes = append(scopes, "push")
	}

	logrus.Debugf("Getting authorization for %s %s", imageName, scopes)
	return NewRequestAuthorization(r.GetAuthConfig(true), ep, "repository", imageName, scopes), nil
}

//
// 1) Check if TarSum of each layer exists /v2/
//  1.a) if 200, continue
//  1.b) if 300, then push the
//  1.c) if anything else, err
// 2) PUT the created/signed manifest
//
func (r *Session) GetV2ImageManifest(ep *Endpoint, imageName, tagName string, auth *RequestAuthorization) ([]byte, string, error) {
	routeURL, err := getV2Builder(ep).BuildManifestURL(imageName, tagName)
	if err != nil {
		return nil, "", err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, "", err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, "", err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, "", errLoginRequired
		} else if res.StatusCode == 404 {
			return nil, "", ErrDoesNotExist
		}
		return nil, "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch for %s:%s", res.StatusCode, imageName, tagName), res)
	}

	manifestBytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, "", fmt.Errorf("Error while reading the http response: %s", err)
	}

	return manifestBytes, res.Header.Get(DockerDigestHeader), nil
}

// - Succeeded to head image blob (already exists)
// - Failed with no error (continue to Push the Blob)
// - Failed with error
func (r *Session) HeadV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, auth *RequestAuthorization) (bool, error) {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return false, err
	}

	method := "HEAD"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return false, err
	}
	if err := auth.Authorize(req); err != nil {
		return false, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return false, err
	}
	res.Body.Close() // close early, since we're not needing a body on this call .. yet?
	switch {
	case res.StatusCode >= 200 && res.StatusCode < 400:
		// return something indicating no push needed
		return true, nil
	case res.StatusCode == 401:
		return false, errLoginRequired
	case res.StatusCode == 404:
		// return something indicating blob push needed
		return false, nil
	}

	return false, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying head request for %s - %s", res.StatusCode, imageName, dgst), res)
}

func (r *Session) GetV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, blobWrtr io.Writer, auth *RequestAuthorization) error {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return err
	}
	if err := auth.Authorize(req); err != nil {
		return err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return errLoginRequired
		}
		return httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob", res.StatusCode, imageName), res)
	}

	_, err = io.Copy(blobWrtr, res.Body)
	return err
}

func (r *Session) GetV2ImageBlobReader(ep *Endpoint, imageName string, dgst digest.Digest, auth *RequestAuthorization) (io.ReadCloser, int64, error) {
	routeURL, err := getV2Builder(ep).BuildBlobURL(imageName, dgst)
	if err != nil {
		return nil, 0, err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, 0, err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, 0, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, 0, err
	}
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, 0, errLoginRequired
		}
		return nil, 0, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob - %s", res.StatusCode, imageName, dgst), res)
	}
	lenStr := res.Header.Get("Content-Length")
	l, err := strconv.ParseInt(lenStr, 10, 64)
	if err != nil {
		return nil, 0, err
	}

	return res.Body, l, err
}

// Push the image to the server for storage.
// 'layer' is an uncompressed reader of the blob to be pushed.
// The server will generate it's own checksum calculation.
func (r *Session) PutV2ImageBlob(ep *Endpoint, imageName string, dgst digest.Digest, blobRdr io.Reader, auth *RequestAuthorization) error {
	location, err := r.initiateBlobUpload(ep, imageName, auth)
	if err != nil {
		return err
	}

	method := "PUT"
	logrus.Debugf("[registry] Calling %q %s", method, location)
	req, err := http.NewRequest(method, location, ioutil.NopCloser(blobRdr))
	if err != nil {
		return err
	}
	queryParams := req.URL.Query()
	queryParams.Add("digest", dgst.String())
	req.URL.RawQuery = queryParams.Encode()
	if err := auth.Authorize(req); err != nil {
		return err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

	if res.StatusCode != 201 {
		if res.StatusCode == 401 {
			return errLoginRequired
		}
		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return err
		}
		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob - %s", res.StatusCode, imageName, dgst), res)
	}

	return nil
}

// initiateBlobUpload gets the blob upload location for the given image name.
func (r *Session) initiateBlobUpload(ep *Endpoint, imageName string, auth *RequestAuthorization) (location string, err error) {
	routeURL, err := getV2Builder(ep).BuildBlobUploadURL(imageName)
	if err != nil {
		return "", err
	}

	logrus.Debugf("[registry] Calling %q %s", "POST", routeURL)
	req, err := http.NewRequest("POST", routeURL, nil)
	if err != nil {
		return "", err
	}

	if err := auth.Authorize(req); err != nil {
		return "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return "", err
	}

	if res.StatusCode != http.StatusAccepted {
		if res.StatusCode == http.StatusUnauthorized {
			return "", errLoginRequired
		}
		if res.StatusCode == http.StatusNotFound {
			return "", ErrDoesNotExist
		}

		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return "", err
		}

		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: unexpected %d response status trying to initiate upload of %s", res.StatusCode, imageName), res)
	}

	if location = res.Header.Get("Location"); location == "" {
		return "", fmt.Errorf("registry did not return a Location header for resumable blob upload for image %s", imageName)
	}

	return
}

// Finally Push the (signed) manifest of the blobs we've just pushed
func (r *Session) PutV2ImageManifest(ep *Endpoint, imageName, tagName string, signedManifest, rawManifest []byte, auth *RequestAuthorization) (digest.Digest, error) {
	routeURL, err := getV2Builder(ep).BuildManifestURL(imageName, tagName)
	if err != nil {
		return "", err
	}

	method := "PUT"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)
	req, err := http.NewRequest(method, routeURL, bytes.NewReader(signedManifest))
	if err != nil {
		return "", err
	}
	if err := auth.Authorize(req); err != nil {
		return "", err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()

	// All 2xx and 3xx responses can be accepted for a put.
	if res.StatusCode >= 400 {
		if res.StatusCode == 401 {
			return "", errLoginRequired
		}
		errBody, err := ioutil.ReadAll(res.Body)
		if err != nil {
			return "", err
		}
		logrus.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
		return "", httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s:%s manifest", res.StatusCode, imageName, tagName), res)
	}

	hdrDigest, err := digest.ParseDigest(res.Header.Get(DockerDigestHeader))
	if err != nil {
		return "", fmt.Errorf("invalid manifest digest from registry: %s", err)
	}

	dgstVerifier, err := digest.NewDigestVerifier(hdrDigest)
	if err != nil {
		return "", fmt.Errorf("invalid manifest digest from registry: %s", err)
	}

	dgstVerifier.Write(rawManifest)

	if !dgstVerifier.Verified() {
		computedDigest, _ := digest.FromBytes(rawManifest)
		return "", fmt.Errorf("unable to verify manifest digest: registry has %q, computed %q", hdrDigest, computedDigest)
	}

	return hdrDigest, nil
}

type remoteTags struct {
	Name string   `json:"name"`
	Tags []string `json:"tags"`
}

// Given a repository name, returns a json array of string tags
func (r *Session) GetV2RemoteTags(ep *Endpoint, imageName string, auth *RequestAuthorization) ([]string, error) {
	routeURL, err := getV2Builder(ep).BuildTagsURL(imageName)
	if err != nil {
		return nil, err
	}

	method := "GET"
	logrus.Debugf("[registry] Calling %q %s", method, routeURL)

	req, err := http.NewRequest(method, routeURL, nil)
	if err != nil {
		return nil, err
	}
	if err := auth.Authorize(req); err != nil {
		return nil, err
	}
	res, err := r.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 401 {
			return nil, errLoginRequired
		} else if res.StatusCode == 404 {
			return nil, ErrDoesNotExist
		}
		return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch for %s", res.StatusCode, imageName), res)
	}

	var remote remoteTags
	if err := json.NewDecoder(res.Body).Decode(&remote); err != nil {
		return nil, fmt.Errorf("Error while decoding the http response: %s", err)
	}
	return remote.Tags, nil
}
<|endoftext|>