<commit_before>// chris 072815

package rebnf

import (
	"errors"
	"io"
	"unicode"

	mathrand "math/rand"
	"unicode/utf8"

	fixrand "chrispennello.com/go/util/fix/math/rand"
	"golang.org/x/exp/ebnf"
)

const (
	maxRepetitions = 100
	maxRecursionDepth = 100
)

// ErrNoStart is returned by Random when the specified start production
// cannot be found in the grammar.
var ErrNoStart = errors.New("start production not found")

// Random generates random productions of the given grammar starting at
// the given start production, and writes them into the destination
// io.Writer.
func Random(dst io.Writer, grammar ebnf.Grammar, start string) error {
	prod, ok := grammar[start]
	if !ok {
		return ErrNoStart
	}
	return random(dst, grammar, prod.Expr, 0)
}

// IsCapital returns a boolean indicating whether or not the first rune
// of the given string is upper case.
func IsCapital(s string) bool {
	ch, _ := utf8.DecodeRuneInString(s)
	return !unicode.IsUpper(ch)
}

// IsTerminal returns a boolean that indicates whether the given
// Expression is a terminal one.  Ranges and Tokens are unconditionally
// considered to be terminal, and Names are terminal iff they're
// capitalized.  Productions are not considered because Alternatives
// contain Names, and you have to loo up the production by name in the
// grammar--it's just not a use case handled by this library, but could
// be added easily if needed.
func IsTerminal(expr ebnf.Expression) bool {
	switch expr.(type) {
	case *ebnf.Name:
		name := expr.(*ebnf.Name)
		return !IsCapital(name.String)
	case *ebnf.Range:
		return true
	case *ebnf.Token:
		return true
	default:
		return false
	}
}

// findTerminals is like filter(IsTerminal, exprs).  It ranges over all
// of the given expressions and produces a new slice of expressions
// containing only those for which IsTerminal returns true.
func findTerminals(exprs []ebnf.Expression) []ebnf.Expression {
	r := make([]ebnf.Expression, 0, len(exprs))
	for _, expr := range exprs {
		if IsTerminal(expr) {
			r = append(r, expr)
		}
	}
	return r
}

// random is the inner, recursive implementation of Random.  It handles
// each of the ebnf.Expression implementations, outputting productions
// randomly to the destination writer.  It implements a recursion depth
// counter, and once the counter exceeds the limit, it favors producing
// terminals over non-terminals.  Note that this does not guarantee
// termination, however.  For example, the pathological grammar "S = S"
// will loop forever.
func random(dst io.Writer, grammar ebnf.Grammar, expr ebnf.Expression, depth int) error {
	switch expr.(type) {
	// Choose a random alternative.
	case ebnf.Alternative:
		alt := expr.(ebnf.Alternative)
		var exprs []ebnf.Expression
		// If maximum recursion depth has been exceeded, attempt
		// to select from only terminal expressions.
		if depth > maxRecursionDepth {
			exprs = findTerminals(alt)
			if len(exprs) == 0 {
				// No luck, we have no choice but to
				// explore one of the non-terminals in
				// this alternative.
				exprs = alt
			}
		} else {
			exprs = alt
		}
		err := random(dst, grammar, exprs[mathrand.Intn(len(exprs))], depth + 1)
		if err != nil {
			return err
		}

	// Evalute the group.
	case *ebnf.Group:
		gr := expr.(*ebnf.Group)
		err := random(dst, grammar, gr.Body, depth + 1)
		if err != nil {
			return err
		}

	// The name refers to a production; look it up and continue the
	// recursion.
	case *ebnf.Name:
		name := expr.(*ebnf.Name)
		err := random(dst, grammar, grammar[name.String], depth + 1)
		if err != nil {
			return err
		}

	// Randomly include the option.
	case *ebnf.Option:
		opt := expr.(*ebnf.Option)
		// If recursion depth has been exceeded, and option is
		// non-termainl, unconditionally omit.
		if depth > maxRecursionDepth && !IsTerminal(opt.Body) {
			// Omit.
		} else if fixrand.Bool() {
			// Otherwise, proceed with usual random
			// inclusion of option.
			err := random(dst, grammar, opt.Body, depth + 1)
			if err != nil {
				return err
			}
		}

	// Produce the production.
	case *ebnf.Production:
		prod := expr.(*ebnf.Production)
		err := random(dst, grammar, prod.Expr, depth + 1)
		if err != nil {
			return err
		}

	// Generate a random string in the given range.
	case *ebnf.Range:
		rng := expr.(*ebnf.Range)
		ch, err := fixrand.ChooseString(rng.Begin.String, rng.End.String)
		if err != nil {
			return err
		}
		if _, err := io.WriteString(dst, ch); err != nil {
			return err
		}

	// Choose a random number of repetitions.
	case *ebnf.Repetition:
		rep := expr.(*ebnf.Repetition)
		// If the recursion depth has been exceeded, and the
		// repetition is non-terminal, unconditionally omit it.
		if depth > maxRecursionDepth && !IsTerminal(rep.Body) {
			// Omit.
		} else {
			// Otherwise, do normal inclusion of a random
			// number of repetitions.
			for i := 0; i < mathrand.Intn(maxRepetitions+1); i++ {
				err := random(dst, grammar, rep.Body, depth + 1)
				if err != nil {
					return err
				}
			}
		}

	// Recurse on each of the expressions.
	case ebnf.Sequence:
		seq := expr.(ebnf.Sequence)
		for _, e := range seq {
			err := random(dst, grammar, e, depth + 1)
			if err != nil {
				return err
			}
		}

	// Emit the token.
	case *ebnf.Token:
		tok := expr.(*ebnf.Token)
		if _, err := io.WriteString(dst, tok.String); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Updates based on go fmt output.<commit_after>// chris 072815

package rebnf

import (
	"errors"
	"io"
	"unicode"

	mathrand "math/rand"
	"unicode/utf8"

	fixrand "chrispennello.com/go/util/fix/math/rand"
	"golang.org/x/exp/ebnf"
)

const (
	maxRepetitions    = 100
	maxRecursionDepth = 100
)

// ErrNoStart is returned by Random when the specified start production
// cannot be found in the grammar.
var ErrNoStart = errors.New("start production not found")

// Random generates random productions of the given grammar starting at
// the given start production, and writes them into the destination
// io.Writer.
func Random(dst io.Writer, grammar ebnf.Grammar, start string) error {
	prod, ok := grammar[start]
	if !ok {
		return ErrNoStart
	}
	return random(dst, grammar, prod.Expr, 0)
}

// IsCapital returns a boolean indicating whether or not the first rune
// of the given string is upper case.
func IsCapital(s string) bool {
	ch, _ := utf8.DecodeRuneInString(s)
	return !unicode.IsUpper(ch)
}

// IsTerminal returns a boolean that indicates whether the given
// Expression is a terminal one.  Ranges and Tokens are unconditionally
// considered to be terminal, and Names are terminal iff they're
// capitalized.  Productions are not considered because Alternatives
// contain Names, and you have to loo up the production by name in the
// grammar--it's just not a use case handled by this library, but could
// be added easily if needed.
func IsTerminal(expr ebnf.Expression) bool {
	switch expr.(type) {
	case *ebnf.Name:
		name := expr.(*ebnf.Name)
		return !IsCapital(name.String)
	case *ebnf.Range:
		return true
	case *ebnf.Token:
		return true
	default:
		return false
	}
}

// findTerminals is like filter(IsTerminal, exprs).  It ranges over all
// of the given expressions and produces a new slice of expressions
// containing only those for which IsTerminal returns true.
func findTerminals(exprs []ebnf.Expression) []ebnf.Expression {
	r := make([]ebnf.Expression, 0, len(exprs))
	for _, expr := range exprs {
		if IsTerminal(expr) {
			r = append(r, expr)
		}
	}
	return r
}

// random is the inner, recursive implementation of Random.  It handles
// each of the ebnf.Expression implementations, outputting productions
// randomly to the destination writer.  It implements a recursion depth
// counter, and once the counter exceeds the limit, it favors producing
// terminals over non-terminals.  Note that this does not guarantee
// termination, however.  For example, the pathological grammar "S = S"
// will loop forever.
func random(dst io.Writer, grammar ebnf.Grammar, expr ebnf.Expression, depth int) error {
	switch expr.(type) {
	// Choose a random alternative.
	case ebnf.Alternative:
		alt := expr.(ebnf.Alternative)
		var exprs []ebnf.Expression
		// If maximum recursion depth has been exceeded, attempt
		// to select from only terminal expressions.
		if depth > maxRecursionDepth {
			exprs = findTerminals(alt)
			if len(exprs) == 0 {
				// No luck, we have no choice but to
				// explore one of the non-terminals in
				// this alternative.
				exprs = alt
			}
		} else {
			exprs = alt
		}
		err := random(dst, grammar, exprs[mathrand.Intn(len(exprs))], depth+1)
		if err != nil {
			return err
		}

	// Evalute the group.
	case *ebnf.Group:
		gr := expr.(*ebnf.Group)
		err := random(dst, grammar, gr.Body, depth+1)
		if err != nil {
			return err
		}

	// The name refers to a production; look it up and continue the
	// recursion.
	case *ebnf.Name:
		name := expr.(*ebnf.Name)
		err := random(dst, grammar, grammar[name.String], depth+1)
		if err != nil {
			return err
		}

	// Randomly include the option.
	case *ebnf.Option:
		opt := expr.(*ebnf.Option)
		// If recursion depth has been exceeded, and option is
		// non-termainl, unconditionally omit.
		if depth > maxRecursionDepth && !IsTerminal(opt.Body) {
			// Omit.
		} else if fixrand.Bool() {
			// Otherwise, proceed with usual random
			// inclusion of option.
			err := random(dst, grammar, opt.Body, depth+1)
			if err != nil {
				return err
			}
		}

	// Produce the production.
	case *ebnf.Production:
		prod := expr.(*ebnf.Production)
		err := random(dst, grammar, prod.Expr, depth+1)
		if err != nil {
			return err
		}

	// Generate a random string in the given range.
	case *ebnf.Range:
		rng := expr.(*ebnf.Range)
		ch, err := fixrand.ChooseString(rng.Begin.String, rng.End.String)
		if err != nil {
			return err
		}
		if _, err := io.WriteString(dst, ch); err != nil {
			return err
		}

	// Choose a random number of repetitions.
	case *ebnf.Repetition:
		rep := expr.(*ebnf.Repetition)
		// If the recursion depth has been exceeded, and the
		// repetition is non-terminal, unconditionally omit it.
		if depth > maxRecursionDepth && !IsTerminal(rep.Body) {
			// Omit.
		} else {
			// Otherwise, do normal inclusion of a random
			// number of repetitions.
			for i := 0; i < mathrand.Intn(maxRepetitions+1); i++ {
				err := random(dst, grammar, rep.Body, depth+1)
				if err != nil {
					return err
				}
			}
		}

	// Recurse on each of the expressions.
	case ebnf.Sequence:
		seq := expr.(ebnf.Sequence)
		for _, e := range seq {
			err := random(dst, grammar, e, depth+1)
			if err != nil {
				return err
			}
		}

	// Emit the token.
	case *ebnf.Token:
		tok := expr.(*ebnf.Token)
		if _, err := io.WriteString(dst, tok.String); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package lshw

//
// A simple wrapper for lshw
//

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"sync"
)

type Class string

const (
	// used to refer to the whole machine (laptop, server, desktop computer)
	Systems Class = "system"
	// internal bus converter (PCI-to-PCI brige, AGP bridge, PCMCIA controler, host bridge)
	Bridge Class = "bridge"
	// memory bank that can contain data, executable code, etc.
	// RAM, BIOS, firmware, extension ROM
	Memory Class = "memory"
	// execution processor	 (CPUs, RAID controller on a SCSI bus)
	Processor Class = "processor"
	// memory address range extension ROM, video memory
	Address Class = "address"
	// storage controller	(SCSI controller, IDE controller)
	Storage Class = "storage"
	// random-access storage device discs, optical storage (CD-ROM, DVD±RW...)
	Disk Class = "disk"
	// sequential-access storage device (DAT, DDS)
	Tape Class = "tape"
	// device-connecting bus (USB, SCSI, Firewire)
	Bus Class = "bus"
	// network interface (Ethernet, FDDI, WiFi, Bluetooth)
	Network Class = "network"
	// display adapter (EGA/VGA, UGA...)
	Display Class = "display"
	// user input device (keyboards, mice, joysticks...)
	Input Class = "input"
	// printing device (printer, all-in-one)
	Printer Class = "printer"
	// audio/video device (sound card, TV-output card, video acquisition card)
	Multimedia Class = "multimedia"
	// line communication device (serial ports, modem)
	Communication Class = "communication"
	// energy source (power supply, internal battery)
	Power Class = "power"
	// disk volume	(filesystem, swap, etc.)
	Volume Class = "volume"
	// generic device (used when no pre-defined class is suitable)
	Generic Class = "generic"
	// Print everything
	All Class = "all"
)

type Format string

const (
	FormatXML     Format = "-xml"     // output hardware tree as XML
	FormatJSON    Format = "-json"    // output hardware tree as JSON
	FormatHTML    Format = "-html"    // output hardware tree as HTML
	FormatShort   Format = "-short"   // output hardware paths
	FormatBusinfo Format = "-businfo" // output bus information
	FormatEmpty   Format = ""
)

type Config struct {
	Class  Class
	Format Format
}

type lshw struct {
	cmd    *exec.Cmd
	config *Config
	lock   sync.Mutex
}

func New(path string, config *Config) (l *lshw, err error) {
	l = new(lshw)
	if path == "" {
		path, err = exec.LookPath("lshw")
		if err != nil {
			return
		}
	}
	l.cmd = exec.Command(path)
	l.config = config
	return
}

func (l *lshw) cmdreset() {
	l.lock.Lock()
	l.cmd.Args = l.cmd.Args[:1]
	l.lock.Unlock()
}

func (l *lshw) SetClass(class Class) {
	l.lock.Lock()
	l.config.Class = class
	l.lock.Unlock()
}

func (l *lshw) SetFormat(format Format) {
	l.lock.Lock()
	l.config.Format = format
	l.lock.Unlock()
}

func (l *lshw) SetConfig(config *Config) {
	l.lock.Lock()
	l.config = config
	l.lock.Unlock()
}

func (l *lshw) Cmd() string {
	return strings.Join(l.cmd.Args, " ")
}

func (l *lshw) Execute() (out []byte, err error) {
	l.cmdreset()

	l.lock.Lock()
	defer l.lock.Unlock()

	if l.config.Class != All {
		l.cmd.Args = append(l.cmd.Args, []string{"-C", string(l.config.Class)}...)
	}
	if l.config.Format != FormatEmpty {
		l.cmd.Args = append(l.cmd.Args, string(l.config.Format))
	}
	out, err = l.cmd.CombinedOutput()
	if err != nil {
		err = fmt.Errorf("%s [%s]", out, err)
	}
	return
}

func (l *lshw) WriteToFile(file string) error {
	out, err := l.Execute()
	if err != nil {
		return err
	}
	l.lock.Lock()
	defer l.lock.Unlock()

	if err := ioutil.WriteFile(file, out, 0); err != nil {
		return err
	}
	return nil
}

func (l *lshw) WriteToStdout() error {
	out, err := l.Execute()
	if err != nil {
		return err
	}
	l.lock.Lock()
	defer l.lock.Unlock()

	_, err = os.Stdout.Write(out)
	return err
}

func (l *lshw) Version() (string, error) {
	l.cmdreset()
	l.cmd.Args = append(l.cmd.Args, "-version")
	ver, err := l.cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("%s [%s]", ver, err)
	}
	return string(ver), nil
}
<commit_msg>Adding makeCmd for lshw<commit_after>package lshw

//
// A simple wrapper for lshw
//

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"sync"
)

type Class string

const (
	// used to refer to the whole machine (laptop, server, desktop computer)
	Systems Class = "system"
	// internal bus converter (PCI-to-PCI brige, AGP bridge, PCMCIA controler, host bridge)
	Bridge Class = "bridge"
	// memory bank that can contain data, executable code, etc.
	// RAM, BIOS, firmware, extension ROM
	Memory Class = "memory"
	// execution processor	 (CPUs, RAID controller on a SCSI bus)
	Processor Class = "processor"
	// memory address range extension ROM, video memory
	Address Class = "address"
	// storage controller	(SCSI controller, IDE controller)
	Storage Class = "storage"
	// random-access storage device discs, optical storage (CD-ROM, DVD±RW...)
	Disk Class = "disk"
	// sequential-access storage device (DAT, DDS)
	Tape Class = "tape"
	// device-connecting bus (USB, SCSI, Firewire)
	Bus Class = "bus"
	// network interface (Ethernet, FDDI, WiFi, Bluetooth)
	Network Class = "network"
	// display adapter (EGA/VGA, UGA...)
	Display Class = "display"
	// user input device (keyboards, mice, joysticks...)
	Input Class = "input"
	// printing device (printer, all-in-one)
	Printer Class = "printer"
	// audio/video device (sound card, TV-output card, video acquisition card)
	Multimedia Class = "multimedia"
	// line communication device (serial ports, modem)
	Communication Class = "communication"
	// energy source (power supply, internal battery)
	Power Class = "power"
	// disk volume	(filesystem, swap, etc.)
	Volume Class = "volume"
	// generic device (used when no pre-defined class is suitable)
	Generic Class = "generic"
	// Print everything
	All Class = "all"
)

type Format string

const (
	FormatXML     Format = "-xml"     // output hardware tree as XML
	FormatJSON    Format = "-json"    // output hardware tree as JSON
	FormatHTML    Format = "-html"    // output hardware tree as HTML
	FormatShort   Format = "-short"   // output hardware paths
	FormatBusinfo Format = "-businfo" // output bus information
	FormatEmpty   Format = ""
)

type Config struct {
	Class  Class
	Format Format
}

type lshw struct {
	cmd    *exec.Cmd
	config *Config
	lock   sync.Mutex
}

func New(path string, config *Config) (l *lshw, err error) {
	l = new(lshw)
	if path == "" {
		path, err = exec.LookPath("lshw")
		if err != nil {
			return
		}
	}
	l.cmd = exec.Command(path)
	l.config = config
	return
}

func (l *lshw) cmdreset() {
	l.lock.Lock()
	l.cmd.Args = l.cmd.Args[:1]
	l.lock.Unlock()
}

func (l *lshw) SetClass(class Class) {
	l.lock.Lock()
	l.config.Class = class
	l.lock.Unlock()
}

func (l *lshw) SetFormat(format Format) {
	l.lock.Lock()
	l.config.Format = format
	l.lock.Unlock()
}

func (l *lshw) SetConfig(config *Config) {
	l.lock.Lock()
	l.config = config
	l.lock.Unlock()
}

func (l *lshw) Cmd() string {
	l.makeCmd()
	return strings.Join(l.cmd.Args, " ")
}

func (l *lshw) Execute() (out []byte, err error) {
	l.cmdreset()

	l.lock.Lock()
	defer l.lock.Unlock()

	l.makeCmd()
	out, err = l.cmd.CombinedOutput()
	if err != nil {
		err = fmt.Errorf("%s [%s]", out, err)
	}
	return
}

func (l *lshw) WriteToFile(file string) error {
	out, err := l.Execute()
	if err != nil {
		return err
	}
	l.lock.Lock()
	defer l.lock.Unlock()

	if err := ioutil.WriteFile(file, out, 0); err != nil {
		return err
	}
	return nil
}

func (l *lshw) WriteToStdout() error {
	out, err := l.Execute()
	if err != nil {
		return err
	}
	l.lock.Lock()
	defer l.lock.Unlock()

	_, err = os.Stdout.Write(out)
	return err
}

func (l *lshw) Version() (string, error) {
	l.cmdreset()
	l.cmd.Args = append(l.cmd.Args, "-version")
	ver, err := l.cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("%s [%s]", ver, err)
	}
	return string(ver), nil
}

