<commit_before>// Package server implements a configurable, general-purpose web server.
// It relies on configurations obtained from the adjacent config package
// and can execute middleware as defined by the adjacent middleware package.
package server

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"runtime"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/miekg/dns"
)

// Server represents an instance of a server, which serves
// DNS requests at a particular address (host and port). A
// server is capable of serving numerous zones on
// the same address and the listener may be stopped for
// graceful termination (POSIX only).
type Server struct {
	Addr        string // Address we listen on
	mux         *dns.ServeMux
	tls         bool // whether this server is serving all HTTPS hosts or not
	TLSConfig   *tls.Config
	OnDemandTLS bool             // whether this server supports on-demand TLS (load certs at handshake-time)
	zones       map[string]zone  // zones keyed by their address
	listener    ListenerFile     // the listener which is bound to the socket
	listenerMu  sync.Mutex       // protects listener
	dnsWg       sync.WaitGroup   // used to wait on outstanding connections
	startChan   chan struct{}    // used to block until server is finished starting
	connTimeout time.Duration    // the maximum duration of a graceful shutdown
	ReqCallback OptionalCallback // if non-nil, is executed at the beginning of every request
	SNICallback func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error)
}

// ListenerFile represents a listener.
type ListenerFile interface {
	net.Listener
	File() (*os.File, error)
}

// OptionalCallback is a function that may or may not handle a request.
// It returns whether or not it handled the request. If it handled the
// request, it is presumed that no further request handling should occur.
type OptionalCallback func(dns.ResponseWriter, *dns.Msg) bool

// New creates a new Server which will bind to addr and serve
// the sites/hosts configured in configs. Its listener will
// gracefully close when the server is stopped which will take
// no longer than gracefulTimeout.
//
// This function does not start serving.
//
// Do not re-use a server (start, stop, then start again). We
// could probably add more locking to make this possible, but
// as it stands, you should dispose of a server after stopping it.
// The behavior of serving with a spent server is undefined.
func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server, error) {
	var useTLS, useOnDemandTLS bool
	if len(configs) > 0 {
		useTLS = configs[0].TLS.Enabled
		useOnDemandTLS = configs[0].TLS.OnDemand
	}

	s := &Server{
		Addr:      addr,
		TLSConfig: new(tls.Config),
		// TODO: Make these values configurable?
		// ReadTimeout:    2 * time.Minute,
		// WriteTimeout:   2 * time.Minute,
		// MaxHeaderBytes: 1 << 16,
		tls:         useTLS,
		OnDemandTLS: useOnDemandTLS,
		zones:       make(map[string]zone),
		startChan:   make(chan struct{}),
		connTimeout: gracefulTimeout,
	}
	mux := dns.NewServeMux()
	mux.Handle(".", s) // wildcard handler, everything will go through here
	s.mux = mux

	// We have to bound our wg with one increment
	// to prevent a "race condition" that is hard-coded
	// into sync.WaitGroup.Wait() - basically, an add
	// with a positive delta must be guaranteed to
	// occur before Wait() is called on the wg.
	// In a way, this kind of acts as a safety barrier.
	s.dnsWg.Add(1)

	// Set up each zone
	for _, conf := range configs {
		// TODO(miek): something better here?
		if _, exists := s.zones[conf.Host]; exists {
			return nil, fmt.Errorf("cannot serve %s - host already defined for address %s", conf.Address(), s.Addr)
		}

		z := zone{config: conf}

		// Build middleware stack
		err := z.buildStack()
		if err != nil {
			return nil, err
		}

		s.zones[conf.Host] = z
	}

	return s, nil
}

// Serve starts the server with an existing listener. It blocks until the
// server stops.
/*
func (s *Server) Serve(ln ListenerFile) error {
	// TODO(miek): Go DNS has no server stuff that allows you to give it a listener
	// and use that.
	err := s.setup()
	if err != nil {
		defer close(s.startChan) // MUST defer so error is properly reported, same with all cases in this file
		return err
	}
	return s.serve(ln)
}
*/

// ListenAndServe starts the server with a new listener. It blocks until the server stops.
func (s *Server) ListenAndServe() error {
	err := s.setup()
	if err != nil {
		close(s.startChan)
		return err
	}

	// TODO(miek): going out on a limb here, let's assume that listening
	// on the part for tcp and udp results in the same error. We can only
	// return the error from the udp listener, disregarding whatever
	// happenend to the tcp one.
	go func() {
		dns.ListenAndServe(s.Addr, "tcp", s.mux)
	}()

	close(s.startChan) // unblock anyone waiting for this to start listening
	return dns.ListenAndServe(s.Addr, "udp", s.mux)
}

// setup prepares the server s to begin listening; it should be
// called just before the listener announces itself on the network
// and should only be called when the server is just starting up.
func (s *Server) setup() error {
	// Execute startup functions now
	for _, z := range s.zones {
		for _, startupFunc := range z.config.Startup {
			err := startupFunc()
			if err != nil {
				return err
			}
		}
	}

	return nil
}

/*
TODO(miek): no such thing in the glorious Go DNS.
// serveTLS serves TLS with SNI and client auth support if s has them enabled. It
// blocks until s quits.
func serveTLS(s *Server, ln net.Listener, tlsConfigs []TLSConfig) error {
	// Customize our TLS configuration
	s.TLSConfig.MinVersion = tlsConfigs[0].ProtocolMinVersion
	s.TLSConfig.MaxVersion = tlsConfigs[0].ProtocolMaxVersion
	s.TLSConfig.CipherSuites = tlsConfigs[0].Ciphers
	s.TLSConfig.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites

	// TLS client authentication, if user enabled it
	err := setupClientAuth(tlsConfigs, s.TLSConfig)
	if err != nil {
		defer close(s.startChan)
		return err
	}

	// Create TLS listener - note that we do not replace s.listener
	// with this TLS listener; tls.listener is unexported and does
	// not implement the File() method we need for graceful restarts
	// on POSIX systems.
	ln = tls.NewListener(ln, s.TLSConfig)

	close(s.startChan) // unblock anyone waiting for this to start listening
	return s.Serve(ln)
}
*/

// Stop stops the server. It blocks until the server is
// totally stopped. On POSIX systems, it will wait for
// connections to close (up to a max timeout of a few
// seconds); on Windows it will close the listener
// immediately.
func (s *Server) Stop() (err error) {

	if runtime.GOOS != "windows" {
		// force connections to close after timeout
		done := make(chan struct{})
		go func() {
			s.dnsWg.Done() // decrement our initial increment used as a barrier
			s.dnsWg.Wait()
			close(done)
		}()

		// Wait for remaining connections to finish or
		// force them all to close after timeout
		select {
		case <-time.After(s.connTimeout):
		case <-done:
		}
	}

	// Close the listener now; this stops the server without delay
	s.listenerMu.Lock()
	if s.listener != nil {
		err = s.listener.Close()
	}
	s.listenerMu.Unlock()

	return
}

// WaitUntilStarted blocks until the server s is started, meaning
// that practically the next instruction is to start the server loop.
// It also unblocks if the server encounters an error during startup.
func (s *Server) WaitUntilStarted() {
	<-s.startChan
}

// ListenerFd gets a dup'ed file of the listener. If there
// is no underlying file, the return value will be nil. It
// is the caller's responsibility to close the file.
func (s *Server) ListenerFd() *os.File {
	s.listenerMu.Lock()
	defer s.listenerMu.Unlock()
	if s.listener != nil {
		file, _ := s.listener.File()
		return file
	}
	return nil
}

// ServeDNS is the entry point for every request to the address that s
// is bound to. It acts as a multiplexer for the requests zonename as
// defined in the request so that the correct zone
// (configuration and middleware stack) will handle the request.
func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	defer func() {
		// In case the user doesn't enable error middleware, we still
		// need to make sure that we stay alive up here
		if rec := recover(); rec != nil {
			DefaultErrorFunc(w, r, dns.RcodeServerFailure)
		}
	}()

	// Execute the optional request callback if it exists
	if s.ReqCallback != nil && s.ReqCallback(w, r) {
		return
	}

	q := r.Question[0].Name
	b := make([]byte, len(q))
	off, end := 0, false
	ctx := context.Background()
	for {
		l := len(q[off:])
		for i := 0; i < l; i++ {
			b[i] = q[off+i]
			// normalize the name for the lookup
			if b[i] >= 'A' && b[i] <= 'Z' {
				b[i] |= ('a' - 'A')
			}
		}

		if h, ok := s.zones[string(b[:l])]; ok {
			if r.Question[0].Qtype != dns.TypeDS {
				rcode, _ := h.stack.ServeDNS(ctx, w, r)
				if RcodeNoClientWrite(rcode) {
					DefaultErrorFunc(w, r, rcode)
				}
				return
			}
		}
		off, end = dns.NextLabel(q, off)
		if end {
			break
		}
	}
	// Wildcard match, if we have found nothing try the root zone as a last resort.
	if h, ok := s.zones["."]; ok {
		rcode, _ := h.stack.ServeDNS(ctx, w, r)
		if RcodeNoClientWrite(rcode) {
			DefaultErrorFunc(w, r, rcode)
		}
		return
	}

	// Still here? Error out with SERVFAIL and some logging
	remoteHost := w.RemoteAddr().String()
	DefaultErrorFunc(w, r, dns.RcodeServerFailure)
	log.Printf("[INFO] %s - No such zone at %s (Remote: %s)", q, s.Addr, remoteHost)
}

// DefaultErrorFunc responds to an HTTP request with a simple description
// of the specified HTTP status code.
func DefaultErrorFunc(w dns.ResponseWriter, r *dns.Msg, rcode int) {
	answer := new(dns.Msg)
	answer.SetRcode(r, rcode)
	w.WriteMsg(answer)
}

// setupClientAuth sets up TLS client authentication only if
// any of the TLS configs specified at least one cert file.
func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error {
	var clientAuth bool
	for _, cfg := range tlsConfigs {
		if len(cfg.ClientCerts) > 0 {
			clientAuth = true
			break
		}
	}

	if clientAuth {
		pool := x509.NewCertPool()
		for _, cfg := range tlsConfigs {
			for _, caFile := range cfg.ClientCerts {
				caCrt, err := ioutil.ReadFile(caFile) // Anyone that gets a cert from this CA can connect
				if err != nil {
					return err
				}
				if !pool.AppendCertsFromPEM(caCrt) {
					return fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile)
				}
			}
		}
		config.ClientCAs = pool
		config.ClientAuth = tls.RequireAndVerifyClientCert
	}

	return nil
}

// RunFirstStartupFuncs runs all of the server's FirstStartup
// callback functions unless one of them returns an error first.
// It is the caller's responsibility to call this only once and
// at the correct time. The functions here should not be executed
// at restarts or where the user does not explicitly start a new
// instance of the server.
func (s *Server) RunFirstStartupFuncs() error {
	for _, z := range s.zones {
		for _, f := range z.config.FirstStartup {
			if err := f(); err != nil {
				return err
			}
		}
	}
	return nil
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
//
// Borrowed from the Go standard library.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

// Accept accepts the connection with a keep-alive enabled.
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

// File implements ListenerFile; returns the underlying file of the listener.
func (ln tcpKeepAliveListener) File() (*os.File, error) {
	return ln.TCPListener.File()
}

// ShutdownCallbacks executes all the shutdown callbacks
// for all the virtualhosts in servers, and returns all the
// errors generated during their execution. In other words,
// an error executing one shutdown callback does not stop
// execution of others. Only one shutdown callback is executed
// at a time. You must protect the servers that are passed in
// if they are shared across threads.
func ShutdownCallbacks(servers []*Server) []error {
	var errs []error
	for _, s := range servers {
		for _, zone := range s.zones {
			for _, shutdownFunc := range zone.config.Shutdown {
				err := shutdownFunc()
				if err != nil {
					errs = append(errs, err)
				}
			}
		}
	}
	return errs
}

func RcodeNoClientWrite(rcode int) bool {
	switch rcode {
	case dns.RcodeServerFailure:
		fallthrough
	case dns.RcodeRefused:
		fallthrough
	case dns.RcodeFormatError:
		fallthrough
	case dns.RcodeNotImplemented:
		return true
	}
	return false
}
<commit_msg>Answer REFUSED when we don't host the zone<commit_after>// Package server implements a configurable, general-purpose web server.
// It relies on configurations obtained from the adjacent config package
// and can execute middleware as defined by the adjacent middleware package.
package server

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"runtime"
	"sync"
	"time"

	"golang.org/x/net/context"

	"github.com/miekg/dns"
)

