<commit_before>// Copyright 2015 The go-hep Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rio

import (
	"io"
)

// Scanner provides a convenient interface for reading records of a rio-stream.
type Scanner struct {
	r   *Reader
	err error   // first non-EOF error encountered while reading the rio-stream.
	rec *Record // last record encountered while reading the rio-stream.
}

// NewScanner returns a new Scanner to read from r.
func NewScanner(r *Reader) *Scanner {
	scan := &Scanner{
		r:   r,
		err: nil,
		rec: newRecord("<N/A>", 0),
	}
	scan.rec.unpack = false
	scan.rec.r = r
	return scan
}

// Scan scans the next Record until io.EOF
func (s *Scanner) Scan() bool {
	if s.err != nil {
		return false
	}

	// FIXME(sbinet): what happens when different record-shapes and record.unpack==true?
	// should we allocate anew?
	err := s.rec.Read()
	if err != nil {
		s.err = err
		return false
	}

	return true
}

// Err returns the first non-EOF error encountered by the reader.
func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

// Record returns the last Record read by the Scanner.
func (s *Scanner) Record() *Record {
	return s.rec
}
<commit_msg>scanner: impl. selection of records<commit_after>// Copyright 2015 The go-hep Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rio

import (
	"io"
	"io/ioutil"
)

// Selector selects Records based on their name
type Selector struct {
	Name   string // Record name
	Unpack bool   // Whether to unpack the Record
}

// Scanner provides a convenient interface for reading records of a rio-stream.
type Scanner struct {
	r   *Reader
	err error   // first non-EOF error encountered while reading the rio-stream.
	rec *Record // last record encountered while reading the rio-stream.

	filter map[string]Selector // records to read. if nil, return everything.
}

// NewScanner returns a new Scanner to read from r.
func NewScanner(r *Reader) *Scanner {
	scan := &Scanner{
		r:      r,
		err:    nil,
		rec:    newRecord("<N/A>", 0),
		filter: make(map[string]Selector, 0),
	}
	scan.rec.unpack = false
	scan.rec.r = r
	return scan
}

// Select sets the records selection function.
func (s *Scanner) Select(selectors []Selector) {
	s.filter = make(map[string]Selector, len(selectors))
	for _, sel := range selectors {
		s.filter[sel.Name] = sel
	}
}

// Scan scans the next Record until io.EOF
func (s *Scanner) Scan() bool {
	if s.err != nil {
		return false
	}

	for {
		err := s.rec.raw.RioDecode(s.r.r)
		if err != nil {
			s.err = err
			return false
		}

		clen := int64(rioAlignU64(s.rec.raw.CLen))

		name := s.rec.Name()
		if len(s.filter) > 0 {
			_, ok := s.filter[name]
			if !ok {
				_, err = s.seek(clen, 0)
				if err != nil {
					s.err = err
					return false
				}
				continue
			}
		}

		s.rec.unpack = s.filter[name].Unpack

		switch s.rec.unpack {

		case true:
			err = s.rec.readBlocks(s.r.r)
			if err != nil {
				s.err = err
				return false
			}
			return true

		case false:
			_, err = s.seek(clen, 0)
			if err != nil {
				s.err = err
				return false
			}
			return true
		}
	}

	return true
}

// seek sets the offset for the next Read or Write on file to offset,
// interpreted according to whence: 0 means relative to the origin of the
// file, 1 means relative to the current offset, and 2 means relative to
// the end. It returns the new offset and an error, if any.
func (s *Scanner) seek(offset int64, whence int) (ret int64, err error) {
	switch r := s.r.r.(type) {
	case io.Seeker:
		return r.Seek(offset, whence)
	default:
		if whence != 0 {
			panic("not implemented")
		}
		return io.CopyN(ioutil.Discard, r, offset)
	}
}

// Err returns the first non-EOF error encountered by the reader.
func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

// Record returns the last Record read by the Scanner.
func (s *Scanner) Record() *Record {
	return s.rec
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"

	"github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v3"
	"github.com/rancher/rancher-compose-executor/convert"
	"github.com/rancher/rancher-compose-executor/project"
	"github.com/rancher/rancher-compose-executor/project/options"
	"github.com/rancher/rancher-compose-executor/utils"
	"golang.org/x/net/context"
)

type ServiceWrapper struct {
	name    string
	project *project.Project
}

func (s *ServiceWrapper) Exists() (bool, error) {
	val, err := s.project.ServerResourceLookup.Service(s.name)
	return val != nil, err
}

func (s *ServiceWrapper) Create(ctx context.Context, options options.Options) error {
	service, err := convert.Service(s.project, s.name)
	if err != nil {
		return err
	}

	logrus.Debugf("Creating service %s", s.name)
	service.CreateOnly = true
	service, err = s.project.Client.Service.Create(service)
	if err != nil {
		return err
	}
	return wait(ctx, s.project.Client, service)
}

func (s *ServiceWrapper) Image() string {
	return s.project.Config.Services[s.name].Image
}

func (s *ServiceWrapper) Labels() map[string]interface{} {
	return utils.ToMapInterface(s.project.Config.Services[s.name].Labels)
}

func (s *ServiceWrapper) upgrade(ctx context.Context, service *client.Service, options options.Options) error {
	if options.NoRecreate {
		return nil
	}

	updates, err := convert.Service(s.project, s.name)
	if err != nil {
		return err
	}

	if options.ForceRecreate {
		if utils.IsSelected(options.Services, s.name) && updates.LaunchConfig != nil {
			updates.LaunchConfig.ForceUpgrade = true
		}
		for i, lc := range updates.SecondaryLaunchConfigs {
			if utils.IsSelected(options.Services, lc.Name) {
				updates.SecondaryLaunchConfigs[i].ForceUpgrade = true
			}
		}
	}

	err = utils.RetryOnError(10, updateServiceWrapper(s.project.Client, service, updates))
	if err != nil {
		return err
	}

	return wait(ctx, s.project.Client, service)
}

func updateServiceWrapper(client *client.RancherClient, service *client.Service, updates *client.Service) func() error {
	return func() error {
		_, err := client.Service.Update(service, updates)
		if err != nil {
			return err
		}
		return nil
	}
}

func (s *ServiceWrapper) rollback(ctx context.Context, service *client.Service) error {
	service, err := s.project.Client.Service.ActionRollback(service, nil)
	if err != nil {
		return err
	}

	return wait(ctx, s.project.Client, service)
}

func (s *ServiceWrapper) Up(ctx context.Context, options options.Options) error {
	service, err := s.project.ServerResourceLookup.Service(s.name)
	if err != nil {
		return err
	}
	if service == nil {
		return fmt.Errorf("Failed to find service %s", s.name)
	}

	if options.Rollback {
		return s.rollback(ctx, service)
	}

	if service.State == "upgraded" {
		service, err = s.project.Client.Service.ActionFinishupgrade(service)
		if err != nil {
			return err
		}
		if err = wait(ctx, s.project.Client, service); err != nil {
			return err
		}
	}

	if service.State == "inactive" {
		service, err = s.project.Client.Service.ActionActivate(service)
		if err != nil {
			return err
		}
		if err = wait(ctx, s.project.Client, service); err != nil {
			return err
		}
	}

	return s.upgrade(ctx, service, options)
}
<commit_msg>always set completeUpdate to true<commit_after>package service

import (
	"fmt"

	"github.com/Sirupsen/logrus"
	"github.com/rancher/go-rancher/v3"
	"github.com/rancher/rancher-compose-executor/convert"
	"github.com/rancher/rancher-compose-executor/project"
	"github.com/rancher/rancher-compose-executor/project/options"
	"github.com/rancher/rancher-compose-executor/utils"
	"golang.org/x/net/context"
)

type ServiceWrapper struct {
	name    string
	project *project.Project
}

func (s *ServiceWrapper) Exists() (bool, error) {
	val, err := s.project.ServerResourceLookup.Service(s.name)
	return val != nil, err
}

func (s *ServiceWrapper) Create(ctx context.Context, options options.Options) error {
	service, err := convert.Service(s.project, s.name)
	if err != nil {
		return err
	}

	logrus.Debugf("Creating service %s", s.name)
	service.CreateOnly = true
	service.CompleteUpdate = true
	if service.LaunchConfig != nil {
		service.LaunchConfig.CompleteUpdate = true
	}
	for i := range service.SecondaryLaunchConfigs {
		service.SecondaryLaunchConfigs[i].CompleteUpdate = true
	}
	service, err = s.project.Client.Service.Create(service)
	if err != nil {
		return err
	}
	return wait(ctx, s.project.Client, service)
}

func (s *ServiceWrapper) Image() string {
	return s.project.Config.Services[s.name].Image
}

func (s *ServiceWrapper) Labels() map[string]interface{} {
	return utils.ToMapInterface(s.project.Config.Services[s.name].Labels)
}

func (s *ServiceWrapper) upgrade(ctx context.Context, service *client.Service, options options.Options) error {
	if options.NoRecreate {
		return nil
	}

	updates, err := convert.Service(s.project, s.name)
	if err != nil {
		return err
	}

	if options.ForceRecreate {
		if utils.IsSelected(options.Services, s.name) && updates.LaunchConfig != nil {
			updates.LaunchConfig.ForceUpgrade = true
		}
		for i, lc := range updates.SecondaryLaunchConfigs {
			if utils.IsSelected(options.Services, lc.Name) {
				updates.SecondaryLaunchConfigs[i].ForceUpgrade = true
			}
		}
	}

	err = utils.RetryOnError(10, updateServiceWrapper(s.project.Client, service, updates))
	if err != nil {
		return err
	}

	return wait(ctx, s.project.Client, service)
}

func updateServiceWrapper(client *client.RancherClient, service *client.Service, updates *client.Service) func() error {
	return func() error {
		_, err := client.Service.Update(service, updates)
		if err != nil {
			return err
		}
		return nil
	}
}

func (s *ServiceWrapper) rollback(ctx context.Context, service *client.Service) error {
	service, err := s.project.Client.Service.ActionRollback(service, nil)
	if err != nil {
		return err
	}

	return wait(ctx, s.project.Client, service)
}

func (s *ServiceWrapper) Up(ctx context.Context, options options.Options) error {
	service, err := s.project.ServerResourceLookup.Service(s.name)
	if err != nil {
		return err
	}
	if service == nil {
		return fmt.Errorf("Failed to find service %s", s.name)
	}

	if options.Rollback {
		return s.rollback(ctx, service)
	}

	if service.State == "upgraded" {
		service, err = s.project.Client.Service.ActionFinishupgrade(service)
		if err != nil {
			return err
		}
		if err = wait(ctx, s.project.Client, service); err != nil {
			return err
		}
	}

	if service.State == "inactive" {
		service, err = s.project.Client.Service.ActionActivate(service)
		if err != nil {
			return err
		}
		if err = wait(ctx, s.project.Client, service); err != nil {
			return err
		}
	}

	return s.upgrade(ctx, service, options)
}
<|endoftext|>


<commit_before>package jo

import (
	"fmt"
)

// Valid scanner states.
const (
	sClean = iota
	sEOF

	sObjectKeyOrBrace
	sObjectColon
	sObjectCommaOrBrace
	sObjectKey

	sArrayElementOrBracket
	sArrayCommaOrBracket

	sString
	sStringEsc
	sStringUnicode
	sStringUnicode1
	sStringUnicode12
	sStringUnicode123

	sNumberNeg
	sNumberZero
	sNumberDigit
	sNumberDot
	sNumberDotDigit
	sNumberExp
	sNumberExpSign
	sNumberExpDigit

	sBoolT
	sBoolTr
	sBoolTru

	sBoolF
	sBoolFa
	sBoolFal
	sBoolFals

	sNullN
	sNullNu
	sNullNul
)

// Scanner is a JSON scanning state machine. The zero value for Scanner is
// ready to be used without any further initialization.
type Scanner struct {
	state int
	err   error
	stack []int
	size  int
	isKey bool
}