func (l *lshw) makeCmd() {
	if l.config.Class != All {
		l.cmd.Args = append(l.cmd.Args, []string{"-C", string(l.config.Class)}...)
	}
	if l.config.Format != FormatEmpty {
		l.cmd.Args = append(l.cmd.Args, string(l.config.Format))
	}
}
<|endoftext|>


<commit_before>// Package herots provide fast way to create TLS services: server and client.
//
// Explanation of the name: HERald Of The Swarm
//
// By the way - have a nice day :)
package herots

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
)

////////////////////////////////////////////////////////////////////////////////
//                             Shared functions                               //
////////////////////////////////////////////////////////////////////////////////

// log - struct for internal log service
type log struct {
	LogLevel       int
	LogDestination io.Writer
}

func (l *log) Log(msg string, lvl int) {
	if l.LogLevel == 0 {
		return
	}

	if l.LogLevel <= lvl {
		fmt.Fprintf(l.LogDestination, "herots: %s\n", msg)
	}
}

////////////////////////////////////////////////////////////////////////////////
//                                  Server                                    //
////////////////////////////////////////////////////////////////////////////////

// Server - primary struct for server implementation.
type Server struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		pool struct {
			IsSet bool
			Pool  *x509.CertPool
		}
	}
	listener net.Listener
	logger   *log
}

// predefined errors messages
const (
	LoadKeyPairError      = "herots: load key pair error"
	LoadClientCaCertError = "herots srv: load client CA cert error"
	StartServerError      = "herots srv: start tls server error"
	NoKeyPairLoad         = "herots: no load key pair (use LoadKeyPair func)"
	AcceptConnError       = "herots srv: connection accept error"
)

// Options - structure, which is used to configure a TLS server and client.
type Options struct {
	// Server host.
	//
	// Default: '127.0.0.1'.
	Host string

	// Server port.
	//
	// Default: '9000'.
	Port int

	// LogLevel provides the opportunity to choose the level of
	// information messages.
	// Each level includes the messages from the previous level.
	// 0 - no messages
	// 1 - notice
	// 2 - info
	// 3 - error
	//
	// Default: '0'.
	LogLevel int

	// LogDestination provides the opportunity to choose the own
	// destination for log messages (errors, info, etc).
	//
	// Default: 'os.Stdout'.
	LogDestination io.Writer

	// TLSAuthType - refer to http://golang.org/pkg/crypto/tls/#ClientAuthType
	//
	// This option ignored for client implementation.
	//
	// Default: tls.RequireAnyClientCert
	TLSAuthType tls.ClientAuthType
}

// NewServer - function for create Server struct
func NewServer(o *Options) *Server {
	s := &Server{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	if o.TLSAuthType == 0 {
		o.TLSAuthType = tls.RequireAnyClientCert
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
	}

	s.options = o
	s.logger = l

	return s
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (s *Server) LoadKeyPair(cert, key []byte) error {
	// create cert pool
	s.certs.pool.Pool = x509.NewCertPool()

	// load keypair
	c, err := tls.X509KeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}
	s.certs.Cert = c

	// add cert to pool
	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}
	s.certs.pool.Pool.AddCert(ca)
	s.certs.pool.IsSet = true

	s.logger.Log("load key pair ok", 2)

	return nil
}

// AddClientCACert - function for adding client CA certificate to
// x509.CertPool (tls.Config.ClientCAs).
//
// By default server add cert from server public/private key pair (LoadKeyPair)
// to cert pool.
func (s *Server) AddClientCACert(cert []byte) error {
	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadClientCaCertError, err)
	}
	s.certs.pool.Pool.AddCert(ca)

	s.logger.Log("load client CA cert ok", 2)

	return nil
}

// Accept - accept and return connections.
func (s *Server) Accept() (net.Conn, error) {
	conn, err := s.listener.Accept()
	if err != nil {
		s.logger.Log("accept conn error: "+err.Error(), 3)
		return conn, fmt.Errorf("%s: %v\n", AcceptConnError, err)
	}
	s.logger.Log("accepted conn from "+conn.RemoteAddr().String(), 2)
	return conn, nil
}

// Start - function for start server.
func (s *Server) Start() error {
	// load keypair check
	if len(s.certs.Cert.Certificate) == 0 {
		return fmt.Errorf("%s\n", NoKeyPairLoad)
	}

	config := tls.Config{
		ClientAuth:   s.options.TLSAuthType,
		Certificates: []tls.Certificate{s.certs.Cert},
		ClientCAs:    s.certs.pool.Pool,
		Rand:         rand.Reader,
	}

	service := s.options.Host + ":" + strconv.Itoa(s.options.Port)

	listener, err := tls.Listen("tcp", service, &config)
	if err != nil {
		return fmt.Errorf("%s: %v\n", StartServerError, err)
	}
	s.listener = listener

	s.logger.Log("listening on "+service, 1)

	return nil
}
<commit_msg>create external keypair loader & refactor Server for new keypair loader<commit_after>// Package herots provide fast way to create TLS services: server and client.
//
// Explanation of the name: HERald Of The Swarm
//
// By the way - have a nice day :)
package herots

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
)