// Server represents an instance of a server, which serves
// DNS requests at a particular address (host and port). A
// server is capable of serving numerous zones on
// the same address and the listener may be stopped for
// graceful termination (POSIX only).
type Server struct {
	Addr        string // Address we listen on
	mux         *dns.ServeMux
	tls         bool // whether this server is serving all HTTPS hosts or not
	TLSConfig   *tls.Config
	OnDemandTLS bool             // whether this server supports on-demand TLS (load certs at handshake-time)
	zones       map[string]zone  // zones keyed by their address
	listener    ListenerFile     // the listener which is bound to the socket
	listenerMu  sync.Mutex       // protects listener
	dnsWg       sync.WaitGroup   // used to wait on outstanding connections
	startChan   chan struct{}    // used to block until server is finished starting
	connTimeout time.Duration    // the maximum duration of a graceful shutdown
	ReqCallback OptionalCallback // if non-nil, is executed at the beginning of every request
	SNICallback func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error)
}

// ListenerFile represents a listener.
type ListenerFile interface {
	net.Listener
	File() (*os.File, error)
}

// OptionalCallback is a function that may or may not handle a request.
// It returns whether or not it handled the request. If it handled the
// request, it is presumed that no further request handling should occur.
type OptionalCallback func(dns.ResponseWriter, *dns.Msg) bool

// New creates a new Server which will bind to addr and serve
// the sites/hosts configured in configs. Its listener will
// gracefully close when the server is stopped which will take
// no longer than gracefulTimeout.
//
// This function does not start serving.
//
// Do not re-use a server (start, stop, then start again). We
// could probably add more locking to make this possible, but
// as it stands, you should dispose of a server after stopping it.
// The behavior of serving with a spent server is undefined.
func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server, error) {
	var useTLS, useOnDemandTLS bool
	if len(configs) > 0 {
		useTLS = configs[0].TLS.Enabled
		useOnDemandTLS = configs[0].TLS.OnDemand
	}

	s := &Server{
		Addr:      addr,
		TLSConfig: new(tls.Config),
		// TODO: Make these values configurable?
		// ReadTimeout:    2 * time.Minute,
		// WriteTimeout:   2 * time.Minute,
		// MaxHeaderBytes: 1 << 16,
		tls:         useTLS,
		OnDemandTLS: useOnDemandTLS,
		zones:       make(map[string]zone),
		startChan:   make(chan struct{}),
		connTimeout: gracefulTimeout,
	}
	mux := dns.NewServeMux()
	mux.Handle(".", s) // wildcard handler, everything will go through here
	s.mux = mux

	// We have to bound our wg with one increment
	// to prevent a "race condition" that is hard-coded
	// into sync.WaitGroup.Wait() - basically, an add
	// with a positive delta must be guaranteed to
	// occur before Wait() is called on the wg.
	// In a way, this kind of acts as a safety barrier.
	s.dnsWg.Add(1)

	// Set up each zone
	for _, conf := range configs {
		// TODO(miek): something better here?
		if _, exists := s.zones[conf.Host]; exists {
			return nil, fmt.Errorf("cannot serve %s - host already defined for address %s", conf.Address(), s.Addr)
		}

		z := zone{config: conf}

		// Build middleware stack
		err := z.buildStack()
		if err != nil {
			return nil, err
		}

		s.zones[conf.Host] = z
	}

	return s, nil
}

// Serve starts the server with an existing listener. It blocks until the
// server stops.
/*
func (s *Server) Serve(ln ListenerFile) error {
	// TODO(miek): Go DNS has no server stuff that allows you to give it a listener
	// and use that.
	err := s.setup()
	if err != nil {
		defer close(s.startChan) // MUST defer so error is properly reported, same with all cases in this file
		return err
	}
	return s.serve(ln)
}
*/

// ListenAndServe starts the server with a new listener. It blocks until the server stops.
func (s *Server) ListenAndServe() error {
	err := s.setup()
	if err != nil {
		close(s.startChan)
		return err
	}

	// TODO(miek): going out on a limb here, let's assume that listening
	// on the part for tcp and udp results in the same error. We can only
	// return the error from the udp listener, disregarding whatever
	// happenend to the tcp one.
	go func() {
		dns.ListenAndServe(s.Addr, "tcp", s.mux)
	}()

	close(s.startChan) // unblock anyone waiting for this to start listening
	return dns.ListenAndServe(s.Addr, "udp", s.mux)
}

// setup prepares the server s to begin listening; it should be
// called just before the listener announces itself on the network
// and should only be called when the server is just starting up.
func (s *Server) setup() error {
	// Execute startup functions now
	for _, z := range s.zones {
		for _, startupFunc := range z.config.Startup {
			err := startupFunc()
			if err != nil {
				return err
			}
		}
	}

	return nil
}

/*
TODO(miek): no such thing in the glorious Go DNS.
// serveTLS serves TLS with SNI and client auth support if s has them enabled. It
// blocks until s quits.
func serveTLS(s *Server, ln net.Listener, tlsConfigs []TLSConfig) error {
	// Customize our TLS configuration
	s.TLSConfig.MinVersion = tlsConfigs[0].ProtocolMinVersion
	s.TLSConfig.MaxVersion = tlsConfigs[0].ProtocolMaxVersion
	s.TLSConfig.CipherSuites = tlsConfigs[0].Ciphers
	s.TLSConfig.PreferServerCipherSuites = tlsConfigs[0].PreferServerCipherSuites

	// TLS client authentication, if user enabled it
	err := setupClientAuth(tlsConfigs, s.TLSConfig)
	if err != nil {
		defer close(s.startChan)
		return err
	}

	// Create TLS listener - note that we do not replace s.listener
	// with this TLS listener; tls.listener is unexported and does
	// not implement the File() method we need for graceful restarts
	// on POSIX systems.
	ln = tls.NewListener(ln, s.TLSConfig)

	close(s.startChan) // unblock anyone waiting for this to start listening
	return s.Serve(ln)
}
*/

// Stop stops the server. It blocks until the server is
// totally stopped. On POSIX systems, it will wait for
// connections to close (up to a max timeout of a few
// seconds); on Windows it will close the listener
// immediately.
func (s *Server) Stop() (err error) {

	if runtime.GOOS != "windows" {
		// force connections to close after timeout
		done := make(chan struct{})
		go func() {
			s.dnsWg.Done() // decrement our initial increment used as a barrier
			s.dnsWg.Wait()
			close(done)
		}()

		// Wait for remaining connections to finish or
		// force them all to close after timeout
		select {
		case <-time.After(s.connTimeout):
		case <-done:
		}
	}

	// Close the listener now; this stops the server without delay
	s.listenerMu.Lock()
	if s.listener != nil {
		err = s.listener.Close()
	}
	s.listenerMu.Unlock()

	return
}

// WaitUntilStarted blocks until the server s is started, meaning
// that practically the next instruction is to start the server loop.
// It also unblocks if the server encounters an error during startup.
func (s *Server) WaitUntilStarted() {
	<-s.startChan
}

// ListenerFd gets a dup'ed file of the listener. If there
// is no underlying file, the return value will be nil. It
// is the caller's responsibility to close the file.
func (s *Server) ListenerFd() *os.File {
	s.listenerMu.Lock()
	defer s.listenerMu.Unlock()
	if s.listener != nil {
		file, _ := s.listener.File()
		return file
	}
	return nil
}

// ServeDNS is the entry point for every request to the address that s
// is bound to. It acts as a multiplexer for the requests zonename as
// defined in the request so that the correct zone
// (configuration and middleware stack) will handle the request.
func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	defer func() {
		// In case the user doesn't enable error middleware, we still
		// need to make sure that we stay alive up here
		if rec := recover(); rec != nil {
			DefaultErrorFunc(w, r, dns.RcodeServerFailure)
		}
	}()

	// Execute the optional request callback if it exists
	if s.ReqCallback != nil && s.ReqCallback(w, r) {
		return
	}

	q := r.Question[0].Name
	b := make([]byte, len(q))
	off, end := 0, false
	ctx := context.Background()
	for {
		l := len(q[off:])
		for i := 0; i < l; i++ {
			b[i] = q[off+i]
			// normalize the name for the lookup
			if b[i] >= 'A' && b[i] <= 'Z' {
				b[i] |= ('a' - 'A')
			}
		}

		if h, ok := s.zones[string(b[:l])]; ok {
			if r.Question[0].Qtype != dns.TypeDS {
				rcode, _ := h.stack.ServeDNS(ctx, w, r)
				if RcodeNoClientWrite(rcode) {
					DefaultErrorFunc(w, r, rcode)
				}
				return
			}
		}
		off, end = dns.NextLabel(q, off)
		if end {
			break
		}
	}
	// Wildcard match, if we have found nothing try the root zone as a last resort.
	if h, ok := s.zones["."]; ok {
		rcode, _ := h.stack.ServeDNS(ctx, w, r)
		if RcodeNoClientWrite(rcode) {
			DefaultErrorFunc(w, r, rcode)
		}
		return
	}

	// Still here? Error out with REFUSED and some logging
	remoteHost := w.RemoteAddr().String()
	DefaultErrorFunc(w, r, dns.RcodeRefused)
	log.Printf("[INFO] %s - No such zone at %s (Remote: %s)", q, s.Addr, remoteHost)
}

// DefaultErrorFunc responds to an HTTP request with a simple description
// of the specified HTTP status code.
func DefaultErrorFunc(w dns.ResponseWriter, r *dns.Msg, rcode int) {
	answer := new(dns.Msg)
	answer.SetRcode(r, rcode)
	w.WriteMsg(answer)
}

// setupClientAuth sets up TLS client authentication only if
// any of the TLS configs specified at least one cert file.
func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error {
	var clientAuth bool
	for _, cfg := range tlsConfigs {
		if len(cfg.ClientCerts) > 0 {
			clientAuth = true
			break
		}
	}

	if clientAuth {
		pool := x509.NewCertPool()
		for _, cfg := range tlsConfigs {
			for _, caFile := range cfg.ClientCerts {
				caCrt, err := ioutil.ReadFile(caFile) // Anyone that gets a cert from this CA can connect
				if err != nil {
					return err
				}
				if !pool.AppendCertsFromPEM(caCrt) {
					return fmt.Errorf("error loading client certificate '%s': no certificates were successfully parsed", caFile)
				}
			}
		}
		config.ClientCAs = pool
		config.ClientAuth = tls.RequireAndVerifyClientCert
	}

	return nil
}

// RunFirstStartupFuncs runs all of the server's FirstStartup
// callback functions unless one of them returns an error first.
// It is the caller's responsibility to call this only once and
// at the correct time. The functions here should not be executed
// at restarts or where the user does not explicitly start a new
// instance of the server.
func (s *Server) RunFirstStartupFuncs() error {
	for _, z := range s.zones {
		for _, f := range z.config.FirstStartup {
			if err := f(); err != nil {
				return err
			}
		}
	}
	return nil
}

// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
//
// Borrowed from the Go standard library.
type tcpKeepAliveListener struct {
	*net.TCPListener
}

// Accept accepts the connection with a keep-alive enabled.
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

// File implements ListenerFile; returns the underlying file of the listener.
func (ln tcpKeepAliveListener) File() (*os.File, error) {
	return ln.TCPListener.File()
}

// ShutdownCallbacks executes all the shutdown callbacks
// for all the virtualhosts in servers, and returns all the
// errors generated during their execution. In other words,
// an error executing one shutdown callback does not stop
// execution of others. Only one shutdown callback is executed
// at a time. You must protect the servers that are passed in
// if they are shared across threads.
func ShutdownCallbacks(servers []*Server) []error {
	var errs []error
	for _, s := range servers {
		for _, zone := range s.zones {
			for _, shutdownFunc := range zone.config.Shutdown {
				err := shutdownFunc()
				if err != nil {
					errs = append(errs, err)
				}
			}
		}
	}
	return errs
}

func RcodeNoClientWrite(rcode int) bool {
	switch rcode {
	case dns.RcodeServerFailure:
		fallthrough
	case dns.RcodeRefused:
		fallthrough
	case dns.RcodeFormatError:
		fallthrough
	case dns.RcodeNotImplemented:
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package server

import (
	"bytes"
	"fmt"
	"github.com/GrappigPanda/notorious/bencode"
	"gopkg.in/redis.v3"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	STARTED = iota
	COMPLETED
	STOPPED
)

type TorrentEvent struct {
	started   int
	completed int
	stopped   int
}

type TorrentRequestData struct {
	info_hash  string //20 byte sha1 hash
	peer_id    string //max len 20
	ip         string //optional
	port       string // port number the peer is listening on
	uploaded   int    // base10 ascii amount uploaded so far
	downloaded int    // base10 ascii amount downloaded so far
	left       int    // # of bytes left to download (base 10 ascii)
	event      int    // TorrentEvent
	numwant    int    // Number of peers requested by client.
	compact    bool   // Bep23 peer list compression decision: True -> compress bep23
}

var ANNOUNCE_URL = "/announce"

var FIELDS = []string{"port", "uploaded", "downloaded", "left", "event", "compact"}

func parseTorrentGetRequestURI(request string, ip string) map[string]interface{} {
	torrentdata := make(map[string]interface{})
	querydata := decodeQueryURL(request)

	lookupvalues := []string{
		"info_hash",
		"peer_id",
		// ip intentially left out
		"port",
		"uploaded",
		"downloaded",
		"left",
		"event",
		"numwant",
		"compact",
	}

	lookupints := []string{
		"uploaded",
		"downloaded",
		"left",
		"event",
		"numwant",
	}

	for i := range lookupvalues {
		index := lookupvalues[i]

		// TODO(ian): Delegate responsibility to another function.
		x := querydata[index]
		if len(x) <= 0 {
			continue
		}

		if index == "info_hash" {
			torrentdata[index] = ParseInfoHash(x[0])
		} else if index == "compact" {
			if querydata[index][0] == "1" {
				torrentdata[index] = true
			} else {
				torrentdata[index] = false
			}
		} else {
			torrentdata[index] = querydata[index][0]
		}

		// TODO(ian): Delegate responsibility here, as well.
		for j := range lookupints {
			if lookupints[j] == index {
				val, _ := strconv.Atoi(index)
				torrentdata[index] = val
			}
		}
	}

	// TODO(ian): Add a generic size lookup function and assert > 0
	x := strings.Split(ip, ":")
	if len(x) > 0 {
		torrentdata["ip"] = x[0]
	}

	fmt.Println(torrentdata)
	return torrentdata
}

func ParseInfoHash(s string) string {
	return fmt.Sprintf("%x", s)
}

func fillEmptyMapValues(torrentMap map[string]interface{}) *TorrentRequestData {
	_, ok := torrentMap["uploaded"]
	if !ok {
		torrentMap["uploaded"] = 0
	}

	_, ok = torrentMap["downloaded"]
	if !ok {
		torrentMap["downloaded"] = 0
	}

	_, ok = torrentMap["left"]
	if !ok {
		torrentMap["left"] = 0
	}

	_, ok = torrentMap["event"]
	if !ok {
		torrentMap["event"] = STOPPED
	}

	_, ok = torrentMap["compact"]
	if !ok {
		torrentMap["compact"] = true
	}

	_, ok = torrentMap["numwant"]
	if !ok {
		torrentMap["numwant"] = 30
	}

	x := TorrentRequestData{
		torrentMap["info_hash"].(string),
		torrentMap["peer_id"].(string),
		torrentMap["ip"].(string),
		torrentMap["port"].(string),
		torrentMap["uploaded"].(int),
		torrentMap["downloaded"].(int),
		torrentMap["left"].(int),
		torrentMap["event"].(int),
		torrentMap["numwant"].(int),
		torrentMap["compact"].(bool),
	}
	return &x
}

func worker(client *redis.Client, torrdata *TorrentRequestData) []string {
	if RedisGetBoolKeyVal(client, torrdata.info_hash, torrdata) {
		x := RedisGetKeyVal(client, torrdata.info_hash, torrdata)

		RedisSetKeyVal(client,
			concatenateKeyMember(torrdata.info_hash, "ip"),
			createIpPortPair(torrdata))

		return x

	} else {
		CreateNewTorrentKey(client, torrdata.info_hash, torrdata)
		return worker(client, torrdata)
	}
}

func compactifyIpPort(ip string) string {
	sz := strings.Split(ip, ":")
	newip := net.IPMask(net.ParseIP(sz[0])).String()
	x, err := strconv.Atoi(sz[1])
	if err != nil {
		panic("Invalid IP!")
	}
	port := fmt.Sprintf("%x", x)

	// TODO(ian): Sometime in the future, support ivp6
	newip = newip[len(newip)-8 : len(newip)]
	port = port[len(port)-4 : len(port)]

	ret := ""

	for i := 0; i < 8; i += 2 {
		ret += fmt.Sprintf("\\%s", newip[i:i+2])
	}

	for i := 0; i < 4; i += 2 {
		ret += fmt.Sprintf("\\%s", port[i:i+2])
	}

	return ret
}

func formatResponseData(ips []string, compact bool) string {
	for i := 0; i <= len(ips); i++ {
		ips[i] = compactifyIpPort(ips[i])
	}
	encodedList := bencode.EncodeList(ips)

	if compact {
		return encodedList
	} else {
		// TODO(ian): Support bep-23
		return EncodeResponse(ipport)
	}
}

func decodeQueryURL(s string) url.Values {
	u, err := url.Parse(s)
	if err != nil {
		panic(err)
	}

	m, _ := url.ParseQuery(u.RawQuery)
	return m
}

func encodeKV(key string, value string) string {
	return fmt.Sprintf("%s%s", bencode.EncodeByteString(key), bencode.EncodeByteString(value))
}

func EncodeResponse(ipport []string) string {
	ret := "d"

	ret += encodeKV("interval", "30") // Interval
	ret += encodeKV("tracker_id", "1234")
	ret += encodeKV("complete", "1")
	ret += encodeKV("incomplete", "111111111111111111111")
	ret += "5:peersd"

	for i := range ipport {
		data := strings.Split(ipport[i], ":")

		ret += encodeKV("peer_id", "1")
		ret += encodeKV("ip", data[0])
		ret += encodeKV("port", data[1])
	}

	ret += "e"

	ret += "e"

	return ret
}

func requestHandler(w http.ResponseWriter, req *http.Request) {
	client := OpenClient()

	torrentdata := parseTorrentGetRequestURI(req.RequestURI, req.RemoteAddr)
	if torrentdata != nil {
		data := fillEmptyMapValues(torrentdata)

		worker(client, data)
		x := RedisGetKeyVal(client, data.info_hash, data)

		response := formatResponseData(x, data)
		fmt.Println(response)

		w.Write([]byte(response))
	}
}

func RunServer() {
	mux := http.NewServeMux()

	mux.HandleFunc("/announce", requestHandler)
	http.ListenAndServe(":3000", mux)
}

func OpenClient() *redis.Client {
	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})

	return client
}

func CreateNewTorrentKey(client *redis.Client, key string, value *TorrentRequestData) {
	// CreateNewTorrentKey creates a new key. By default, it adds a member
	// ":ip". I don't think this ought to ever be generalized, as I just want
	// Redis to function in one specific way in notorious.

	// TODO(ian): You might want to set this explicitly in parameters
	// value := *TorrentRequestData
	client.SAdd(key, "ip")
}

func createIpPortPair(value *TorrentRequestData) string {
	// createIpPortPair creates a string formatted ("%s:%s", value.ip,
	// value.port) looking like so: "127.0.0.1:6886" and returns this value.
	fmt.Println(value.ip, value.port)
	return fmt.Sprintf("%s:%s", value.ip, value.port)
}

func RedisSetKeyVal(client *redis.Client, keymember string, value string) {
	// RedisSetKeyVal sets a key:member's value to value. Returns nothing as of
	// yet.
	client.SAdd(keymember, value)
}

func RedisGetKeyVal(client *redis.Client, key string, value *TorrentRequestData) []string {
	// RedisGetKeyVal retrieves a value from the Redis store by looking up the
	// provided key. If the key does not yet exist, we create the key in the KV
	// storage or if the value is empty, we add the current requester to the
	// list.
	keymember := concatenateKeyMember(key, "ip")

	val, err := client.SMembers(keymember).Result()
	if err != nil {
		// Fail because the key doesn't exist in the KV storage.
		CreateNewTorrentKey(client, keymember, value)
	}

	// If no keys yet exist in the KV storage.
	if len(val) == 0 {
		RedisSetKeyVal(client, keymember, createIpPortPair(value))
	}

	return val
}

func RedisGetBoolKeyVal(client *redis.Client, key string, value interface{}) bool {
	_, err := client.Get(key).Result()

	return err != nil
}

func concatenateKeyMember(key string, member string) string {
	var buffer bytes.Buffer

	buffer.WriteString(key)
	buffer.WriteString(":")
	buffer.WriteString(member)

	return buffer.String()
}
<commit_msg>Test commit to see if ci is owrking<commit_after>package server

import (
	"bytes"
	"fmt"
	"github.com/GrappigPanda/notorious/bencode"
	"gopkg.in/redis.v3"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	STARTED = iota
	COMPLETED
	STOPPED
)

type TorrentEvent struct {
	started   int
	completed int
	stopped   int
}

type TorrentRequestData struct {
	info_hash  string //20 byte sha1 hash
	peer_id    string //max len 20
	ip         string //optional
	port       string // port number the peer is listening on
	uploaded   int    // base10 ascii amount uploaded so far
	downloaded int    // base10 ascii amount downloaded so far
	left       int    // # of bytes left to download (base 10 ascii)
	event      int    // TorrentEvent
	numwant    int    // Number of peers requested by client.
	compact    bool   // Bep23 peer list compression decision: True -> compress bep23
}

var ANNOUNCE_URL = "/announce"

var FIELDS = []string{"port", "uploaded", "downloaded", "left", "event", "compact"}