// Scan feeds another byte to the scanner.
//
// The first return value, refered to as an opcode, tells the caller about
// significant parsing events like beginning and ending values, so that the
// caller can follow along if it wishes.
//
// The second return value is used to indicate whether or not, which is
// necessary because of number literals (is 123 a whole value, or just the
// beginning of 12345?). Even though it will only ever be either 1 or 0, it is
// an integer rather than a boolean to allow for these kinds of constructs:
//
//     for i := 0; i < len(input); {
//         _, n := s.Scan(input[i])
//         i += n
//     }
func (s *Scanner) Scan(c byte) (Op, int) {
rewind:
	switch s.state {
	case sClean:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '{':
			s.state = sObjectKeyOrBrace
			return OpObjectStart, 1
		case '[':
			s.state = sArrayElementOrBracket
			return OpArrayStart, 1
		case '"':
			s.state = sString
			s.isKey = false
			return OpStringStart, 1
		case '-':
			s.state = sNumberNeg
			return OpNumberStart, 1
		case '0':
			s.state = sNumberZero
			return OpNumberStart, 1
		case '1', '2', '3', '4', '5', '6', '7', '8', '9':
			s.state = sNumberDigit
			return OpNumberStart, 1
		case 't':
			s.state = sBoolT
			return OpBoolStart, 1
		case 'f':
			s.state = sBoolF
			return OpBoolStart, 1
		case 'n':
			s.state = sNullN
			return OpNullStart, 1
		}
		return s.errorf(`expected start of JSON value, found %q`, c)

	case sObjectKeyOrBrace:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '"':
			s.push(sObjectColon)
			s.state = sString
			s.isKey = true
			return OpObjectKeyStart, 1
		case '}':
			s.state = s.pop()
			return OpObjectEnd, 1
		}
		return s.errorf(`expected object key or '}', found %q`, c)

	case sObjectColon:
		switch c {
		case ' ', '\t', 'r', '\n':
			return OpSpace, 1
		case ':':
			s.push(sObjectCommaOrBrace)
			s.state = sClean
			return OpContinue, 1
		}
		return s.errorf(`expected ':' after object key, found %q`, c)

	case sObjectCommaOrBrace:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case ',':
			s.state = sObjectKey
			return OpContinue, 1
		case '}':
			s.state = s.pop()
			return OpObjectEnd, 1
		}
		return s.errorf(`expected object key or '}' after object value, found %q`, c)

	case sObjectKey:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '"':
			s.push(sObjectColon)
			s.state = sString
			s.isKey = true
			return OpObjectKeyStart, 1
		}
		return s.errorf(`expected object key after ',', found %q`, c)

	case sArrayElementOrBracket:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case ']':
			s.state = s.pop()
			return OpArrayEnd, 1
		}
		s.push(sArrayCommaOrBracket)
		s.state = sClean
		goto rewind

	case sArrayCommaOrBracket:
		switch c {
		case ' ', '\t', '\n', '\r':
			return OpSpace, 1
		case ',':
			s.state = sArrayElementOrBracket
			return OpContinue, 1
		case ']':
			s.state = s.pop()
			return OpArrayEnd, 1
		}
		return s.errorf(`expected ',' or ']' after array element, found %q`, c)

	case sString:
		if c == '"' {
			s.state = s.pop()
			if s.isKey {
				return OpObjectKeyEnd, 1
			}
			return OpStringEnd, 1
		}
		if c == '\\' {
			s.state = sStringEsc
			return OpContinue, 1
		}
		if c >= 0x20 {
			return OpContinue, 1
		}
		return s.errorf(`unexpected control character in string literal`)

	case sStringEsc:
		switch c {
		case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
			s.state = sString
			return OpContinue, 1
		case 'u':
			s.state = sStringUnicode
			return OpContinue, 1
		}
		return s.errorf(`illegal escape sequence in string literal`)

	case sStringUnicode:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode1
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode1:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode12
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode12:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode123
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode123:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sString
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sNumberNeg:
		if c == '0' {
			s.state = sNumberZero
			return OpContinue, 1
		}
		if '1' <= c && c <= '9' {
			s.state = sNumberDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after "-", found %q`, c)

	case sNumberDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		fallthrough

	case sNumberZero:
		if c == '.' {
			s.state = sNumberDot
			return OpContinue, 1
		}
		if c == 'e' || c == 'E' {
			s.state = sNumberExp
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sNumberDot:
		if '0' <= c && c <= '9' {
			s.state = sNumberDotDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after decimal point, found %q`, c)

	case sNumberDotDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		if c == 'e' || c == 'E' {
			s.state = sNumberExp
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sNumberExp:
		if '0' <= c && c <= '9' {
			s.state = sNumberExpDigit
			return OpContinue, 1
		}
		if c == '-' || c == '+' {
			s.state = sNumberExpSign
			return OpContinue, 1
		}
		return s.errorf(`expected sign or digit in exponent, found %q`, c)

	case sNumberExpSign:
		if '0' <= c && c <= '9' {
			s.state = sNumberExpDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after exponent sign, found %q`)

	case sNumberExpDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sBoolT:
		if c == 'r' {
			s.state = sBoolTr
			return OpContinue, 1
		}
		return s.errorf(`expected 'r' after "t", found %q`, c)

	case sBoolTr:
		if c == 'u' {
			s.state = sBoolTru
			return OpContinue, 1
		}
		return s.errorf(`expected 'u' after "tr", found %q`, c)

	case sBoolTru:
		if c == 'e' {
			s.state = s.pop()
			return OpBoolEnd, 1
		}
		return s.errorf(`expected 'e' after "tru", found %q`, c)

	case sBoolF:
		if c == 'a' {
			s.state = sBoolFa
			return OpContinue, 1
		}
		return s.errorf(`expected 'a' after "f", found %q`, c)

	case sBoolFa:
		if c == 'l' {
			s.state = sBoolFal
			return OpContinue, 1
		}
		return s.errorf(`expected 'l' after "fa", found %q`, c)

	case sBoolFal:
		if c == 's' {
			s.state = sBoolFals
			return OpContinue, 1
		}
		return s.errorf(`expected 's' after "fal", found %q`, c)

	case sBoolFals:
		if c == 'e' {
			s.state = s.pop()
			return OpBoolEnd, 1
		}
		return s.errorf(`expected 'e' after "fals", found %q`, c)

	case sNullN:
		if c == 'u' {
			s.state = sNullNu
			return OpContinue, 1
		}
		return s.errorf(`expected 'u' after "n", found %q`, c)

	case sNullNu:
		if c == 'l' {
			s.state = sNullNul
			return OpContinue, 1
		}
		return s.errorf(`expected 'l' after "nu", found %q`, c)

	case sNullNul:
		if c == 'l' {
			s.state = s.pop()
			return OpNullEnd, 1
		}
		return s.errorf(`expected 'l' after "nul", found %q`, c)

	case sEOF:
		if c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
			return OpSpace, 1
		}
		return s.errorf(`unexpected %q after top-level value`, c)
	}

	return OpContinue, 1
}

// Eof signals the scanner that the end of input has been reached. It returns
// an opcode, just as s.Scan does, which will be either OpEOF, OpNumberEnd or
// OpSyntaxError.
func (s *Scanner) Eof() Op {
	switch s.state {
	case sNumberZero, sNumberDigit, sNumberDotDigit, sNumberExpDigit:
		if len(s.stack) == 0 {
			s.state = sEOF
			return OpNumberEnd
		}
	case sEOF:
		return OpEOF
	}

	op, _ := s.errorf(`unexpected end of JSON input`)
	return op
}

// LastError returns the last error raised by the Scan or Eof methods.
func (s *Scanner) LastError() error {
	return s.err
}

// Reset resets the scanner's internal state.
func (s *Scanner) Reset() {
	s.state = 0
	s.err = nil
	s.stack = s.stack[:0]
	s.size = 0
}

// push adds a new state to the stack.
func (s *Scanner) push(x int) {
	if len(s.stack) == s.size {
		s.stack = append(s.stack, x)
	} else {
		s.stack[s.size] = x
	}
	s.size++
}

// pop takes the top state from the stack.
func (s *Scanner) pop() int {
	if s.size == 0 {
		return sEOF
	}

	s.size--
	return s.stack[s.size]
}

// errorf is a convenience function which both sets the scanner's error
// field and returns an OpSyntaxError opcode.
func (s *Scanner) errorf(format string, args ...interface{}) (Op, int) {
	s.err = fmt.Errorf(format, args...)
	return OpSyntaxError, 0
}
<commit_msg>Panic on invalid internal scanner states<commit_after>package jo

import (
	"fmt"
)

// Valid scanner states.
const (
	sClean = iota
	sEOF

	sObjectKeyOrBrace
	sObjectColon
	sObjectCommaOrBrace
	sObjectKey

	sArrayElementOrBracket
	sArrayCommaOrBracket

	sString
	sStringEsc
	sStringUnicode
	sStringUnicode1
	sStringUnicode12
	sStringUnicode123

	sNumberNeg
	sNumberZero
	sNumberDigit
	sNumberDot
	sNumberDotDigit
	sNumberExp
	sNumberExpSign
	sNumberExpDigit

	sBoolT
	sBoolTr
	sBoolTru

	sBoolF
	sBoolFa
	sBoolFal
	sBoolFals

	sNullN
	sNullNu
	sNullNul
)

// Scanner is a JSON scanning state machine. The zero value for Scanner is
// ready to be used without any further initialization.
type Scanner struct {
	state int
	err   error
	stack []int
	size  int
	isKey bool
}

// Scan feeds another byte to the scanner.
//
// The first return value, refered to as an opcode, tells the caller about
// significant parsing events like beginning and ending values, so that the
// caller can follow along if it wishes.
//
// The second return value is used to indicate whether or not, which is
// necessary because of number literals (is 123 a whole value, or just the
// beginning of 12345?). Even though it will only ever be either 1 or 0, it is
// an integer rather than a boolean to allow for these kinds of constructs:
//
//     for i := 0; i < len(input); {
//         _, n := s.Scan(input[i])
//         i += n
//     }
func (s *Scanner) Scan(c byte) (Op, int) {
rewind:
	switch s.state {
	case sClean:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '{':
			s.state = sObjectKeyOrBrace
			return OpObjectStart, 1
		case '[':
			s.state = sArrayElementOrBracket
			return OpArrayStart, 1
		case '"':
			s.state = sString
			s.isKey = false
			return OpStringStart, 1
		case '-':
			s.state = sNumberNeg
			return OpNumberStart, 1
		case '0':
			s.state = sNumberZero
			return OpNumberStart, 1
		case '1', '2', '3', '4', '5', '6', '7', '8', '9':
			s.state = sNumberDigit
			return OpNumberStart, 1
		case 't':
			s.state = sBoolT
			return OpBoolStart, 1
		case 'f':
			s.state = sBoolF
			return OpBoolStart, 1
		case 'n':
			s.state = sNullN
			return OpNullStart, 1
		}
		return s.errorf(`expected start of JSON value, found %q`, c)

	case sObjectKeyOrBrace:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '"':
			s.push(sObjectColon)
			s.state = sString
			s.isKey = true
			return OpObjectKeyStart, 1
		case '}':
			s.state = s.pop()
			return OpObjectEnd, 1
		}
		return s.errorf(`expected object key or '}', found %q`, c)

	case sObjectColon:
		switch c {
		case ' ', '\t', 'r', '\n':
			return OpSpace, 1
		case ':':
			s.push(sObjectCommaOrBrace)
			s.state = sClean
			return OpContinue, 1
		}
		return s.errorf(`expected ':' after object key, found %q`, c)

	case sObjectCommaOrBrace:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case ',':
			s.state = sObjectKey
			return OpContinue, 1
		case '}':
			s.state = s.pop()
			return OpObjectEnd, 1
		}
		return s.errorf(`expected object key or '}' after object value, found %q`, c)

	case sObjectKey:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case '"':
			s.push(sObjectColon)
			s.state = sString
			s.isKey = true
			return OpObjectKeyStart, 1
		}
		return s.errorf(`expected object key after ',', found %q`, c)

	case sArrayElementOrBracket:
		switch c {
		case ' ', '\t', '\r', '\n':
			return OpSpace, 1
		case ']':
			s.state = s.pop()
			return OpArrayEnd, 1
		}
		s.push(sArrayCommaOrBracket)
		s.state = sClean
		goto rewind

	case sArrayCommaOrBracket:
		switch c {
		case ' ', '\t', '\n', '\r':
			return OpSpace, 1
		case ',':
			s.state = sArrayElementOrBracket
			return OpContinue, 1
		case ']':
			s.state = s.pop()
			return OpArrayEnd, 1
		}
		return s.errorf(`expected ',' or ']' after array element, found %q`, c)

	case sString:
		if c == '"' {
			s.state = s.pop()
			if s.isKey {
				return OpObjectKeyEnd, 1
			}
			return OpStringEnd, 1
		}
		if c == '\\' {
			s.state = sStringEsc
			return OpContinue, 1
		}
		if c >= 0x20 {
			return OpContinue, 1
		}
		return s.errorf(`unexpected control character in string literal`)

	case sStringEsc:
		switch c {
		case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
			s.state = sString
			return OpContinue, 1
		case 'u':
			s.state = sStringUnicode
			return OpContinue, 1
		}
		return s.errorf(`illegal escape sequence in string literal`)

	case sStringUnicode:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode1
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode1:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode12
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode12:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sStringUnicode123
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sStringUnicode123:
		if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
			s.state = sString
			return OpContinue, 1
		}
		return s.errorf(`illegal unicode escape sequence in string literal`)

	case sNumberNeg:
		if c == '0' {
			s.state = sNumberZero
			return OpContinue, 1
		}
		if '1' <= c && c <= '9' {
			s.state = sNumberDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after "-", found %q`, c)

	case sNumberDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		fallthrough

	case sNumberZero:
		if c == '.' {
			s.state = sNumberDot
			return OpContinue, 1
		}
		if c == 'e' || c == 'E' {
			s.state = sNumberExp
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sNumberDot:
		if '0' <= c && c <= '9' {
			s.state = sNumberDotDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after decimal point, found %q`, c)

	case sNumberDotDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		if c == 'e' || c == 'E' {
			s.state = sNumberExp
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sNumberExp:
		if '0' <= c && c <= '9' {
			s.state = sNumberExpDigit
			return OpContinue, 1
		}
		if c == '-' || c == '+' {
			s.state = sNumberExpSign
			return OpContinue, 1
		}
		return s.errorf(`expected sign or digit in exponent, found %q`, c)

	case sNumberExpSign:
		if '0' <= c && c <= '9' {
			s.state = sNumberExpDigit
			return OpContinue, 1
		}
		return s.errorf(`expected digit after exponent sign, found %q`)

	case sNumberExpDigit:
		if '0' <= c && c <= '9' {
			return OpContinue, 1
		}
		s.state = s.pop()
		return OpNumberEnd, 0

	case sBoolT:
		if c == 'r' {
			s.state = sBoolTr
			return OpContinue, 1
		}
		return s.errorf(`expected 'r' after "t", found %q`, c)

	case sBoolTr:
		if c == 'u' {
			s.state = sBoolTru
			return OpContinue, 1
		}
		return s.errorf(`expected 'u' after "tr", found %q`, c)

	case sBoolTru:
		if c == 'e' {
			s.state = s.pop()
			return OpBoolEnd, 1
		}
		return s.errorf(`expected 'e' after "tru", found %q`, c)

	case sBoolF:
		if c == 'a' {
			s.state = sBoolFa
			return OpContinue, 1
		}
		return s.errorf(`expected 'a' after "f", found %q`, c)

	case sBoolFa:
		if c == 'l' {
			s.state = sBoolFal
			return OpContinue, 1
		}
		return s.errorf(`expected 'l' after "fa", found %q`, c)

	case sBoolFal:
		if c == 's' {
			s.state = sBoolFals
			return OpContinue, 1
		}
		return s.errorf(`expected 's' after "fal", found %q`, c)

	case sBoolFals:
		if c == 'e' {
			s.state = s.pop()
			return OpBoolEnd, 1
		}
		return s.errorf(`expected 'e' after "fals", found %q`, c)

	case sNullN:
		if c == 'u' {
			s.state = sNullNu
			return OpContinue, 1
		}
		return s.errorf(`expected 'u' after "n", found %q`, c)

	case sNullNu:
		if c == 'l' {
			s.state = sNullNul
			return OpContinue, 1
		}
		return s.errorf(`expected 'l' after "nu", found %q`, c)

	case sNullNul:
		if c == 'l' {
			s.state = s.pop()
			return OpNullEnd, 1
		}
		return s.errorf(`expected 'l' after "nul", found %q`, c)

	case sEOF:
		if c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
			return OpSpace, 1
		}
		return s.errorf(`unexpected %q after top-level value`, c)
	}

	panic("invalid internal state")
}

// Eof signals the scanner that the end of input has been reached. It returns
// an opcode, just as s.Scan does, which will be either OpEOF, OpNumberEnd or
// OpSyntaxError.
func (s *Scanner) Eof() Op {
	switch s.state {
	case sNumberZero, sNumberDigit, sNumberDotDigit, sNumberExpDigit:
		if len(s.stack) == 0 {
			s.state = sEOF
			return OpNumberEnd
		}
	case sEOF:
		return OpEOF
	}

	op, _ := s.errorf(`unexpected end of JSON input`)
	return op
}

// LastError returns the last error raised by the Scan or Eof methods.
func (s *Scanner) LastError() error {
	return s.err
}

// Reset resets the scanner's internal state.
func (s *Scanner) Reset() {
	s.state = 0
	s.err = nil
	s.stack = s.stack[:0]
	s.size = 0
}

// push adds a new state to the stack.
func (s *Scanner) push(x int) {
	if len(s.stack) == s.size {
		s.stack = append(s.stack, x)
	} else {
		s.stack[s.size] = x
	}
	s.size++
}

// pop takes the top state from the stack.
func (s *Scanner) pop() int {
	if s.size == 0 {
		return sEOF
	}

	s.size--
	return s.stack[s.size]
}

// errorf is a convenience function which both sets the scanner's error
// field and returns an OpSyntaxError opcode.
func (s *Scanner) errorf(format string, args ...interface{}) (Op, int) {
	s.err = fmt.Errorf(format, args...)
	return OpSyntaxError, 0
}
<|endoftext|>


<commit_before>// Copyright 2011 Arne Roomann-Kurrik.
//
// 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 oauth1a implements the OAuth 1.0a specification.
*/
package oauth1a

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
)

// Container for client-specific configuration related to the OAuth process.
// This struct is intended to be serialized and stored for future use.
type ClientConfig struct {
	ConsumerSecret string
	ConsumerKey    string
	CallbackURL    string
}

// Represents an API which offers OAuth access.
type Service struct {
	RequestURL   string
	AuthorizeURL string
	AccessURL    string
	*ClientConfig
	Signer
}

// Signs an HTTP request with the needed OAuth parameters.
func (s *Service) Sign(request *http.Request, userConfig *UserConfig) error {
	return s.Signer.Sign(request, s.ClientConfig, userConfig)
}

// Interface for any OAuth signing implementations.
type Signer interface {
	Sign(request *http.Request, config *ClientConfig, user *UserConfig) error
}

// A Signer which implements the HMAC-SHA1 signing algorithm.
type HmacSha1Signer struct{}

// Sort a set of request parameters alphabetically, and encode according to the
// OAuth 1.0a specification.
func (HmacSha1Signer) encodeParameters(params map[string]string) string {
	keys := make([]string, len(params))
	encodedParts := make([]string, len(params))
	i := 0
	for key, _ := range params {
		keys[i] = key
		i += 1
	}
	sort.Strings(keys)
	for i, key := range keys {
		value := params[key]
		encoded := Rfc3986Escape(key) + "=" + Rfc3986Escape(value)
		encodedParts[i] = encoded
	}
	return url.QueryEscape(strings.Join(encodedParts, "&"))
}

// Generate a unique nonce value.  Should not be called more than once per
// nanosecond
// TODO: Come up with a better generation method.
func (HmacSha1Signer) GenerateNonce() string {
	ns := time.Now()
	token := fmt.Sprintf("OAuth Client Lib %v", ns)
	h := sha1.New()
	h.Write([]byte(token))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// Generate a timestamp.
func (HmacSha1Signer) GenerateTimestamp() int64 {
	return time.Now().UTC().Unix()
}

// Returns a map of all of the oauth_* (including signature) parameters for the
// given request, and the signature base string used to generate the signature.
func (s *HmacSha1Signer) GetOAuthParams(request *http.Request, clientConfig *ClientConfig, userConfig *UserConfig, nonce string, timestamp string) (map[string]string, string) {
	request.ParseForm()
	oauthParams := map[string]string{
		"oauth_consumer_key":     clientConfig.ConsumerKey,
		"oauth_nonce":            nonce,
		"oauth_signature_method": "HMAC-SHA1",
		"oauth_timestamp":        timestamp,
		"oauth_version":          "1.0",
	}
	tokenKey, tokenSecret := userConfig.GetToken()
	if tokenKey != "" {
		oauthParams["oauth_token"] = tokenKey
	}
	signingParams := map[string]string{}
	for key, value := range oauthParams {
		signingParams[key] = value
	}
	for key, value := range request.URL.Query() {
		//TODO: Support multiple parameters with the same name.
		signingParams[key] = value[0]
	}
	for key, value := range request.Form {
		//TODO: Support multiple parameters with the same name.
		signingParams[key] = value[0]
	}
	signingUrl := fmt.Sprintf("%v://%v%v", request.URL.Scheme, request.URL.Host, request.URL.Path)
	signatureParts := []string{
		request.Method,
		url.QueryEscape(signingUrl),
		s.encodeParameters(signingParams)}
	signatureBase := strings.Join(signatureParts, "&")
	oauthParams["oauth_signature"] = s.GetSignature(clientConfig.ConsumerSecret, tokenSecret, signatureBase)
	return oauthParams, signatureBase
}

// Calculates the HMAC-SHA1 signature of a base string, given a consumer and
// token secret.
func (s *HmacSha1Signer) GetSignature(consumerSecret string, tokenSecret string, signatureBase string) string {
	signingKey := consumerSecret + "&" + tokenSecret
	signer := hmac.New(sha1.New, []byte(signingKey))
	signer.Write([]byte(signatureBase))
	oauthSignature := base64.StdEncoding.EncodeToString(signer.Sum(nil))
	return oauthSignature
}

// Given an unsigned request, add the appropriate OAuth Authorization header
// using the HMAC-SHA1 algorithm.
func (s *HmacSha1Signer) Sign(request *http.Request, clientConfig *ClientConfig, userConfig *UserConfig) error {
	var (
		nonce string
		timestamp string
	)
	if nonce = request.Header.Get("X-OAuth-Nonce"); nonce != "" {
		request.Header.Del("X-OAuth-Nonce")
	} else {
		nonce = s.GenerateNonce()
	}
	if timestamp = request.Header.Get("X-OAuth-Timestamp"); timestamp != "" {
		request.Header.Del("X-OAuth-Timestamp")
	} else {
		timestamp = fmt.Sprintf("%v", s.GenerateTimestamp())
	}
	oauthParams, _ := s.GetOAuthParams(request, clientConfig, userConfig, nonce, timestamp)
	headerParts := make([]string, len(oauthParams))
	var i = 0
	for key, value := range oauthParams {
		headerParts[i] = Rfc3986Escape(key) + "=\"" + Rfc3986Escape(value) + "\""
		i += 1
	}
	sort.Strings(headerParts)
	oauthHeader := "OAuth " + strings.Join(headerParts, ", ")
	request.Header["Authorization"] = []string{oauthHeader}
	return nil
}

// Characters which should not be escaped according to RFC 3986.
const UNESCAPE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~"

// Escapes a string more in line with Rfc3986 than http.URLEscape.
// URLEscape was converting spaces to "+" instead of "%20", which was messing up
// the signing of requests.
func Rfc3986Escape(input string) string {
	var output bytes.Buffer
	// Convert string to bytes because iterating over a unicode string
	// in go parses runes, not bytes.
	for _, c := range []byte(input) {
		if strings.IndexAny(string(c), UNESCAPE_CHARS) == -1 {
			encoded := fmt.Sprintf("%%%X", c)
			output.Write([]uint8(encoded))
		} else {
			output.WriteByte(uint8(c))
		}
	}
	return string(output.Bytes())
}
<commit_msg>Repopulate the body of a request after eating it for signing<commit_after>// Copyright 2011 Arne Roomann-Kurrik.
//
// 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 oauth1a implements the OAuth 1.0a specification.
*/
package oauth1a

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
)

// Container for client-specific configuration related to the OAuth process.
// This struct is intended to be serialized and stored for future use.
type ClientConfig struct {
	ConsumerSecret string
	ConsumerKey    string
	CallbackURL    string
}

// Represents an API which offers OAuth access.
type Service struct {
	RequestURL   string
	AuthorizeURL string
	AccessURL    string
	*ClientConfig
	Signer
}

// Signs an HTTP request with the needed OAuth parameters.
func (s *Service) Sign(request *http.Request, userConfig *UserConfig) error {
	return s.Signer.Sign(request, s.ClientConfig, userConfig)
}

// Interface for any OAuth signing implementations.
type Signer interface {
	Sign(request *http.Request, config *ClientConfig, user *UserConfig) error
}

// A Signer which implements the HMAC-SHA1 signing algorithm.
type HmacSha1Signer struct{}

// Sort a set of request parameters alphabetically, and encode according to the
// OAuth 1.0a specification.
func (HmacSha1Signer) encodeParameters(params map[string]string) string {
	keys := make([]string, len(params))
	encodedParts := make([]string, len(params))
	i := 0
	for key, _ := range params {
		keys[i] = key
		i += 1
	}
	sort.Strings(keys)
	for i, key := range keys {
		value := params[key]
		encoded := Rfc3986Escape(key) + "=" + Rfc3986Escape(value)
		encodedParts[i] = encoded
	}
	return url.QueryEscape(strings.Join(encodedParts, "&"))
}

// Generate a unique nonce value.  Should not be called more than once per
// nanosecond
// TODO: Come up with a better generation method.
func (HmacSha1Signer) GenerateNonce() string {
	ns := time.Now()
	token := fmt.Sprintf("OAuth Client Lib %v", ns)
	h := sha1.New()
	h.Write([]byte(token))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// Generate a timestamp.
func (HmacSha1Signer) GenerateTimestamp() int64 {
	return time.Now().UTC().Unix()
}

// Returns a map of all of the oauth_* (including signature) parameters for the
// given request, and the signature base string used to generate the signature.
func (s *HmacSha1Signer) GetOAuthParams(request *http.Request, clientConfig *ClientConfig, userConfig *UserConfig, nonce string, timestamp string) (map[string]string, string) {
	oauthParams := map[string]string{
		"oauth_consumer_key":     clientConfig.ConsumerKey,
		"oauth_nonce":            nonce,
		"oauth_signature_method": "HMAC-SHA1",
		"oauth_timestamp":        timestamp,
		"oauth_version":          "1.0",
	}
	tokenKey, tokenSecret := userConfig.GetToken()
	if tokenKey != "" {
		oauthParams["oauth_token"] = tokenKey
	}
	signingParams := map[string]string{}
	for key, value := range oauthParams {
		signingParams[key] = value
	}
	for key, value := range request.URL.Query() {
		//TODO: Support multiple parameters with the same name.
		signingParams[key] = value[0]
	}
	if request.Body != nil && request.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
		request.ParseForm()
		for key, value := range request.Form {
			//TODO: Support multiple parameters with the same name.
			signingParams[key] = value[0]
		}
		// Calling ParseForm clears out the reader.  It may be
		// necessary to do this in a less destructive way, but for
		// right now, this code reinitializes the body of the request.
		var body io.Reader = strings.NewReader(request.Form.Encode())
		rc, ok := body.(io.ReadCloser)
		if !ok && body != nil {
			rc = ioutil.NopCloser(body)
		}
		request.Body = rc
		if body != nil {
			switch v := body.(type) {
			case *strings.Reader:
				request.ContentLength = int64(v.Len())
			case *bytes.Buffer:
				request.ContentLength = int64(v.Len())
			}
		}
	}
	signingUrl := fmt.Sprintf("%v://%v%v", request.URL.Scheme, request.URL.Host, request.URL.Path)
	signatureParts := []string{
		request.Method,
		url.QueryEscape(signingUrl),
		s.encodeParameters(signingParams)}
	signatureBase := strings.Join(signatureParts, "&")
	oauthParams["oauth_signature"] = s.GetSignature(clientConfig.ConsumerSecret, tokenSecret, signatureBase)
	return oauthParams, signatureBase
}

// Calculates the HMAC-SHA1 signature of a base string, given a consumer and
// token secret.
func (s *HmacSha1Signer) GetSignature(consumerSecret string, tokenSecret string, signatureBase string) string {
	signingKey := consumerSecret + "&" + tokenSecret
	signer := hmac.New(sha1.New, []byte(signingKey))
	signer.Write([]byte(signatureBase))
	oauthSignature := base64.StdEncoding.EncodeToString(signer.Sum(nil))
	return oauthSignature
}

// Given an unsigned request, add the appropriate OAuth Authorization header
// using the HMAC-SHA1 algorithm.
func (s *HmacSha1Signer) Sign(request *http.Request, clientConfig *ClientConfig, userConfig *UserConfig) error {
	var (
		nonce     string
		timestamp string
	)
	if nonce = request.Header.Get("X-OAuth-Nonce"); nonce != "" {
		request.Header.Del("X-OAuth-Nonce")
	} else {
		nonce = s.GenerateNonce()
	}
	if timestamp = request.Header.Get("X-OAuth-Timestamp"); timestamp != "" {
		request.Header.Del("X-OAuth-Timestamp")
	} else {
		timestamp = fmt.Sprintf("%v", s.GenerateTimestamp())
	}
	oauthParams, _ := s.GetOAuthParams(request, clientConfig, userConfig, nonce, timestamp)
	headerParts := make([]string, len(oauthParams))
	var i = 0
	for key, value := range oauthParams {
		headerParts[i] = Rfc3986Escape(key) + "=\"" + Rfc3986Escape(value) + "\""
		i += 1
	}
	sort.Strings(headerParts)
	oauthHeader := "OAuth " + strings.Join(headerParts, ", ")
	request.Header["Authorization"] = []string{oauthHeader}
	return nil
}

// Characters which should not be escaped according to RFC 3986.
const UNESCAPE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~"

// Escapes a string more in line with Rfc3986 than http.URLEscape.
// URLEscape was converting spaces to "+" instead of "%20", which was messing up
// the signing of requests.
func Rfc3986Escape(input string) string {
	var output bytes.Buffer
	// Convert string to bytes because iterating over a unicode string
	// in go parses runes, not bytes.
	for _, c := range []byte(input) {
		if strings.IndexAny(string(c), UNESCAPE_CHARS) == -1 {
			encoded := fmt.Sprintf("%%%X", c)
			output.Write([]uint8(encoded))
		} else {
			output.WriteByte(uint8(c))
		}
	}
	return string(output.Bytes())
}
<|endoftext|>


<commit_before>package main

import "fmt"

type TreeNode struct {
  Val int
  Left, Right *TreeNode
}

func preorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, root.Val)
  result = append(result, preorder_traversal_recursive(root.Left)...)
  result = append(result, preorder_traversal_recursive(root.Right)...)
  return result
}

func preorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
    result = append(result, n.Val)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if lastPop == current.Left {
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    }
  }
  return result
}

func inorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, inorder_traversal_recursive(root.Left)...)
  result = append(result, root.Val)
  result = append(result, inorder_traversal_recursive(root.Right)...)
  return result
}

func inorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if lastPop == current.Left {
      result = append(result, current.Val)
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        result = append(result, current.Val)
        push(current.Right)
      } else {
        lastPop = pop()
       	result = append(result, current.Val)
      }
    }
  }
  return result
}

func postorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, postorder_traversal_recursive(root.Left)...)
  result = append(result, postorder_traversal_recursive(root.Right)...)
  result = append(result, root.Val)
  return result
}

func postorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    result = append(result, n.Val)
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if lastPop == current.Left {
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    }
  }
  return result
}

func main() {
  /*
       5
     /   \
    2     4
   / \   /
  1   7 3
  */
  root := &TreeNode{
    Val: 5,
    Left: &TreeNode{
      Val: 2,
      Left: &TreeNode{
        Val: 1,
      },
      Right: &TreeNode{
        Val: 7,
      },
    },
    Right: &TreeNode{
      Val: 4,
      Left: &TreeNode{
        Val: 3,
      },
    },
  }

  fmt.Println(preorder_traversal_recursive(root))
  fmt.Println(preorder_traversal_iterate(root))
  fmt.Println(inorder_traversal_recursive(root))
  fmt.Println(inorder_traversal_iterate(root))
  fmt.Println(postorder_traversal_recursive(root))
  fmt.Println(postorder_traversal_iterate(root))
}
<commit_msg>fix: bug when node without left or right child<commit_after>package main

import "fmt"

type TreeNode struct {
  Val int
  Left, Right *TreeNode
}

func preorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, root.Val)
  result = append(result, preorder_traversal_recursive(root.Left)...)
  result = append(result, preorder_traversal_recursive(root.Right)...)
  return result
}

func preorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
    result = append(result, n.Val)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if current.Left != nil && lastPop == current.Left {
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if current.Right != nil && lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    }
  }
  return result
}

func inorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, inorder_traversal_recursive(root.Left)...)
  result = append(result, root.Val)
  result = append(result, inorder_traversal_recursive(root.Right)...)
  return result
}

func inorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if current.Left != nil && lastPop == current.Left {
      result = append(result, current.Val)
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if current.Right != nil && lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        result = append(result, current.Val)
        push(current.Right)
      } else {
        lastPop = pop()
       	result = append(result, current.Val)
      }
    }
  }
  return result
}

func postorder_traversal_recursive(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  var result []int
  result = append(result, postorder_traversal_recursive(root.Left)...)
  result = append(result, postorder_traversal_recursive(root.Right)...)
  result = append(result, root.Val)
  return result
}

func postorder_traversal_iterate(root *TreeNode) []int {
  if root == nil {
    return []int{}
  }
  stack := make([]*TreeNode, 0)
  var result []int
  var lastPop *TreeNode
  push := func(n *TreeNode) {
    stack = append(stack, n)
  }
  top := func() *TreeNode {
    return stack[len(stack)-1]
  }
  pop := func() *TreeNode {
    n := top()
    stack = stack[:len(stack)-1]
    result = append(result, n.Val)
    return n
  }
  push(root)
  for len(stack) > 0 {
    current := top()
    if current.Left != nil && lastPop == current.Left {
      if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    } else if current.Right != nil && lastPop == current.Right {
      lastPop = pop()
    } else {
      if current.Left != nil {
        push(current.Left)
      } else if current.Right != nil {
        push(current.Right)
      } else {
        lastPop = pop()
      }
    }
  }
  return result
}

func main() {
  /*
       5
     /   \
    2     4
   / \   /
  1   7 3
 /
0
  */
  root := &TreeNode{
    Val: 5,
    Left: &TreeNode{
      Val: 2,
      Left: &TreeNode{
        Val: 1,
        Left: &TreeNode{
          Val: 0,
        },
      },
      Right: &TreeNode{
        Val: 7,
      },
    },
    Right: &TreeNode{
      Val: 4,
      Left: &TreeNode{
        Val: 3,
      },
    },
  }

  fmt.Println(preorder_traversal_recursive(root))
  fmt.Println(preorder_traversal_iterate(root))
  fmt.Println(inorder_traversal_recursive(root))
  fmt.Println(inorder_traversal_iterate(root))
  fmt.Println(postorder_traversal_recursive(root))
  fmt.Println(postorder_traversal_iterate(root))
}
<|endoftext|>


<commit_before>package oci

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/mrunalp/ocid/utils"
)

// New creates a new Runtime with options provided
func New(runtimePath string, containerDir string) (*Runtime, error) {
	r := &Runtime{
		name:         filepath.Base(runtimePath),
		path:         runtimePath,
		containerDir: containerDir,
	}
	return r, nil
}

// Runtime stores the information about a oci runtime
type Runtime struct {
	name         string
	path         string
	sandboxDir   string
	containerDir string
}

// Name returns the name of the OCI Runtime
func (r *Runtime) Name() string {
	return r.name
}

// Path returns the full path the OCI Runtime executable
func (r *Runtime) Path() string {
	return r.path
}

// ContainerDir returns the path to the base directory for storing container configurations
func (r *Runtime) ContainerDir() string {
	return r.containerDir
}

// Version returns the version of the OCI Runtime
func (r *Runtime) Version() (string, error) {
	runtimeVersion, err := getOCIVersion(r.path, "-v")
	if err != nil {
		return "", err
	}
	return runtimeVersion, nil
}

func getOCIVersion(name string, args ...string) (string, error) {
	out, err := utils.ExecCmd(name, args...)
	if err != nil {
		return "", err
	}

	firstLine := out[:strings.Index(out, "\n")]
	v := firstLine[strings.LastIndex(firstLine, " ")+1:]
	return v, nil
}

// CreateContainer creates a container.
func (r *Runtime) CreateContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "--systemd-cgroup", "create", "--bundle", c.bundlePath, c.name)
}

// StartContainer starts a container.
func (r *Runtime) StartContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "start", c.name)
}

// StopContainer stops a container.
func (r *Runtime) StopContainer(c *Container) error {
	// TODO: Check if it is still running after some time and send SIGKILL
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", c.name)
}

// DeleteContainer deletes a container.
func (r *Runtime) DeleteContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "delete", c.name)
}

// Container respresents a runtime container.
type Container struct {
	name       string
	bundlePath string
	logPath    string
	labels     map[string]string
	sandbox    string
}

// NewContainer creates a container object.
func NewContainer(name string, bundlePath string, logPath string, labels map[string]string, sandbox string) (*Container, error) {
	c := &Container{
		name:       name,
		bundlePath: bundlePath,
		logPath:    logPath,
		labels:     labels,
		sandbox:    sandbox,
	}
	return c, nil
}

// Name returns the name of the container.
func (c *Container) Name() string {
	return c.name
}

// BundlePath returns the bundlePath of the container.
func (c *Container) BundlePath() string {
	return c.bundlePath
}

// LogPath returns the log path of the container.
func (c *Container) LogPath() string {
	return c.logPath
}

// Labels returns the labels of the container.
func (c *Container) Labels() map[string]string {
	return c.labels
}

// Sandbox returns the sandbox name of the container.
func (c *Container) Sandbox() string {
	return c.sandbox
}
<commit_msg>Add methods for updating and getting the container status<commit_after>package oci

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/mrunalp/ocid/utils"
	"github.com/opencontainers/runtime-spec/specs-go"
)

// New creates a new Runtime with options provided
func New(runtimePath string, containerDir string) (*Runtime, error) {
	r := &Runtime{
		name:         filepath.Base(runtimePath),
		path:         runtimePath,
		containerDir: containerDir,
	}
	return r, nil
}

// Runtime stores the information about a oci runtime
type Runtime struct {
	name         string
	path         string
	sandboxDir   string
	containerDir string
}

// Name returns the name of the OCI Runtime
func (r *Runtime) Name() string {
	return r.name
}

// Path returns the full path the OCI Runtime executable
func (r *Runtime) Path() string {
	return r.path
}

// ContainerDir returns the path to the base directory for storing container configurations
func (r *Runtime) ContainerDir() string {
	return r.containerDir
}

// Version returns the version of the OCI Runtime
func (r *Runtime) Version() (string, error) {
	runtimeVersion, err := getOCIVersion(r.path, "-v")
	if err != nil {
		return "", err
	}
	return runtimeVersion, nil
}

func getOCIVersion(name string, args ...string) (string, error) {
	out, err := utils.ExecCmd(name, args...)
	if err != nil {
		return "", err
	}

	firstLine := out[:strings.Index(out, "\n")]
	v := firstLine[strings.LastIndex(firstLine, " ")+1:]
	return v, nil
}

// CreateContainer creates a container.
func (r *Runtime) CreateContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "--systemd-cgroup", "create", "--bundle", c.bundlePath, c.name)
}

// StartContainer starts a container.
func (r *Runtime) StartContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "start", c.name)
}

// StopContainer stops a container.
func (r *Runtime) StopContainer(c *Container) error {
	// TODO: Check if it is still running after some time and send SIGKILL
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", c.name)
}

// DeleteContainer deletes a container.
func (r *Runtime) DeleteContainer(c *Container) error {
	return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "delete", c.name)
}

// updateStatus refreshes the status of the container.
func (r *Runtime) UpdateStatus(c *Container) error {
	out, err := exec.Command(r.path, "state", c.name).Output()
	if err != nil {
		return fmt.Errorf("error getting container state for %s: %s", c.name, err)
	}
	stateReader := bytes.NewReader(out)
	if err := json.NewDecoder(stateReader).Decode(&c.state); err != nil {
		return fmt.Errorf("failed to decode container status for %s: %s", c.name, err)
	}
	return nil
}

// ContainerStatus returns the state of a container.
func (r *Runtime) ContainerStatus(c *Container) *specs.State {
	return c.state
}

// Container respresents a runtime container.
type Container struct {
	name       string
	bundlePath string
	logPath    string
	labels     map[string]string
	sandbox    string
	state      *specs.State
}

// ContainerStatus represents the status of a container.
type ContainerStatus struct {
}

// NewContainer creates a container object.
func NewContainer(name string, bundlePath string, logPath string, labels map[string]string, sandbox string) (*Container, error) {
	c := &Container{
		name:       name,
		bundlePath: bundlePath,
		logPath:    logPath,
		labels:     labels,
		sandbox:    sandbox,
	}
	return c, nil
}

// Name returns the name of the container.
func (c *Container) Name() string {
	return c.name
}

// BundlePath returns the bundlePath of the container.
func (c *Container) BundlePath() string {
	return c.bundlePath
}

// LogPath returns the log path of the container.
func (c *Container) LogPath() string {
	return c.logPath
}

// Labels returns the labels of the container.
func (c *Container) Labels() map[string]string {
	return c.labels
}

// Sandbox returns the sandbox name of the container.
func (c *Container) Sandbox() string {
	return c.sandbox
}
<|endoftext|>


<commit_before>package http

import (
	"net/http"
	"os"

	gorillaHandlers "github.com/gorilla/handlers"

	"github.com/coreos/etcd-discovery/handlers"
	"github.com/gorilla/mux"

)

func init() {
	r := mux.NewRouter()

	r.HandleFunc("/", handlers.HomeHandler)
	r.HandleFunc("/new", handlers.NewTokenHandler)
	r.HandleFunc("/health", handlers.HealthHandler)

	// Only allow exact tokens with GETs and PUTs
	r.HandleFunc("/{token:[a-f0-9]{32}}", handlers.TokenHandler).
		Methods("GET", "PUT")
	r.HandleFunc("/{token:[a-f0-9]{32}}/", handlers.TokenHandler).
		Methods("GET", "PUT")
	r.HandleFunc("/{token:[a-f0-9]{32}}/{machine}", handlers.TokenHandler).
		Methods("GET", "PUT")
	r.HandleFunc("/{token:[a-f0-9]{32}}/_state", handlers.TokenHandler).
		Methods("DELETE")

	logH := gorillaHandlers.LoggingHandler(os.Stdout, r)

	http.Handle("/", logH)
}
<commit_msg>feat(http): let users remove old nodes<commit_after>package http

import (
	"net/http"
	"os"

	gorillaHandlers "github.com/gorilla/handlers"

	"github.com/coreos/etcd-discovery/handlers"
	"github.com/gorilla/mux"

)

func init() {
	r := mux.NewRouter()

	r.HandleFunc("/", handlers.HomeHandler)
	r.HandleFunc("/new", handlers.NewTokenHandler)
	r.HandleFunc("/health", handlers.HealthHandler)

	// Only allow exact tokens with GETs and PUTs
	r.HandleFunc("/{token:[a-f0-9]{32}}", handlers.TokenHandler).
		Methods("GET", "PUT")
	r.HandleFunc("/{token:[a-f0-9]{32}}/", handlers.TokenHandler).
		Methods("GET", "PUT")
	r.HandleFunc("/{token:[a-f0-9]{32}}/{machine}", handlers.TokenHandler).
		Methods("GET", "PUT", "DELETE")

	logH := gorillaHandlers.LoggingHandler(os.Stdout, r)

	http.Handle("/", logH)
}
<|endoftext|>


<commit_before>package http

import (
	"net"
	"net/http"
	"sync"
	"time"

	c "github.com/d0ngw/go/common"
	"golang.org/x/net/netutil"
)

type tcpKeepAliveListener struct {
	*net.TCPListener
}

// Accept接受连接
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return nil, err
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

// GraceableHandler 安全地关闭的处理器
type GraceableHandler struct {
	handler   http.Handler
	waitGroup *sync.WaitGroup
}

func (p *GraceableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	p.waitGroup.Add(1)
	defer p.waitGroup.Done()

	p.handler.ServeHTTP(w, r)
}

// Service Http服务
type Service struct {
	c.BaseService
	Conf         *Config
	listener     net.Listener
	serveMux     *http.ServeMux
	graceHandler *GraceableHandler
	server       *http.Server
}

// Init 初始化Http服务
func (p *Service) Init() bool {
	p.Lock()
	defer p.Unlock()

	serveMux := http.NewServeMux()

	for pattern, handler := range p.Conf.handles {
		if handler == nil {
			c.Criticalf("Can't bind nil handlerFunc to path %s", pattern)
			return false
		}
		serveMux.Handle(pattern, p.handleWithMiddleware(handler))
	}

	graceHandler := &GraceableHandler{
		handler:   serveMux,
		waitGroup: &sync.WaitGroup{}}

	server := &http.Server{
		Addr:         p.Conf.Addr,
		ReadTimeout:  p.Conf.ReadTimeout * time.Second,
		WriteTimeout: p.Conf.WriteTimeout * time.Second,
		Handler:      graceHandler}

	if p.Conf.Addr == "" {
		p.Conf.Addr = ":http"
	}

	p.graceHandler = graceHandler
	p.server = server
	p.serveMux = serveMux
	return true
}

// handleWithMiddleware 依次调用各个middleware
func (p *Service) handleWithMiddleware(handler *handlerWithMiddleware) http.HandlerFunc {
	originHandler := func(w http.ResponseWriter, r *http.Request) {
		if ok, err := ErrorFromRequestContext(r); ok {
			c.Errorf("stop handle %s,cause by error:%s", r.RequestURI, err)
		} else {
			handler.handlerFunc(w, r)
		}
	}

	var middlewares = append(handler.middlewares, p.Conf.middlewares...)
	var middlewareCount = len(middlewares)

	h := originHandler
	for i := middlewareCount - 1; i >= 0; i-- {
		m := middlewares[i]
		h0 := h
		h = func(w http.ResponseWriter, r *http.Request) {
			c.Debugf("handle %s,invoke middleware %T", r.RequestURI, m)
			m.Handle(h0)(w, r)
		}
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h(w, r)
	})
}

// Start 启动Http服务,开始端口监听和服务处理
func (p *Service) Start() bool {
	p.Lock()
	defer p.Unlock()

	c.Infof("Listen at %s", p.Conf.Addr)
	ln, err := net.Listen("tcp", p.Conf.Addr)
	if err != nil {
		c.Errorf("Listen at %s fail,error:%v", p.Conf.Addr, err)
		return false
	}

	tcpListener := tcpKeepAliveListener{ln.(*net.TCPListener)}
	if p.Conf.MaxConns > 0 {
		p.listener = netutil.LimitListener(tcpListener, p.Conf.MaxConns)
	} else {
		p.listener = tcpListener
	}

	p.graceHandler.waitGroup.Add(1)

	go func() {
		defer p.graceHandler.waitGroup.Done()
		err := p.server.Serve(p.listener)
		if err != nil {
			c.Errorf("server.Serve return with error:%v", err)
		}
	}()
	return true
}

// Stop 停止Http服务,关闭端口监听和服务处理
func (p *Service) Stop() bool {
	p.Lock()
	defer p.Unlock()

	if p.listener != nil {
		if err := p.listener.Close(); err != nil {
			c.Errorf("Close listener error:%v", err)
		}
	}

	//等待所有的服务
	c.Infof("Waiting shutdown")
	p.graceHandler.waitGroup.Wait()
	c.Infof("Finish shutdown")

	p.listener = nil
	p.graceHandler = nil
	p.server = nil
	p.serveMux = nil
	return true
}
<commit_msg>fix loc<commit_after>package http

import (
	"net"
	"net/http"
	"sync"
	"time"

	c "github.com/d0ngw/go/common"
	"golang.org/x/net/netutil"
)

type tcpKeepAliveListener struct {
	*net.TCPListener
}

// Accept接受连接
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return nil, err
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

// GraceableHandler 安全地关闭的处理器
type GraceableHandler struct {
	handler   http.Handler
	waitGroup *sync.WaitGroup
}

func (p *GraceableHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	p.waitGroup.Add(1)
	defer p.waitGroup.Done()

	p.handler.ServeHTTP(w, r)
}

// Service Http服务
type Service struct {
	c.BaseService
	Conf         *Config
	listener     net.Listener
	serveMux     *http.ServeMux
	graceHandler *GraceableHandler
	server       *http.Server
	lock         sync.Mutex
}

// Init 初始化Http服务
func (p *Service) Init() bool {
	p.lock.Lock()
	defer p.lock.Unlock()

	serveMux := http.NewServeMux()

	for pattern, handler := range p.Conf.handles {
		if handler == nil {
			c.Criticalf("Can't bind nil handlerFunc to path %s", pattern)
			return false
		}
		serveMux.Handle(pattern, p.handleWithMiddleware(handler))
	}

	graceHandler := &GraceableHandler{
		handler:   serveMux,
		waitGroup: &sync.WaitGroup{}}

	server := &http.Server{
		Addr:         p.Conf.Addr,
		ReadTimeout:  p.Conf.ReadTimeout * time.Second,
		WriteTimeout: p.Conf.WriteTimeout * time.Second,
		Handler:      graceHandler}

	if p.Conf.Addr == "" {
		p.Conf.Addr = ":http"
	}

	p.graceHandler = graceHandler
	p.server = server
	p.serveMux = serveMux
	return true
}

// handleWithMiddleware 依次调用各个middleware
func (p *Service) handleWithMiddleware(handler *handlerWithMiddleware) http.HandlerFunc {
	originHandler := func(w http.ResponseWriter, r *http.Request) {
		if ok, err := ErrorFromRequestContext(r); ok {
			c.Errorf("stop handle %s,cause by error:%s", r.RequestURI, err)
		} else {
			handler.handlerFunc(w, r)
		}
	}

	var middlewares = append(handler.middlewares, p.Conf.middlewares...)
	var middlewareCount = len(middlewares)

	h := originHandler
	for i := middlewareCount - 1; i >= 0; i-- {
		m := middlewares[i]
		h0 := h
		h = func(w http.ResponseWriter, r *http.Request) {
			c.Debugf("handle %s,invoke middleware %T", r.RequestURI, m)
			m.Handle(h0)(w, r)
		}
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h(w, r)
	})
}

// Start 启动Http服务,开始端口监听和服务处理
func (p *Service) Start() bool {
	p.lock.Lock()
	defer p.lock.Unlock()

	c.Infof("Listen at %s", p.Conf.Addr)
	ln, err := net.Listen("tcp", p.Conf.Addr)
	if err != nil {
		c.Errorf("Listen at %s fail,error:%v", p.Conf.Addr, err)
		return false
	}

	tcpListener := tcpKeepAliveListener{ln.(*net.TCPListener)}
	if p.Conf.MaxConns > 0 {
		p.listener = netutil.LimitListener(tcpListener, p.Conf.MaxConns)
	} else {
		p.listener = tcpListener
	}

	p.graceHandler.waitGroup.Add(1)

	go func() {
		defer p.graceHandler.waitGroup.Done()
		err := p.server.Serve(p.listener)
		if err != nil {
			c.Errorf("server.Serve return with error:%v", err)
		}
	}()
	return true
}

// Stop 停止Http服务,关闭端口监听和服务处理
func (p *Service) Stop() bool {
	p.lock.Lock()
	defer p.lock.Unlock()

	if p.listener != nil {
		if err := p.listener.Close(); err != nil {
			c.Errorf("Close listener error:%v", err)
		}
	}

	//等待所有的服务
	c.Infof("Waiting shutdown")
	p.graceHandler.waitGroup.Wait()
	c.Infof("Finish shutdown")

	p.listener = nil
	p.graceHandler = nil
	p.server = nil
	p.serveMux = nil
	return true
}
<|endoftext|>


<commit_before>package proxyclient

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
	"time"
)

type HttpTCPConn struct {
	Conn                            //http 协议时是原始链接、https协议时是tls.Conn
	rawConn               TCPConn   //原始链接
	tlsConn               *tls.Conn //tls链接
	localAddr, remoteAddr net.TCPAddr
	localHost, remoteHost string
	LocalPort, remotePort uint16
	proxyClient           ProxyClient
	r                     io.Reader
}

type httpProxyClient struct {
	proxyAddr          string
	proxyDomain        string // 用于ssl证书验证
	proxyType          string // socks4 socks5
							  //TODO: 用户名、密码
	insecureSkipVerify bool
	upProxy            ProxyClient
	query              map[string][]string
}

// 创建代理客户端
// ProxyType				http https
// ProxyAddr 				127.0.0.1:5555
// proxyDomain				ssl 验证域名，"" 则使用 proxyAddr 部分的域名
// insecureSkipVerify		使用https代理时是否忽略证书检查
// UpProxy
func NewHttpProxyClient(proxyType string, proxyAddr string, proxyDomain string, insecureSkipVerify bool, upProxy ProxyClient, query        map[string][]string) (ProxyClient, error) {
	proxyType = strings.ToLower(strings.Trim(proxyType, " \r\n\t"))
	if proxyType != "http" && proxyType != "https" {
		return nil, errors.New("ProxyType 错误的格式，只支持http、https代理。")
	}

	if upProxy == nil {
		nUpProxy, err := NewDriectProxyClient("", make(map[string][]string))
		if err != nil {
			return nil, fmt.Errorf("创建直连代理错误：%v", err)
		}
		upProxy = nUpProxy
	}

	if proxyDomain == "" {
		host, _, err := net.SplitHostPort(proxyAddr)
		if err != nil {
			return nil, fmt.Errorf("proxyAddr 格式错误：%v", err)
		}
		proxyDomain = host
	}

	return &httpProxyClient{proxyAddr, proxyDomain, proxyType, insecureSkipVerify, upProxy, query}, nil
}

func (p *httpProxyClient) Dial(network, address string) (net.Conn, error) {
	if strings.HasPrefix(strings.ToLower(network), "tcp") {
		return p.DialTCPSAddr(network, address)
	} else if strings.HasPrefix(strings.ToLower(network), "udp") {
		return nil, errors.New("不支持UDP协议。")
	} else {
		return nil, errors.New("未知的 network 类型。")
	}
}

func (p *httpProxyClient) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
	switch network {
	case "tcp", "tcp4", "tcp6":
		return p.DialTCPSAddrTimeout(network, address, timeout)
	default:
		return nil, fmt.Errorf("不支持的协议")
	}
}

func (p *httpProxyClient) DialTCP(network string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
	if laddr != nil || laddr.Port != 0 {
		return nil, errors.New("代理协议不支持指定本地地址。")
	}

	return p.DialTCPSAddr(network, raddr.String())
}

func (p *httpProxyClient) DialTCPSAddr(network string, raddr string) (ProxyTCPConn, error) {
	return p.DialTCPSAddrTimeout(network, raddr, 0)
}

func (p *httpProxyClient) DialTCPSAddrTimeout(network string, raddr string, timeout time.Duration) (rconn ProxyTCPConn, rerr error) {
	// 截止时间
	finalDeadline := time.Time{}
	if timeout != 0 {
		finalDeadline = time.Now().Add(timeout)
	}

	var tlsConn *tls.Conn
	rawConn, err := p.upProxy.DialTCPSAddrTimeout(network, p.proxyAddr, timeout)
	if err != nil {
		return nil, fmt.Errorf("无法连接代理服务器 %v ，错误：%v", p.proxyAddr, err)
	}

	var c Conn = rawConn

	ch := make(chan int, 1)

	// 实际执行部分
	run := func() {
		if p.proxyType == "https" {
			tlsConn = tls.Client(c, &tls.Config{ServerName: p.proxyDomain, InsecureSkipVerify: p.insecureSkipVerify})
			if err := tlsConn.Handshake(); err != nil {
				tlsConn.Close()
				rerr = fmt.Errorf("TLS 协议握手错误：%v", err)
				ch <- 0
				return
			}
			if p.insecureSkipVerify == false && tlsConn.VerifyHostname(p.proxyDomain) != nil {
				tlsConn.Close()
				rerr = fmt.Errorf("TLS 协议域名验证失败：%v", err)
				ch <- 0
				return
			}
			c = tlsConn
		}

		req, err := http.NewRequest("CONNECT", p.proxyAddr, nil)
		if err != nil {
			c.Close()
			rerr = fmt.Errorf("创建请求错误：%v", err)
			ch <- 0
			return
		}
		req.URL.Path = raddr
		req.URL.Host = p.proxyAddr

		if err := req.Write(c); err != nil {
			c.Close()
			rerr = fmt.Errorf("写请求错误：%v", err)
			ch <- 0
			return
		}

		br := bufio.NewReader(c)

		res, err := http.ReadResponse(br, req)
		if err != nil {
			c.Close()
			rerr = fmt.Errorf("响应格式错误：%v", err)
			ch <- 0
			return
		}

		if res.StatusCode != 200 {
			c.Close()
			rerr = fmt.Errorf("响应错误：%v", res)
			ch <- 0
			return
		}

		rconn = &HttpTCPConn{c, rawConn, tlsConn, net.TCPAddr{}, net.TCPAddr{}, "", "", 0, 0, p, res.Body}
		ch <- 1
		return
	}

	if timeout == 0 {
		run()
		return
	} else {
		c.SetDeadline(finalDeadline)

		ntimeout := finalDeadline.Sub(time.Now())
		if ntimeout <= 0 {
			return nil, fmt.Errorf("timeout")
		}
		t := time.NewTimer(ntimeout)
		defer t.Stop()

		go run()

		select {
		case <-t.C:
			return nil, fmt.Errorf("连接超时。")
		case <-ch:
			return
		}
	}
}
// 重写了 Read 接口
// 由于 http 协议问题，解析响应需要读缓冲，所以必须重写 Read 来兼容读缓冲功能。
func (c *HttpTCPConn) Read(b []byte) (n int, err error) {
	return c.r.Read(b)
}

func (c *HttpTCPConn) SetLinger(sec int) error {
	return c.rawConn.SetLinger(sec)
}

func (c *HttpTCPConn) SetNoDelay(noDelay bool) error {
	return c.rawConn.SetNoDelay(noDelay)
}
func (c *HttpTCPConn) SetReadBuffer(bytes int) error {
	return c.rawConn.SetReadBuffer(bytes)
}
func (c *HttpTCPConn) SetWriteBuffer(bytes int) error {
	return c.rawConn.SetWriteBuffer(bytes)
}

func (p *httpProxyClient) DialUDP(network string, laddr, raddr *net.UDPAddr) (net.Conn, error) {
	return nil, fmt.Errorf("%v 代理不支持 UDP 转发。", p.proxyType)
}

func (p *httpProxyClient) UpProxy() ProxyClient {
	return p.upProxy
}

func (p *httpProxyClient) SetUpProxy(upProxy ProxyClient) error {
	p.upProxy = upProxy
	return nil
}

func (c *HttpTCPConn) ProxyClient() ProxyClient {
	return c.proxyClient
}

func (c *httpProxyClient)GetProxyAddrQuery() map[string][]string {
	return c.query
}<commit_msg>fix bug<commit_after>package proxyclient

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
	"time"
)

type HttpTCPConn struct {
	Conn                            //http 协议时是原始链接、https协议时是tls.Conn
	rawConn               TCPConn   //原始链接
	tlsConn               *tls.Conn //tls链接
	localAddr, remoteAddr net.TCPAddr
	localHost, remoteHost string
	LocalPort, remotePort uint16
	proxyClient           ProxyClient
	r                     io.ReadCloser // http Body
}

type httpProxyClient struct {
	proxyAddr          string
	proxyDomain        string // 用于ssl证书验证
	proxyType          string // socks4 socks5
							  //TODO: 用户名、密码
	insecureSkipVerify bool
	upProxy            ProxyClient
	query              map[string][]string
}

// 创建代理客户端
// ProxyType				http https
// ProxyAddr 				127.0.0.1:5555
// proxyDomain				ssl 验证域名，"" 则使用 proxyAddr 部分的域名
// insecureSkipVerify		使用https代理时是否忽略证书检查
// UpProxy
func NewHttpProxyClient(proxyType string, proxyAddr string, proxyDomain string, insecureSkipVerify bool, upProxy ProxyClient, query        map[string][]string) (ProxyClient, error) {
	proxyType = strings.ToLower(strings.Trim(proxyType, " \r\n\t"))
	if proxyType != "http" && proxyType != "https" {
		return nil, errors.New("ProxyType 错误的格式，只支持http、https代理。")
	}

	if upProxy == nil {
		nUpProxy, err := NewDriectProxyClient("", make(map[string][]string))
		if err != nil {
			return nil, fmt.Errorf("创建直连代理错误：%v", err)
		}
		upProxy = nUpProxy
	}

	if proxyDomain == "" {
		host, _, err := net.SplitHostPort(proxyAddr)
		if err != nil {
			return nil, fmt.Errorf("proxyAddr 格式错误：%v", err)
		}
		proxyDomain = host
	}

	return &httpProxyClient{proxyAddr, proxyDomain, proxyType, insecureSkipVerify, upProxy, query}, nil
}

func (p *httpProxyClient) Dial(network, address string) (net.Conn, error) {
	if strings.HasPrefix(strings.ToLower(network), "tcp") {
		return p.DialTCPSAddr(network, address)
	} else if strings.HasPrefix(strings.ToLower(network), "udp") {
		return nil, errors.New("不支持UDP协议。")
	} else {
		return nil, errors.New("未知的 network 类型。")
	}
}

func (p *httpProxyClient) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
	switch network {
	case "tcp", "tcp4", "tcp6":
		return p.DialTCPSAddrTimeout(network, address, timeout)
	default:
		return nil, fmt.Errorf("不支持的协议")
	}
}

func (p *httpProxyClient) DialTCP(network string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
	if laddr != nil || laddr.Port != 0 {
		return nil, errors.New("代理协议不支持指定本地地址。")
	}

	return p.DialTCPSAddr(network, raddr.String())
}

func (p *httpProxyClient) DialTCPSAddr(network string, raddr string) (ProxyTCPConn, error) {
	return p.DialTCPSAddrTimeout(network, raddr, 0)
}

func (p *httpProxyClient) DialTCPSAddrTimeout(network string, raddr string, timeout time.Duration) (rconn ProxyTCPConn, rerr error) {
	// 截止时间
	finalDeadline := time.Time{}
	if timeout != 0 {
		finalDeadline = time.Now().Add(timeout)
	}

	var tlsConn *tls.Conn
	rawConn, err := p.upProxy.DialTCPSAddrTimeout(network, p.proxyAddr, timeout)
	if err != nil {
		return nil, fmt.Errorf("无法连接代理服务器 %v ，错误：%v", p.proxyAddr, err)
	}

	var c Conn = rawConn

	ch := make(chan int, 1)

	// 实际执行部分
	run := func() {
		if p.proxyType == "https" {
			tlsConn = tls.Client(c, &tls.Config{ServerName: p.proxyDomain, InsecureSkipVerify: p.insecureSkipVerify})
			if err := tlsConn.Handshake(); err != nil {
				tlsConn.Close()
				rerr = fmt.Errorf("TLS 协议握手错误：%v", err)
				ch <- 0
				return
			}
			if p.insecureSkipVerify == false && tlsConn.VerifyHostname(p.proxyDomain) != nil {
				tlsConn.Close()
				rerr = fmt.Errorf("TLS 协议域名验证失败：%v", err)
				ch <- 0
				return
			}
			c = tlsConn
		}

		req, err := http.NewRequest("CONNECT", p.proxyAddr, nil)
		if err != nil {
			c.Close()
			rerr = fmt.Errorf("创建请求错误：%v", err)
			ch <- 0
			return
		}
		req.URL.Path = raddr
		req.URL.Host = p.proxyAddr

		if err := req.Write(c); err != nil {
			c.Close()
			rerr = fmt.Errorf("写请求错误：%v", err)
			ch <- 0
			return
		}

		br := bufio.NewReader(c)

		res, err := http.ReadResponse(br, req)
		if err != nil {
			c.Close()
			rerr = fmt.Errorf("响应格式错误：%v", err)
			ch <- 0
			return
		}

		if res.StatusCode != 200 {
			c.Close()
			rerr = fmt.Errorf("响应错误：%v", res)
			ch <- 0
			return
		}

		rconn = &HttpTCPConn{c, rawConn, tlsConn, net.TCPAddr{}, net.TCPAddr{}, "", "", 0, 0, p, res.Body}
		ch <- 1
		return
	}

	if timeout == 0 {
		run()
		return
	} else {
		c.SetDeadline(finalDeadline)

		ntimeout := finalDeadline.Sub(time.Now())
		if ntimeout <= 0 {
			return nil, fmt.Errorf("timeout")
		}
		t := time.NewTimer(ntimeout)
		defer t.Stop()

		go run()

		select {
		case <-t.C:
			return nil, fmt.Errorf("连接超时。")
		case <-ch:
			return
		}
	}
}
// 重写了 Read 接口
// 由于 http 协议问题，解析响应需要读缓冲，所以必须重写 Read 来兼容读缓冲功能。
func (c *HttpTCPConn) Read(b []byte) (n int, err error) {
	return c.r.Read(b)
}
// 重写了 Read 接口
// 由于 http 协议问题，解析响应需要读缓冲，所以必须重写 Read 来兼容读缓冲功能。
func (c *HttpTCPConn) Close()   error {
	c.r.Close()
	return c.Conn.Close()
}

func (c *HttpTCPConn) SetLinger(sec int) error {
	return c.rawConn.SetLinger(sec)
}

func (c *HttpTCPConn) SetNoDelay(noDelay bool) error {
	return c.rawConn.SetNoDelay(noDelay)
}
func (c *HttpTCPConn) SetReadBuffer(bytes int) error {
	return c.rawConn.SetReadBuffer(bytes)
}
func (c *HttpTCPConn) SetWriteBuffer(bytes int) error {
	return c.rawConn.SetWriteBuffer(bytes)
}

func (p *httpProxyClient) DialUDP(network string, laddr, raddr *net.UDPAddr) (net.Conn, error) {
	return nil, fmt.Errorf("%v 代理不支持 UDP 转发。", p.proxyType)
}

func (p *httpProxyClient) UpProxy() ProxyClient {
	return p.upProxy
}

func (p *httpProxyClient) SetUpProxy(upProxy ProxyClient) error {
	p.upProxy = upProxy
	return nil
}

func (c *HttpTCPConn) ProxyClient() ProxyClient {
	return c.proxyClient
}

func (c *httpProxyClient)GetProxyAddrQuery() map[string][]string {
	return c.query
}<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 cmac

import (
	"crypto/des"
	"encoding/hex"
	aes_testing "github.com/jacobsa/aes/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestSubkey(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type SubkeyTest struct{}

func init() { RegisterTestSuite(&SubkeyTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *SubkeyTest) BlockSizeTooSmall() {
	ciph, err := des.NewCipher(make([]byte, 8))
	AssertEq(nil, err)

	f := func() { generateSubkeys(ciph) }
	ExpectThat(f, Panics(HasSubstr("16-byte")))
}

func (t *SubkeyTest) KeyTooLong() {
	key := make([]byte, 17)
	f := func() { generateSubkey(key) }
	ExpectThat(f, Panics(HasSubstr("16-byte")))
}

func (t *SubkeyTest) Rfc4493GoldenTestCase() {
	key, err := hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c")
	AssertEq(nil, err)

	expectedK1, err := hex.DecodeString("fbeed618357133667c85e08f7236a8de")
	AssertEq(nil, err)

	expectedK2, err := hex.DecodeString("f7ddac306ae266ccf90bc11ee46d513b")
	AssertEq(nil, err)

	k1, k2 := generateSubkey(key)
	ExpectThat(k1, DeepEquals(expectedK1))
	ExpectThat(k2, DeepEquals(expectedK2))
}

func (t *SubkeyTest) GeneratedTestCases() {
	cases := aes_testing.GenerateSubkeyCases()
	AssertGe(len(cases), 100)

	for i, c := range cases {
		k1, k2 := generateSubkey(c.Key)
		ExpectThat(k1, DeepEquals(c.K1), "Test case %d: %v", i, c)
		ExpectThat(k2, DeepEquals(c.K2), "Test case %d: %v", i, c)
	}
}
<commit_msg>Made subkey_test.go build again.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 cmac

import (
	"crypto/aes"
	"crypto/des"
	"encoding/hex"
	aes_testing "github.com/jacobsa/aes/testing"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestSubkey(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type SubkeyTest struct{}

func init() { RegisterTestSuite(&SubkeyTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *SubkeyTest) WrongBlockSize() {
	ciph, err := des.NewCipher(make([]byte, 8))
	AssertEq(nil, err)

	f := func() { generateSubkeys(ciph) }
	ExpectThat(f, Panics(HasSubstr("16-byte")))
}

func (t *SubkeyTest) Rfc4493GoldenTestCase() {
	key, err := hex.DecodeString("2b7e151628aed2a6abf7158809cf4f3c")
	AssertEq(nil, err)

	expectedK1, err := hex.DecodeString("fbeed618357133667c85e08f7236a8de")
	AssertEq(nil, err)

	expectedK2, err := hex.DecodeString("f7ddac306ae266ccf90bc11ee46d513b")
	AssertEq(nil, err)

	ciph, err := aes.NewCipher(key)
	AssertEq(nil, err)

	k1, k2 := generateSubkeys(ciph)
	ExpectThat(k1, DeepEquals(expectedK1))
	ExpectThat(k2, DeepEquals(expectedK2))
}

func (t *SubkeyTest) GeneratedTestCases() {
	cases := aes_testing.GenerateSubkeyCases()
	AssertGe(len(cases), 100)

	for i, c := range cases {
		ciph, err := aes.NewCipher(c.Key)
		AssertEq(nil, err)

		k1, k2 := generateSubkeys(ciph)
		ExpectThat(k1, DeepEquals(c.K1), "Test case %d: %v", i, c)
		ExpectThat(k2, DeepEquals(c.K2), "Test case %d: %v", i, c)
	}
}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/moov-io/ach"
)

func dumpFiles(paths []string) error {
	for i := range paths {
		if i > 0 {
			fmt.Println("") // extra newline between multiple ACH files
		}
		fmt.Printf("Describing ACH file '%s'\n", paths[i])
		file, err := readACHFile(paths[i])
		if err != nil {
			return fmt.Errorf("problem reading %s: %v", paths[i], err)
		}
		dumpFile(file)
	}
	return nil
}

func dumpFile(file *ach.File) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
	defer w.Flush()

	fh := file.Header

	// FileHeader
	fmt.Fprintln(w, "  Origin\tOriginName\tDestination\tDestinationName")
	fmt.Fprintln(w, fmt.Sprintf("  %s\t%s\t%s\t%s\t", fh.ImmediateOrigin, fh.ImmediateOriginName, fh.ImmediateDestination, fh.ImmediateDestinationName))

	// Batches
	for i := range file.Batches {
		fmt.Fprintln(w, "\n  BatchNumber\tType\tServiceClass\tAddendas\tTotalDebits\tTotalCredits")

		bh := file.Batches[i].GetHeader()
		bc := file.Batches[i].GetControl()
		fmt.Fprintln(w, fmt.Sprintf("  %d\t%s\t%d\t%d\t%d\t%d", bh.BatchNumber, bh.StandardEntryClassCode, bh.ServiceClassCode, bc.EntryAddendaCount, bc.TotalDebitEntryDollarAmount, bc.TotalCreditEntryDollarAmount))

		entries := file.Batches[i].GetEntries()
		if len(entries) > 0 {
			fmt.Fprintln(w, "\n    TxCode\tAccountNumber\tAmount\tName\tTraceNumber")
		}
		for j := range entries {
			e := entries[j]
			fmt.Fprintln(w, fmt.Sprintf("    %d\t%s\t%d\t%s\t%s", e.TransactionCode, e.DFIAccountNumber, e.Amount, e.IndividualName, e.TraceNumber))
		}
	}
	// TODO(adam): Do different stuff with -v enabeld
}

func readACHFile(path string) (*ach.File, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("problem opening %s: %v", path, err)
	}
	defer fd.Close()

	f, err := ach.NewReader(fd).Read()
	return &f, err
}
<commit_msg>cmd/ach: include FileControl, minor formatting tweaks<commit_after>// Copyright 2019 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/moov-io/ach"
)

func dumpFiles(paths []string) error {
	for i := range paths {
		if i > 0 {
			fmt.Println("") // extra newline between multiple ACH files
		}
		fmt.Printf("Describing ACH file '%s'\n\n", paths[i])
		file, err := readACHFile(paths[i])
		if err != nil {
			return fmt.Errorf("problem reading %s: %v", paths[i], err)
		}
		dumpFile(file)
	}
	return nil
}

func dumpFile(file *ach.File) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
	defer w.Flush()

	fh, fc := file.Header, file.Control

	// FileHeader
	fmt.Fprintln(w, "  Origin\tOriginName\tDestination\tDestinationName\tFileCreationDate\tFileCreationTime")
	fmt.Fprintln(w, fmt.Sprintf("  %s\t%s\t%s\t%s\t%s\t%s", fh.ImmediateOrigin, fh.ImmediateOriginName, fh.ImmediateDestination, fh.ImmediateDestinationName, fh.FileCreationDate, fh.FileCreationTime))

	// FileControl
	fmt.Fprintln(w, "\n  BatchCount\tBlockCount\tEntryAddendaCount\tTotalDebitAmount\tTotalCreditAmount")
	fmt.Fprintln(w, fmt.Sprintf("  %d\t%d\t%d\t%d\t%d", fc.BatchCount, fc.BlockCount, fc.EntryAddendaCount, fc.TotalDebitEntryDollarAmountInFile, fc.TotalCreditEntryDollarAmountInFile))

	// Batches
	for i := range file.Batches {
		fmt.Fprintln(w, "\n  BatchNumber\tType\tServiceClass\tAddendas\tTotalDebits\tTotalCredits")

		bh := file.Batches[i].GetHeader()
		bc := file.Batches[i].GetControl()
		fmt.Fprintln(w, fmt.Sprintf("  %d\t%s\t%d\t%d\t%d\t%d", bh.BatchNumber, bh.StandardEntryClassCode, bh.ServiceClassCode, bc.EntryAddendaCount, bc.TotalDebitEntryDollarAmount, bc.TotalCreditEntryDollarAmount))

		entries := file.Batches[i].GetEntries()
		if len(entries) > 0 {
			fmt.Fprintln(w, "\n    TxCode\tAccountNumber\tAmount\tName\tTraceNumber")
		}
		for j := range entries {
			e := entries[j]
			fmt.Fprintln(w, fmt.Sprintf("    %d\t%s\t%d\t%s\t%s", e.TransactionCode, e.DFIAccountNumber, e.Amount, e.IndividualName, e.TraceNumber))
		}
	}
	// TODO(adam): Do different stuff with -v enabeld
}

func readACHFile(path string) (*ach.File, error) {
	fd, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("problem opening %s: %v", path, err)
	}
	defer fd.Close()

	f, err := ach.NewReader(fd).Read()
	return &f, err
}
<|endoftext|>


<commit_before>/*
Copyright 2022 The Kubernetes Authors.

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 main

import (
	"context"
	"flag"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"k8s.io/klog/v2"
)

func main() {
	// klog setup
	klog.InitFlags(nil)
	flag.Parse()
	defer klog.Flush()

	// cloud run expects us to listen to HTTP on $PORT
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	// make it possible to override k8s.gcr.io without rebuilding in the future
	upstreamRegistry := os.Getenv("UPSTREAM_REGISTRY")
	if upstreamRegistry == "" {
		upstreamRegistry = "https://k8s.gcr.io"
	}

	// actually serve traffic
	klog.InfoS("listening", "port", port)
	server := &http.Server{
		Addr:        ":" + port,
		Handler:     makeHandler(upstreamRegistry),
		ReadTimeout: 10 * time.Second,
	}

	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	// start serving
	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			klog.Fatal(err)
		}
	}()
	klog.Infof("Server started")

	// Graceful shutdown
	<-done
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		klog.Fatalf("Server didn't exit gracefully %v", err)
	}
}

func makeHandler(upstreamRegistry string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// right now we just need to serve a redirect, but all
		// valid requests should be at /v2/ or /v1/, so we leave this check
		// in the future we will selectively redirect clients to different copies
		path := r.URL.Path
		switch {
		case strings.HasPrefix(path, "/v2/"):
			doV2(w, r, upstreamRegistry)
		case strings.HasPrefix(path, "/v1/"):
			doV1(w, r, upstreamRegistry)
		default:
			klog.V(2).InfoS("unknown request", "path", path)
			http.NotFound(w, r)
		}
	})
}

func doV2(w http.ResponseWriter, r *http.Request, upstreamRegistry string) {
	path := r.URL.Path
	klog.V(2).InfoS("v2 request", "path", path)
	http.Redirect(w, r, upstreamRegistry+path, http.StatusPermanentRedirect)
}

// TODO: should we even be supporting v1 API anymore?
func doV1(w http.ResponseWriter, r *http.Request, upstreamRegistry string) {
	path := r.URL.Path
	klog.V(2).InfoS("v1 request", "path", path)
	http.Redirect(w, r, upstreamRegistry+path, http.StatusPermanentRedirect)
}
<commit_msg>drop v1 support<commit_after>/*
Copyright 2022 The Kubernetes Authors.

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 main

import (
	"context"
	"flag"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"k8s.io/klog/v2"
)

func main() {
	// klog setup
	klog.InitFlags(nil)
	flag.Parse()
	defer klog.Flush()

	// cloud run expects us to listen to HTTP on $PORT
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	// make it possible to override k8s.gcr.io without rebuilding in the future
	upstreamRegistry := os.Getenv("UPSTREAM_REGISTRY")
	if upstreamRegistry == "" {
		upstreamRegistry = "https://k8s.gcr.io"
	}

	// actually serve traffic
	klog.InfoS("listening", "port", port)
	server := &http.Server{
		Addr:        ":" + port,
		Handler:     makeHandler(upstreamRegistry),
		ReadTimeout: 10 * time.Second,
	}

	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	// start serving
	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			klog.Fatal(err)
		}
	}()
	klog.Infof("Server started")

	// Graceful shutdown
	<-done
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		klog.Fatalf("Server didn't exit gracefully %v", err)
	}
}

func makeHandler(upstreamRegistry string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// right now we just need to serve a redirect, but all
		// valid requests should be at /v2/, so we leave this check
		// in the future we will selectively redirect clients to different copies
		path := r.URL.Path
		switch {
		case strings.HasPrefix(path, "/v2/"):
			doV2(w, r, upstreamRegistry)
		default:
			klog.V(2).InfoS("unknown request", "path", path)
			http.NotFound(w, r)
		}
	})
}

func doV2(w http.ResponseWriter, r *http.Request, upstreamRegistry string) {
	path := r.URL.Path
	klog.V(2).InfoS("v2 request", "path", path)
	http.Redirect(w, r, upstreamRegistry+path, http.StatusPermanentRedirect)
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"

	"github.com/daveym/lint/lintapi"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var authenticateCmd = &cobra.Command{
	Use:   "auth",
	Short: "Authenticate against Pocket using your consumer key. One off activity.",
	Long: `To access the Pocket API, you need to authenticate with your consumer key. Your consumer key
	can be found under the development area within the pocket website`,
	Run: func(cmd *cobra.Command, args []string) {

		fmt.Println(viper.Get("AccessToken"))

		AuthNResp := &LintApi.AuthenticationResponse{}
		err := LintApi.Authenticate(LintApi.ConsumerKey, AuthNResp)

		if err != nil {
			fmt.Println("Please check your consumer key, it does not appear to be valid.")
			return
		}

		browser := exec.Command("open", LintApi.UserAuthorisationURL+
			"request_token="+AuthNResp.Code+
			"&redirect_uri="+LintApi.RedirectURI)

		_, err = browser.Output()

		if err != nil {
			println("Error opening authentication page. Please check your connectivity/default browser.")
			return
		}

		fmt.Println("Press ENTER when you have authorised Lint to access to Pocket.")
		bufio.NewReader(os.Stdin).ReadBytes('\n')

		AuthRResp := &LintApi.AuthorisationResponse{}
		err = LintApi.Authorise(LintApi.ConsumerKey, AuthNResp.Code, AuthRResp)

		if err != nil {
			fmt.Println("Error authorising your consumer key and request token. Have you granted permission to Lint?")
		}

		println(AuthRResp.AccessToken, AuthRResp.Username)
	}}

func init() {
	RootCmd.AddCommand(authenticateCmd)
}
<commit_msg>AccessToken Persistance working<commit_after>package cmd

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

	"github.com/daveym/lint/lintapi"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var authenticateCmd = &cobra.Command{
	Use:   "auth",
	Short: "Authenticate against Pocket  to get an Access Token. One off activity.",
	Long: `To access the Pocket API, you need to authenticate with your consumer key. Your consumer key
	can be found under the development area within the pocket website`,
	Run: func(cmd *cobra.Command, args []string) {

		if len(viper.GetString("AccessToken")) == 0 {

			AuthNResp := &LintApi.AuthenticationResponse{}
			err := LintApi.Authenticate(LintApi.ConsumerKey, AuthNResp)

			if err != nil {
				fmt.Println("Please check your consumer key, it does not appear to be valid.")
				return
			}

			browser := exec.Command("open", LintApi.UserAuthorisationURL+
				"request_token="+AuthNResp.Code+
				"&redirect_uri="+LintApi.RedirectURI)

			_, err = browser.Output()

			if err != nil {
				println("Error opening authentication page. Please check your connectivity/default browser.")
				return
			}

			fmt.Println("Press ENTER when you have authorised Lint to access to Pocket.")
			bufio.NewReader(os.Stdin).ReadBytes('\n')

			AuthRResp := &LintApi.AuthorisationResponse{}
			err = LintApi.Authorise(LintApi.ConsumerKey, AuthNResp.Code, AuthRResp)

			if err != nil {
				fmt.Println("Error authorising your consumer key and request token. Have you granted permission to Lint?")
			}

			cfgval := fmt.Sprintf("AccessToken: %v\nUsername: %v", AuthRResp.AccessToken, AuthRResp.Username)
			err = ioutil.WriteFile(LintApi.CfgFile, []byte(cfgval), 0644)

			viper.Set("AccessToken", AuthRResp.AccessToken)
			viper.Set("Username", AuthRResp.Username)

			println("Authentication Successful - Access Token is persisted to lint.yaml")

		} else {
			println("Already authenticated - Access Token present in lint.yaml")
		}
	}}

func init() {
	RootCmd.AddCommand(authenticateCmd)
}
<|endoftext|>