////////////////////////////////////////////////////////////////////////////////
//                             Shared functions                               //
////////////////////////////////////////////////////////////////////////////////

// log - struct for internal log service
type log struct {
	LogLevel       int
	LogDestination io.Writer
}

func (l *log) Log(msg string, lvl int) {
	if l.LogLevel == 0 {
		return
	}

	if l.LogLevel <= lvl {
		fmt.Fprintf(l.LogDestination, "herots: %s\n", msg)
	}
}

// loadKeyPair - internal function for load certificate and private key pair.
func loadKeyPair(cert, key []byte) (tls.Certificate, *x509.Certificate, error) {
	c, err := tls.X509KeyPair(cert, key)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return tls.Certificate{}, &x509.Certificate{}, err
	}

	return c, ca, nil
}

////////////////////////////////////////////////////////////////////////////////
//                                  Server                                    //
////////////////////////////////////////////////////////////////////////////////

// Server - primary struct for server implementation.
type Server struct {
	options *Options
	certs   struct {
		Cert tls.Certificate
		pool struct {
			IsSet bool
			Pool  *x509.CertPool
		}
	}
	listener net.Listener
	logger   *log
}

// predefined errors messages
const (
	LoadKeyPairError      = "herots: load key pair error"
	LoadClientCaCertError = "herots srv: load client CA cert error"
	StartServerError      = "herots srv: start tls server error"
	NoKeyPairLoad         = "herots: no load key pair (use LoadKeyPair func)"
	AcceptConnError       = "herots srv: connection accept error"
)

// Options - structure, which is used to configure a TLS server and client.
type Options struct {
	// Server host.
	//
	// Default: '127.0.0.1'.
	Host string

	// Server port.
	//
	// Default: '9000'.
	Port int

	// LogLevel provides the opportunity to choose the level of
	// information messages.
	// Each level includes the messages from the previous level.
	// 0 - no messages
	// 1 - notice
	// 2 - info
	// 3 - error
	//
	// Default: '0'.
	LogLevel int

	// LogDestination provides the opportunity to choose the own
	// destination for log messages (errors, info, etc).
	//
	// Default: 'os.Stdout'.
	LogDestination io.Writer

	// TLSAuthType - refer to http://golang.org/pkg/crypto/tls/#ClientAuthType
	//
	// This option ignored for client implementation.
	//
	// Default: tls.RequireAnyClientCert
	TLSAuthType tls.ClientAuthType
}

// NewServer - function for create Server struct
func NewServer(o *Options) *Server {
	s := &Server{}

	// check mandatory options
	if o.LogDestination == nil {
		o.LogDestination = os.Stdout
	}

	if o.Port == 0 {
		o.Port = 9000
	}

	if o.TLSAuthType == 0 {
		o.TLSAuthType = tls.RequireAnyClientCert
	}

	l := &log{
		LogLevel:       o.LogLevel,
		LogDestination: o.LogDestination,
	}

	s.options = o
	s.logger = l

	return s
}

// LoadKeyPair - function for load certificate and private key pair.
//
// Public/private key pair require as PEM encoded data.
func (s *Server) LoadKeyPair(cert, key []byte) error {
	c, ca, err := loadKeyPair(cert, key)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadKeyPairError, err)
	}

	s.certs.Cert = c

	s.certs.pool.Pool = x509.NewCertPool()
	s.certs.pool.Pool.AddCert(ca)
	s.certs.pool.IsSet = true

	return nil
}

// AddClientCACert - function for adding client CA certificate to
// x509.CertPool (tls.Config.ClientCAs).
//
// By default server add cert from server public/private key pair (LoadKeyPair)
// to cert pool.
func (s *Server) AddClientCACert(cert []byte) error {
	pemData, _ := pem.Decode(cert)
	ca, err := x509.ParseCertificate(pemData.Bytes)
	if err != nil {
		return fmt.Errorf("%s: %v\n", LoadClientCaCertError, err)
	}
	s.certs.pool.Pool.AddCert(ca)

	s.logger.Log("load client CA cert ok", 2)

	return nil
}

// Accept - accept and return connections.
func (s *Server) Accept() (net.Conn, error) {
	conn, err := s.listener.Accept()
	if err != nil {
		s.logger.Log("accept conn error: "+err.Error(), 3)
		return conn, fmt.Errorf("%s: %v\n", AcceptConnError, err)
	}
	s.logger.Log("accepted conn from "+conn.RemoteAddr().String(), 2)
	return conn, nil
}

// Start - function for start server.
func (s *Server) Start() error {
	// load keypair check
	if len(s.certs.Cert.Certificate) == 0 {
		return fmt.Errorf("%s\n", NoKeyPairLoad)
	}

	config := tls.Config{
		ClientAuth:   s.options.TLSAuthType,
		Certificates: []tls.Certificate{s.certs.Cert},
		ClientCAs:    s.certs.pool.Pool,
		Rand:         rand.Reader,
	}

	service := s.options.Host + ":" + strconv.Itoa(s.options.Port)

	listener, err := tls.Listen("tcp", service, &config)
	if err != nil {
		return fmt.Errorf("%s: %v\n", StartServerError, err)
	}
	s.listener = listener

	s.logger.Log("listening on "+service, 1)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	fmt.Println("Initializing Octave CPU...")
	cpu := &CPU{running: true, sp: 65535}

	file, err := os.Open(os.Args[1])

	if err != nil {
		return
	}

	defer file.Close()

	cpu.memory, err = ioutil.ReadAll(file)

	cpu.stack = stack{cpu}
	cpu.devices[0] = cpu.stack
	cpu.devices[1] = tty{bufio.NewReader(os.Stdin)}

	if err != nil {
		return
	}

	for cpu.running {
		inst_byte := fetch(cpu)
		inst_func := decode(inst_byte)
		inst_func(inst_byte, cpu)
	}
}

type CPU struct {
	memory    []uint8
	registers [4]uint8
	pc        uint16
	sp        uint16
	running   bool
	result    uint8
	devices   [8]Device
	stack     stack
}

type instruction func(uint8, *CPU)

type Device interface {
	read() uint8
	write(uint8)
}

type tty struct {
	reader *bufio.Reader
}

func (t tty) read() uint8 {
	b, _ := t.reader.ReadByte()
	return b
}

func (t tty) write(char uint8) {
	fmt.Printf("%c", char)
}

type stack struct {
	cpu *CPU
}

func (s stack) read() uint8 {
	value := s.cpu.memory[s.cpu.sp]
	s.cpu.sp++
	return value
}

func (s stack) write(char uint8) {
	s.cpu.memory[s.cpu.sp] = char
	s.cpu.sp--
}

func fetch(cpu *CPU) uint8 {
	inst := cpu.memory[cpu.pc]
	cpu.pc = cpu.pc + 1
	return inst
}

func decode(i uint8) instruction {
	inst := illegal

	switch i >> 5 {
	case 0:
		fmt.Fprint(os.Stderr, "jmp\n")
		inst = jmp
	case 1:
		fmt.Fprint(os.Stderr, "loadi\n")
		inst = loadi
	case 2:
		fmt.Fprint(os.Stderr, "math\n")
		inst = math
	case 3:
		fmt.Fprint(os.Stderr, "logic\n")
		inst = logic
	case 4:
		fmt.Fprint(os.Stderr, "mem\n")
		inst = mem
	case 5:
		fmt.Fprint(os.Stderr, "stack\n")
		inst = stacki
	case 6:
		fmt.Fprint(os.Stderr, "in\n")
		inst = in
	case 7:
		fmt.Fprint(os.Stderr, "out\n")
		inst = out
	}

	return inst
}

func jmp(i uint8, cpu *CPU) {
	if i == 0 {
		cpu.running = false
	}

	register := i << 3 >> 6
	n := i << 5 >> 7
	z := i << 6 >> 7
	p := i << 7 >> 7

	if (n == 1 && cpu.result < 0) || (z == 1 && cpu.result == 0) || (p == 1 && cpu.result > 0) {
		offset := int8(cpu.registers[register])
		fmt.Fprintf(os.Stderr, "Taking jump to %v\n", offset)
		cpu.pc = uint16(int32(cpu.pc) + int32(offset))
	}
}

func loadi(i uint8, cpu *CPU) {
	location := i << 3 >> 7

	if location == 0 {
		cpu.registers[0] = (i << 4) | (cpu.registers[0] << 4 >> 4)
	} else {
		cpu.registers[0] = (i << 4 >> 4) | (cpu.registers[0] >> 4 << 4)
	}
}

func math(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	destination := i << 4 >> 6
	source := i << 6 >> 6

	if operation == 0 {
		cpu.registers[destination] = cpu.registers[destination] + cpu.registers[source]
	} else {
		cpu.registers[destination] = cpu.registers[source]
	}

	cpu.result = cpu.registers[destination]
}

func logic(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	destination := i << 4 >> 6
	source := i << 6 >> 6

	if operation == 0 {
		cpu.registers[destination] = cpu.registers[destination] & cpu.registers[source]
	} else {
		cpu.registers[destination] = cpu.registers[destination] ^ cpu.registers[source]
	}

	cpu.result = cpu.registers[destination]
}

func mem(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	address_high := i << 4 >> 6
	address_low := i << 6 >> 6
	address := uint16(cpu.registers[address_high])<<8 + uint16(cpu.registers[address_low])

	if operation == 0 {
		// LOAD
		fmt.Fprintf(os.Stderr, "Loading %v\n to R0", address)
		cpu.registers[0] = cpu.memory[address]
	} else {
		// STORE
		fmt.Fprintf(os.Stderr, "Storing R0 to %v\n", address)
		cpu.memory[address] = cpu.registers[0]
	}
}

func pop16(s stack) uint16 {
	byte_1 := s.read()
	byte_2 := s.read()
	return uint16(byte_1)<<8 + uint16(byte_2)
}

func pop32(s stack) uint32 {
	byte_1 := s.read()
	byte_2 := s.read()
	byte_3 := s.read()
	byte_4 := s.read()
	return uint32(byte_1)<<24 + uint32(byte_2)<<16 + uint32(byte_3)<<8 + uint32(byte_4)
}

func push16(s stack, value uint16) {
	byte_1 := uint8(value >> 8)
	byte_2 := uint8(value << 8 >> 8)
	s.write(byte_2)
	s.write(byte_1)
}

func stacki(i uint8, cpu *CPU) {
	stacki := i << 3 >> 3

	switch stacki {
	case 0:
		// add16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a + b)
	case 1:
		// sub16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a - b)
	case 2:
		// mul16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a * b)
	case 3:
		// div16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a / b)
	case 4:
		// mod16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a % b)
	case 5:
		// neg16
		a := cpu.stack.read()
		cpu.stack.write(uint8(int8(a) * -1))
	case 6:
		// and16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a & b)
	case 7:
		// or16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a | b)
	case 8:
		// xor16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a ^ b)
	case 9:
		// not16
		a := cpu.stack.read()
		cpu.stack.write(^a)
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
	case 16:
	case 17:
	case 18:
	case 19:
	case 20:
		// Get jump address off the stack
		new_pc_high := cpu.devices[0].read()
		new_pc_low := cpu.devices[0].read()
		new_pc := uint16(new_pc_high)<<8 + uint16(new_pc_low)

		// Push next address to the stack
		pc_high := cpu.pc >> 8
		pc_low := cpu.pc << 8 >> 8
		cpu.devices[0].write(uint8(pc_low))
		cpu.devices[0].write(uint8(pc_high))

		// Jump
		cpu.pc = new_pc
	case 21:
		// trap
	case 22:
		// Get return address off the stack
		pc_high := cpu.devices[0].read()
		pc_low := cpu.devices[0].read()
		pc := uint16(pc_high)<<8 + uint16(pc_low)

		// Jump
		cpu.pc = pc
	case 23:
		// iret
	default:
		// device := stacki - 24
		// TODO: enable device
	}
}

func in(i uint8, cpu *CPU) {
	device := i << 5 >> 5
	destination := i << 3 >> 6
	cpu.registers[destination] = cpu.devices[device].read()
}