func parseTorrentGetRequestURI(request string, ip string) map[string]interface{} {
	torrentdata := make(map[string]interface{})
	querydata := decodeQueryURL(request)

	lookupvalues := []string{
		"info_hash",
		"peer_id",
		// ip intentially left out
		"port",
		"uploaded",
		"downloaded",
		"left",
		"event",
		"numwant",
		"compact",
	}

	lookupints := []string{
		"uploaded",
		"downloaded",
		"left",
		"event",
		"numwant",
	}

	for i := range lookupvalues {
		index := lookupvalues[i]

		// TODO(ian): Delegate responsibility to another function.
		x := querydata[index]
		if len(x) <= 0 {
			continue
		}

		if index == "info_hash" {
			torrentdata[index] = ParseInfoHash(x[0])
		} else if index == "compact" {
			if querydata[index][0] == "1" {
				torrentdata[index] = true
			} else {
				torrentdata[index] = false
			}
		} else {
			torrentdata[index] = querydata[index][0]
		}

		// TODO(ian): Delegate responsibility here, as well.
		for j := range lookupints {
			if lookupints[j] == index {
				val, _ := strconv.Atoi(index)
				torrentdata[index] = val
			}
		}
	}

	// TODO(ian): Add a generic size lookup function and assert > 0
	x := strings.Split(ip, ":")
	if len(x) > 0 {
		torrentdata["ip"] = x[0]
	}

	fmt.Println(torrentdata)
	return torrentdata
}

func ParseInfoHash(s string) string {
	return fmt.Sprintf("%x", s)
}

func fillEmptyMapValues(torrentMap map[string]interface{}) *TorrentRequestData {
	_, ok := torrentMap["uploaded"]
	if !ok {
		torrentMap["uploaded"] = 0
	}

	_, ok = torrentMap["downloaded"]
	if !ok {
		torrentMap["downloaded"] = 0
	}

	_, ok = torrentMap["left"]
	if !ok {
		torrentMap["left"] = 0
	}

	_, ok = torrentMap["event"]
	if !ok {
		torrentMap["event"] = STOPPED
	}

	_, ok = torrentMap["compact"]
	if !ok {
		torrentMap["compact"] = true
	}

	_, ok = torrentMap["numwant"]
	if !ok {
		torrentMap["numwant"] = 30
	}

	x := TorrentRequestData{
		torrentMap["info_hash"].(string),
		torrentMap["peer_id"].(string),
		torrentMap["ip"].(string),
		torrentMap["port"].(string),
		torrentMap["uploaded"].(int),
		torrentMap["downloaded"].(int),
		torrentMap["left"].(int),
		torrentMap["event"].(int),
		torrentMap["numwant"].(int),
		torrentMap["compact"].(bool),
	}

	return &x
}

func worker(client *redis.Client, torrdata *TorrentRequestData) []string {
	if RedisGetBoolKeyVal(client, torrdata.info_hash, torrdata) {
		x := RedisGetKeyVal(client, torrdata.info_hash, torrdata)

		RedisSetKeyVal(client,
			concatenateKeyMember(torrdata.info_hash, "ip"),
			createIpPortPair(torrdata))

		return x

	} else {
		CreateNewTorrentKey(client, torrdata.info_hash, torrdata)
		return worker(client, torrdata)
	}
}

func compactifyIpPort(ip string) string {
	sz := strings.Split(ip, ":")
	newip := net.IPMask(net.ParseIP(sz[0])).String()
	x, err := strconv.Atoi(sz[1])
	if err != nil {
		panic("Invalid IP!")
	}
	port := fmt.Sprintf("%x", x)

	// TODO(ian): Sometime in the future, support ivp6
	newip = newip[len(newip)-8 : len(newip)]
	port = port[len(port)-4 : len(port)]

	ret := ""

	for i := 0; i < 8; i += 2 {
		ret += fmt.Sprintf("\\%s", newip[i:i+2])
	}

	for i := 0; i < 4; i += 2 {
		ret += fmt.Sprintf("\\%s", port[i:i+2])
	}

	return ret
}

func formatResponseData(ips []string, compact bool) string {
	for i := 0; i <= len(ips); i++ {
		ips[i] = compactifyIpPort(ips[i])
	}
	encodedList := bencode.EncodeList(ips)

	if compact {
		return encodedList
	} else {
		// TODO(ian): Support bep-23
		return EncodeResponse(ipport)
	}
}

func decodeQueryURL(s string) url.Values {
	u, err := url.Parse(s)
	if err != nil {
		panic(err)
	}

	m, _ := url.ParseQuery(u.RawQuery)
	return m
}

func encodeKV(key string, value string) string {
	return fmt.Sprintf("%s%s", bencode.EncodeByteString(key), bencode.EncodeByteString(value))
}

func EncodeResponse(ipport []string) string {
	ret := "d"

	ret += encodeKV("interval", "30") // Interval
	ret += encodeKV("tracker_id", "1234")
	ret += encodeKV("complete", "1")
	ret += encodeKV("incomplete", "111111111111111111111")
	ret += "5:peersd"

	for i := range ipport {
		data := strings.Split(ipport[i], ":")

		ret += encodeKV("peer_id", "1")
		ret += encodeKV("ip", data[0])
		ret += encodeKV("port", data[1])
	}

	ret += "e"

	ret += "e"

	return ret
}

func requestHandler(w http.ResponseWriter, req *http.Request) {
	client := OpenClient()

	torrentdata := parseTorrentGetRequestURI(req.RequestURI, req.RemoteAddr)
	if torrentdata != nil {
		data := fillEmptyMapValues(torrentdata)

		worker(client, data)
		x := RedisGetKeyVal(client, data.info_hash, data)

		response := formatResponseData(x, data)
		fmt.Println(response)

		w.Write([]byte(response))
	}
}

func RunServer() {
	mux := http.NewServeMux()

	mux.HandleFunc("/announce", requestHandler)
	http.ListenAndServe(":3000", mux)
}

func OpenClient() *redis.Client {
	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})

	return client
}

func CreateNewTorrentKey(client *redis.Client, key string, value *TorrentRequestData) {
	// CreateNewTorrentKey creates a new key. By default, it adds a member
	// ":ip". I don't think this ought to ever be generalized, as I just want
	// Redis to function in one specific way in notorious.

	// TODO(ian): You might want to set this explicitly in parameters
	// value := *TorrentRequestData
	client.SAdd(key, "ip")
}

func createIpPortPair(value *TorrentRequestData) string {
	// createIpPortPair creates a string formatted ("%s:%s", value.ip,
	// value.port) looking like so: "127.0.0.1:6886" and returns this value.
	fmt.Println(value.ip, value.port)
	return fmt.Sprintf("%s:%s", value.ip, value.port)
}

func RedisSetKeyVal(client *redis.Client, keymember string, value string) {
	// RedisSetKeyVal sets a key:member's value to value. Returns nothing as of
	// yet.
	client.SAdd(keymember, value)
}

func RedisGetKeyVal(client *redis.Client, key string, value *TorrentRequestData) []string {
	// RedisGetKeyVal retrieves a value from the Redis store by looking up the
	// provided key. If the key does not yet exist, we create the key in the KV
	// storage or if the value is empty, we add the current requester to the
	// list.
	keymember := concatenateKeyMember(key, "ip")

	val, err := client.SMembers(keymember).Result()
	if err != nil {
		// Fail because the key doesn't exist in the KV storage.
		CreateNewTorrentKey(client, keymember, value)
	}

	// If no keys yet exist in the KV storage.
	if len(val) == 0 {
		RedisSetKeyVal(client, keymember, createIpPortPair(value))
	}

	return val
}

func RedisGetBoolKeyVal(client *redis.Client, key string, value interface{}) bool {
	_, err := client.Get(key).Result()

	return err != nil
}

func concatenateKeyMember(key string, member string) string {
	var buffer bytes.Buffer

	buffer.WriteString(key)
	buffer.WriteString(":")
	buffer.WriteString(member)

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


<commit_before>package main

import (
	"html/template"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
	"github.com/jessfraz/reg/clair"
	"github.com/jessfraz/reg/registry"
	"github.com/jessfraz/reg/utils"
	wordwrap "github.com/mitchellh/go-wordwrap"
	"github.com/urfave/cli"
)

const (
	// VERSION is the binary version.
	VERSION = "v0.2.0"

	dockerConfigPath = ".docker/config.json"
)

var (
	updating = false
	wg       sync.WaitGroup
	r        *registry.Registry
	cl       *clair.Clair
	tmpl     *template.Template
)

// preload initializes any global options and configuration
// before the main or sub commands are run.
func preload(c *cli.Context) (err error) {
	if c.GlobalBool("debug") {
		logrus.SetLevel(logrus.DebugLevel)
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "reg-server"
	app.Version = VERSION
	app.Author = "@jessfraz"
	app.Email = "no-reply@butts.com"
	app.Usage = "Docker registry v2 static UI server."
	app.Before = preload
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug, d",
			Usage: "run in debug mode",
		},
		cli.StringFlag{
			Name:  "username, u",
			Usage: "username for the registry",
		},
		cli.StringFlag{
			Name:  "password, p",
			Usage: "password for the registry",
		},
		cli.StringFlag{
			Name:  "registry, r",
			Usage: "URL to the private registry (ex. r.j3ss.co)",
		},
		cli.BoolFlag{
			Name:  "insecure, k",
			Usage: "do not verify tls certificates of registry",
		},
		cli.StringFlag{
			Name:  "port",
			Value: "8080",
			Usage: "port for server to run on",
		},
		cli.StringFlag{
			Name:  "cert",
			Usage: "path to ssl cert",
		},
		cli.StringFlag{
			Name:  "key",
			Usage: "path to ssl key",
		},
		cli.StringFlag{
			Name:  "interval",
			Value: "5m",
			Usage: "interval to generate new index.html's at",
		},
		cli.StringFlag{
			Name:  "clair",
			Usage: "url to clair instance",
		},
		cli.IntFlag{
			Name:  "workers, w",
			Value: 20,
			Usage: "number of workers to analyse for vulnerabilities",
		},
	}
	app.Action = func(c *cli.Context) error {
		auth, err := utils.GetAuthConfig(c)
		if err != nil {
			logrus.Fatal(err)
		}

		// create the registry client
		if c.GlobalBool("insecure") {
			r, err = registry.NewInsecure(auth, c.GlobalBool("debug"))
			if err != nil {
				logrus.Fatal(err)
			}
		} else {
			r, err = registry.New(auth, c.GlobalBool("debug"))
			if err != nil {
				logrus.Fatal(err)
			}
		}

		// create a clair instance if needed
		if c.GlobalString("clair") != "" {
			cl, err = clair.New(c.GlobalString("clair"), c.GlobalBool("debug"))
			if err != nil {
				logrus.Warnf("creation of clair failed: %v", err)
			}
		}

		// get the path to the static directory
		wd, err := os.Getwd()
		if err != nil {
			logrus.Fatal(err)
		}
		staticDir := filepath.Join(wd, "static")

		// create the template
		templateDir := filepath.Join(staticDir, "../templates")

		// make sure all the templates exist
		vulns := filepath.Join(templateDir, "vulns.html")
		if _, err := os.Stat(vulns); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", vulns)
		}
		layout := filepath.Join(templateDir, "repositories.html")
		if _, err := os.Stat(layout); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", layout)
		}
		tags := filepath.Join(templateDir, "tags.html")
		if _, err := os.Stat(tags); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", tags)
		}

		funcMap := template.FuncMap{
			"trim": func(s string) string {
				return wordwrap.WrapString(s, 80)
			},
			"color": func(s string) string {
				switch s = strings.ToLower(s); s {
				case "high":
					return "danger"
				case "critical":
					return "danger"
				case "defcon1":
					return "danger"
				case "medium":
					return "warning"
				case "low":
					return "info"
				case "negligible":
					return "info"
				case "unknown":
					return "default"
				default:
					return "default"
				}
			},
		}

		tmpl = template.Must(template.New("").Funcs(funcMap).ParseGlob(templateDir + "/*.html"))

		rc := registryController{
			reg: r,
			cl:  cl,
		}

		// create mux server
		mux := mux.NewRouter()

		// static files handler
		staticHandler := http.FileServer(http.Dir(staticDir))
		mux.Handle("/static", staticHandler)
		mux.HandleFunc("/repo/{repo}", rc.tagsHandler)
		mux.HandleFunc("/repo/{repo}/{tag}", rc.tagHandler)
		mux.HandleFunc("/repo/{repo}/{tag}/vulns", rc.vulnerabilitiesHandler)
		mux.HandleFunc("/", rc.repositoriesHandler)

		// set up the server
		port := c.String("port")
		server := &http.Server{
			Addr:    ":" + port,
			Handler: mux,
		}
		logrus.Infof("Starting server on port %q", port)
		if c.String("cert") != "" && c.String("key") != "" {
			logrus.Fatal(server.ListenAndServeTLS(c.String("cert"), c.String("key")))
		} else {
			logrus.Fatal(server.ListenAndServe())
		}

		return nil
	}

	app.Run(os.Args)
}
<commit_msg>remove unneeded vars<commit_after>package main