func out(i uint8, cpu *CPU) {
	device := i << 3 >> 5
	source := i << 6 >> 6
	cpu.devices[device].write(cpu.registers[source])
}

func illegal(i uint8, cpu *CPU) {
}
<commit_msg>Maybe fix stack<commit_after>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	fmt.Println("Initializing Octave CPU...")
	cpu := &CPU{running: true, sp: 0xFFFF}

	file, err := os.Open(os.Args[1])

	if err != nil {
		return
	}

	defer file.Close()

	mem, err := ioutil.ReadAll(file)

	for i, val := range mem {
		cpu.memory[i] = val
	}

	cpu.stack = stack{cpu}
	cpu.devices[0] = cpu.stack
	cpu.devices[1] = tty{bufio.NewReader(os.Stdin)}

	if err != nil {
		return
	}

	for cpu.running {
		inst_byte := fetch(cpu)
		inst_func := decode(inst_byte)
		inst_func(inst_byte, cpu)
	}
}

type CPU struct {
	memory    [1 << 16]uint8
	registers [4]uint8
	pc        uint16
	sp        uint16
	running   bool
	result    uint8
	devices   [8]Device
	stack     stack
}

type instruction func(uint8, *CPU)

type Device interface {
	read() uint8
	write(uint8)
}

type tty struct {
	reader *bufio.Reader
}

func (t tty) read() uint8 {
	b, _ := t.reader.ReadByte()
	return b
}

func (t tty) write(char uint8) {
	fmt.Printf("%c", char)
}

type stack struct {
	cpu *CPU
}

func (s stack) read() uint8 {
	s.cpu.sp++
	value := s.cpu.memory[s.cpu.sp]
	return value
}

func (s stack) write(char uint8) {
	s.cpu.memory[s.cpu.sp] = char
	s.cpu.sp--
}

func fetch(cpu *CPU) uint8 {
	inst := cpu.memory[cpu.pc]
	cpu.pc = cpu.pc + 1
	return inst
}

func decode(i uint8) instruction {
	inst := illegal

	switch i >> 5 {
	case 0:
		fmt.Fprint(os.Stderr, "jmp\n")
		inst = jmp
	case 1:
		fmt.Fprint(os.Stderr, "loadi\n")
		inst = loadi
	case 2:
		fmt.Fprint(os.Stderr, "math\n")
		inst = math
	case 3:
		fmt.Fprint(os.Stderr, "logic\n")
		inst = logic
	case 4:
		fmt.Fprint(os.Stderr, "mem\n")
		inst = mem
	case 5:
		fmt.Fprint(os.Stderr, "stack\n")
		inst = stacki
	case 6:
		fmt.Fprint(os.Stderr, "in\n")
		inst = in
	case 7:
		fmt.Fprint(os.Stderr, "out\n")
		inst = out
	}

	return inst
}

func jmp(i uint8, cpu *CPU) {
	if i == 0 {
		cpu.running = false
	}

	register := i << 3 >> 6
	n := i << 5 >> 7
	z := i << 6 >> 7
	p := i << 7 >> 7

	if (n == 1 && cpu.result < 0) || (z == 1 && cpu.result == 0) || (p == 1 && cpu.result > 0) {
		offset := int8(cpu.registers[register])
		fmt.Fprintf(os.Stderr, "Taking jump to %v\n", offset)
		cpu.pc = uint16(int32(cpu.pc) + int32(offset))
	}
}

func loadi(i uint8, cpu *CPU) {
	location := i << 3 >> 7

	if location == 0 {
		cpu.registers[0] = (i << 4) | (cpu.registers[0] << 4 >> 4)
	} else {
		cpu.registers[0] = (i << 4 >> 4) | (cpu.registers[0] >> 4 << 4)
	}
}

func math(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	destination := i << 4 >> 6
	source := i << 6 >> 6

	if operation == 0 {
		cpu.registers[destination] = cpu.registers[destination] + cpu.registers[source]
	} else {
		cpu.registers[destination] = cpu.registers[source]
	}

	cpu.result = cpu.registers[destination]
}

func logic(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	destination := i << 4 >> 6
	source := i << 6 >> 6

	if operation == 0 {
		cpu.registers[destination] = cpu.registers[destination] & cpu.registers[source]
	} else {
		cpu.registers[destination] = cpu.registers[destination] ^ cpu.registers[source]
	}

	cpu.result = cpu.registers[destination]
}

func mem(i uint8, cpu *CPU) {
	operation := i << 3 >> 7
	address_high := i << 4 >> 6
	address_low := i << 6 >> 6
	address := uint16(cpu.registers[address_high])<<8 + uint16(cpu.registers[address_low])

	if operation == 0 {
		// LOAD
		fmt.Fprintf(os.Stderr, "Loading %v\n to R0", address)
		cpu.registers[0] = cpu.memory[address]
	} else {
		// STORE
		fmt.Fprintf(os.Stderr, "Storing R0 to %v\n", address)
		cpu.memory[address] = cpu.registers[0]
	}
}

func pop16(s stack) uint16 {
	byte_1 := s.read()
	byte_2 := s.read()
	return uint16(byte_1)<<8 + uint16(byte_2)
}

func pop32(s stack) uint32 {
	byte_1 := s.read()
	byte_2 := s.read()
	byte_3 := s.read()
	byte_4 := s.read()
	return uint32(byte_1)<<24 + uint32(byte_2)<<16 + uint32(byte_3)<<8 + uint32(byte_4)
}

func push16(s stack, value uint16) {
	byte_1 := uint8(value >> 8)
	byte_2 := uint8(value << 8 >> 8)
	s.write(byte_2)
	s.write(byte_1)
}

func stacki(i uint8, cpu *CPU) {
	stacki := i << 3 >> 3

	switch stacki {
	case 0:
		// add16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a + b)
	case 1:
		// sub16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a - b)
	case 2:
		// mul16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a * b)
	case 3:
		// div16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a / b)
	case 4:
		// mod16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a % b)
	case 5:
		// neg16
		a := cpu.stack.read()
		cpu.stack.write(uint8(int8(a) * -1))
	case 6:
		// and16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a & b)
	case 7:
		// or16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a | b)
	case 8:
		// xor16
		b := cpu.stack.read()
		a := cpu.stack.read()
		cpu.stack.write(a ^ b)
	case 9:
		// not16
		a := cpu.stack.read()
		cpu.stack.write(^a)
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
	case 16:
	case 17:
	case 18:
	case 19:
	case 20:
		// Get jump address off the stack
		new_pc_high := cpu.devices[0].read()
		new_pc_low := cpu.devices[0].read()
		new_pc := uint16(new_pc_high)<<8 + uint16(new_pc_low)

		// Push next address to the stack
		pc_high := cpu.pc >> 8
		pc_low := cpu.pc << 8 >> 8
		cpu.devices[0].write(uint8(pc_low))
		cpu.devices[0].write(uint8(pc_high))

		// Jump
		cpu.pc = new_pc
	case 21:
		// trap
	case 22:
		// Get return address off the stack
		pc_high := cpu.devices[0].read()
		pc_low := cpu.devices[0].read()
		pc := uint16(pc_high)<<8 + uint16(pc_low)

		// Jump
		cpu.pc = pc
	case 23:
		// iret
	default:
		// device := stacki - 24
		// TODO: enable device
	}
}

func in(i uint8, cpu *CPU) {
	device := i << 5 >> 5
	destination := i << 3 >> 6
	cpu.registers[destination] = cpu.devices[device].read()
}

func out(i uint8, cpu *CPU) {
	device := i << 3 >> 5
	source := i << 6 >> 6
	cpu.devices[device].write(cpu.registers[source])
}

func illegal(i uint8, cpu *CPU) {
}
<|endoftext|>


<commit_before>package torutil

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"strconv"

	freeport "github.com/phayes/freeport"
)

type TorConnection struct {
	ControlPort int `json:"port"`
	Port        int `json:"controlPort"`
}

func Spawn(dataDir string, tc TorConnection) {
	cmd := "tor"
	pid := fmt.Sprintf("tor%d.pid", tc.ControlPort)
	ddir := fmt.Sprintf("%s/tor%d", dataDir, tc.ControlPort)
	args := []string{"--RunAsDaemon", "1", "--CookieAuthentication", "0", "--ControlPort", strconv.Itoa(tc.ControlPort), "--PidFile", pid, "--SocksPort", strconv.Itoa(tc.Port), "--DataDirectory", ddir}

	os.MkdirAll(ddir, 0777)

	exec.Command(cmd, args...).Output()
}

func Create(dataDir string) TorConnection {
	tc := TorConnection{ControlPort: freeport.GetPort(), Port: freeport.GetPort()}
	Spawn(dataDir, tc)
	return tc
}

func ControlCommand(command string, port int) {
	conn, _ := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
	fmt.Fprintf(conn, "AUTHENTICATE\r\n")
	fmt.Fprintf(conn, "%s\r\n", command)
}

func Cycle(tc TorConnection) {
	ControlCommand("SIGNAL NEWNYM", tc.ControlPort)
}

func Shutdown(tc TorConnection) {
	ControlCommand("SIGNAL HALT", tc.ControlPort)
}
<commit_msg>Log tor output on error for debugging<commit_after>package torutil

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"strconv"

	freeport "github.com/phayes/freeport"
)

type TorConnection struct {
	ControlPort int `json:"port"`
	Port        int `json:"controlPort"`
}

func Spawn(dataDir string, tc TorConnection) {
	cmd := "tor"
	pid := fmt.Sprintf("tor%d.pid", tc.ControlPort)
	ddir := fmt.Sprintf("%s/tor%d", dataDir, tc.ControlPort)
	args := []string{"--RunAsDaemon", "1", "--CookieAuthentication", "0", "--ControlPort", strconv.Itoa(tc.ControlPort), "--PidFile", pid, "--SocksPort", strconv.Itoa(tc.Port), "--DataDirectory", ddir}

	os.MkdirAll(ddir, 0777)

	out, err := exec.Command(cmd, args...).Output()
	if err != nil {
		fmt.Printf("Error: %v\nOutput: %s\n", err, out)
	}
}

func Create(dataDir string) TorConnection {
	tc := TorConnection{ControlPort: freeport.GetPort(), Port: freeport.GetPort()}
	Spawn(dataDir, tc)
	return tc
}

func ControlCommand(command string, port int) {
	conn, _ := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
	fmt.Fprintf(conn, "AUTHENTICATE\r\n")
	fmt.Fprintf(conn, "%s\r\n", command)
}

func Cycle(tc TorConnection) {
	ControlCommand("SIGNAL NEWNYM", tc.ControlPort)
}

func Shutdown(tc TorConnection) {
	ControlCommand("SIGNAL HALT", tc.ControlPort)
}
<|endoftext|>


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

package handlers

import (
	"context"
	"math/rand"
	"net"
	"time"

	"github.com/scionproto/scion/go/lib/addr"
	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/ctrl/path_mgmt"
	"github.com/scionproto/scion/go/lib/ctrl/seg"
	"github.com/scionproto/scion/go/lib/infra"
	"github.com/scionproto/scion/go/lib/infra/dedupe"
	"github.com/scionproto/scion/go/lib/log"
	"github.com/scionproto/scion/go/lib/pathdb/query"
	"github.com/scionproto/scion/go/path_srv/internal/addrutil"
	"github.com/scionproto/scion/go/proto"
)

type segReqNonCoreHandler struct {
	segReqHandler
}

func NewSegReqNonCoreHandler(args HandlerArgs, segsDeduper dedupe.Deduper) infra.Handler {
	f := func(r *infra.Request) {
		handler := &segReqNonCoreHandler{
			segReqHandler: segReqHandler{
				baseHandler: newBaseHandler(r, args),
				localIA:     args.IA,
				segsDeduper: segsDeduper,
			},
		}
		handler.Handle()
	}
	return infra.HandlerFunc(f)
}

func (h *segReqNonCoreHandler) Handle() {
	logger := log.FromCtx(h.request.Context())
	segReq, ok := h.request.Message.(*path_mgmt.SegReq)
	if !ok {
		logger.Error("[segReqHandler] wrong message type, expected path_mgmt.SegReq",
			"msg", h.request.Message, "type", common.TypeOf(h.request.Message))
		return
	}
	logger.Debug("[segReqHandler] Received", "segReq", segReq)
	msger, ok := infra.MessengerFromContext(h.request.Context())
	if !ok {
		logger.Warn("[segReqHandler] Unable to service request, no Messenger found")
		return
	}
	if !h.validSrcDst(segReq) {
		return
	}
	subCtx, cancelF := context.WithTimeout(h.request.Context(), HandlerTimeout)
	defer cancelF()
	var err error
	dstCore, err := h.isCoreDst(subCtx, msger, segReq)
	if err != nil {
		logger.Error("[segReqHandler] Failed to determine dest type", "err", err)
		h.sendEmptySegReply(subCtx, segReq, msger)
		return
	}
	coreASes, err := h.coreASes(subCtx)
	if err != nil {
		logger.Error("[segReqHandler] Failed to find local core ASes", "err", err)
		h.sendEmptySegReply(subCtx, segReq, msger)
		return
	}
	if dstCore {
		h.handleCoreDst(subCtx, segReq, msger, segReq.DstIA(), coreASes.ASList())
	} else {
		h.handleNonCoreDst(subCtx, segReq, msger, segReq.DstIA(), coreASes.ASList())
	}
}

func (h *segReqNonCoreHandler) validSrcDst(segReq *path_mgmt.SegReq) bool {
	logger := log.FromCtx(h.request.Context())
	if !segReq.SrcIA().IsZero() && !segReq.SrcIA().Eq(h.localIA) {
		logger.Warn("[segReqHandler] Drop, invalid srcIA",
			"srcIA", segReq.SrcIA())
		return false
	}
	return h.isValidDst(segReq)
}

func (h *segReqNonCoreHandler) handleCoreDst(ctx context.Context, segReq *path_mgmt.SegReq,
	msger infra.Messenger, dst addr.IA, coreASes []addr.IA) {

	logger := log.FromCtx(ctx)
	dstISDLocal := segReq.DstIA().I == h.localIA.I
	logger.Debug("[segReqHandler] handleCoreDst", "remote", dstISDLocal)
	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, !segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("[segReqHandler] Failed to find up segments", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	if len(upSegs) == 0 {
		logger.Warn("[segReqHandler] No up segments found")
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	// TODO(lukedirtwalker): in case of CacheOnly we can use a single query,
	// else we should start go routines for the core segs here.
	var coreSegs []*seg.PathSegment
	// All firstIAs of upSegs that are connected, used for filtering later.
	connFirstIAs := make(map[addr.IA]struct{})
	// TODO(lukedirtwalker): we shouldn't just query all cores, this could be a lot of overhead.
	// Add a limit of cores we query.
	for _, src := range upSegs.FirstIAs() {
		if !src.Eq(dst) {
			res, err := h.fetchCoreSegs(ctx, msger, src, dst, segReq.Flags.CacheOnly)
			if err != nil {
				logger.Error("[segReqHandler] Failed to find core segs", "err", err)
				continue
			}
			if len(res) > 0 {
				coreSegs = append(coreSegs, res...)
				connFirstIAs[src] = struct{}{}
			}
		} else {
			connFirstIAs[src] = struct{}{}
		}
	}
	// Make sure we only return connected segments.
	upSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connFirstIAs[s.FirstIA()]
		return connected
	})
	logger.Debug("[segReqHandler] found", "up", len(upSegs), "core", len(coreSegs))
	h.sendReply(ctx, msger, upSegs, coreSegs, nil, segReq)
}

func (h *segReqNonCoreHandler) handleNonCoreDst(ctx context.Context, segReq *path_mgmt.SegReq,
	msger infra.Messenger, dstIA addr.IA, coreASes []addr.IA) {

	logger := log.FromCtx(ctx)
	cPSResolve := func() (net.Addr, error) {
		return h.corePSAddr(ctx, coreASes)
	}
	downSegs, err := h.fetchDownSegs(ctx, msger, dstIA, cPSResolve, segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("Failed to find down segs", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	if len(downSegs) == 0 {
		logger.Warn("[segReqHandler] No down segments found")
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, !segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("Failed to find up segs", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	var coreSegs []*seg.PathSegment
	// All firstIAs of up-/down-Segs that are connected, used for filtering later.
	connUpFirstIAs := make(map[addr.IA]struct{})
	connDownFirstIAs := make(map[addr.IA]struct{})
	// TODO(lukedirtwalker): in case of CacheOnly we can use a single query,
	// else we should start go routines for the core segs here.
	for _, dst := range downSegs.FirstIAs() {
		// TODO(lukedirtwalker): we shouldn't just query all cores, this could be a lot of overhead.
		// Add a limit of cores we query.
		for _, src := range upSegs.FirstIAs() {
			if src.Eq(dst) {
				connUpFirstIAs[src] = struct{}{}
				connDownFirstIAs[dst] = struct{}{}
				continue
			}
			cs, err := h.fetchCoreSegs(ctx, msger, src, dst, segReq.Flags.CacheOnly)
			if err != nil {
				logger.Error("Failed to find core segs", "src", src, "dst", dst, "err", err)
				continue
			}
			if len(cs) > 0 {
				coreSegs = append(coreSegs, cs...)
				connUpFirstIAs[src] = struct{}{}
				connDownFirstIAs[dst] = struct{}{}
			}
		}
	}
	// Make sure we only return connected segments.
	// No need to filter cores, since we only query for connected ones.
	upSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connUpFirstIAs[s.FirstIA()]
		return connected
	})
	downSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connDownFirstIAs[s.FirstIA()]
		return connected
	})
	logger.Debug("[segReqHandler:handleNonCoreDst] found segs",
		"up", len(upSegs), "core", len(coreSegs), "down", len(downSegs))
	h.sendReply(ctx, msger, upSegs, coreSegs, downSegs, segReq)
}

func (h *segReqNonCoreHandler) fetchUpSegsFromDB(ctx context.Context,
	coreASes []addr.IA, retry bool) (seg.Segments, error) {

	query := &query.Params{
		SegTypes: []proto.PathSegType{proto.PathSegType_up},
		StartsAt: coreASes,
		EndsAt:   []addr.IA{h.localIA},
	}
	if retry {
		return h.fetchSegsFromDBRetry(ctx, query)
	}
	return h.fetchSegsFromDB(ctx, query)
}

func (h *segReqNonCoreHandler) fetchCoreSegs(ctx context.Context,
	msger infra.Messenger, src, dst addr.IA, dbOnly bool) ([]*seg.PathSegment, error) {

	logger := log.FromCtx(ctx)
	// try local cache first, inverse query since core segs are stored in inverse direction.
	q := &query.Params{
		SegTypes: []proto.PathSegType{proto.PathSegType_core},
		StartsAt: []addr.IA{dst},
		EndsAt:   []addr.IA{src},
	}
	segs, err := h.fetchSegsFromDB(ctx, q)
	if err != nil {
		return nil, err
	}
	if dbOnly || len(segs) > 0 {
		refetch := !dbOnly
		if !dbOnly {
			refetch, err = h.shouldRefetchSegsForDst(ctx, dst, time.Now())
			if err != nil {
				logger.Warn("[segReqHandler] failed to get last query", "err", err)
			}
		}
		if !refetch {
			return segs, nil
		}
	}
	// try remote:
	cPS, err := h.corePSAddr(ctx, []addr.IA{src})
	if err != nil {
		return nil, err
	}
	logger.Debug("[segReqHandler] Request core segments", "src", src, "dst", dst, "remote", cPS)
	if err = h.fetchAndSaveSegs(ctx, msger, src, dst, cPS); err != nil {
		return nil, err
	}
	// TODO(lukedirtwalker): if fetchAndSaveSegs returns verified segs we don't need to query.
	return h.fetchSegsFromDB(ctx, q)
}