import (
	"html/template"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/mux"
	"github.com/jessfraz/reg/clair"
	"github.com/jessfraz/reg/registry"
	"github.com/jessfraz/reg/utils"
	wordwrap "github.com/mitchellh/go-wordwrap"
	"github.com/urfave/cli"
)

const (
	// VERSION is the binary version.
	VERSION = "v0.2.0"

	dockerConfigPath = ".docker/config.json"
)

var (
	r    *registry.Registry
	cl   *clair.Clair
	tmpl *template.Template
)

// preload initializes any global options and configuration
// before the main or sub commands are run.
func preload(c *cli.Context) (err error) {
	if c.GlobalBool("debug") {
		logrus.SetLevel(logrus.DebugLevel)
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "reg-server"
	app.Version = VERSION
	app.Author = "@jessfraz"
	app.Email = "no-reply@butts.com"
	app.Usage = "Docker registry v2 static UI server."
	app.Before = preload
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug, d",
			Usage: "run in debug mode",
		},
		cli.StringFlag{
			Name:  "username, u",
			Usage: "username for the registry",
		},
		cli.StringFlag{
			Name:  "password, p",
			Usage: "password for the registry",
		},
		cli.StringFlag{
			Name:  "registry, r",
			Usage: "URL to the private registry (ex. r.j3ss.co)",
		},
		cli.BoolFlag{
			Name:  "insecure, k",
			Usage: "do not verify tls certificates of registry",
		},
		cli.StringFlag{
			Name:  "port",
			Value: "8080",
			Usage: "port for server to run on",
		},
		cli.StringFlag{
			Name:  "cert",
			Usage: "path to ssl cert",
		},
		cli.StringFlag{
			Name:  "key",
			Usage: "path to ssl key",
		},
		cli.StringFlag{
			Name:  "clair",
			Usage: "url to clair instance",
		},
	}
	app.Action = func(c *cli.Context) error {
		auth, err := utils.GetAuthConfig(c)
		if err != nil {
			logrus.Fatal(err)
		}

		// create the registry client
		if c.GlobalBool("insecure") {
			r, err = registry.NewInsecure(auth, c.GlobalBool("debug"))
			if err != nil {
				logrus.Fatal(err)
			}
		} else {
			r, err = registry.New(auth, c.GlobalBool("debug"))
			if err != nil {
				logrus.Fatal(err)
			}
		}

		// create a clair instance if needed
		if c.GlobalString("clair") != "" {
			cl, err = clair.New(c.GlobalString("clair"), c.GlobalBool("debug"))
			if err != nil {
				logrus.Warnf("creation of clair failed: %v", err)
			}
		}

		// get the path to the static directory
		wd, err := os.Getwd()
		if err != nil {
			logrus.Fatal(err)
		}
		staticDir := filepath.Join(wd, "static")

		// create the template
		templateDir := filepath.Join(staticDir, "../templates")

		// make sure all the templates exist
		vulns := filepath.Join(templateDir, "vulns.html")
		if _, err := os.Stat(vulns); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", vulns)
		}
		layout := filepath.Join(templateDir, "repositories.html")
		if _, err := os.Stat(layout); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", layout)
		}
		tags := filepath.Join(templateDir, "tags.html")
		if _, err := os.Stat(tags); os.IsNotExist(err) {
			logrus.Fatalf("Template %s not found", tags)
		}

		funcMap := template.FuncMap{
			"trim": func(s string) string {
				return wordwrap.WrapString(s, 80)
			},
			"color": func(s string) string {
				switch s = strings.ToLower(s); s {
				case "high":
					return "danger"
				case "critical":
					return "danger"
				case "defcon1":
					return "danger"
				case "medium":
					return "warning"
				case "low":
					return "info"
				case "negligible":
					return "info"
				case "unknown":
					return "default"
				default:
					return "default"
				}
			},
		}

		tmpl = template.Must(template.New("").Funcs(funcMap).ParseGlob(templateDir + "/*.html"))

		rc := registryController{
			reg: r,
			cl:  cl,
		}

		// create mux server
		mux := mux.NewRouter()

		// static files handler
		staticHandler := http.FileServer(http.Dir(staticDir))
		mux.Handle("/static", staticHandler)
		mux.HandleFunc("/repo/{repo}", rc.tagsHandler)
		mux.HandleFunc("/repo/{repo}/{tag}", rc.tagHandler)
		mux.HandleFunc("/repo/{repo}/{tag}/vulns", rc.vulnerabilitiesHandler)
		mux.HandleFunc("/", rc.repositoriesHandler)

		// set up the server
		port := c.String("port")
		server := &http.Server{
			Addr:    ":" + port,
			Handler: mux,
		}
		logrus.Infof("Starting server on port %q", port)
		if c.String("cert") != "" && c.String("key") != "" {
			logrus.Fatal(server.ListenAndServeTLS(c.String("cert"), c.String("key")))
		} else {
			logrus.Fatal(server.ListenAndServe())
		}

		return nil
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import "log"

func main() {
	log.Println("Hello World")
}
<commit_msg>HTTP Handlers skeleton<commit_after>package main

import (
	"log"
	"net/http"
	"sync"
)

// Todo is a representation of each item that
// we are going to maintain in our service
type Todo struct {
	ID        uint64
	Task      string
	Completed bool
}

var todos []Todo
var lock sync.RWMutex

func main() {
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		// Authenticate and return JWT
	})

	http.HandleFunc("/todos", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodGet {
			// Return all the Todo items
		} else if r.Method == http.MethodPost {
			// Create a new Todo item
		} else {
			http.NotFound(w, r)
		}
	})

	http.HandleFunc("/todo", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodPut {
			// Update the particular Todo item
		} else if r.Method == http.MethodDelete {
			// Delete the particular Todo item
		} else {
			http.NotFound(w, r)
		}
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}
<|endoftext|>


<commit_before>package server

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"bazil.org/bazil/cas/chunks/kvchunks"
	"bazil.org/bazil/fs"
	"bazil.org/bazil/fs/wire"
	"bazil.org/bazil/kv"
	"bazil.org/bazil/kv/kvfiles"
	"bazil.org/bazil/kv/kvmulti"
	"bazil.org/bazil/kv/untrusted"
	"bazil.org/bazil/tokens"
	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"code.google.com/p/goprotobuf/proto"
	"github.com/boltdb/bolt"
)

type mountState struct {
	// closed after the serve loop has exited
	unmounted chan struct{}
}

type App struct {
	DataDir  string
	lockFile *os.File
	DB       *bolt.DB
	mounts   struct {
		sync.Mutex
		open map[fs.VolumeID]*mountState
	}
}

func New(dataDir string) (app *App, err error) {
	err = os.Mkdir(dataDir, 0700)
	if err != nil && !os.IsExist(err) {
		return nil, err
	}

	lockPath := filepath.Join(dataDir, "lock")
	lockFile, err := lock(lockPath)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			// if we're reporting an error, also unlock
			_ = lockFile.Close()
		}
	}()

	kvpath := filepath.Join(dataDir, "chunks")
	err = kvfiles.Create(kvpath)
	if err != nil {
		return nil, err
	}

	dbpath := filepath.Join(dataDir, "bazil.bolt")
	db, err := bolt.Open(dbpath, 0600)
	if err != nil {
		return nil, err
	}

	err = db.Update(func(tx *bolt.Tx) error {
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketBazil)); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketVolume)); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketVolName)); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		db.Close()
		return nil, err
	}

	app = &App{
		DataDir:  dataDir,
		lockFile: lockFile,
		DB:       db,
	}
	app.mounts.open = make(map[fs.VolumeID]*mountState)
	return app, nil
}

func (app *App) Close() {
	app.DB.Close()
	app.lockFile.Close()
}

// TODO this function smells
func (app *App) serveMount(vol *fs.Volume, id *fs.VolumeID, mountpoint string) error {
	conn, err := fuse.Mount(mountpoint)
	if err != nil {
		return fmt.Errorf("mount fail: %v", err)
	}

	serveErr := make(chan error, 1)
	go func() {
		defer func() {
			// remove map entry on unmount or failed mount
			app.mounts.Lock()
			delete(app.mounts.open, *id)
			app.mounts.Unlock()
		}()
		defer conn.Close()
		serveErr <- fusefs.Serve(conn, vol)
	}()

	select {
	case <-conn.Ready:
		if conn.MountError != nil {
			return fmt.Errorf("mount fail (delayed): %v", err)
		}
		return nil
	case err = <-serveErr:
		// Serve quit early
		if err != nil {
			return fmt.Errorf("filesystem failure: %v", err)
		}
		return errors.New("Serve exited early")
	}
}

type MountInfo struct {
	VolumeID fs.VolumeID
}

func (app *App) openKV(conf *wire.KV) (kv.KV, error) {
	var kvstores []kv.KV

	if conf.Local != nil {
		kvpath := filepath.Join(app.DataDir, "chunks")
		var s kv.KV
		var err error
		s, err = kvfiles.Open(kvpath)
		if err != nil {
			return nil, err
		}
		if conf.Local.Secret != nil {
			var secret [32]byte
			copy(secret[:], conf.Local.Secret)
			s = untrusted.New(s, &secret)
		}
		kvstores = append(kvstores, s)
	}

	for _, ext := range conf.External {
		var s kv.KV
		var err error
		s, err = kvfiles.Open(ext.Path)
		if err != nil {
			return nil, err
		}
		if ext.Secret != nil {
			var secret [32]byte
			copy(secret[:], ext.Secret)
			s = untrusted.New(s, &secret)
		}
		kvstores = append(kvstores, s)
	}

	if len(conf.XXX_unrecognized) > 0 {
		return nil, fmt.Errorf("unknown storage: %v", conf)
	}

	return kvmulti.New(kvstores...), nil
}

// Mount makes the contents of the volume visible at the given
// mountpoint. If Mount returns with a nil error, the mount has
// occurred.
func (app *App) Mount(volumeName string, mountpoint string) (*MountInfo, error) {
	// TODO obey `bazil -debug server run`

	var vol *fs.Volume
	var volumeID *fs.VolumeID
	var ready = make(chan error, 1)
	app.mounts.Lock()
	err := app.DB.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(tokens.BucketVolName))
		val := bucket.Get([]byte(volumeName))
		if val == nil {
			return errors.New("volume not found")
		}
		var volConf wire.VolumeConfig
		if err := proto.Unmarshal(val, &volConf); err != nil {
			return err
		}
		var err error
		volumeID, err = fs.NewVolumeID(volConf.VolumeID)
		if err != nil {
			return err
		}
		if _, ok := app.mounts.open[*volumeID]; ok {
			return errors.New("volume already mounted")
		}

		kvstore, err := app.openKV(&volConf.Storage)
		if err != nil {
			return err
		}

		chunkStore := kvchunks.New(kvstore)
		vol, err = fs.Open(app.DB, chunkStore, volumeID)
		if err != nil {
			return err
		}
		mnt := &mountState{
			unmounted: make(chan struct{}),
		}
		go func() {
			defer close(mnt.unmounted)
			ready <- app.serveMount(vol, volumeID, mountpoint)
		}()
		app.mounts.open[*volumeID] = mnt
		return nil
	})
	app.mounts.Unlock()
	if err != nil {
		return nil, err
	}
	err = <-ready
	if err != nil {
		return nil, err
	}
	info := &MountInfo{
		VolumeID: *volumeID,
	}
	return info, nil
}

var NotMountedError = errors.New("not currently mounted")

func (app *App) WaitForUnmount(volumeID *fs.VolumeID) error {
	app.mounts.Lock()
	// we hold onto mnt after releasing the lock, but it's safe in
	// this case; gc keeps it pinned, and we don't look at mutable
	// data
	mnt, ok := app.mounts.open[*volumeID]
	app.mounts.Unlock()
	if !ok {
		return NotMountedError
	}
	<-mnt.unmounted
	return nil
}
<commit_msg>server: Remove mount table entry if mount helper exits with error<commit_after>package server

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"bazil.org/bazil/cas/chunks/kvchunks"
	"bazil.org/bazil/fs"
	"bazil.org/bazil/fs/wire"
	"bazil.org/bazil/kv"
	"bazil.org/bazil/kv/kvfiles"
	"bazil.org/bazil/kv/kvmulti"
	"bazil.org/bazil/kv/untrusted"
	"bazil.org/bazil/tokens"
	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"code.google.com/p/goprotobuf/proto"
	"github.com/boltdb/bolt"
)

type mountState struct {
	// closed after the serve loop has exited
	unmounted chan struct{}
}

type App struct {
	DataDir  string
	lockFile *os.File
	DB       *bolt.DB
	mounts   struct {
		sync.Mutex
		open map[fs.VolumeID]*mountState
	}
}

func New(dataDir string) (app *App, err error) {
	err = os.Mkdir(dataDir, 0700)
	if err != nil && !os.IsExist(err) {
		return nil, err
	}

	lockPath := filepath.Join(dataDir, "lock")
	lockFile, err := lock(lockPath)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			// if we're reporting an error, also unlock
			_ = lockFile.Close()
		}
	}()

	kvpath := filepath.Join(dataDir, "chunks")
	err = kvfiles.Create(kvpath)
	if err != nil {
		return nil, err
	}

	dbpath := filepath.Join(dataDir, "bazil.bolt")
	db, err := bolt.Open(dbpath, 0600)
	if err != nil {
		return nil, err
	}

	err = db.Update(func(tx *bolt.Tx) error {
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketBazil)); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketVolume)); err != nil {
			return err
		}
		if _, err := tx.CreateBucketIfNotExists([]byte(tokens.BucketVolName)); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		db.Close()
		return nil, err
	}

	app = &App{
		DataDir:  dataDir,
		lockFile: lockFile,
		DB:       db,
	}
	app.mounts.open = make(map[fs.VolumeID]*mountState)
	return app, nil
}

func (app *App) Close() {
	app.DB.Close()
	app.lockFile.Close()
}

// TODO this function smells
func (app *App) serveMount(vol *fs.Volume, id *fs.VolumeID, mountpoint string) error {
	conn, err := fuse.Mount(mountpoint)
	if err != nil {
		// remove map entry if the mount never took place
		app.mounts.Lock()
		delete(app.mounts.open, *id)
		app.mounts.Unlock()
		return fmt.Errorf("mount fail: %v", err)
	}

	serveErr := make(chan error, 1)
	go func() {
		defer func() {
			// remove map entry on unmount or failed mount
			app.mounts.Lock()
			delete(app.mounts.open, *id)
			app.mounts.Unlock()
		}()
		defer conn.Close()
		serveErr <- fusefs.Serve(conn, vol)
	}()

	select {
	case <-conn.Ready:
		if conn.MountError != nil {
			return fmt.Errorf("mount fail (delayed): %v", err)
		}
		return nil
	case err = <-serveErr:
		// Serve quit early
		if err != nil {
			return fmt.Errorf("filesystem failure: %v", err)
		}
		return errors.New("Serve exited early")
	}
}

type MountInfo struct {
	VolumeID fs.VolumeID
}

func (app *App) openKV(conf *wire.KV) (kv.KV, error) {
	var kvstores []kv.KV

	if conf.Local != nil {
		kvpath := filepath.Join(app.DataDir, "chunks")
		var s kv.KV
		var err error
		s, err = kvfiles.Open(kvpath)
		if err != nil {
			return nil, err
		}
		if conf.Local.Secret != nil {
			var secret [32]byte
			copy(secret[:], conf.Local.Secret)
			s = untrusted.New(s, &secret)
		}
		kvstores = append(kvstores, s)
	}

	for _, ext := range conf.External {
		var s kv.KV
		var err error
		s, err = kvfiles.Open(ext.Path)
		if err != nil {
			return nil, err
		}
		if ext.Secret != nil {
			var secret [32]byte
			copy(secret[:], ext.Secret)
			s = untrusted.New(s, &secret)
		}
		kvstores = append(kvstores, s)
	}

	if len(conf.XXX_unrecognized) > 0 {
		return nil, fmt.Errorf("unknown storage: %v", conf)
	}

	return kvmulti.New(kvstores...), nil
}

// Mount makes the contents of the volume visible at the given
// mountpoint. If Mount returns with a nil error, the mount has
// occurred.
func (app *App) Mount(volumeName string, mountpoint string) (*MountInfo, error) {
	// TODO obey `bazil -debug server run`

	var vol *fs.Volume
	var volumeID *fs.VolumeID
	var ready = make(chan error, 1)
	app.mounts.Lock()
	err := app.DB.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket([]byte(tokens.BucketVolName))
		val := bucket.Get([]byte(volumeName))
		if val == nil {
			return errors.New("volume not found")
		}
		var volConf wire.VolumeConfig
		if err := proto.Unmarshal(val, &volConf); err != nil {
			return err
		}
		var err error
		volumeID, err = fs.NewVolumeID(volConf.VolumeID)
		if err != nil {
			return err
		}
		if _, ok := app.mounts.open[*volumeID]; ok {
			return errors.New("volume already mounted")
		}

		kvstore, err := app.openKV(&volConf.Storage)
		if err != nil {
			return err
		}

		chunkStore := kvchunks.New(kvstore)
		vol, err = fs.Open(app.DB, chunkStore, volumeID)
		if err != nil {
			return err
		}
		mnt := &mountState{
			unmounted: make(chan struct{}),
		}
		go func() {
			defer close(mnt.unmounted)
			ready <- app.serveMount(vol, volumeID, mountpoint)
		}()
		app.mounts.open[*volumeID] = mnt
		return nil
	})
	app.mounts.Unlock()
	if err != nil {
		return nil, err
	}
	err = <-ready
	if err != nil {
		return nil, err
	}
	info := &MountInfo{
		VolumeID: *volumeID,
	}
	return info, nil
}

var NotMountedError = errors.New("not currently mounted")

func (app *App) WaitForUnmount(volumeID *fs.VolumeID) error {
	app.mounts.Lock()
	// we hold onto mnt after releasing the lock, but it's safe in
	// this case; gc keeps it pinned, and we don't look at mutable
	// data
	mnt, ok := app.mounts.open[*volumeID]
	app.mounts.Unlock()
	if !ok {
		return NotMountedError
	}
	<-mnt.unmounted
	return nil
}
<|endoftext|>


<commit_before>package weavedns

import (
	"fmt"
	"github.com/miekg/dns"
	"net"
)

const (
	LOCAL_DOMAIN = "weave.local."
)

func checkFatal(e error) {
	if e != nil {
		Error.Fatal(e)
	}
}

func checkWarn(e error) {
	if e != nil {
		Warning.Println(e)
	}
}

func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	m.RecursionAvailable = true
	m.Rcode = dns.RcodeNameError
	return m
}

func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
	return func(w dns.ResponseWriter, r *dns.Msg) {
		q := r.Question[0]
		Debug.Printf("Local query: %s", q)
		ip, err := zone.MatchLocal(q.Name)
		if err == nil {
			m := makeDNSReply(r, q.Name, dns.TypeA, []net.IP{ip})
			w.WriteMsg(m)
		} else {
			Debug.Printf("Failed lookup for %s; sending mDNS query", q.Name)
			// We don't know the answer; see if someone else does
			channel := make(chan *ResponseA)
			replies := make([]net.IP, 0)
			go func() {
				for resp := range channel {
					Debug.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
					replies = append(replies, resp.Addr)
				}
				var responseMsg *dns.Msg
				if len(replies) > 0 {
					responseMsg = makeDNSReply(r, q.Name, dns.TypeA, replies)
				} else {
					responseMsg = makeDNSFailResponse(r)
				}
				w.WriteMsg(responseMsg)
			}()
			mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
		}
		return
	}
}

/* When we receive a request for a name outside of our '.weave' domain, call
   the underlying lookup mechanism and return the answer(s) it gives.
   Unfortunately, this means that TTLs from a real DNS server are lost - FIXME.
*/
func notUsHandler() dns.HandlerFunc {
	return func(w dns.ResponseWriter, r *dns.Msg) {
		q := r.Question[0]
		Debug.Printf("Non-local query: %s", q)
		addrs, err := net.LookupIP(q.Name)
		var responseMsg *dns.Msg
		if err == nil {
			responseMsg = makeDNSReply(r, q.Name, q.Qtype, addrs)
		} else {
			responseMsg = makeDNSFailResponse(r)
			Debug.Print("Failed fallback lookup", err)
		}
		w.WriteMsg(responseMsg)
	}
}

func StartServer(zone Zone, iface *net.Interface, dnsPort int, httpPort int, wait int) error {
	go ListenHttp(LOCAL_DOMAIN, zone, httpPort)

	mdnsClient, err := NewMDNSClient()
	checkFatal(err)

	ifaceName := "default interface"
	if iface != nil {
		ifaceName = iface.Name
	}
	Info.Printf("Using mDNS on %s", ifaceName)
	err = mdnsClient.Start(iface)
	checkFatal(err)

	LocalServeMux := dns.NewServeMux()
	LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler(zone, mdnsClient))
	LocalServeMux.HandleFunc(".", notUsHandler())

	mdnsServer, err := NewMDNSServer(zone)
	checkFatal(err)

	err = mdnsServer.Start(iface)
	checkFatal(err)

	address := fmt.Sprintf(":%d", dnsPort)
	err = dns.ListenAndServe(address, "udp", LocalServeMux)
	checkFatal(err)

	Info.Printf("Listening for DNS on %s", address)
	return nil
}
<commit_msg>Improve debug messages<commit_after>package weavedns

import (
	"fmt"
	"github.com/miekg/dns"
	"net"
)

const (
	LOCAL_DOMAIN = "weave.local."
)

func checkFatal(e error) {
	if e != nil {
		Error.Fatal(e)
	}
}

func checkWarn(e error) {
	if e != nil {
		Warning.Println(e)
	}
}

func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	m.RecursionAvailable = true
	m.Rcode = dns.RcodeNameError
	return m
}

func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
	return func(w dns.ResponseWriter, r *dns.Msg) {
		q := r.Question[0]
		Debug.Printf("Local query: %+v", q)
		ip, err := zone.MatchLocal(q.Name)
		if err == nil {
			m := makeDNSReply(r, q.Name, dns.TypeA, []net.IP{ip})
			w.WriteMsg(m)
		} else {
			Debug.Printf("Failed lookup for %s; sending mDNS query", q.Name)
			// We don't know the answer; see if someone else does
			channel := make(chan *ResponseA)
			replies := make([]net.IP, 0)
			go func() {
				for resp := range channel {
					Debug.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
					replies = append(replies, resp.Addr)
				}
				var responseMsg *dns.Msg
				if len(replies) > 0 {
					responseMsg = makeDNSReply(r, q.Name, dns.TypeA, replies)
				} else {
					responseMsg = makeDNSFailResponse(r)
				}
				w.WriteMsg(responseMsg)
			}()
			mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
		}
		return
	}
}