func (h *segReqNonCoreHandler) corePSAddr(ctx context.Context,
	coreASes []addr.IA) (net.Addr, error) {

	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, true)
	if err != nil {
		return nil, err
	}
	if len(upSegs) < 1 {
		return nil, common.NewBasicError("No up segments found!", nil)
	}
	// select a core AS we have an up segment to.
	seg := upSegs[rand.Intn(len(upSegs))]
	return addrutil.GetPath(addr.SvcPS, seg, seg.FirstIA(), h.topology)
}
<commit_msg>PS: Handle ISD-local AS-wildcard seg requests (#2284)<commit_after>// Copyright 2018 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package handlers

import (
	"context"
	"math/rand"
	"net"
	"time"

	"github.com/scionproto/scion/go/lib/addr"
	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/ctrl/path_mgmt"
	"github.com/scionproto/scion/go/lib/ctrl/seg"
	"github.com/scionproto/scion/go/lib/infra"
	"github.com/scionproto/scion/go/lib/infra/dedupe"
	"github.com/scionproto/scion/go/lib/log"
	"github.com/scionproto/scion/go/lib/pathdb/query"
	"github.com/scionproto/scion/go/path_srv/internal/addrutil"
	"github.com/scionproto/scion/go/proto"
)

type segReqNonCoreHandler struct {
	segReqHandler
}

func NewSegReqNonCoreHandler(args HandlerArgs, segsDeduper dedupe.Deduper) infra.Handler {
	f := func(r *infra.Request) {
		handler := &segReqNonCoreHandler{
			segReqHandler: segReqHandler{
				baseHandler: newBaseHandler(r, args),
				localIA:     args.IA,
				segsDeduper: segsDeduper,
			},
		}
		handler.Handle()
	}
	return infra.HandlerFunc(f)
}

func (h *segReqNonCoreHandler) Handle() {
	logger := log.FromCtx(h.request.Context())
	segReq, ok := h.request.Message.(*path_mgmt.SegReq)
	if !ok {
		logger.Error("[segReqHandler] wrong message type, expected path_mgmt.SegReq",
			"msg", h.request.Message, "type", common.TypeOf(h.request.Message))
		return
	}
	logger.Debug("[segReqHandler] Received", "segReq", segReq)
	msger, ok := infra.MessengerFromContext(h.request.Context())
	if !ok {
		logger.Warn("[segReqHandler] Unable to service request, no Messenger found")
		return
	}
	if !h.validSrcDst(segReq) {
		return
	}
	subCtx, cancelF := context.WithTimeout(h.request.Context(), HandlerTimeout)
	defer cancelF()
	var err error
	dstCore, err := h.isCoreDst(subCtx, msger, segReq)
	if err != nil {
		logger.Error("[segReqHandler] Failed to determine dest type", "err", err)
		h.sendEmptySegReply(subCtx, segReq, msger)
		return
	}
	coreASes, err := h.coreASes(subCtx)
	if err != nil {
		logger.Error("[segReqHandler] Failed to find local core ASes", "err", err)
		h.sendEmptySegReply(subCtx, segReq, msger)
		return
	}
	if dstCore {
		h.handleCoreDst(subCtx, segReq, msger, segReq.DstIA(), coreASes.ASList())
	} else {
		h.handleNonCoreDst(subCtx, segReq, msger, segReq.DstIA(), coreASes.ASList())
	}
}

func (h *segReqNonCoreHandler) validSrcDst(segReq *path_mgmt.SegReq) bool {
	logger := log.FromCtx(h.request.Context())
	if !segReq.SrcIA().IsZero() && !segReq.SrcIA().Eq(h.localIA) {
		logger.Warn("[segReqHandler] Drop, invalid srcIA",
			"srcIA", segReq.SrcIA())
		return false
	}
	return h.isValidDst(segReq)
}

func (h *segReqNonCoreHandler) handleCoreDst(ctx context.Context, segReq *path_mgmt.SegReq,
	msger infra.Messenger, dst addr.IA, coreASes []addr.IA) {

	logger := log.FromCtx(ctx)
	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, !segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("[segReqHandler] Failed to find up segments", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	if len(upSegs) == 0 {
		logger.Warn("[segReqHandler] No up segments found")
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	// TODO(lukedirtwalker): in case of CacheOnly we can use a single query,
	// else we should start go routines for the core segs here.
	var coreSegs []*seg.PathSegment
	// All firstIAs of upSegs that are connected, used for filtering later.
	connFirstIAs := make(map[addr.IA]struct{})
	// For a local wildcard we return all the upSegs.
	if segReq.DstIA().A == 0 && segReq.DstIA().I == h.localIA.I {
		for _, ia := range coreASes {
			connFirstIAs[ia] = struct{}{}
		}
	}
	// TODO(lukedirtwalker): we shouldn't just query all cores, this could be a lot of overhead.
	// Add a limit of cores we query.
	for _, src := range upSegs.FirstIAs() {
		if !src.Eq(dst) {
			res, err := h.fetchCoreSegs(ctx, msger, src, dst, segReq.Flags.CacheOnly)
			if err != nil {
				logger.Error("[segReqHandler] Failed to find core segs", "err", err)
				continue
			}
			if len(res) > 0 {
				coreSegs = append(coreSegs, res...)
				connFirstIAs[src] = struct{}{}
			}
		} else {
			connFirstIAs[src] = struct{}{}
		}
	}
	// Make sure we only return connected segments.
	upSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connFirstIAs[s.FirstIA()]
		return connected
	})
	logger.Debug("[segReqHandler] found", "up", len(upSegs), "core", len(coreSegs))
	h.sendReply(ctx, msger, upSegs, coreSegs, nil, segReq)
}

func (h *segReqNonCoreHandler) handleNonCoreDst(ctx context.Context, segReq *path_mgmt.SegReq,
	msger infra.Messenger, dstIA addr.IA, coreASes []addr.IA) {

	logger := log.FromCtx(ctx)
	cPSResolve := func() (net.Addr, error) {
		return h.corePSAddr(ctx, coreASes)
	}
	downSegs, err := h.fetchDownSegs(ctx, msger, dstIA, cPSResolve, segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("Failed to find down segs", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	if len(downSegs) == 0 {
		logger.Warn("[segReqHandler] No down segments found")
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, !segReq.Flags.CacheOnly)
	if err != nil {
		logger.Error("Failed to find up segs", "err", err)
		h.sendEmptySegReply(ctx, segReq, msger)
		return
	}
	var coreSegs []*seg.PathSegment
	// All firstIAs of up-/down-Segs that are connected, used for filtering later.
	connUpFirstIAs := make(map[addr.IA]struct{})
	connDownFirstIAs := make(map[addr.IA]struct{})
	// TODO(lukedirtwalker): in case of CacheOnly we can use a single query,
	// else we should start go routines for the core segs here.
	for _, dst := range downSegs.FirstIAs() {
		// TODO(lukedirtwalker): we shouldn't just query all cores, this could be a lot of overhead.
		// Add a limit of cores we query.
		for _, src := range upSegs.FirstIAs() {
			if src.Eq(dst) {
				connUpFirstIAs[src] = struct{}{}
				connDownFirstIAs[dst] = struct{}{}
				continue
			}
			cs, err := h.fetchCoreSegs(ctx, msger, src, dst, segReq.Flags.CacheOnly)
			if err != nil {
				logger.Error("Failed to find core segs", "src", src, "dst", dst, "err", err)
				continue
			}
			if len(cs) > 0 {
				coreSegs = append(coreSegs, cs...)
				connUpFirstIAs[src] = struct{}{}
				connDownFirstIAs[dst] = struct{}{}
			}
		}
	}
	// Make sure we only return connected segments.
	// No need to filter cores, since we only query for connected ones.
	upSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connUpFirstIAs[s.FirstIA()]
		return connected
	})
	downSegs.FilterSegs(func(s *seg.PathSegment) bool {
		_, connected := connDownFirstIAs[s.FirstIA()]
		return connected
	})
	logger.Debug("[segReqHandler:handleNonCoreDst] found segs",
		"up", len(upSegs), "core", len(coreSegs), "down", len(downSegs))
	h.sendReply(ctx, msger, upSegs, coreSegs, downSegs, segReq)
}

func (h *segReqNonCoreHandler) fetchUpSegsFromDB(ctx context.Context,
	coreASes []addr.IA, retry bool) (seg.Segments, error) {

	query := &query.Params{
		SegTypes: []proto.PathSegType{proto.PathSegType_up},
		StartsAt: coreASes,
		EndsAt:   []addr.IA{h.localIA},
	}
	if retry {
		return h.fetchSegsFromDBRetry(ctx, query)
	}
	return h.fetchSegsFromDB(ctx, query)
}

func (h *segReqNonCoreHandler) fetchCoreSegs(ctx context.Context,
	msger infra.Messenger, src, dst addr.IA, dbOnly bool) ([]*seg.PathSegment, error) {

	logger := log.FromCtx(ctx)
	// try local cache first, inverse query since core segs are stored in inverse direction.
	q := &query.Params{
		SegTypes: []proto.PathSegType{proto.PathSegType_core},
		StartsAt: []addr.IA{dst},
		EndsAt:   []addr.IA{src},
	}
	segs, err := h.fetchSegsFromDB(ctx, q)
	if err != nil {
		return nil, err
	}
	if dbOnly || len(segs) > 0 {
		refetch := !dbOnly
		if !dbOnly {
			refetch, err = h.shouldRefetchSegsForDst(ctx, dst, time.Now())
			if err != nil {
				logger.Warn("[segReqHandler] failed to get last query", "err", err)
			}
		}
		if !refetch {
			return segs, nil
		}
	}
	// try remote:
	cPS, err := h.corePSAddr(ctx, []addr.IA{src})
	if err != nil {
		return nil, err
	}
	logger.Debug("[segReqHandler] Request core segments", "src", src, "dst", dst, "remote", cPS)
	if err = h.fetchAndSaveSegs(ctx, msger, src, dst, cPS); err != nil {
		return nil, err
	}
	// TODO(lukedirtwalker): if fetchAndSaveSegs returns verified segs we don't need to query.
	return h.fetchSegsFromDB(ctx, q)
}

func (h *segReqNonCoreHandler) corePSAddr(ctx context.Context,
	coreASes []addr.IA) (net.Addr, error) {

	upSegs, err := h.fetchUpSegsFromDB(ctx, coreASes, true)
	if err != nil {
		return nil, err
	}
	if len(upSegs) < 1 {
		return nil, common.NewBasicError("No up segments found!", nil)
	}
	// select a core AS we have an up segment to.
	seg := upSegs[rand.Intn(len(upSegs))]
	return addrutil.GetPath(addr.SvcPS, seg, seg.FirstIA(), h.topology)
}
<|endoftext|>


<commit_before>package tracker

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

type TrackResult struct {
	TargetURL         string
	TargetText        string
	TargetStatusCode  int
	ResultStatusCode  int
	ResultTextMatched bool
}

func Perform(targetURL, targetText string, targetStatusCode int) (TrackResult, error) {
	trackResult := TrackResult{targetURL, targetText, targetStatusCode, 0, false}

	resp, err := http.Get(targetURL)
	if err != nil {
		return trackResult, err
	}

	trackResult.ResultStatusCode = resp.StatusCode

	if trackResult.ResultStatusCode != targetStatusCode {
		return trackResult, fmt.Errorf("StatusCodeMatchError: Looked for (%d), but found (%d)", trackResult.TargetStatusCode, trackResult.ResultStatusCode)
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return trackResult, err
	}

	match, err := regexp.MatchString(targetText, string(body))
	if err != nil {
		return trackResult, err
	}

	trackResult.ResultTextMatched = match

	if !trackResult.ResultTextMatched {
		return trackResult, fmt.Errorf("TextMatchError: Looked for (%s)", trackResult.TargetText)
	}

	return trackResult, nil
}
<commit_msg>Modified status comparison way that it does not fail if target status code is not set<commit_after>package tracker

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

type TrackResult struct {
	TargetURL         string
	TargetText        string
	TargetStatusCode  int
	ResultStatusCode  int
	ResultTextMatched bool
}

func Perform(targetURL, targetText string, targetStatusCode int) (TrackResult, error) {
	trackResult := TrackResult{targetURL, targetText, targetStatusCode, 0, false}

	resp, err := http.Get(targetURL)
	if err != nil {
		return trackResult, err
	}

	trackResult.ResultStatusCode = resp.StatusCode

	if trackResult.TargetStatusCode == 0 {
		// TODO Log that status comparison was skipped because it was not set
	} else if trackResult.ResultStatusCode != targetStatusCode {
		return trackResult, fmt.Errorf("StatusCodeMatchError: Looked for (%d), but found (%d)", trackResult.TargetStatusCode, trackResult.ResultStatusCode)
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return trackResult, err
	}

	match, err := regexp.MatchString(targetText, string(body))
	if err != nil {
		return trackResult, err
	}

	trackResult.ResultTextMatched = match

	if !trackResult.ResultTextMatched {
		return trackResult, fmt.Errorf("TextMatchError: Looked for (%s)", trackResult.TargetText)
	}

	return trackResult, nil
}
<|endoftext|>


<commit_before>package publicip

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/koding/kite"
)

// The sites that PublicIP() uses to get the public IP from.
//
// Note that the site must return *only* the IP characters.
var echoSites = []string{
	// In the future, maybe koding.com/-/echoip first?
	"http://echoip.com",
	"http://api.ipify.org",
	"http://ipinfo.io/ip",
	"http://ifconfig.co",
}

var testSites = []string{
	// Definitely in future - koding.com/-/testip
	"http://rjk.io/test",
	"http://ifconfig.co/test",
}

var defaultClient = &http.Client{
	Transport: &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		ResponseHeaderTimeout: 15 * time.Second,
		Dial: (&net.Dialer{
			Timeout: 5 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	},
	Timeout: 15 * time.Second,
}

// PublicIP returns an IP that is supposed to be Public.
func PublicIP() (net.IP, error) {
	return publicIP(echoSites[0])
}

// publicIP requests a URL and returns a netIP for the response.
func publicIP(host string) (net.IP, error) {
	resp, err := defaultClient.Get(host)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	out, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	n := net.ParseIP(string(bytes.TrimSpace(out)))
	if n == nil {
		return nil, fmt.Errorf("cannot parse ip %s", string(out))
	}

	return n, nil
}

// PublicIPRetry fetches the public IP, retrying as many times as requested.
// An *optional* logger is provided, to log retry progress.
func PublicIPRetry(maxRetries int, retryPause time.Duration, log kite.Logger) (net.IP, error) {
	return publicIPRetry(echoSites, maxRetries, retryPause, log)
}

func publicIPRetry(hosts []string, maxRetries int, retryPause time.Duration, log kite.Logger) (net.IP, error) {
	if maxRetries <= 0 {
		return nil, errors.New("PublicIPRetry: maxRetries must be larger than 0")
	}

	var (
		ip  net.IP
		err error
	)

	for i := 0; i < maxRetries; i++ {
		host := hosts[i%len(hosts)]
		ip, err = publicIP(host)

		// If there's no error, we successfully got the IP.
		if err == nil {
			return ip, nil
		}

		if log != nil {
			log.Warning(
				"Retrying fetch of PublicIP due to error. delay:%s, err:%s",
				retryPause, err,
			)
		}

		if retryPause > 0 {
			// Pause before retrying.
			time.Sleep(retryPause)
		}
	}

	return nil, err
}

func isReachable(port, service string) (bool, error) {
	resp, err := defaultClient.Get(service + "/" + port)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusGone {
		return false, nil
	}

	// addr is reachable when it replied with 2xx HTTP status code
	if resp.StatusCode/100 == 2 {
		return true, nil
	}

	return false, fmt.Errorf("error status: %s (%d)", resp.Status, resp.StatusCode)
}

type testServer struct {
	serving  chan struct{}
	closed   chan struct{}
	listener net.Listener
}

func newTestServer(addr string) (*testServer, error) {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	t := &testServer{
		serving:  make(chan struct{}),
		closed:   make(chan struct{}),
		listener: l,
	}

	go t.serve()
	<-t.serving

	return t, nil
}

func (t *testServer) handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(204)
}

func (t *testServer) serve() {
	close(t.serving)
	defer close(t.closed)

	http.Serve(t.listener, http.HandlerFunc(t.handler))
}

func (t *testServer) Close() error {
	t.listener.Close()
	<-t.closed
	return nil
}

// IsReachableRetry test whether the given address is reachable from the internet or not.
//
// When a public IP address is behind NAT it's often not reachable from the
// outside.
//
// When it returns non-nil error, the test has failed and we're unable
// to say the ip is reachable or not.
func IsReachableRetry(addr string, maxRetries int, retryPause time.Duration, log kite.Logger) (bool, error) {
	if maxRetries <= 0 {
		return false, errors.New("IsReachableRetry: retry number must be larger than 0")
	}

	_, port, err := net.SplitHostPort(addr)
	if err != nil {
		return false, err
	}

	t, err := newTestServer(net.JoinHostPort("0.0.0.0", port))
	if err != nil {
		return false, err
	}
	defer t.Close()

	var ok bool
	for i := 0; i < maxRetries; i++ {
		service := testSites[i%len(testSites)]

		ok, err = isReachable(port, service)
		if err == nil {
			return ok, nil
		}

		if log != nil {
			log.Warning("retrying test of %q address reachability; delay=%s, err=%s", addr, retryPause, err)
		}

		if retryPause > 0 {
			time.Sleep(retryPause)
		}
	}

	return false, err
}
<commit_msg>klient/info/publicip: adapt isReachable to new api<commit_after>package publicip