/* When we receive a request for a name outside of our '.weave' domain, call
   the underlying lookup mechanism and return the answer(s) it gives.
   Unfortunately, this means that TTLs from a real DNS server are lost - FIXME.
*/
func notUsHandler() dns.HandlerFunc {
	return func(w dns.ResponseWriter, r *dns.Msg) {
		q := r.Question[0]
		Debug.Printf("Non-local query: %+v", q)
		addrs, err := net.LookupIP(q.Name)
		var responseMsg *dns.Msg
		if err == nil {
			responseMsg = makeDNSReply(r, q.Name, q.Qtype, addrs)
		} else {
			responseMsg = makeDNSFailResponse(r)
			Debug.Print("Failed fallback lookup ", err)
		}
		w.WriteMsg(responseMsg)
	}
}

func StartServer(zone Zone, iface *net.Interface, dnsPort int, httpPort int, wait int) error {
	go ListenHttp(LOCAL_DOMAIN, zone, httpPort)

	mdnsClient, err := NewMDNSClient()
	checkFatal(err)

	ifaceName := "default interface"
	if iface != nil {
		ifaceName = iface.Name
	}
	Info.Printf("Using mDNS on %s", ifaceName)
	err = mdnsClient.Start(iface)
	checkFatal(err)

	LocalServeMux := dns.NewServeMux()
	LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler(zone, mdnsClient))
	LocalServeMux.HandleFunc(".", notUsHandler())

	mdnsServer, err := NewMDNSServer(zone)
	checkFatal(err)

	err = mdnsServer.Start(iface)
	checkFatal(err)

	address := fmt.Sprintf(":%d", dnsPort)
	Info.Printf("Listening for DNS on %s", address)
	err = dns.ListenAndServe(address, "udp", LocalServeMux)
	checkFatal(err)

	return nil
}
<|endoftext|>


<commit_before>package consensus

import (
	"fmt"
	"math"
	"math/big"
)

// A Currency represents a number of siacoins or siafunds. Internally, a
// Currency value is unbounded; however, Currency values sent over the wire
// protocol are subject to a maximum size of 255 bytes (approximately 10^614).
// Unlike the math/big library, whose methods modify their receiver, all
// arithmetic Currency methods return a new value. This is necessary to
// preserve the immutability of types containing Currency fields.
type Currency struct {
	i big.Int
}

// NewCurrency creates a Currency value from a big.Int.
func NewCurrency(b *big.Int) (c Currency) {
	c.i = *b
	return
}

// NewCurrency64 creates a Currency value from a uint64.
func NewCurrency64(x uint64) (c Currency) {
	c.i.SetUint64(x)
	return
}

// Big returns the value of c as a *big.Int. Importantly, it does not provide
// access to the c's internal big.Int object, only a copy. This is in
// accordance with the immutability constraint described above.
func (c Currency) Big() *big.Int {
	return new(big.Int).Set(&c.i)
}

// Cmp compares two Currency values. The return value follows the convention
// of the math/big package.
func (c Currency) Cmp(y Currency) int {
	return c.i.Cmp(&y.i)
}

// Sign returns the sign of a Currency. The return value follows of the
// convention of the math/big package.
func (c Currency) Sign() int {
	return c.i.Sign()
}

// Add returns a new Currency value y = c + x.
func (c Currency) Add(x Currency) (y Currency) {
	y.i.Add(&c.i, &x.i)
	return
}

// Sub returns a new Currency value y = c - x.
func (c Currency) Sub(x Currency) (y Currency) {
	y.i.Sub(&c.i, &x.i)
	return
}

// Mul returns a new Currency value y = c * x.
func (c Currency) Mul(x Currency) (y Currency) {
	y.i.Mul(&c.i, &x.i)
	return
}

// Div returns a new Currency value y = c / x.
func (c Currency) Div(x Currency) (y Currency) {
	y.i.Div(&c.i, &x.i)
	return
}

// MulFloat returns a new Currency value y = c * x, where x is a float64.
func (c Currency) MulFloat(x float64) (y Currency) {
	yRat := new(big.Rat).Mul(
		new(big.Rat).SetInt(&c.i),
		new(big.Rat).SetFloat64(x),
	)
	y.i.Div(yRat.Num(), yRat.Denom())
	return
}

// Sqrt returns a new Currency value y = sqrt(c)
func (c Currency) Sqrt() (y Currency) {
	f, _ := new(big.Rat).SetInt(&c.i).Float64()
	sqrt := new(big.Rat).SetFloat64(math.Sqrt(f))
	y.i.Div(sqrt.Num(), sqrt.Denom())
	return
}

// RoundDown returns the largest multiple of n <= c.
func (c Currency) RoundDown(n uint64) (y Currency) {
	diff := new(big.Int).Mod(&c.i, new(big.Int).SetUint64(n))
	y.i.Sub(&c.i, diff)
	return
}

// MarshalSia implements the encoding.SiaMarshaler interface. It returns the
// byte-slice representation of the Currency's internal big.Int, prepended
// with a single byte indicating the length of the slice. This implies a
// maximum encodable value of 2^(255 * 8), or approximately 10^614.
//
// Note that as the bytes of the big.Int correspond to the absolute value of
// the integer, there is no way to marshal a negative Currency.
func (c Currency) MarshalSia() []byte {
	b := c.i.Bytes()
	return append(
		[]byte{byte(len(b))},
		b...,
	)
}

// UnmarshalSia implements the encoding.SiaUnmarshaler interface. See
// MarshalSia for a description of how Currency values are marshalled.
func (c *Currency) UnmarshalSia(b []byte) int {
	var n int
	n, b = int(b[0]), b[1:]
	c.i.SetBytes(b[:n])
	return 1 + n
}

// MarshalJSON implements the json.Marshaler interface.
func (c Currency) MarshalJSON() ([]byte, error) {
	return c.i.MarshalJSON()
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (c *Currency) UnmarshalJSON(b []byte) error {
	return c.i.UnmarshalJSON(b)
}

// Scan implements the fmt.Scanner interface, allowing Currency values to be
// scanned from text.
func (c *Currency) Scan(s fmt.ScanState, ch rune) error {
	return c.i.Scan(s, ch)
}
<commit_msg>implement Currency String method<commit_after>package consensus

import (
	"fmt"
	"math"
	"math/big"
)

// A Currency represents a number of siacoins or siafunds. Internally, a
// Currency value is unbounded; however, Currency values sent over the wire
// protocol are subject to a maximum size of 255 bytes (approximately 10^614).
// Unlike the math/big library, whose methods modify their receiver, all
// arithmetic Currency methods return a new value. This is necessary to
// preserve the immutability of types containing Currency fields.
type Currency struct {
	i big.Int
}

// NewCurrency creates a Currency value from a big.Int.
func NewCurrency(b *big.Int) (c Currency) {
	c.i = *b
	return
}

// NewCurrency64 creates a Currency value from a uint64.
func NewCurrency64(x uint64) (c Currency) {
	c.i.SetUint64(x)
	return
}

// Big returns the value of c as a *big.Int. Importantly, it does not provide
// access to the c's internal big.Int object, only a copy. This is in
// accordance with the immutability constraint described above.
func (c Currency) Big() *big.Int {
	return new(big.Int).Set(&c.i)
}

// Cmp compares two Currency values. The return value follows the convention
// of the math/big package.
func (c Currency) Cmp(y Currency) int {
	return c.i.Cmp(&y.i)
}

// Sign returns the sign of a Currency. The return value follows of the
// convention of the math/big package.
func (c Currency) Sign() int {
	return c.i.Sign()
}

// Add returns a new Currency value y = c + x.
func (c Currency) Add(x Currency) (y Currency) {
	y.i.Add(&c.i, &x.i)
	return
}

// Sub returns a new Currency value y = c - x.
func (c Currency) Sub(x Currency) (y Currency) {
	y.i.Sub(&c.i, &x.i)
	return
}

// Mul returns a new Currency value y = c * x.
func (c Currency) Mul(x Currency) (y Currency) {
	y.i.Mul(&c.i, &x.i)
	return
}

// Div returns a new Currency value y = c / x.
func (c Currency) Div(x Currency) (y Currency) {
	y.i.Div(&c.i, &x.i)
	return
}

// MulFloat returns a new Currency value y = c * x, where x is a float64.
func (c Currency) MulFloat(x float64) (y Currency) {
	yRat := new(big.Rat).Mul(
		new(big.Rat).SetInt(&c.i),
		new(big.Rat).SetFloat64(x),
	)
	y.i.Div(yRat.Num(), yRat.Denom())
	return
}

// Sqrt returns a new Currency value y = sqrt(c)
func (c Currency) Sqrt() (y Currency) {
	f, _ := new(big.Rat).SetInt(&c.i).Float64()
	sqrt := new(big.Rat).SetFloat64(math.Sqrt(f))
	y.i.Div(sqrt.Num(), sqrt.Denom())
	return
}

// RoundDown returns the largest multiple of n <= c.
func (c Currency) RoundDown(n uint64) (y Currency) {
	diff := new(big.Int).Mod(&c.i, new(big.Int).SetUint64(n))
	y.i.Sub(&c.i, diff)
	return
}

// String implements the fmt.Stringer interface.
func (c Currency) String() string {
	return c.i.String()
}

// MarshalSia implements the encoding.SiaMarshaler interface. It returns the
// byte-slice representation of the Currency's internal big.Int, prepended
// with a single byte indicating the length of the slice. This implies a
// maximum encodable value of 2^(255 * 8), or approximately 10^614.
//
// Note that as the bytes of the big.Int correspond to the absolute value of
// the integer, there is no way to marshal a negative Currency.
func (c Currency) MarshalSia() []byte {
	b := c.i.Bytes()
	return append(
		[]byte{byte(len(b))},
		b...,
	)
}

// UnmarshalSia implements the encoding.SiaUnmarshaler interface. See
// MarshalSia for a description of how Currency values are marshalled.
func (c *Currency) UnmarshalSia(b []byte) int {
	var n int
	n, b = int(b[0]), b[1:]
	c.i.SetBytes(b[:n])
	return 1 + n
}

// MarshalJSON implements the json.Marshaler interface.
func (c Currency) MarshalJSON() ([]byte, error) {
	return c.i.MarshalJSON()
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (c *Currency) UnmarshalJSON(b []byte) error {
	return c.i.UnmarshalJSON(b)
}

// Scan implements the fmt.Scanner interface, allowing Currency values to be
// scanned from text.
func (c *Currency) Scan(s fmt.ScanState, ch rune) error {
	return c.i.Scan(s, ch)
}
<|endoftext|>


<commit_before>package main

import "net/http"
import "fmt"
import "html"
import "time"
import "io/ioutil"
import "strings"
import "./players"
func getPlayerOfIp(ip string) players.NetworkPlayer {
	for _, plr := range networkPlayerList {
		plrIp := plr.GetIp()
		if plrIp == ip[:strings.Index(ip, ":")] {
			return plr
		}
	}
	//for now, add a player to the list and return it
	networkPlayerList=append(networkPlayerList,players.NewNetworkPlayer("uwe",3,ip))
	return networkPlayerList[len(networkPlayerList)-1]
}
func fileServe(w http.ResponseWriter, r *http.Request) {
	b,_ := ioutil.ReadFile("client/"+html.EscapeString(r.URL.Path)[1:])
	if r.URL.Path[len(r.URL.Path)-4:] == ".css" {
		w.Header().Set("Content-Type", "text/css; charset=utf-8")
	}
	w.Write(b)
}
func eventFunc(w http.ResponseWriter, r *http.Request) {
	plr := getPlayerOfIp(r.RemoteAddr)
	for len(plr.GetDataToBeSent()) == 0 {
		time.Sleep(time.Second / 2)
	}
	_, err := w.Write(plr.GetDataToBeSent()[0])
	if err == nil {
		plr.RemoveASentData()
	}
}
func chatFunc(w http.ResponseWriter, r *http.Request) {
	chat := ""
	r.ParseForm()
	for key := range r.Form {
		chat=key
		break
	}

	plr := getPlayerOfIp(r.RemoteAddr)
	data := []byte("CHAT"+plr.GetName()+": "+chat)
	for _, plr2 := range networkPlayerList {
		plr2.SendData(data)
	}
}
func setupServer(quitChan chan struct{}) {
	http.HandleFunc("/ordos.html",fileServe)
	http.HandleFunc("/ordos.js",fileServe)
	http.HandleFunc("/ordos.css",fileServe)
	http.HandleFunc("/event",eventFunc)
	http.HandleFunc("/chat",chatFunc)
	go http.ListenAndServe(":8081",nil)
	fmt.Println("Server loaded")
}
<commit_msg>lets try something else<commit_after>package main

import "net/http"
import "fmt"
import "html"
import "time"
import "io/ioutil"
import "strings"
import "./players"
func getPlayerOfIp(ip string) players.NetworkPlayer {
	for _, plr := range networkPlayerList {
		plrIp := plr.GetIp()
		if plrIp == ip[:strings.Index(ip, ":")] {
			return plr
		}
	}
	//for now, add a player to the list and return it
	networkPlayerList=append(networkPlayerList,players.NewNetworkPlayer("uwe",3,ip))
	return networkPlayerList[len(networkPlayerList)-1]
}
func fileServe(w http.ResponseWriter, r *http.Request) {
	b,_ := ioutil.ReadFile("client/"+html.EscapeString(r.URL.Path)[1:])
	if r.URL.Path[len(r.URL.Path)-4:] == ".css" {
		w.Header().Set("Content-Type", "text/css; charset=utf-8")
	}
	w.Write(b)
}
func eventFunc(w http.ResponseWriter, r *http.Request) {
	plr := getPlayerOfIp(r.RemoteAddr)
	for len(plr.GetDataToBeSent()) == 0 {
		time.Sleep(time.Second / 2)
	}
	_, err := w.Write(plr.GetDataToBeSent()[0])
	if err == nil {
		plr.RemoveASentData()
	}
}
func chatFunc(w http.ResponseWriter, r *http.Request) {
	chat := ""
	r.ParseForm()
	for key := range r.Form {
		chat=key
		break
	}

	chat = strings.Replace(chat,"&","&",-1)
	chat = strings.Replace(chat,"<","<",-1)
	chat = strings.Replace(chat,">",">",-1)

	plr := getPlayerOfIp(r.RemoteAddr)
	data := []byte("CHAT"+plr.GetName()+": "+chat)
	for _, plr2 := range networkPlayerList {
		plr2.SendData(data)
	}
}
func setupServer(quitChan chan struct{}) {
	http.HandleFunc("/ordos.html",fileServe)
	http.HandleFunc("/ordos.js",fileServe)
	http.HandleFunc("/ordos.css",fileServe)
	http.HandleFunc("/event",eventFunc)
	http.HandleFunc("/chat",chatFunc)
	go http.ListenAndServe(":8081",nil)
	fmt.Println("Server loaded")
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"fmt"
	"strconv"
	"net/http"
	"io/ioutil"
	"encoding/json"
	"github.com/feeddageek/redstone.go/minecraft"
)

type Server struct {
	Jar	minecraft.Jar
	World	minecraft.World
	Port	uint16
	i	*minecraft.Instance
}

var s Server

//THE ROAD TO WISDOM
//Err and err and err again,
//but less and less and less.
func r2w(err error){
	if err != nil {
		log.Fatal(err)
	}
}

func ressourceHandler(w http.ResponseWriter, req *http.Request) {
	//TODO add a handler that serve static ressources
}

func loginHandler(w http.ResponseWriter, req *http.Request) {
	//TODO add a mechanism to handle authentication
}

func redstoneHandler(w http.ResponseWriter, req *http.Request) {
	if s.i!=nil  && s.i.Running(){
		w.Write([]byte("The server is running.\n"))
	} else {
		var err error
		s.i,err = minecraft.Start(s.Jar,s.World)
		if err != nil {
			w.Write([]byte("An error has occured.\n"))
			fmt.Fprintf(w, "Not started : %s", err.Error())
		} else {
			w.Write([]byte("Started.\n"))
		}
	}
}

func stopHandler(w http.ResponseWriter, req *http.Request) {
	if err := s.i.Stop(); err != nil {
		fmt.Fprintf(w, "Not stopped : %s", err.Error())
	} else {
		w.Write([]byte("Stopped.\n"))
	}
}

func main() {
	f,err:= ioutil.ReadFile("redstone.json")
	r2w(err)
	err = json.Unmarshal(f,&s)
	r2w(err)
	http.HandleFunc("/res/", ressourceHandler)
	http.HandleFunc("/redstone/", redstoneHandler)
	log.SetFlags(0)
	err = http.ListenAndServe(":"+strconv.Itoa(int(s.Port)), nil)
	r2w(err)
}
<commit_msg>Adding TSL support, closes #10<commit_after>package main

import (
	"log"
	"fmt"
	"strconv"
	"net/http"
	"io/ioutil"
	"encoding/json"
	"github.com/feeddageek/redstone.go/minecraft"
)

type Server struct {
	Jar	minecraft.Jar
	World	minecraft.World
	Port	uint16
	Conf	Httpconf
	i	*minecraft.Instance
}

type Httpconf struct {
	Port	uint16
	Tls	bool
	Cert	string
	Key	string
}

var s Server

//THE ROAD TO WISDOM
//Err and err and err again,
//but less and less and less.
func r2w(err error){
	if err != nil {
		log.Fatal(err)
	}
}

func ressourceHandler(w http.ResponseWriter, req *http.Request) {
	//TODO add a handler that serve static ressources
}

func loginHandler(w http.ResponseWriter, req *http.Request) {
	//TODO add a mechanism to handle authentication
}

func redstoneHandler(w http.ResponseWriter, req *http.Request) {
	if s.i!=nil  && s.i.Running(){
		w.Write([]byte("The server is running.\n"))
	} else {
		var err error
		s.i,err = minecraft.Start(s.Jar,s.World)
		if err != nil {
			w.Write([]byte("An error has occured.\n"))
			fmt.Fprintf(w, "Not started : %s", err.Error())
		} else {
			w.Write([]byte("Started.\n"))
		}
	}
}

func stopHandler(w http.ResponseWriter, req *http.Request) {
	if err := s.i.Stop(); err != nil {
		fmt.Fprintf(w, "Not stopped : %s", err.Error())
	} else {
		w.Write([]byte("Stopped.\n"))
	}
}

func main() {
	f,err:= ioutil.ReadFile("redstone.json")
	r2w(err)
	err = json.Unmarshal(f,&s)
	r2w(err)
	http.HandleFunc("/res/", ressourceHandler)
	http.HandleFunc("/redstone/", redstoneHandler)
	log.SetFlags(0)
	if !s.Conf.Tls || s.Conf.Key == "" || s.Conf.Cert == "" {
		err = http.ListenAndServe(":"+strconv.Itoa(int(s.Conf.Port)), nil)
	} else {
		err = http.ListenAndServeTLS(":"+strconv.Itoa(int(s.Conf.Port)),s.Conf.Cert,s.Conf.Key, nil)
	}
	r2w(err)
}
<|endoftext|>


<commit_before>// Package config contains: json.go - syslog.go
//
// Json reads and extracts the information JSON configuration file
//
package config

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

// Copy contains Clone options
type Copy struct {
	Enable	bool	`json:"enable"`
	Name	string	`json:"name"`
}

// Data contains the information of each dataset
type Data struct {
	Enable	bool	`json:"enable"`
	Name	string	`json:"name"`
	Snap	string	`json:"snapshot"`
	Retain	int	`json:"retain"`
	Backup	bool	`json:"backup"`
	Clone	Copy
	Roll	bool	`json:"rollback"`
}

// Pool extracts the interface of JSON file
type Pool struct {
	Dataset	[]Data	`json:"datasets"`
}

// Json reads the 'JSON' file and checks how many datasets are there
func JSON() (int, string, error) {
	w, _ := LogBook()
	jsonFile := "/usr/local/etc/zeplic.d/config.json"
	configFile, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		fmt.Printf("\nThe file '%s' does not exist! Please, check your configuration...\n\n", jsonFile)
		os.Exit(1)
	}
	var values Pool
	err = json.Unmarshal(configFile, &values)
	if err != nil {
		w.Err("[ERROR] config/json.go:40 *** Impossible to parse the JSON configuration file ***")
		os.Exit(1)
	}
	return len(values.Dataset), jsonFile, nil
}

// Extract returns the value of each configuration file field
func Extract(i int) ([]interface{}) {
	_, path, _ := JSON()
	configFile, _ := ioutil.ReadFile(path)
	var values Pool
	json.Unmarshal(configFile, &values)

	takedataset := values.Dataset[i].Enable
	clone := values.Dataset[i].Clone.Name
	dataset	:= values.Dataset[i].Name
	snap := values.Dataset[i].Snap
	retain := values.Dataset[i].Retain
	takebackup := values.Dataset[i].Backup
	takeclone := values.Dataset[i].Clone.Enable
	takerollback := values.Dataset[i].Roll

	pieces := []interface{}{takedataset, clone, dataset, snap, retain, takebackup, takeclone, takerollback}
	return pieces
}
<commit_msg>Revised for Side CI<commit_after>// Package config contains: json.go - syslog.go
//
// Json reads and extracts the information JSON configuration file
//
package config

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

// Copy contains Clone options
type Copy struct {
	Enable	bool	`json:"enable"`
	Name	string	`json:"name"`
}

// Data contains the information of each dataset
type Data struct {
	Enable	bool	`json:"enable"`
	Name	string	`json:"name"`
	Snap	string	`json:"snapshot"`
	Retain	int	`json:"retain"`
	Backup	bool	`json:"backup"`
	Clone	Copy
	Roll	bool	`json:"rollback"`
}

// Pool extracts the interface of JSON file
type Pool struct {
	Dataset	[]Data	`json:"datasets"`
}

// JSON reads the 'JSON' file and checks how many datasets are there
func JSON() (int, string, error) {
	w, _ := LogBook()
	jsonFile := "/usr/local/etc/zeplic.d/config.json"
	configFile, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		fmt.Printf("\nThe file '%s' does not exist! Please, check your configuration...\n\n", jsonFile)
		os.Exit(1)
	}
	var values Pool
	err = json.Unmarshal(configFile, &values)
	if err != nil {
		w.Err("[ERROR] config/json.go:40 *** Impossible to parse the JSON configuration file ***")
		os.Exit(1)
	}
	return len(values.Dataset), jsonFile, nil
}

// Extract returns the value of each configuration file field
func Extract(i int) ([]interface{}) {
	_, path, _ := JSON()
	configFile, _ := ioutil.ReadFile(path)
	var values Pool
	json.Unmarshal(configFile, &values)

	takedataset := values.Dataset[i].Enable
	clone := values.Dataset[i].Clone.Name
	dataset	:= values.Dataset[i].Name
	snap := values.Dataset[i].Snap
	retain := values.Dataset[i].Retain
	takebackup := values.Dataset[i].Backup
	takeclone := values.Dataset[i].Clone.Enable
	takerollback := values.Dataset[i].Roll

	pieces := []interface{}{takedataset, clone, dataset, snap, retain, takebackup, takeclone, takerollback}
	return pieces
}
<|endoftext|>