import (
	"bytes"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/koding/kite"
)

// The sites that PublicIP() uses to get the public IP from.
//
// Note that the site must return *only* the IP characters.
var echoSites = []string{
	// In the future, maybe koding.com/-/echoip first?
	"http://echoip.com",
	"http://api.ipify.org",
	"http://ipinfo.io/ip",
	"http://ifconfig.co",
}

var testSites = []string{
	// Definitely in future - koding.com/-/testip
	"http://rjk.io/test",
	"http://ifconfig.co/test",
}

var defaultClient = &http.Client{
	Transport: &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		ResponseHeaderTimeout: 15 * time.Second,
		Dial: (&net.Dialer{
			Timeout: 5 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	},
	Timeout: 15 * time.Second,
}

// PublicIP returns an IP that is supposed to be Public.
func PublicIP() (net.IP, error) {
	return publicIP(echoSites[0])
}

// publicIP requests a URL and returns a netIP for the response.
func publicIP(host string) (net.IP, error) {
	resp, err := defaultClient.Get(host)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	out, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	n := net.ParseIP(string(bytes.TrimSpace(out)))
	if n == nil {
		return nil, fmt.Errorf("cannot parse ip %s", string(out))
	}

	return n, nil
}

// PublicIPRetry fetches the public IP, retrying as many times as requested.
// An *optional* logger is provided, to log retry progress.
func PublicIPRetry(maxRetries int, retryPause time.Duration, log kite.Logger) (net.IP, error) {
	return publicIPRetry(echoSites, maxRetries, retryPause, log)
}

func publicIPRetry(hosts []string, maxRetries int, retryPause time.Duration, log kite.Logger) (net.IP, error) {
	if maxRetries <= 0 {
		return nil, errors.New("PublicIPRetry: maxRetries must be larger than 0")
	}

	var (
		ip  net.IP
		err error
	)

	for i := 0; i < maxRetries; i++ {
		host := hosts[i%len(hosts)]
		ip, err = publicIP(host)

		// If there's no error, we successfully got the IP.
		if err == nil {
			return ip, nil
		}

		if log != nil {
			log.Warning(
				"Retrying fetch of PublicIP due to error. delay:%s, err:%s",
				retryPause, err,
			)
		}

		if retryPause > 0 {
			// Pause before retrying.
			time.Sleep(retryPause)
		}
	}

	return nil, err
}

func isReachable(addr, service string) (bool, error) {
	ip, port, err := net.SplitHostPort(addr)
	if err != nil {
		return false, err
	}
	req, err := http.NewRequest("GET", service+"/"+port, nil)
	if err != nil {
		return false, err
	}
	req.Header.Set("X-Real-IP", ip)
	resp, err := defaultClient.Do(req)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusGone {
		return false, nil
	}

	// addr is reachable when it replied with 2xx HTTP status code
	if resp.StatusCode/100 == 2 {
		return true, nil
	}

	return false, fmt.Errorf("error status: %s (%d)", resp.Status, resp.StatusCode)
}

type testServer struct {
	serving  chan struct{}
	closed   chan struct{}
	listener net.Listener
}

func newTestServer(addr string) (*testServer, error) {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	t := &testServer{
		serving:  make(chan struct{}),
		closed:   make(chan struct{}),
		listener: l,
	}

	go t.serve()
	<-t.serving

	return t, nil
}

func (t *testServer) handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(204)
}

func (t *testServer) serve() {
	close(t.serving)
	defer close(t.closed)

	http.Serve(t.listener, http.HandlerFunc(t.handler))
}

func (t *testServer) Close() error {
	t.listener.Close()
	<-t.closed
	return nil
}

// IsReachableRetry test whether the given address is reachable from the internet or not.
//
// When a public IP address is behind NAT it's often not reachable from the
// outside.
//
// When it returns non-nil error, the test has failed and we're unable
// to say the ip is reachable or not.
func IsReachableRetry(addr string, maxRetries int, retryPause time.Duration, log kite.Logger) (bool, error) {
	if maxRetries <= 0 {
		return false, errors.New("IsReachableRetry: retry number must be larger than 0")
	}

	_, port, err := net.SplitHostPort(addr)
	if err != nil {
		return false, err
	}

	t, err := newTestServer(net.JoinHostPort("0.0.0.0", port))
	if err != nil {
		return false, err
	}
	defer t.Close()

	var ok bool
	for i := 0; i < maxRetries; i++ {
		service := testSites[i%len(testSites)]

		ok, err = isReachable(addr, service)
		if err == nil {
			return ok, nil
		}

		if log != nil {
			log.Warning("retrying test of %q address reachability; delay=%s, err=%s", addr, retryPause, err)
		}

		if retryPause > 0 {
			time.Sleep(retryPause)
		}
	}

	return false, err
}
<|endoftext|>


<commit_before>// Copyright 2016 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"bufio"
	"fmt"
	"io"
	"strconv"
)

// ParseError is returned for parsing reader errors.
// The first line is 1.
type ParseError struct {
	Line   int    // Line number where the error accurd
	Record string // Name of the record type being parsed
	Err    error  // The actual error
}

func (e *ParseError) Error() string {
	if e.Record == "" {
		return fmt.Sprintf("line:%d %T %s", e.Line, e.Err, e.Err)
	}
	return fmt.Sprintf("line:%d record:%s %T %s", e.Line, e.Record, e.Err, e.Err)
}

// Reader reads records from a ACH-encoded file.
type Reader struct {
	// r handles the IO.Reader sent to be parser.
	scanner *bufio.Scanner
	// file is ach.file model being built as r is parsed.
	File File
	// line is the current line being parsed from the input r
	line string
	// currentBatch is the current Batch entries being parsed
	currentBatch Batcher
	// line number of the file being parsed
	lineNum int
	// recordName holds the current record name being parsed.
	recordName string
}

// error creates a new ParseError based on err.
func (r *Reader) error(err error) error {
	return &ParseError{
		Line:   r.lineNum,
		Record: r.recordName,
		Err:    err,
	}
}

// addCurrentBatch creates the current batch type for the file being read. A successful
// current batch will be added to r.File once parsed.
func (r *Reader) addCurrentBatch(batch Batcher) {
	r.currentBatch = batch
}

// NewReader returns a new ACH Reader that reads from r.
func NewReader(r io.Reader) *Reader {
	return &Reader{
		scanner: bufio.NewScanner(r),
	}
}

// Read reads each line of the ACH file and defines which parser to use based
// on the first character of each line. It also enforces ACH formating rules and returns
// the appropriate error if issues are found.
func (r *Reader) Read() (File, error) {
	r.lineNum = 0
	// read through the entire file
	for r.scanner.Scan() {
		line := r.scanner.Text()
		r.lineNum++
		lineLength := len(line)

		switch {
		case r.lineNum == 1 && lineLength > RecordLength && lineLength%RecordLength == 0:
			if err := r.processFixedWidthFile(&line); err != nil {
				return r.File, err
			}
		case lineLength != RecordLength:
			msg := fmt.Sprintf(msgRecordLength, lineLength)
			err := &FileError{FieldName: "RecordLength", Value: strconv.Itoa(lineLength), Msg: msg}
			return r.File, r.error(err)
		default:
			r.line = line
			if err := r.parseLine(); err != nil {
				return r.File, err
			}
		}
	}
	if (FileHeader{}) == r.File.Header {
		// Their must be at least one File Header
		r.recordName = "FileHeader"
		return r.File, r.error(&FileError{Msg: msgFileHeader})
	}
	if (FileControl{}) == r.File.Control {
		// Their must be at least one File Control
		r.recordName = "FileControl"
		return r.File, r.error(&FileError{Msg: msgFileControl})
	}

	return r.File, nil
}

func (r *Reader) processFixedWidthFile(line *string) error {
	// it should be safe to parse this byte by byte since ACH files are ascii only
	record := ""
	for i, c := range *line {
		record = record + string(c)
		if i > 0 && (i+1)%RecordLength == 0 {
			r.line = record
			if err := r.parseLine(); err != nil {
				return err
			}
			record = ""
		}
	}
	return nil
}

func (r *Reader) parseLine() error {
	switch r.line[:1] {
	case fileHeaderPos:
		if err := r.parseFileHeader(); err != nil {
			return err
		}
	case batchHeaderPos:
		if err := r.parseBatchHeader(); err != nil {
			return err
		}
	case entryDetailPos:
		if err := r.parseEntryDetail(); err != nil {
			return err
		}
	case entryAddendaPos:
		if err := r.parseAddenda(); err != nil {
			return err
		}
	case batchControlPos:
		if err := r.parseBatchControl(); err != nil {
			return err
		}
		if err := r.currentBatch.Validate(); err != nil {
			r.recordName = "Batches"
			return r.error(err)
		}
		r.File.AddBatch(r.currentBatch)
		r.currentBatch = nil
	case fileControlPos:
		if r.line[:2] == "99" {
			// final blocking padding
			break
		}
		if err := r.parseFileControl(); err != nil {
			return err
		}
	default:
		msg := fmt.Sprintf(msgUnknownRecordType, r.line[:1])
		return r.error(&FileError{FieldName: "recordType", Value: r.line[:1], Msg: msg})
	}
	return nil
}

// parseFileHeader takes the input record string and parses the FileHeaderRecord values
func (r *Reader) parseFileHeader() error {
	r.recordName = "FileHeader"
	if (FileHeader{}) != r.File.Header {
		// Their can only be one File Header per File exit
		r.error(&FileError{Msg: msgFileHeader})
	}
	r.File.Header.Parse(r.line)

	if err := r.File.Header.Validate(); err != nil {
		return r.error(err)
	}
	return nil
}

// parseBatchHeader takes the input record string and parses the FileHeaderRecord values
func (r *Reader) parseBatchHeader() error {
	r.recordName = "BatchHeader"
	if r.currentBatch != nil {
		// batch header inside of current batch
		return r.error(&FileError{Msg: msgFileBatchInside})
	}

	// Ensure we have a valid batch header before building a batch.
	bh := NewBatchHeader()
	bh.Parse(r.line)
	if err := bh.Validate(); err != nil {
		return r.error(err)
	}

	// Passing SEC type into NewBatch creates a Batcher of SEC code type.
	batch, err := NewBatch(BatchParam{
		StandardEntryClass: bh.StandardEntryClassCode})
	if err != nil {
		return r.error(err)
	}

	batch.SetHeader(bh)
	r.addCurrentBatch(batch)
	return nil
}

// parseEntryDetail takes the input record string and parses the EntryDetailRecord values
func (r *Reader) parseEntryDetail() error {
	r.recordName = "EntryDetail"
	if r.currentBatch == nil {
		return r.error(&FileError{Msg: msgFileBatchOutside})
	}
	ed := new(EntryDetail)
	ed.Parse(r.line)
	if err := ed.Validate(); err != nil {
		return r.error(err)
	}
	r.currentBatch.AddEntry(ed)
	return nil
}

// parseAddendaRecord takes the input record string and create an Addenda Type appended to the last EntryDetail
func (r *Reader) parseAddenda() error {
	r.recordName = "Addenda"

	if r.currentBatch == nil {
		msg := fmt.Sprintf(msgFileBatchOutside)
		return r.error(&FileError{FieldName: "Addenda", Msg: msg})
	}
	if len(r.currentBatch.GetEntries()) == 0 {
		return r.error(&FileError{FieldName: "Addenda", Msg: msgFileBatchOutside})
	}
	entryIndex := len(r.currentBatch.GetEntries()) - 1
	entry := r.currentBatch.GetEntries()[entryIndex]

	if entry.AddendaRecordIndicator == 1 {
		// Passing TypeCode type into NewAddenda creates a Addendumer of type copde type.
		addenda, err := NewAddenda(AddendaParam{
			TypeCode: r.line[1:3]})
		if err != nil {
			return r.error(err)
		}
		addenda.Parse(r.line)
		if err := addenda.Validate(); err != nil {
			return r.error(err)
		}
		r.currentBatch.GetEntries()[entryIndex].AddAddenda(addenda)
	} else {
		msg := fmt.Sprintf(msgBatchAddendaIndicator)
		return r.error(&FileError{FieldName: "AddendaRecordIndicator", Msg: msg})
	}

	return nil
}

// parseBatchControl takes the input record string and parses the BatchControlRecord values
func (r *Reader) parseBatchControl() error {
	r.recordName = "BatchControl"
	if r.currentBatch == nil {
		// batch Control without a current batch
		return r.error(&FileError{Msg: msgFileBatchOutside})
	}
	r.currentBatch.GetControl().Parse(r.line)
	if err := r.currentBatch.GetControl().Validate(); err != nil {
		return r.error(err)
	}
	return nil
}

// parseFileControl takes the input record string and parses the FileControlRecord values
func (r *Reader) parseFileControl() error {
	r.recordName = "FileControl"
	if (FileControl{}) != r.File.Control {
		// Can be only one file control per file
		return r.error(&FileError{Msg: msgFileControl})
	}
	r.File.Control.Parse(r.line)
	if err := r.File.Control.Validate(); err != nil {
		return r.error(err)
	}
	return nil
}
<commit_msg>Modify NewBatch to utilize batchheader.BatchParam<commit_after>// Copyright 2016 The ACH Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
	"bufio"
	"fmt"
	"io"
	"strconv"
)

// ParseError is returned for parsing reader errors.
// The first line is 1.
type ParseError struct {
	Line   int    // Line number where the error accurd
	Record string // Name of the record type being parsed
	Err    error  // The actual error
}

func (e *ParseError) Error() string {
	if e.Record == "" {
		return fmt.Sprintf("line:%d %T %s", e.Line, e.Err, e.Err)
	}
	return fmt.Sprintf("line:%d record:%s %T %s", e.Line, e.Record, e.Err, e.Err)
}

// Reader reads records from a ACH-encoded file.
type Reader struct {
	// r handles the IO.Reader sent to be parser.
	scanner *bufio.Scanner
	// file is ach.file model being built as r is parsed.
	File File
	// line is the current line being parsed from the input r
	line string
	// currentBatch is the current Batch entries being parsed
	currentBatch Batcher
	// line number of the file being parsed
	lineNum int
	// recordName holds the current record name being parsed.
	recordName string
}

// error creates a new ParseError based on err.
func (r *Reader) error(err error) error {
	return &ParseError{
		Line:   r.lineNum,
		Record: r.recordName,
		Err:    err,
	}
}

// addCurrentBatch creates the current batch type for the file being read. A successful
// current batch will be added to r.File once parsed.
func (r *Reader) addCurrentBatch(batch Batcher) {
	r.currentBatch = batch
}

// NewReader returns a new ACH Reader that reads from r.
func NewReader(r io.Reader) *Reader {
	return &Reader{
		scanner: bufio.NewScanner(r),
	}
}

// Read reads each line of the ACH file and defines which parser to use based
// on the first character of each line. It also enforces ACH formating rules and returns
// the appropriate error if issues are found.
func (r *Reader) Read() (File, error) {
	r.lineNum = 0
	// read through the entire file
	for r.scanner.Scan() {
		line := r.scanner.Text()
		r.lineNum++
		lineLength := len(line)

		switch {
		case r.lineNum == 1 && lineLength > RecordLength && lineLength%RecordLength == 0:
			if err := r.processFixedWidthFile(&line); err != nil {
				return r.File, err
			}
		case lineLength != RecordLength:
			msg := fmt.Sprintf(msgRecordLength, lineLength)
			err := &FileError{FieldName: "RecordLength", Value: strconv.Itoa(lineLength), Msg: msg}
			return r.File, r.error(err)
		default:
			r.line = line
			if err := r.parseLine(); err != nil {
				return r.File, err
			}
		}
	}
	if (FileHeader{}) == r.File.Header {
		// Their must be at least one File Header
		r.recordName = "FileHeader"
		return r.File, r.error(&FileError{Msg: msgFileHeader})
	}
	if (FileControl{}) == r.File.Control {
		// Their must be at least one File Control
		r.recordName = "FileControl"
		return r.File, r.error(&FileError{Msg: msgFileControl})
	}

	return r.File, nil
}

func (r *Reader) processFixedWidthFile(line *string) error {
	// it should be safe to parse this byte by byte since ACH files are ascii only
	record := ""
	for i, c := range *line {
		record = record + string(c)
		if i > 0 && (i+1)%RecordLength == 0 {
			r.line = record
			if err := r.parseLine(); err != nil {
				return err
			}
			record = ""
		}
	}
	return nil
}

func (r *Reader) parseLine() error {
	switch r.line[:1] {
	case fileHeaderPos:
		if err := r.parseFileHeader(); err != nil {
			return err
		}
	case batchHeaderPos:
		if err := r.parseBatchHeader(); err != nil {
			return err
		}
	case entryDetailPos:
		if err := r.parseEntryDetail(); err != nil {
			return err
		}
	case entryAddendaPos:
		if err := r.parseAddenda(); err != nil {
			return err
		}
	case batchControlPos:
		if err := r.parseBatchControl(); err != nil {
			return err
		}
		if err := r.currentBatch.Validate(); err != nil {
			r.recordName = "Batches"
			return r.error(err)
		}
		r.File.AddBatch(r.currentBatch)
		r.currentBatch = nil
	case fileControlPos:
		if r.line[:2] == "99" {
			// final blocking padding
			break
		}
		if err := r.parseFileControl(); err != nil {
			return err
		}
	default:
		msg := fmt.Sprintf(msgUnknownRecordType, r.line[:1])
		return r.error(&FileError{FieldName: "recordType", Value: r.line[:1], Msg: msg})
	}
	return nil
}

// parseFileHeader takes the input record string and parses the FileHeaderRecord values
func (r *Reader) parseFileHeader() error {
	r.recordName = "FileHeader"
	if (FileHeader{}) != r.File.Header {
		// Their can only be one File Header per File exit
		r.error(&FileError{Msg: msgFileHeader})
	}
	r.File.Header.Parse(r.line)

	if err := r.File.Header.Validate(); err != nil {
		return r.error(err)
	}
	return nil
}

// parseBatchHeader takes the input record string and parses the FileHeaderRecord values
func (r *Reader) parseBatchHeader() error {
	r.recordName = "BatchHeader"
	if r.currentBatch != nil {
		// batch header inside of current batch
		return r.error(&FileError{Msg: msgFileBatchInside})
	}

	// Ensure we have a valid batch header before building a batch.
	bh := NewBatchHeader()
	bh.Parse(r.line)
	if err := bh.Validate(); err != nil {
		return r.error(err)
	}

	// Passing SEC type into NewBatch creates a Batcher of SEC code type.
	batch, err := NewBatch(bh.BatchParam())
	if err != nil {
		return r.error(err)
	}

	batch.SetHeader(bh)
	r.addCurrentBatch(batch)
	return nil
}

// parseEntryDetail takes the input record string and parses the EntryDetailRecord values
func (r *Reader) parseEntryDetail() error {
	r.recordName = "EntryDetail"
	if r.currentBatch == nil {
		return r.error(&FileError{Msg: msgFileBatchOutside})
	}
	ed := new(EntryDetail)
	ed.Parse(r.line)
	if err := ed.Validate(); err != nil {
		return r.error(err)
	}
	r.currentBatch.AddEntry(ed)
	return nil
}

// parseAddendaRecord takes the input record string and create an Addenda Type appended to the last EntryDetail
func (r *Reader) parseAddenda() error {
	r.recordName = "Addenda"

	if r.currentBatch == nil {
		msg := fmt.Sprintf(msgFileBatchOutside)
		return r.error(&FileError{FieldName: "Addenda", Msg: msg})
	}
	if len(r.currentBatch.GetEntries()) == 0 {
		return r.error(&FileError{FieldName: "Addenda", Msg: msgFileBatchOutside})
	}
	entryIndex := len(r.currentBatch.GetEntries()) - 1
	entry := r.currentBatch.GetEntries()[entryIndex]

	if entry.AddendaRecordIndicator == 1 {
		// Passing TypeCode type into NewAddenda creates a Addendumer of type copde type.
		addenda, err := NewAddenda(AddendaParam{
			TypeCode: r.line[1:3]})
		if err != nil {
			return r.error(err)
		}
		addenda.Parse(r.line)
		if err := addenda.Validate(); err != nil {
			return r.error(err)
		}
		r.currentBatch.GetEntries()[entryIndex].AddAddenda(addenda)
	} else {
		msg := fmt.Sprintf(msgBatchAddendaIndicator)
		return r.error(&FileError{FieldName: "AddendaRecordIndicator", Msg: msg})
	}

	return nil
}

// parseBatchControl takes the input record string and parses the BatchControlRecord values
func (r *Reader) parseBatchControl() error {
	r.recordName = "BatchControl"
	if r.currentBatch == nil {
		// batch Control without a current batch
		return r.error(&FileError{Msg: msgFileBatchOutside})
	}
	r.currentBatch.GetControl().Parse(r.line)
	if err := r.currentBatch.GetControl().Validate(); err != nil {
		return r.error(err)
	}
	return nil
}

// parseFileControl takes the input record string and parses the FileControlRecord values
func (r *Reader) parseFileControl() error {
	r.recordName = "FileControl"
	if (FileControl{}) != r.File.Control {
		// Can be only one file control per file
		return r.error(&FileError{Msg: msgFileControl})
	}
	r.File.Control.Parse(r.line)
	if err := r.File.Control.Validate(); err != nil {
		return r.error(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"socialapi/config"
	"socialapi/workers/common/handler"
	"socialapi/workers/common/mux"
)

const (
	OauthAuthorization = "oauth-authorization"
	GenerateToken      = "generate-token"
)

// AddHandlers adds handlers for slack integration
func AddHandlers(m *mux.Mux, config *config.Config) {
	oauth := &Oauth{}
	m.AddUnscopedHandler(
		handler.Request{
			Handler:  oauth.AuthorizeClient,
			Name:     OauthAuthorization,
			Type:     handler.GetRequest,
			Endpoint: "/oauth/authorize",
		},
	)
	m.AddUnscopedHandler(
		handler.Request{
			Handler:  oauth.GenerateToken,
			Name:     GenerateToken,
			Type:     handler.GetRequest,
			Endpoint: "/oauth/token",
		},
	)

}
<commit_msg>go/oauth: add mongo session data into OauthHandler func<commit_after>package api

import (
	"koding/db/mongodb"
	"socialapi/config"
	"socialapi/workers/common/handler"
	"socialapi/workers/common/mux"

	"github.com/RangelReale/osin"
	"github.com/osin-mongo-storage/mgostore"
	"gopkg.in/mgo.v2"
)

const (
	OauthAuthorization = "oauth-authorization"
	GenerateToken      = "generate-token"
)

// AddHandlers adds handlers for slack integration
func AddHandlers(m *mux.Mux, config *config.Config) {
	mgo = mongodb.NewMongoDB(config.Mongo)
	session := mgo.Session
	dbName := ""

	oauth := NewOAuthHandler(session, dbName)
	m.AddUnscopedHandler(
		handler.Request{
			Handler:  oauth.AuthorizeClient,
			Name:     OauthAuthorization,
			Type:     handler.GetRequest,
			Endpoint: "/oauth/authorize",
		},
	)
	m.AddUnscopedHandler(
		handler.Request{
			Handler:  oauth.GenerateToken,
			Name:     GenerateToken,
			Type:     handler.GetRequest,
			Endpoint: "/oauth/token",
		},
	)

}

func NewOAuthHandler(session *mgo.Session, dbName string) *Oauth {
	sconfig := osin.NewServerConfig()
	sconfig.AllowedAuthorizeTypes = osin.AllowedAuthorizeType{osin.CODE, osin.TOKEN}
	sconfig.AllowedAccessTypes = osin.AllowedAccessType{osin.AUTHORIZATION_CODE,
		osin.REFRESH_TOKEN, osin.PASSWORD, osin.CLIENT_CREDENTIALS, osin.ASSERTION}
	sconfig.AllowGetAccessRequest = true
	storage := mgostore.New(session, dbName)
	server := osin.NewServer(sconfig, storage)

	return &Oauth{
		sconfig: sconfig,
		server:  server,
		Storage: storage,
	}
}
<|endoftext|>