<commit_before>package smux

import (
	"encoding/binary"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"

	"github.com/pkg/errors"
	siasync "github.com/NebulousLabs/Sia/sync" // TODO: Replace with github.com/NebulousLabs/trymutex
)

const (
	defaultAcceptBacklog = 1024
)

var (
	errBrokenPipe      = errors.New("broken pipe")
	errGoAway          = errors.New("stream id overflows, should start a new connection")
	errInvalidProtocol = errors.New("invalid protocol version")
	errLargeFrame      = errors.New("frame is too large to send")
	errWriteTimeout    = errors.New("unable to write to conn within the write timeout")
)

// Session defines a multiplexed connection for streams
type Session struct {
	conn net.Conn
	dataWasRead int32 // used to determine if KeepAlive has failed
	sendMu siasync.TryMutex // ensures only one thread sends at a time

	config           *Config
	nextStreamID     uint32 // next stream identifier
	nextStreamIDLock sync.Mutex

	bucket       int32         // token bucket
	bucketNotify chan struct{} // used for waiting for tokens

	streams    map[uint32]*Stream // all streams in this session
	streamLock sync.Mutex         // locks streams

	die       chan struct{} // flag session has died
	dieLock   sync.Mutex
	chAccepts chan *Stream

	goAway int32 // flag id exhausted

	deadline atomic.Value
}

func newSession(config *Config, conn net.Conn, client bool) *Session {
	s := new(Session)
	s.die = make(chan struct{})
	s.conn = conn
	s.config = config
	s.streams = make(map[uint32]*Stream)
	s.chAccepts = make(chan *Stream, defaultAcceptBacklog)
	s.bucket = int32(config.MaxReceiveBuffer)
	s.bucketNotify = make(chan struct{}, 1)

	if client {
		s.nextStreamID = 1
	} else {
		s.nextStreamID = 0
	}

	go s.recvLoop()
	// keepaliveSend and keepaliveTimeout need to be separate threads, because
	// the keepaliveSend can block, and especially if the underlying conn has no
	// deadline or a very long deadline, we may not check the keepaliveTimeout
	// for an extended period of time and potentially even end in a deadlock.
	go s.keepAliveSend()
	go s.keepAliveTimeout()
	return s
}

// OpenStream is used to create a new stream
func (s *Session) OpenStream() (*Stream, error) {
	if s.IsClosed() {
		return nil, errBrokenPipe
	}

	// generate stream id
	s.nextStreamIDLock.Lock()
	if s.goAway > 0 {
		s.nextStreamIDLock.Unlock()
		return nil, errGoAway
	}

	s.nextStreamID += 2
	sid := s.nextStreamID
	if sid == sid%2 { // stream-id overflows
		s.goAway = 1
		s.nextStreamIDLock.Unlock()
		return nil, errGoAway
	}
	s.nextStreamIDLock.Unlock()

	stream := newStream(sid, s.config.MaxFrameSize, s)

	if _, err := s.writeFrame(newFrame(cmdSYN, sid), time.Now().Add(s.config.WriteTimeout)); err != nil {
		return nil, errors.Wrap(err, "writeFrame")
	}

	s.streamLock.Lock()
	s.streams[sid] = stream
	s.streamLock.Unlock()
	return stream, nil
}

// AcceptStream is used to block until the next available stream
// is ready to be accepted.
func (s *Session) AcceptStream() (*Stream, error) {
	var deadline <-chan time.Time
	if d, ok := s.deadline.Load().(time.Time); ok && !d.IsZero() {
		timer := time.NewTimer(d.Sub(time.Now()))
		defer timer.Stop()
		deadline = timer.C
	}
	select {
	case stream := <-s.chAccepts:
		return stream, nil
	case <-deadline:
		return nil, errTimeout
	case <-s.die:
		return nil, errBrokenPipe
	}
}

// Close is used to close the session and all streams.
func (s *Session) Close() (err error) {
	s.dieLock.Lock()

	select {
	case <-s.die:
		s.dieLock.Unlock()
		return errBrokenPipe
	default:
		close(s.die)
		s.dieLock.Unlock()
		s.streamLock.Lock()
		for k := range s.streams {
			s.streams[k].sessionClose()
		}
		s.streamLock.Unlock()
		s.notifyBucket()
		return s.conn.Close()
	}
}

// notifyBucket notifies recvLoop that bucket is available
func (s *Session) notifyBucket() {
	select {
	case s.bucketNotify <- struct{}{}:
	default:
	}
}

// IsClosed does a safe check to see if we have shutdown
func (s *Session) IsClosed() bool {
	select {
	case <-s.die:
		return true
	default:
		return false
	}
}

// NumStreams returns the number of currently open streams
func (s *Session) NumStreams() int {
	if s.IsClosed() {
		return 0
	}
	s.streamLock.Lock()
	defer s.streamLock.Unlock()
	return len(s.streams)
}

// SetDeadline sets a deadline used by Accept* calls.
// A zero time value disables the deadline.
func (s *Session) SetDeadline(t time.Time) error {
	s.deadline.Store(t)
	return nil
}

// notify the session that a stream has closed
func (s *Session) streamClosed(sid uint32) {
	s.streamLock.Lock()
	if n := s.streams[sid].recycleTokens(); n > 0 { // return remaining tokens to the bucket
		if atomic.AddInt32(&s.bucket, int32(n)) > 0 {
			s.notifyBucket()
		}
	}
	delete(s.streams, sid)
	s.streamLock.Unlock()
}

// returnTokens is called by stream to return token after read
func (s *Session) returnTokens(n int) {
	if atomic.AddInt32(&s.bucket, int32(n)) > 0 {
		s.notifyBucket()
	}
}

// session read a frame from underlying connection
// it's data is pointed to the input buffer
func (s *Session) readFrame(buffer []byte) (f Frame, err error) {
	if _, err := io.ReadFull(s.conn, buffer[:headerSize]); err != nil {
		return f, errors.Wrap(err, "readFrame")
	}

	dec := rawHeader(buffer)
	if dec.Version() != version {
		return f, errInvalidProtocol
	}

	f.ver = dec.Version()
	f.cmd = dec.Cmd()
	f.sid = dec.StreamID()
	if length := dec.Length(); length > 0 {
		if _, err := io.ReadFull(s.conn, buffer[headerSize:headerSize+length]); err != nil {
			return f, errors.Wrap(err, "readFrame")
		}
		f.data = buffer[headerSize : headerSize+length]
	}
	return f, nil
}

// recvLoop keeps on reading from underlying connection if tokens are available
func (s *Session) recvLoop() {
	buffer := make([]byte, (1<<16)+headerSize)
	for {
		for atomic.LoadInt32(&s.bucket) <= 0 && !s.IsClosed() {
			<-s.bucketNotify
		}

		if f, err := s.readFrame(buffer); err == nil {
			atomic.StoreInt32(&s.dataWasRead, 1)

			switch f.cmd {
			case cmdNOP:
			case cmdSYN:
				s.streamLock.Lock()
				if _, ok := s.streams[f.sid]; !ok {
					stream := newStream(f.sid, s.config.MaxFrameSize, s)
					s.streams[f.sid] = stream
					select {
					case s.chAccepts <- stream:
					case <-s.die:
					}
				}
				s.streamLock.Unlock()
			case cmdFIN:
				s.streamLock.Lock()
				if stream, ok := s.streams[f.sid]; ok {
					stream.markRST()
					stream.notifyReadEvent()
				}
				s.streamLock.Unlock()
			case cmdPSH:
				s.streamLock.Lock()
				if stream, ok := s.streams[f.sid]; ok {
					atomic.AddInt32(&s.bucket, -int32(len(f.data)))
					stream.pushBytes(f.data)
					stream.notifyReadEvent()
				}
				s.streamLock.Unlock()
			default:
				s.Close()
				return
			}
		} else {
			s.Close()
			return
		}
	}
}

// keepAliveSend will periodically send a keepalive meesage to the remote peer.
func (s *Session) keepAliveSend() {
	keepAliveTimeout := time.After(s.config.KeepAliveInterval)
	for {
		select {
		case <-s.die:
			return
		case <-keepAliveTimeout:
			keepAliveTimeout = time.After(s.config.KeepAliveInterval) // set before writing so we start sending the next one in time
			s.writeFrame(newFrame(cmdNOP, 0), time.Now().Add(s.config.WriteTimeout))
			s.notifyBucket() // force a signal to the recvLoop
		}
	}
}

// keepAliveTimeout will periodically check that some sort of message has been
// sent by the remote peer, closing the session if not.
func (s *Session) keepAliveTimeout() {
	timeoutChan := time.After(s.config.KeepAliveTimeout)
	for {
		select {
		case <-s.die:
			return
		case <-timeoutChan:
			if !atomic.CompareAndSwapInt32(&s.dataWasRead, 1, 0) {
				s.Close()
				return
			}
			timeoutChan = time.After(s.config.KeepAliveTimeout)
		}
	}
}

// writeFrame writes the frame to the underlying connection
// and returns the number of bytes written if successful
func (s *Session) writeFrame(frame Frame, timeout time.Time) (int, error) {
	// Verify the frame data size.
	if len(frame.data) > 1<<16 {
		return 0, errLargeFrame
	}

	// Ensure that the configured WriteTimeout is the maximum amount of time
	// that we can wait to send a single frame.
	latestTimeout := time.Now().Add(s.config.WriteTimeout)
	if timeout.IsZero() || timeout.After(latestTimeout) {
		timeout = latestTimeout
	}

	// Determine how much time remains in the timeout, wait for up to that long
	// to grab the sendMu.
	currentTime := time.Now()
	if !timeout.After(currentTime) {
		return 0, errWriteTimeout
	}
	remaining := currentTime.Sub(timeout)
	if !s.sendMu.TryLockTimed(remaining) {
		return 0, errWriteTimeout
	}
	defer s.sendMu.Unlock()

	// Check again that the stream has not been killed.
	select {
	case <-s.die:
		return 0, errBrokenPipe
	default:
	}

	// Prepare the write data.
	buf := make([]byte, headerSize+len(frame.data))
	buf[0] = frame.ver
	buf[1] = frame.cmd
	binary.LittleEndian.PutUint16(buf[2:], uint16(len(frame.data)))
	binary.LittleEndian.PutUint32(buf[4:], frame.sid)
	copy(buf[headerSize:], frame.data)

	// Write the data using the provided writeTimeout.
	s.conn.SetWriteDeadline(timeout)
	n, err := s.conn.Write(buf[:headerSize+len(frame.data)])
	s.conn.SetWriteDeadline(time.Time{})
	n -= headerSize
	if n < 0 {
		n = 0
	}
	return n, err
}
<commit_msg>fix mistaken subtraction ordering<commit_after>package smux

import (
	"encoding/binary"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"

	"github.com/pkg/errors"
	siasync "github.com/NebulousLabs/Sia/sync" // TODO: Replace with github.com/NebulousLabs/trymutex
)

const (
	defaultAcceptBacklog = 1024
)

var (
	errBrokenPipe      = errors.New("broken pipe")
	errGoAway          = errors.New("stream id overflows, should start a new connection")
	errInvalidProtocol = errors.New("invalid protocol version")
	errLargeFrame      = errors.New("frame is too large to send")
	errWriteTimeout    = errors.New("unable to write to conn within the write timeout")
)

// Session defines a multiplexed connection for streams
type Session struct {
	conn net.Conn
	dataWasRead int32 // used to determine if KeepAlive has failed
	sendMu siasync.TryMutex // ensures only one thread sends at a time

	config           *Config
	nextStreamID     uint32 // next stream identifier
	nextStreamIDLock sync.Mutex

	bucket       int32         // token bucket
	bucketNotify chan struct{} // used for waiting for tokens

	streams    map[uint32]*Stream // all streams in this session
	streamLock sync.Mutex         // locks streams

	die       chan struct{} // flag session has died
	dieLock   sync.Mutex
	chAccepts chan *Stream

	goAway int32 // flag id exhausted

	deadline atomic.Value
}

func newSession(config *Config, conn net.Conn, client bool) *Session {
	s := new(Session)
	s.die = make(chan struct{})
	s.conn = conn
	s.config = config
	s.streams = make(map[uint32]*Stream)
	s.chAccepts = make(chan *Stream, defaultAcceptBacklog)
	s.bucket = int32(config.MaxReceiveBuffer)
	s.bucketNotify = make(chan struct{}, 1)

	if client {
		s.nextStreamID = 1
	} else {
		s.nextStreamID = 0
	}

	go s.recvLoop()
	// keepaliveSend and keepaliveTimeout need to be separate threads, because
	// the keepaliveSend can block, and especially if the underlying conn has no
	// deadline or a very long deadline, we may not check the keepaliveTimeout
	// for an extended period of time and potentially even end in a deadlock.
	go s.keepAliveSend()
	go s.keepAliveTimeout()
	return s
}

// OpenStream is used to create a new stream
func (s *Session) OpenStream() (*Stream, error) {
	if s.IsClosed() {
		return nil, errBrokenPipe
	}

	// generate stream id
	s.nextStreamIDLock.Lock()
	if s.goAway > 0 {
		s.nextStreamIDLock.Unlock()
		return nil, errGoAway
	}

	s.nextStreamID += 2
	sid := s.nextStreamID
	if sid == sid%2 { // stream-id overflows
		s.goAway = 1
		s.nextStreamIDLock.Unlock()
		return nil, errGoAway
	}
	s.nextStreamIDLock.Unlock()

	stream := newStream(sid, s.config.MaxFrameSize, s)

	if _, err := s.writeFrame(newFrame(cmdSYN, sid), time.Now().Add(s.config.WriteTimeout)); err != nil {
		return nil, errors.Wrap(err, "writeFrame")
	}

	s.streamLock.Lock()
	s.streams[sid] = stream
	s.streamLock.Unlock()
	return stream, nil
}

// AcceptStream is used to block until the next available stream
// is ready to be accepted.
func (s *Session) AcceptStream() (*Stream, error) {
	var deadline <-chan time.Time
	if d, ok := s.deadline.Load().(time.Time); ok && !d.IsZero() {
		timer := time.NewTimer(d.Sub(time.Now()))
		defer timer.Stop()
		deadline = timer.C
	}
	select {
	case stream := <-s.chAccepts:
		return stream, nil
	case <-deadline:
		return nil, errTimeout
	case <-s.die:
		return nil, errBrokenPipe
	}
}

// Close is used to close the session and all streams.
func (s *Session) Close() (err error) {
	s.dieLock.Lock()

	select {
	case <-s.die:
		s.dieLock.Unlock()
		return errBrokenPipe
	default:
		close(s.die)
		s.dieLock.Unlock()
		s.streamLock.Lock()
		for k := range s.streams {
			s.streams[k].sessionClose()
		}
		s.streamLock.Unlock()
		s.notifyBucket()
		return s.conn.Close()
	}
}

// notifyBucket notifies recvLoop that bucket is available
func (s *Session) notifyBucket() {
	select {
	case s.bucketNotify <- struct{}{}:
	default:
	}
}

// IsClosed does a safe check to see if we have shutdown
func (s *Session) IsClosed() bool {
	select {
	case <-s.die:
		return true
	default:
		return false
	}
}

// NumStreams returns the number of currently open streams
func (s *Session) NumStreams() int {
	if s.IsClosed() {
		return 0
	}
	s.streamLock.Lock()
	defer s.streamLock.Unlock()
	return len(s.streams)
}

// SetDeadline sets a deadline used by Accept* calls.
// A zero time value disables the deadline.
func (s *Session) SetDeadline(t time.Time) error {
	s.deadline.Store(t)
	return nil
}

// notify the session that a stream has closed
func (s *Session) streamClosed(sid uint32) {
	s.streamLock.Lock()
	if n := s.streams[sid].recycleTokens(); n > 0 { // return remaining tokens to the bucket
		if atomic.AddInt32(&s.bucket, int32(n)) > 0 {
			s.notifyBucket()
		}
	}
	delete(s.streams, sid)
	s.streamLock.Unlock()
}

// returnTokens is called by stream to return token after read
func (s *Session) returnTokens(n int) {
	if atomic.AddInt32(&s.bucket, int32(n)) > 0 {
		s.notifyBucket()
	}
}

// session read a frame from underlying connection
// it's data is pointed to the input buffer
func (s *Session) readFrame(buffer []byte) (f Frame, err error) {
	if _, err := io.ReadFull(s.conn, buffer[:headerSize]); err != nil {
		return f, errors.Wrap(err, "readFrame")
	}

	dec := rawHeader(buffer)
	if dec.Version() != version {
		return f, errInvalidProtocol
	}

	f.ver = dec.Version()
	f.cmd = dec.Cmd()
	f.sid = dec.StreamID()
	if length := dec.Length(); length > 0 {
		if _, err := io.ReadFull(s.conn, buffer[headerSize:headerSize+length]); err != nil {
			return f, errors.Wrap(err, "readFrame")
		}
		f.data = buffer[headerSize : headerSize+length]
	}
	return f, nil
}

// recvLoop keeps on reading from underlying connection if tokens are available
func (s *Session) recvLoop() {
	buffer := make([]byte, (1<<16)+headerSize)
	for {
		for atomic.LoadInt32(&s.bucket) <= 0 && !s.IsClosed() {
			<-s.bucketNotify
		}

		if f, err := s.readFrame(buffer); err == nil {
			atomic.StoreInt32(&s.dataWasRead, 1)

			switch f.cmd {
			case cmdNOP:
			case cmdSYN:
				s.streamLock.Lock()
				if _, ok := s.streams[f.sid]; !ok {
					stream := newStream(f.sid, s.config.MaxFrameSize, s)
					s.streams[f.sid] = stream
					select {
					case s.chAccepts <- stream:
					case <-s.die:
					}
				}
				s.streamLock.Unlock()
			case cmdFIN:
				s.streamLock.Lock()
				if stream, ok := s.streams[f.sid]; ok {
					stream.markRST()
					stream.notifyReadEvent()
				}
				s.streamLock.Unlock()
			case cmdPSH:
				s.streamLock.Lock()
				if stream, ok := s.streams[f.sid]; ok {
					atomic.AddInt32(&s.bucket, -int32(len(f.data)))
					stream.pushBytes(f.data)
					stream.notifyReadEvent()
				}
				s.streamLock.Unlock()
			default:
				s.Close()
				return
			}
		} else {
			s.Close()
			return
		}
	}
}

// keepAliveSend will periodically send a keepalive meesage to the remote peer.
func (s *Session) keepAliveSend() {
	keepAliveTimeout := time.After(s.config.KeepAliveInterval)
	for {
		select {
		case <-s.die:
			return
		case <-keepAliveTimeout:
			keepAliveTimeout = time.After(s.config.KeepAliveInterval) // set before writing so we start sending the next one in time
			s.writeFrame(newFrame(cmdNOP, 0), time.Now().Add(s.config.WriteTimeout))
			s.notifyBucket() // force a signal to the recvLoop
		}
	}
}

// keepAliveTimeout will periodically check that some sort of message has been
// sent by the remote peer, closing the session if not.
func (s *Session) keepAliveTimeout() {
	timeoutChan := time.After(s.config.KeepAliveTimeout)
	for {
		select {
		case <-s.die:
			return
		case <-timeoutChan:
			if !atomic.CompareAndSwapInt32(&s.dataWasRead, 1, 0) {
				s.Close()
				return
			}
			timeoutChan = time.After(s.config.KeepAliveTimeout)
		}
	}
}

// writeFrame writes the frame to the underlying connection
// and returns the number of bytes written if successful
func (s *Session) writeFrame(frame Frame, timeout time.Time) (int, error) {
	// Verify the frame data size.
	if len(frame.data) > 1<<16 {
		return 0, errLargeFrame
	}

	// Ensure that the configured WriteTimeout is the maximum amount of time
	// that we can wait to send a single frame.
	latestTimeout := time.Now().Add(s.config.WriteTimeout)
	if timeout.IsZero() || timeout.After(latestTimeout) {
		timeout = latestTimeout
	}

	// Determine how much time remains in the timeout, wait for up to that long
	// to grab the sendMu.
	currentTime := time.Now()
	if !timeout.After(currentTime) {
		return 0, errWriteTimeout
	}
	remaining := timeout.Sub(currentTime)
	if !s.sendMu.TryLockTimed(remaining) {
		return 0, errWriteTimeout
	}
	defer s.sendMu.Unlock()

	// Check again that the stream has not been killed.
	select {
	case <-s.die:
		return 0, errBrokenPipe
	default:
	}

	// Prepare the write data.
	buf := make([]byte, headerSize+len(frame.data))
	buf[0] = frame.ver
	buf[1] = frame.cmd
	binary.LittleEndian.PutUint16(buf[2:], uint16(len(frame.data)))
	binary.LittleEndian.PutUint32(buf[4:], frame.sid)
	copy(buf[headerSize:], frame.data)

	// Write the data using the provided writeTimeout.
	s.conn.SetWriteDeadline(timeout)
	n, err := s.conn.Write(buf[:headerSize+len(frame.data)])
	s.conn.SetWriteDeadline(time.Time{})
	n -= headerSize
	if n < 0 {
		n = 0
	}
	return n, err
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Copyright 2014 Cloudbase Solutions SRL
// Licensed under the AGPLv3, see LICENCE file for details.

package version_test

import (
	"sort"

	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/testing"
	"github.com/juju/juju/version"
)

type supportedSeriesWindowsSuite struct {
	testing.BaseSuite
}

var _ = gc.Suite(&supportedSeriesWindowsSuite{})

func (s *supportedSeriesWindowsSuite) TestSeriesVersion(c *gc.C) {
	vers, err := version.SeriesVersion("win8")
	if err != nil {
		c.Assert(err, gc.Not(gc.ErrorMatches), `invalid series "win8"`, gc.Commentf(`unable to lookup series "win8"`))
	} else {
		c.Assert(err, jc.ErrorIsNil)
	}
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(vers, gc.Equals, "win8")
}

func (s *supportedSeriesWindowsSuite) TestSupportedSeries(c *gc.C) {
	expectedSeries := []string{
		"centos7",
		"precise",
		"quantal",
		"raring",
		"saucy",
		"trusty",
		"utopic",
		"vivid",
		"win2012",
		"win2012hv",
		"win2012hvr2",
		"win2012r2",
		"win7",
		"win8",
		"win81",
	}
	series := version.SupportedSeries()
	sort.Strings(series)
	c.Assert(series, gc.DeepEquals, expectedSeries)
}
<commit_msg>Add arch series to windows test<commit_after>// Copyright 2014 Canonical Ltd.
// Copyright 2014 Cloudbase Solutions SRL
// Licensed under the AGPLv3, see LICENCE file for details.

package version_test

import (
	"sort"

	jc "github.com/juju/testing/checkers"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/testing"
	"github.com/juju/juju/version"
)

type supportedSeriesWindowsSuite struct {
	testing.BaseSuite
}

var _ = gc.Suite(&supportedSeriesWindowsSuite{})

func (s *supportedSeriesWindowsSuite) TestSeriesVersion(c *gc.C) {
	vers, err := version.SeriesVersion("win8")
	if err != nil {
		c.Assert(err, gc.Not(gc.ErrorMatches), `invalid series "win8"`, gc.Commentf(`unable to lookup series "win8"`))
	} else {
		c.Assert(err, jc.ErrorIsNil)
	}
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(vers, gc.Equals, "win8")
}

func (s *supportedSeriesWindowsSuite) TestSupportedSeries(c *gc.C) {
	expectedSeries := []string{
		"arch",
		"centos7",
		"precise",
		"quantal",
		"raring",
		"saucy",
		"trusty",
		"utopic",
		"vivid",
		"win2012",
		"win2012hv",
		"win2012hvr2",
		"win2012r2",
		"win7",
		"win8",
		"win81",
	}
	series := version.SupportedSeries()
	sort.Strings(series)
	c.Assert(series, gc.DeepEquals, expectedSeries)
}
<|endoftext|>


<commit_before>package dpsink

import (
	"encoding/json"
	"expvar"
	"fmt"
	"github.com/signalfx/golib/datapoint"
	"github.com/signalfx/golib/event"
	"github.com/signalfx/golib/log"
	"golang.org/x/net/context"
	"net/http"
	"sync"
	"sync/atomic"
	"time"
)

// FlagCheck checks a context to see if a debug flag is set
type FlagCheck interface {
	HasFlag(ctx context.Context) bool
}

// ItemFlagger will flag events and datapoints according to which dimensions are set or if the
// connection context has a flag set.
type ItemFlagger struct {
	CtxFlagCheck        FlagCheck
	Logger              log.Logger
	EventMetaName       string
	MetricDimensionName string
	dimensions          map[string]string
	mu                  sync.RWMutex
	stats               struct {
		totalDpCtxSignals int64
		totalEvCtxSignals int64
		totalDpDimSignals int64
		totalEvDimSignals int64
	}
}

// SetDatapointFlag flags the datapoint as connected to this flagger
func (f *ItemFlagger) SetDatapointFlag(dp *datapoint.Datapoint) {
	dp.Meta[f] = struct{}{}
}

// HasDatapointFlag return true if the datapoint is connected to this item
func (f *ItemFlagger) HasDatapointFlag(dp *datapoint.Datapoint) bool {
	_, exists := dp.Meta[f]
	return exists
}

// SetEventFlag flags the event as connected to this flagger
func (f *ItemFlagger) SetEventFlag(ev *event.Event) {
	ev.Meta[f.EventMetaName] = f
}

// HasEventFlag return true if the event is connected to this item
func (f *ItemFlagger) HasEventFlag(ev *event.Event) bool {
	if f == nil {
		return false
	}
	setTo, exists := ev.Meta[f.EventMetaName]
	return exists && setTo == f
}

// SetDimensions controls which dimensions are flagged
func (f *ItemFlagger) SetDimensions(dims map[string]string) {
	f.mu.Lock()
	f.dimensions = dims
	f.mu.Unlock()
}

// GetDimensions returns which dimensions are flagged
func (f *ItemFlagger) GetDimensions() map[string]string {
	f.mu.RLock()
	ret := f.dimensions
	f.mu.RUnlock()
	return ret
}

// AddDatapoints adds a signal to each datapoint if the signal is inside the context
func (f *ItemFlagger) AddDatapoints(ctx context.Context, points []*datapoint.Datapoint, next Sink) error {
	if f.CtxFlagCheck.HasFlag(ctx) {
		atomic.AddInt64(&f.stats.totalDpCtxSignals, 1)
		for _, dp := range points {
			f.SetDatapointFlag(dp)
		}
		return next.AddDatapoints(ctx, points)
	}
	dims := f.GetDimensions()
	if len(dims) == 0 {
		return next.AddDatapoints(ctx, points)
	}
	for _, dp := range points {
		if dpMatches(dp, f.MetricDimensionName, dims) {
			atomic.AddInt64(&f.stats.totalDpDimSignals, 1)
			f.SetDatapointFlag(dp)
		}
	}
	return next.AddDatapoints(ctx, points)
}

// AddEvents adds a signal to each event if the signal is inside the context
func (f *ItemFlagger) AddEvents(ctx context.Context, events []*event.Event, next Sink) error {
	if f.CtxFlagCheck.HasFlag(ctx) {
		atomic.AddInt64(&f.stats.totalEvCtxSignals, 1)
		for _, dp := range events {
			f.SetEventFlag(dp)
		}
		return next.AddEvents(ctx, events)
	}
	dims := f.GetDimensions()
	if len(dims) == 0 {
		return next.AddEvents(ctx, events)
	}
	for _, ev := range events {
		if evMatches(ev, dims) {
			atomic.AddInt64(&f.stats.totalEvDimSignals, 1)
			f.SetEventFlag(ev)
		}
	}
	return next.AddEvents(ctx, events)
}

// Datapoints returns debug stat information about the flagger
func (f *ItemFlagger) Datapoints() []*datapoint.Datapoint {
	return []*datapoint.Datapoint{
		datapoint.New("totalDpCtxSignals", nil, datapoint.NewIntValue(f.stats.totalDpCtxSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalEvCtxSignals", nil, datapoint.NewIntValue(f.stats.totalEvCtxSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalDpDimSignals", nil, datapoint.NewIntValue(f.stats.totalDpDimSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalEvDimSignals", nil, datapoint.NewIntValue(f.stats.totalEvDimSignals), datapoint.Counter, time.Time{}),
	}
}

// ServeHTTP supports GET to see the current dimensions and POST to change the current dimensions.
// POST expects (and GET returns) a JSON encoded map[string]string
func (f *ItemFlagger) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		var newDimensions map[string]string
		err := json.NewDecoder(req.Body).Decode(&newDimensions)
		if err != nil {
			rw.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(rw, "Cannot decode request JSON: %s", err.Error())
			return
		}
		log.IfErr(f.Logger, req.Body.Close())
		f.SetDimensions(newDimensions)
		fmt.Fprintf(rw, "Dimensions updated!")
		return
	}
	if req.Method == "GET" {
		log.IfErr(f.Logger, json.NewEncoder(rw).Encode(f.GetDimensions()))
		return
	}
	http.NotFound(rw, req)
}

// Var returns the dimensions that are being filtered
func (f *ItemFlagger) Var() expvar.Var {
	return expvar.Func(func() interface{} {
		return f.GetDimensions()
	})
}

func dpMatches(dp *datapoint.Datapoint, MetricDimensionName string, dimsToCheck map[string]string) bool {
	for k, v := range dimsToCheck {
		if k == MetricDimensionName {
			if v != dp.Metric {
				return false
			}
			continue
		}
		dpVal, exists := dp.Dimensions[k]
		if !exists || dpVal != v {
			return false
		}
	}
	return true
}

func evMatches(ev *event.Event, dimsToCheck map[string]string) bool {
	for k, v := range dimsToCheck {
		dpVal, exists := ev.Dimensions[k]
		if !exists || dpVal != v {
			return false
		}
	}
	return true
}
<commit_msg>Include SetDatapointFlags non sink helper<commit_after>package dpsink

import (
	"encoding/json"
	"expvar"
	"fmt"
	"github.com/signalfx/golib/datapoint"
	"github.com/signalfx/golib/event"
	"github.com/signalfx/golib/log"
	"golang.org/x/net/context"
	"net/http"
	"sync"
	"sync/atomic"
	"time"
)

// FlagCheck checks a context to see if a debug flag is set
type FlagCheck interface {
	HasFlag(ctx context.Context) bool
}

// ItemFlagger will flag events and datapoints according to which dimensions are set or if the
// connection context has a flag set.
type ItemFlagger struct {
	CtxFlagCheck        FlagCheck
	Logger              log.Logger
	EventMetaName       string
	MetricDimensionName string
	dimensions          map[string]string
	mu                  sync.RWMutex
	stats               struct {
		totalDpCtxSignals int64
		totalEvCtxSignals int64
		totalDpDimSignals int64
		totalEvDimSignals int64
	}
}

// SetDatapointFlag flags the datapoint as connected to this flagger
func (f *ItemFlagger) SetDatapointFlag(dp *datapoint.Datapoint) {
	dp.Meta[f] = struct{}{}
}

// HasDatapointFlag return true if the datapoint is connected to this item
func (f *ItemFlagger) HasDatapointFlag(dp *datapoint.Datapoint) bool {
	_, exists := dp.Meta[f]
	return exists
}

// SetEventFlag flags the event as connected to this flagger
func (f *ItemFlagger) SetEventFlag(ev *event.Event) {
	ev.Meta[f.EventMetaName] = f
}

// HasEventFlag return true if the event is connected to this item
func (f *ItemFlagger) HasEventFlag(ev *event.Event) bool {
	if f == nil {
		return false
	}
	setTo, exists := ev.Meta[f.EventMetaName]
	return exists && setTo == f
}

// SetDimensions controls which dimensions are flagged
func (f *ItemFlagger) SetDimensions(dims map[string]string) {
	f.mu.Lock()
	f.dimensions = dims
	f.mu.Unlock()
}

// GetDimensions returns which dimensions are flagged
func (f *ItemFlagger) GetDimensions() map[string]string {
	f.mu.RLock()
	ret := f.dimensions
	f.mu.RUnlock()
	return ret
}

// SetDatapointFlags sets the log flag for every datapoint if the signal is inside the context
func (f *ItemFlagger) SetDatapointFlags(ctx context.Context, points []*datapoint.Datapoint) {
	if f.CtxFlagCheck.HasFlag(ctx) {
		atomic.AddInt64(&f.stats.totalDpCtxSignals, 1)
		for _, dp := range points {
			f.SetDatapointFlag(dp)
		}
	}
	dims := f.GetDimensions()
	if len(dims) == 0 {
		return
	}
	for _, dp := range points {
		if dpMatches(dp, f.MetricDimensionName, dims) {
			atomic.AddInt64(&f.stats.totalDpDimSignals, 1)
			f.SetDatapointFlag(dp)
		}
	}
}

// AddDatapoints adds a signal to each datapoint if the signal is inside the context
func (f *ItemFlagger) AddDatapoints(ctx context.Context, points []*datapoint.Datapoint, next Sink) error {
	f.SetDatapointFlags(ctx, points)
	return next.AddDatapoints(ctx, points)
}

// AddEvents adds a signal to each event if the signal is inside the context
func (f *ItemFlagger) AddEvents(ctx context.Context, events []*event.Event, next Sink) error {
	if f.CtxFlagCheck.HasFlag(ctx) {
		atomic.AddInt64(&f.stats.totalEvCtxSignals, 1)
		for _, dp := range events {
			f.SetEventFlag(dp)
		}
		return next.AddEvents(ctx, events)
	}
	dims := f.GetDimensions()
	if len(dims) == 0 {
		return next.AddEvents(ctx, events)
	}
	for _, ev := range events {
		if evMatches(ev, dims) {
			atomic.AddInt64(&f.stats.totalEvDimSignals, 1)
			f.SetEventFlag(ev)
		}
	}
	return next.AddEvents(ctx, events)
}

// Datapoints returns debug stat information about the flagger
func (f *ItemFlagger) Datapoints() []*datapoint.Datapoint {
	return []*datapoint.Datapoint{
		datapoint.New("totalDpCtxSignals", nil, datapoint.NewIntValue(f.stats.totalDpCtxSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalEvCtxSignals", nil, datapoint.NewIntValue(f.stats.totalEvCtxSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalDpDimSignals", nil, datapoint.NewIntValue(f.stats.totalDpDimSignals), datapoint.Counter, time.Time{}),
		datapoint.New("totalEvDimSignals", nil, datapoint.NewIntValue(f.stats.totalEvDimSignals), datapoint.Counter, time.Time{}),
	}
}

// ServeHTTP supports GET to see the current dimensions and POST to change the current dimensions.
// POST expects (and GET returns) a JSON encoded map[string]string
func (f *ItemFlagger) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		var newDimensions map[string]string
		err := json.NewDecoder(req.Body).Decode(&newDimensions)
		if err != nil {
			rw.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(rw, "Cannot decode request JSON: %s", err.Error())
			return
		}
		log.IfErr(f.Logger, req.Body.Close())
		f.SetDimensions(newDimensions)
		fmt.Fprintf(rw, "Dimensions updated!")
		return
	}
	if req.Method == "GET" {
		log.IfErr(f.Logger, json.NewEncoder(rw).Encode(f.GetDimensions()))
		return
	}
	http.NotFound(rw, req)
}

// Var returns the dimensions that are being filtered
func (f *ItemFlagger) Var() expvar.Var {
	return expvar.Func(func() interface{} {
		return f.GetDimensions()
	})
}

func dpMatches(dp *datapoint.Datapoint, MetricDimensionName string, dimsToCheck map[string]string) bool {
	for k, v := range dimsToCheck {
		if k == MetricDimensionName {
			if v != dp.Metric {
				return false
			}
			continue
		}
		dpVal, exists := dp.Dimensions[k]
		if !exists || dpVal != v {
			return false
		}
	}
	return true
}

func evMatches(ev *event.Event, dimsToCheck map[string]string) bool {
	for k, v := range dimsToCheck {
		dpVal, exists := ev.Dimensions[k]
		if !exists || dpVal != v {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package graph

import (
	"fmt"

	"github.com/oinume/algo/datastructure/stack"
)

type Finder interface {
	Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool
}

// dfsRecursiveFinder is depth first search finder
type dfsRecursiveFinder struct {
	visited map[*Vertex]struct{}
}

func NewDFSRecursiveFinder() Finder {
	return &dfsRecursiveFinder{
		visited: make(map[*Vertex]struct{}, 100),
	}
}

func (dfs *dfsRecursiveFinder) Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool {
	//fmt.Printf("Find(): start = %+v\n", start)
	visitor.Visit(g, start)

	if start.IsEqual(target) {
		return true
	}
	if _, visited := dfs.visited[start]; visited {
		return false
	}

	dfs.visited[start] = struct{}{}
	edges := g.Edges(start)
	//fmt.Printf("edges = %+v\n", edges)
	for _, edge := range edges {
		if _, visited := dfs.visited[edge.end]; visited {
			continue
		}
		if result := dfs.Find(g, edge.end, target, visitor); result {
			return result
		}
	}

	return false
}

type dfsLoopFinder struct {
	visited map[*Vertex]struct{}
}

func NewDFSLoopFinder() Finder {
	return &dfsLoopFinder{
		visited: make(map[*Vertex]struct{}, 100),
	}
}

func (dfs *dfsLoopFinder) Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool {
	st := stack.NewStack(g.vertices.Size())
	st.Push(start)

	for !st.IsEmpty() {
		v, err := st.Pop()
		if err != nil {
			// Must not reach here
			return false
		}

		vertex := v.(*Vertex)
		fmt.Printf("vertex:%v, edges=%+v\n", vertex, g.Edges(vertex))
		visitor.Visit(g, vertex)
		if vertex.IsEqual(target) {
			return true
		}
		dfs.visited[vertex] = struct{}{}

		for _, edge := range g.Edges(vertex) {
			if _, visited := dfs.visited[edge.end]; visited {
				continue
			}
			st.Push(edge.end)
			fmt.Printf("Pushed: %+v\n", edge.end)
		}
	}

	return false
}

type Visitor interface {
	Visit(g *Graph, v *Vertex)
}

type nopVisitor struct{}

func (nv *nopVisitor) Visit(g *Graph, v *Vertex) {}

func (nv *nopVisitor) Visited() []*Vertex {
	return nil
}

func NewListVisitor() Visitor {
	return &listVisitor{
		list: make([]*Vertex, 0, 100),
	}
}

type listVisitor struct {
	list []*Vertex
}

func (lv *listVisitor) Visit(g *Graph, v *Vertex) {
	lv.list = append(lv.list, v)
}
<commit_msg>Remove debug print<commit_after>package graph

import (
	"github.com/oinume/algo/datastructure/stack"
)

type Finder interface {
	Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool
}

// dfsRecursiveFinder is depth first search finder
type dfsRecursiveFinder struct {
	visited map[*Vertex]struct{}
}

func NewDFSRecursiveFinder() Finder {
	return &dfsRecursiveFinder{
		visited: make(map[*Vertex]struct{}, 100),
	}
}

func (dfs *dfsRecursiveFinder) Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool {
	//fmt.Printf("Find(): start = %+v\n", start)
	visitor.Visit(g, start)

	if start.IsEqual(target) {
		return true
	}
	if _, visited := dfs.visited[start]; visited {
		return false
	}

	dfs.visited[start] = struct{}{}
	edges := g.Edges(start)
	//fmt.Printf("edges = %+v\n", edges)
	for _, edge := range edges {
		if _, visited := dfs.visited[edge.end]; visited {
			continue
		}
		if result := dfs.Find(g, edge.end, target, visitor); result {
			return result
		}
	}

	return false
}

type dfsLoopFinder struct {
	visited map[*Vertex]struct{}
}

func NewDFSLoopFinder() Finder {
	return &dfsLoopFinder{
		visited: make(map[*Vertex]struct{}, 100),
	}
}

func (dfs *dfsLoopFinder) Find(g *Graph, start *Vertex, target *Vertex, visitor Visitor) bool {
	st := stack.NewStack(g.vertices.Size())
	st.Push(start)

	for !st.IsEmpty() {
		v, err := st.Pop()
		if err != nil {
			// Must not reach here
			return false
		}

		vertex := v.(*Vertex)
		//fmt.Printf("vertex:%v, edges=%+v\n", vertex, g.Edges(vertex))
		visitor.Visit(g, vertex)
		if vertex.IsEqual(target) {
			return true
		}
		dfs.visited[vertex] = struct{}{}

		for _, edge := range g.Edges(vertex) {
			if _, visited := dfs.visited[edge.end]; visited {
				continue
			}
			st.Push(edge.end)
			//fmt.Printf("Pushed: %+v\n", edge.end)
		}
	}

	return false
}

type Visitor interface {
	Visit(g *Graph, v *Vertex)
}

type nopVisitor struct{}

func (nv *nopVisitor) Visit(g *Graph, v *Vertex) {}

func (nv *nopVisitor) Visited() []*Vertex {
	return nil
}

func NewListVisitor() Visitor {
	return &listVisitor{
		list: make([]*Vertex, 0, 100),
	}
}

type listVisitor struct {
	list []*Vertex
}

func (lv *listVisitor) Visit(g *Graph, v *Vertex) {
	lv.list = append(lv.list, v)
}
<|endoftext|>


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

package auth

import (
	"math/rand"
	"reflect"
	"strings"
	"time"

	"github.com/Unknwon/com"
	"github.com/Unknwon/macaron"
	"github.com/macaron-contrib/binding"
	"github.com/macaron-contrib/session"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/uuid"
)

func IsAPIPath(url string) bool {
	return strings.HasPrefix(url, "/api/")
}

// SignedInID returns the id of signed in user.
func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
	if !models.HasEngine {
		return 0
	}

	// Check access token.
	if IsAPIPath(ctx.Req.URL.Path) {
		tokenSHA := ctx.Query("token")
		if len(tokenSHA) == 0 {
			// Well, check with header again.
			auHead := ctx.Req.Header.Get("Authorization")
			if len(auHead) > 0 {
				auths := strings.Fields(auHead)
				if len(auths) == 2 && auths[0] == "token" {
					tokenSHA = auths[1]
				}
			}
		}

		// Let's see if token is valid.
		if len(tokenSHA) > 0 {
			t, err := models.GetAccessTokenBySHA(tokenSHA)
			if err != nil {
				if models.IsErrAccessTokenNotExist(err) {
					log.Error(4, "GetAccessTokenBySHA: %v", err)
				}
				return 0
			}
			t.Updated = time.Now()
			if err = models.UpdateAccessToekn(t); err != nil {
				log.Error(4, "UpdateAccessToekn: %v", err)
			}
			return t.UID
		}
	}

	uid := sess.Get("uid")
	if uid == nil {
		return 0
	}
	if id, ok := uid.(int64); ok {
		if _, err := models.GetUserByID(id); err != nil {
			if !models.IsErrUserNotExist(err) {
				log.Error(4, "GetUserById: %v", err)
			}
			return 0
		}
		return id
	}
	return 0
}

// SignedInUser returns the user object of signed user.
// It returns a bool value to indicate whether user uses basic auth or not.
func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) {
	if !models.HasEngine {
		return nil, false
	}

	uid := SignedInID(ctx, sess)

	if uid <= 0 {
		if setting.Service.EnableReverseProxyAuth {
			webAuthUser := ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
			if len(webAuthUser) > 0 {
				u, err := models.GetUserBySandstormID(webAuthUser)
				if err != nil {
					if !models.IsErrSandstormUserNotExist(err) {
						log.Error(4, "GetUserBySandstormID: %v", err)
						return nil, false
					}

					// Check if enabled auto-registration.
					if setting.Service.EnableReverseProxyAutoRegister {
						randomDigit := func() string {
							return string(rune('0' + rand.Intn(10)))
						}

						handle := ctx.Req.Header.Get("X-Sandstorm-Preferred-Handle")
						if len(handle) == 0 {
							handle = "gogsuser"
						}

						for suffix := ""; len(suffix) < 5; suffix += randomDigit() {
							u := &models.User{
								SandstormId: webAuthUser,
								Name:        handle + suffix,
								Email:       uuid.NewV4().String() + "@localhost",
								Passwd:      webAuthUser,
								IsActive:    true,
							}
							err = models.CreateUser(u)
							if err == nil {
								return u, false
							}
						}

						// FIXME: should I create a system notice?
						log.Error(4, "CreateUser: %v", err)
						return nil, false
					}
				}
				return u, false
			}
		}

		// Check with basic auth.
		baHead := ctx.Req.Header.Get("Authorization")
		if len(baHead) > 0 {
			auths := strings.Fields(baHead)
			if len(auths) == 2 && auths[0] == "Basic" {
				uname, passwd, _ := base.BasicAuthDecode(auths[1])

				u, err := models.UserSignIn(uname, passwd)
				if err != nil {
					if !models.IsErrUserNotExist(err) {
						log.Error(4, "UserSignIn: %v", err)
					}
					return nil, false
				}

				return u, true
			}
		}
		return nil, false
	}

	u, err := models.GetUserByID(uid)
	if err != nil {
		log.Error(4, "GetUserById: %v", err)
		return nil, false
	}
	return u, false
}

type Form interface {
	binding.Validator
}

func init() {
	binding.SetNameMapper(com.ToSnakeCase)
}

// AssignForm assign form values back to the template data.
func AssignForm(form interface{}, data map[string]interface{}) {
	typ := reflect.TypeOf(form)
	val := reflect.ValueOf(form)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		fieldName := field.Tag.Get("form")
		// Allow ignored fields in the struct
		if fieldName == "-" {
			continue
		} else if len(fieldName) == 0 {
			fieldName = com.ToSnakeCase(field.Name)
		}

		data[fieldName] = val.Field(i).Interface()
	}
}

func getSize(field reflect.StructField, prefix string) string {
	for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
		if strings.HasPrefix(rule, prefix) {
			return rule[len(prefix) : len(rule)-1]
		}
	}
	return ""
}

func GetSize(field reflect.StructField) string {
	return getSize(field, "Size(")
}

func GetMinSize(field reflect.StructField) string {
	return getSize(field, "MinSize(")
}

func GetMaxSize(field reflect.StructField) string {
	return getSize(field, "MaxSize(")
}

// FIXME: struct contains a struct
func validateStruct(obj interface{}) binding.Errors {

	return nil
}

func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
	if errs.Len() == 0 {
		return errs
	}

	data["HasError"] = true
	AssignForm(f, data)

	typ := reflect.TypeOf(f)
	val := reflect.ValueOf(f)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		fieldName := field.Tag.Get("form")
		// Allow ignored fields in the struct
		if fieldName == "-" {
			continue
		}

		if errs[0].FieldNames[0] == field.Name {
			data["Err_"+field.Name] = true

			trName := field.Tag.Get("locale")
			if len(trName) == 0 {
				trName = l.Tr("form." + field.Name)
			} else {
				trName = l.Tr(trName)
			}

			switch errs[0].Classification {
			case binding.ERR_REQUIRED:
				data["ErrorMsg"] = trName + l.Tr("form.require_error")
			case binding.ERR_ALPHA_DASH:
				data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
			case binding.ERR_ALPHA_DASH_DOT:
				data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
			case binding.ERR_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
			case binding.ERR_MIN_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
			case binding.ERR_MAX_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
			case binding.ERR_EMAIL:
				data["ErrorMsg"] = trName + l.Tr("form.email_error")
			case binding.ERR_URL:
				data["ErrorMsg"] = trName + l.Tr("form.url_error")
			default:
				data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
			}
			return errs
		}
	}
	return errs
}
<commit_msg>Give users random passwords instead of their Sandstorm IDs<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package auth

import (
	"math/rand"
	"reflect"
	"strings"
	"time"

	"github.com/Unknwon/com"
	"github.com/Unknwon/macaron"
	"github.com/macaron-contrib/binding"
	"github.com/macaron-contrib/session"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/uuid"
)

func IsAPIPath(url string) bool {
	return strings.HasPrefix(url, "/api/")
}

// SignedInID returns the id of signed in user.
func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
	if !models.HasEngine {
		return 0
	}

	// Check access token.
	if IsAPIPath(ctx.Req.URL.Path) {
		tokenSHA := ctx.Query("token")
		if len(tokenSHA) == 0 {
			// Well, check with header again.
			auHead := ctx.Req.Header.Get("Authorization")
			if len(auHead) > 0 {
				auths := strings.Fields(auHead)
				if len(auths) == 2 && auths[0] == "token" {
					tokenSHA = auths[1]
				}
			}
		}

		// Let's see if token is valid.
		if len(tokenSHA) > 0 {
			t, err := models.GetAccessTokenBySHA(tokenSHA)
			if err != nil {
				if models.IsErrAccessTokenNotExist(err) {
					log.Error(4, "GetAccessTokenBySHA: %v", err)
				}
				return 0
			}
			t.Updated = time.Now()
			if err = models.UpdateAccessToekn(t); err != nil {
				log.Error(4, "UpdateAccessToekn: %v", err)
			}
			return t.UID
		}
	}

	uid := sess.Get("uid")
	if uid == nil {
		return 0
	}
	if id, ok := uid.(int64); ok {
		if _, err := models.GetUserByID(id); err != nil {
			if !models.IsErrUserNotExist(err) {
				log.Error(4, "GetUserById: %v", err)
			}
			return 0
		}
		return id
	}
	return 0
}

// SignedInUser returns the user object of signed user.
// It returns a bool value to indicate whether user uses basic auth or not.
func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) {
	if !models.HasEngine {
		return nil, false
	}

	uid := SignedInID(ctx, sess)

	if uid <= 0 {
		if setting.Service.EnableReverseProxyAuth {
			webAuthUser := ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
			if len(webAuthUser) > 0 {
				u, err := models.GetUserBySandstormID(webAuthUser)
				if err != nil {
					if !models.IsErrSandstormUserNotExist(err) {
						log.Error(4, "GetUserBySandstormID: %v", err)
						return nil, false
					}

					// Check if enabled auto-registration.
					if setting.Service.EnableReverseProxyAutoRegister {
						randomDigit := func() string {
							return string(rune('0' + rand.Intn(10)))
						}

						password := ""
						for i := 0; i < 16; i++ {
							password += randomDigit()
						}

						handle := ctx.Req.Header.Get("X-Sandstorm-Preferred-Handle")
						if len(handle) == 0 {
							handle = "gogsuser"
						}

						for suffix := ""; len(suffix) < 5; suffix += randomDigit() {
							u := &models.User{
								SandstormId: webAuthUser,
								Name:        handle + suffix,
								Email:       uuid.NewV4().String() + "@localhost",
								Passwd:      password,
								IsActive:    true,
							}
							err = models.CreateUser(u)
							if err == nil {
								return u, false
							}
						}

						// FIXME: should I create a system notice?
						log.Error(4, "CreateUser: %v", err)
						return nil, false
					}
				}
				return u, false
			}
		}

		// Check with basic auth.
		baHead := ctx.Req.Header.Get("Authorization")
		if len(baHead) > 0 {
			auths := strings.Fields(baHead)
			if len(auths) == 2 && auths[0] == "Basic" {
				uname, passwd, _ := base.BasicAuthDecode(auths[1])

				u, err := models.UserSignIn(uname, passwd)
				if err != nil {
					if !models.IsErrUserNotExist(err) {
						log.Error(4, "UserSignIn: %v", err)
					}
					return nil, false
				}

				return u, true
			}
		}
		return nil, false
	}

	u, err := models.GetUserByID(uid)
	if err != nil {
		log.Error(4, "GetUserById: %v", err)
		return nil, false
	}
	return u, false
}

type Form interface {
	binding.Validator
}

func init() {
	binding.SetNameMapper(com.ToSnakeCase)
}

// AssignForm assign form values back to the template data.
func AssignForm(form interface{}, data map[string]interface{}) {
	typ := reflect.TypeOf(form)
	val := reflect.ValueOf(form)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		fieldName := field.Tag.Get("form")
		// Allow ignored fields in the struct
		if fieldName == "-" {
			continue
		} else if len(fieldName) == 0 {
			fieldName = com.ToSnakeCase(field.Name)
		}

		data[fieldName] = val.Field(i).Interface()
	}
}

func getSize(field reflect.StructField, prefix string) string {
	for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
		if strings.HasPrefix(rule, prefix) {
			return rule[len(prefix) : len(rule)-1]
		}
	}
	return ""
}

func GetSize(field reflect.StructField) string {
	return getSize(field, "Size(")
}

func GetMinSize(field reflect.StructField) string {
	return getSize(field, "MinSize(")
}

func GetMaxSize(field reflect.StructField) string {
	return getSize(field, "MaxSize(")
}

// FIXME: struct contains a struct
func validateStruct(obj interface{}) binding.Errors {

	return nil
}

func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
	if errs.Len() == 0 {
		return errs
	}

	data["HasError"] = true
	AssignForm(f, data)

	typ := reflect.TypeOf(f)
	val := reflect.ValueOf(f)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)

		fieldName := field.Tag.Get("form")
		// Allow ignored fields in the struct
		if fieldName == "-" {
			continue
		}

		if errs[0].FieldNames[0] == field.Name {
			data["Err_"+field.Name] = true

			trName := field.Tag.Get("locale")
			if len(trName) == 0 {
				trName = l.Tr("form." + field.Name)
			} else {
				trName = l.Tr(trName)
			}

			switch errs[0].Classification {
			case binding.ERR_REQUIRED:
				data["ErrorMsg"] = trName + l.Tr("form.require_error")
			case binding.ERR_ALPHA_DASH:
				data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
			case binding.ERR_ALPHA_DASH_DOT:
				data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
			case binding.ERR_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
			case binding.ERR_MIN_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
			case binding.ERR_MAX_SIZE:
				data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
			case binding.ERR_EMAIL:
				data["ErrorMsg"] = trName + l.Tr("form.email_error")
			case binding.ERR_URL:
				data["ErrorMsg"] = trName + l.Tr("form.url_error")
			default:
				data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
			}
			return errs
		}
	}
	return errs
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go 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 runtime

import (
	"runtime/internal/sys"
	"unsafe"
)

type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

// An notInHeapSlice is a slice backed by go:notinheap memory.
type notInHeapSlice struct {
	array *notInHeap
	len   int
	cap   int
}

// maxElems is a lookup table containing the maximum capacity for a slice.
// The index is the size of the slice element.
var maxElems = [...]uintptr{
	^uintptr(0),
	maxAlloc / 1, maxAlloc / 2, maxAlloc / 3, maxAlloc / 4,
	maxAlloc / 5, maxAlloc / 6, maxAlloc / 7, maxAlloc / 8,
	maxAlloc / 9, maxAlloc / 10, maxAlloc / 11, maxAlloc / 12,
	maxAlloc / 13, maxAlloc / 14, maxAlloc / 15, maxAlloc / 16,
	maxAlloc / 17, maxAlloc / 18, maxAlloc / 19, maxAlloc / 20,
	maxAlloc / 21, maxAlloc / 22, maxAlloc / 23, maxAlloc / 24,
	maxAlloc / 25, maxAlloc / 26, maxAlloc / 27, maxAlloc / 28,
	maxAlloc / 29, maxAlloc / 30, maxAlloc / 31, maxAlloc / 32,
}

// maxSliceCap returns the maximum capacity for a slice.
func maxSliceCap(elemsize uintptr) uintptr {
	if elemsize < uintptr(len(maxElems)) {
		return maxElems[elemsize]
	}
	return maxAlloc / elemsize
}

func makeslice(et *_type, len, cap int) slice {
	// NOTE: The len > maxElements check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	maxElements := maxSliceCap(et.size)
	if len < 0 || uintptr(len) > maxElements {
		panic(errorString("makeslice: len out of range"))
	}

	if cap < len || uintptr(cap) > maxElements {
		panic(errorString("makeslice: cap out of range"))
	}

	p := mallocgc(et.size*uintptr(cap), et, true)
	return slice{p, len, cap}
}

func makeslice64(et *_type, len64, cap64 int64) slice {
	len := int(len64)
	if int64(len) != len64 {
		panic(errorString("makeslice: len out of range"))
	}

	cap := int(cap64)
	if int64(cap) != cap64 {
		panic(errorString("makeslice: cap out of range"))
	}

	return makeslice(et, len, cap)
}

// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
// copied into it.
// The new slice's length is set to the old slice's length,
// NOT to the new requested capacity.
// This is for codegen convenience. The old slice's length is used immediately
// to calculate where to write new values during an append.
// TODO: When the old backend is gone, reconsider this decision.
// The SSA backend might prefer the new length or to return only ptr/cap and save stack space.
func growslice(et *_type, old slice, cap int) slice {
	if raceenabled {
		callerpc := getcallerpc()
		racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice))
	}
	if msanenabled {
		msanread(old.array, uintptr(old.len*int(et.size)))
	}

	if et.size == 0 {
		if cap < old.cap {
			panic(errorString("growslice: cap out of range"))
		}
		// append should not create a slice with nil pointer but non-zero len.
		// We assume that append doesn't need to preserve old.array in this case.
		return slice{unsafe.Pointer(&zerobase), old.len, cap}
	}

	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

	var overflow bool
	var lenmem, newlenmem, capmem uintptr
	const ptrSize = unsafe.Sizeof((*byte)(nil))
	// Specialize for common values of et.size.
	// For 1 we don't need any division/multiplication.
	// For ptrSize, compiler will optimize division/multiplication into a shift by a constant.
	// For powers of 2, use a variable shift.
	switch {
	case et.size == 1:
		lenmem = uintptr(old.len)
		newlenmem = uintptr(cap)
		capmem = roundupsize(uintptr(newcap))
		overflow = uintptr(newcap) > maxAlloc
		newcap = int(capmem)
	case et.size == ptrSize:
		lenmem = uintptr(old.len) * ptrSize
		newlenmem = uintptr(cap) * ptrSize
		capmem = roundupsize(uintptr(newcap) * ptrSize)
		overflow = uintptr(newcap) > maxAlloc/ptrSize
		newcap = int(capmem / ptrSize)
	case isPowerOfTwo(et.size):
		var shift uintptr
		if ptrSize == 8 {
			// Mask shift for better code generation.
			shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
		} else {
			shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
		}
		lenmem = uintptr(old.len) << shift
		newlenmem = uintptr(cap) << shift
		capmem = roundupsize(uintptr(newcap) << shift)
		overflow = uintptr(newcap) > (maxAlloc >> shift)
		newcap = int(capmem >> shift)
	default:
		lenmem = uintptr(old.len) * et.size
		newlenmem = uintptr(cap) * et.size
		capmem = roundupsize(uintptr(newcap) * et.size)
		overflow = uintptr(newcap) > maxSliceCap(et.size)
		newcap = int(capmem / et.size)
	}

	// The check of overflow (uintptr(newcap) > maxSliceCap(et.size))
	// in addition to capmem > _MaxMem is needed to prevent an overflow
	// which can be used to trigger a segfault on 32bit architectures
	// with this example program:
	//
	// type T [1<<27 + 1]int64
	//
	// var d T
	// var s []T
	//
	// func main() {
	//   s = append(s, d, d, d, d)
	//   print(len(s), "\n")
	// }
	if cap < old.cap || overflow || capmem > maxAlloc {
		panic(errorString("growslice: cap out of range"))
	}

	var p unsafe.Pointer
	if et.kind&kindNoPointers != 0 {
		p = mallocgc(capmem, nil, false)
		memmove(p, old.array, lenmem)
		// The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
		// Only clear the part that will not be overwritten.
		memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
	} else {
		// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
		p = mallocgc(capmem, et, true)
		if !writeBarrier.enabled {
			memmove(p, old.array, lenmem)
		} else {
			for i := uintptr(0); i < lenmem; i += et.size {
				typedmemmove(et, add(p, i), add(old.array, i))
			}
		}
	}

	return slice{p, old.len, newcap}
}

func isPowerOfTwo(x uintptr) bool {
	return x&(x-1) == 0
}

func slicecopy(to, fm slice, width uintptr) int {
	if fm.len == 0 || to.len == 0 {
		return 0
	}

	n := fm.len
	if to.len < n {
		n = to.len
	}

	if width == 0 {
		return n
	}

	if raceenabled {
		callerpc := getcallerpc()
		pc := funcPC(slicecopy)
		racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
		racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
	}
	if msanenabled {
		msanwrite(to.array, uintptr(n*int(width)))
		msanread(fm.array, uintptr(n*int(width)))
	}

	size := uintptr(n) * width
	if size == 1 { // common case worth about 2x to do here
		// TODO: is this still worth it with new memmove impl?
		*(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
	} else {
		memmove(to.array, fm.array, size)
	}
	return n
}

func slicestringcopy(to []byte, fm string) int {
	if len(fm) == 0 || len(to) == 0 {
		return 0
	}

	n := len(fm)
	if len(to) < n {
		n = len(to)
	}

	if raceenabled {
		callerpc := getcallerpc()
		pc := funcPC(slicestringcopy)
		racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
	}
	if msanenabled {
		msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
	}

	memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
	return n
}
<commit_msg>runtime: use sys.PtrSize in growslice<commit_after>// Copyright 2009 The Go 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 runtime

import (
	"runtime/internal/sys"
	"unsafe"
)

type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

// An notInHeapSlice is a slice backed by go:notinheap memory.
type notInHeapSlice struct {
	array *notInHeap
	len   int
	cap   int
}

// maxElems is a lookup table containing the maximum capacity for a slice.
// The index is the size of the slice element.
var maxElems = [...]uintptr{
	^uintptr(0),
	maxAlloc / 1, maxAlloc / 2, maxAlloc / 3, maxAlloc / 4,
	maxAlloc / 5, maxAlloc / 6, maxAlloc / 7, maxAlloc / 8,
	maxAlloc / 9, maxAlloc / 10, maxAlloc / 11, maxAlloc / 12,
	maxAlloc / 13, maxAlloc / 14, maxAlloc / 15, maxAlloc / 16,
	maxAlloc / 17, maxAlloc / 18, maxAlloc / 19, maxAlloc / 20,
	maxAlloc / 21, maxAlloc / 22, maxAlloc / 23, maxAlloc / 24,
	maxAlloc / 25, maxAlloc / 26, maxAlloc / 27, maxAlloc / 28,
	maxAlloc / 29, maxAlloc / 30, maxAlloc / 31, maxAlloc / 32,
}

// maxSliceCap returns the maximum capacity for a slice.
func maxSliceCap(elemsize uintptr) uintptr {
	if elemsize < uintptr(len(maxElems)) {
		return maxElems[elemsize]
	}
	return maxAlloc / elemsize
}

func makeslice(et *_type, len, cap int) slice {
	// NOTE: The len > maxElements check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	maxElements := maxSliceCap(et.size)
	if len < 0 || uintptr(len) > maxElements {
		panic(errorString("makeslice: len out of range"))
	}

	if cap < len || uintptr(cap) > maxElements {
		panic(errorString("makeslice: cap out of range"))
	}

	p := mallocgc(et.size*uintptr(cap), et, true)
	return slice{p, len, cap}
}

func makeslice64(et *_type, len64, cap64 int64) slice {
	len := int(len64)
	if int64(len) != len64 {
		panic(errorString("makeslice: len out of range"))
	}

	cap := int(cap64)
	if int64(cap) != cap64 {
		panic(errorString("makeslice: cap out of range"))
	}

	return makeslice(et, len, cap)
}

// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
// copied into it.
// The new slice's length is set to the old slice's length,
// NOT to the new requested capacity.
// This is for codegen convenience. The old slice's length is used immediately
// to calculate where to write new values during an append.
// TODO: When the old backend is gone, reconsider this decision.
// The SSA backend might prefer the new length or to return only ptr/cap and save stack space.
func growslice(et *_type, old slice, cap int) slice {
	if raceenabled {
		callerpc := getcallerpc()
		racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice))
	}
	if msanenabled {
		msanread(old.array, uintptr(old.len*int(et.size)))
	}

	if et.size == 0 {
		if cap < old.cap {
			panic(errorString("growslice: cap out of range"))
		}
		// append should not create a slice with nil pointer but non-zero len.
		// We assume that append doesn't need to preserve old.array in this case.
		return slice{unsafe.Pointer(&zerobase), old.len, cap}
	}

	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

	var overflow bool
	var lenmem, newlenmem, capmem uintptr
	// Specialize for common values of et.size.
	// For 1 we don't need any division/multiplication.
	// For sys.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
	// For powers of 2, use a variable shift.
	switch {
	case et.size == 1:
		lenmem = uintptr(old.len)
		newlenmem = uintptr(cap)
		capmem = roundupsize(uintptr(newcap))
		overflow = uintptr(newcap) > maxAlloc
		newcap = int(capmem)
	case et.size == sys.PtrSize:
		lenmem = uintptr(old.len) * sys.PtrSize
		newlenmem = uintptr(cap) * sys.PtrSize
		capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
		overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
		newcap = int(capmem / sys.PtrSize)
	case isPowerOfTwo(et.size):
		var shift uintptr
		if sys.PtrSize == 8 {
			// Mask shift for better code generation.
			shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
		} else {
			shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
		}
		lenmem = uintptr(old.len) << shift
		newlenmem = uintptr(cap) << shift
		capmem = roundupsize(uintptr(newcap) << shift)
		overflow = uintptr(newcap) > (maxAlloc >> shift)
		newcap = int(capmem >> shift)
	default:
		lenmem = uintptr(old.len) * et.size
		newlenmem = uintptr(cap) * et.size
		capmem = roundupsize(uintptr(newcap) * et.size)
		overflow = uintptr(newcap) > maxSliceCap(et.size)
		newcap = int(capmem / et.size)
	}

	// The check of overflow (uintptr(newcap) > maxSliceCap(et.size))
	// in addition to capmem > _MaxMem is needed to prevent an overflow
	// which can be used to trigger a segfault on 32bit architectures
	// with this example program:
	//
	// type T [1<<27 + 1]int64
	//
	// var d T
	// var s []T
	//
	// func main() {
	//   s = append(s, d, d, d, d)
	//   print(len(s), "\n")
	// }
	if cap < old.cap || overflow || capmem > maxAlloc {
		panic(errorString("growslice: cap out of range"))
	}

	var p unsafe.Pointer
	if et.kind&kindNoPointers != 0 {
		p = mallocgc(capmem, nil, false)
		memmove(p, old.array, lenmem)
		// The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
		// Only clear the part that will not be overwritten.
		memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
	} else {
		// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
		p = mallocgc(capmem, et, true)
		if !writeBarrier.enabled {
			memmove(p, old.array, lenmem)
		} else {
			for i := uintptr(0); i < lenmem; i += et.size {
				typedmemmove(et, add(p, i), add(old.array, i))
			}
		}
	}

	return slice{p, old.len, newcap}
}

func isPowerOfTwo(x uintptr) bool {
	return x&(x-1) == 0
}

func slicecopy(to, fm slice, width uintptr) int {
	if fm.len == 0 || to.len == 0 {
		return 0
	}

	n := fm.len
	if to.len < n {
		n = to.len
	}

	if width == 0 {
		return n
	}

	if raceenabled {
		callerpc := getcallerpc()
		pc := funcPC(slicecopy)
		racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
		racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
	}
	if msanenabled {
		msanwrite(to.array, uintptr(n*int(width)))
		msanread(fm.array, uintptr(n*int(width)))
	}

	size := uintptr(n) * width
	if size == 1 { // common case worth about 2x to do here
		// TODO: is this still worth it with new memmove impl?
		*(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
	} else {
		memmove(to.array, fm.array, size)
	}
	return n
}

func slicestringcopy(to []byte, fm string) int {
	if len(fm) == 0 || len(to) == 0 {
		return 0
	}

	n := len(fm)
	if len(to) < n {
		n = len(to)
	}

	if raceenabled {
		callerpc := getcallerpc()
		pc := funcPC(slicestringcopy)
		racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
	}
	if msanenabled {
		msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
	}

	memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
	return n
}
<|endoftext|>


<commit_before>package moxxiConf

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"text/template"
)

func CreateMux(handlers []HandlerConfig, l *log.Logger) *http.ServeMux {
	mux := http.NewServeMux()
	for _, handler := range handlers {
		switch handler.handlerType {
		case "json":
			mux.HandleFunc(handler.handlerRoute, JSONHandler(handler, l))
		case "form":
			mux.HandleFunc(handler.handlerRoute, FormHandler(handler, l))
		case "static":
			mux.HandleFunc(handler.handlerRoute, StaticHandler(handler, l))
		}
	}
	return mux
}

// FormHandler - creates and returns a Handler for both Query and Form requests
func FormHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {
	confWriter := confWrite(config)

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

		if extErr := r.ParseForm(); extErr != nil {
			http.Error(w, extErr.Error(), http.StatusBadRequest)
			return
		}

		if r.Form.Get("host") == "" {
			pkgErr := &NewErr{Code: ErrNoHostname}
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}
		host := r.Form.Get("host")

		if r.Form.Get("ip") == "" {
			pkgErr := &NewErr{Code: ErrNoIP}
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}

		tls := parseCheckbox(r.Form.Get("tls"))

		port, err := strconv.Atoi(r.Form.Get("port"))
		if err != nil {
			port = 80
		}

		vhost := siteParams{
			IntHost:      host,
			IntIP:        r.Form.Get("ip"),
			Encrypted:    tls,
			IntPort:      port,
			StripHeaders: r.Form["header"],
		}

		vhost, pkgErr := confCheck(vhost, config)
		if pkgErr != nil {
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}

		if vhost, pkgErr = confWriter(vhost); pkgErr != nil {
			http.Error(w, pkgErr.Error(), http.StatusInternalServerError)
			l.Println(pkgErr.LogError(r))
			return
		}

		if extErr := config.resTempl.Execute(w, []siteParams{vhost}); extErr != nil {
			http.Error(w, extErr.Error(), http.StatusInternalServerError)
			l.Println(extErr.Error())
			return
		}
		return
	}
}

// JSONHandler - creates and returns a Handler for JSON body requests
func JSONHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {

	var tStart, tEnd, tBody *template.Template

	for _, each := range config.resTempl.Templates() {
		switch each.Name() {
		case "start":
			tStart = each
		case "end":
			tEnd = each
		case "body":
			tBody = each
		}
	}

	if tStart == nil || tEnd == nil || tBody == nil {
		return InvalidHandler("bad template", http.StatusInternalServerError)
	}

	confWriter := confWrite(config)

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

		var emptyInterface interface{}
		type locSiteParams struct {
			ExtHost      string
			IntHost      string
			IntIP        string
			IntPort      int
			Encrypted    bool
			StripHeaders []string
			ErrorString  string
			Error        Err
		}

		tStart.Execute(w, emptyInterface)

		decoder := json.NewDecoder(r.Body)

		for decoder.More() {
			var v siteParams
			if err := decoder.Decode(&v); err != nil {
				continue
			}

			v, err := confCheck(v, config)
			if err == nil || err.GetCode() == ErrBadHostnameTrace {
				v, err = confWriter(v)
			}

			var vPlus = struct {
				ExtHost      string
				IntHost      string
				IntIP        string
				IntPort      int
				Encrypted    bool
				StripHeaders []string
				Error        string
			}{
				ExtHost:      v.ExtHost,
				IntHost:      v.IntHost,
				IntIP:        v.IntIP,
				IntPort:      v.IntPort,
				Encrypted:    v.Encrypted,
				StripHeaders: v.StripHeaders,
			}

			if err != nil {
				l.Println(err.LogError(r))
				vPlus.Error = err.Error()
			}

			if err := tBody.Execute(w, vPlus); err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				l.Println(err.Error())
				return
			}
		}
		tEnd.Execute(w, emptyInterface)
	}
}

// StaticHandler - creates and returns a Handler to simply respond with a static response to every request
func StaticHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {
	res, err := ioutil.ReadFile(config.resFile)
	if err != nil {
		l.Printf("bad static response file %s - %v", config.resFile, err)
		return InvalidHandler("no data", http.StatusInternalServerError)
	}

	return func(w http.ResponseWriter, r *http.Request) {
		if _, err := w.Write(res); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
}

func InvalidHandler(msg string, code int) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, msg, code)
	}
}
<commit_msg>changed the handler config to write out a conf and honor errors even if stuff's bad<commit_after>package moxxiConf

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"text/template"
)

func CreateMux(handlers []HandlerConfig, l *log.Logger) *http.ServeMux {
	mux := http.NewServeMux()
	for _, handler := range handlers {
		switch handler.handlerType {
		case "json":
			mux.HandleFunc(handler.handlerRoute, JSONHandler(handler, l))
		case "form":
			mux.HandleFunc(handler.handlerRoute, FormHandler(handler, l))
		case "static":
			mux.HandleFunc(handler.handlerRoute, StaticHandler(handler, l))
		}
	}
	return mux
}

// FormHandler - creates and returns a Handler for both Query and Form requests
func FormHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {
	confWriter := confWrite(config)

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

		if extErr := r.ParseForm(); extErr != nil {
			http.Error(w, extErr.Error(), http.StatusBadRequest)
			return
		}

		if r.Form.Get("host") == "" {
			pkgErr := &NewErr{Code: ErrNoHostname}
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}
		host := r.Form.Get("host")

		if r.Form.Get("ip") == "" {
			pkgErr := &NewErr{Code: ErrNoIP}
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}

		tls := parseCheckbox(r.Form.Get("tls"))

		port, err := strconv.Atoi(r.Form.Get("port"))
		if err != nil {
			port = 80
		}

		vhost := siteParams{
			IntHost:      host,
			IntIP:        r.Form.Get("ip"),
			Encrypted:    tls,
			IntPort:      port,
			StripHeaders: r.Form["header"],
		}

		vhost, pkgErr := confCheck(vhost, config)
		if pkgErr != nil {
			http.Error(w, pkgErr.Error(), http.StatusPreconditionFailed)
			l.Println(pkgErr.LogError(r))
			return
		}

		if vhost, pkgErr = confWriter(vhost); pkgErr != nil {
			http.Error(w, pkgErr.Error(), http.StatusInternalServerError)
			l.Println(pkgErr.LogError(r))
			return
		}

		if extErr := config.resTempl.Execute(w, []siteParams{vhost}); extErr != nil {
			http.Error(w, extErr.Error(), http.StatusInternalServerError)
			l.Println(extErr.Error())
			return
		}
		return
	}
}

// JSONHandler - creates and returns a Handler for JSON body requests
func JSONHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {

	var tStart, tEnd, tBody *template.Template

	for _, each := range config.resTempl.Templates() {
		switch each.Name() {
		case "start":
			tStart = each
		case "end":
			tEnd = each
		case "body":
			tBody = each
		}
	}

	if tStart == nil || tEnd == nil || tBody == nil {
		return InvalidHandler("bad template", http.StatusInternalServerError)
	}

	confWriter := confWrite(config)

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

		var emptyInterface interface{}
		type locSiteParams struct {
			ExtHost      string
			IntHost      string
			IntIP        string
			IntPort      int
			Encrypted    bool
			StripHeaders []string
			ErrorString  string
			Error        Err
		}

		tStart.Execute(w, emptyInterface)

		decoder := json.NewDecoder(r.Body)

		for decoder.More() {
			var v siteParams
			if err := decoder.Decode(&v); err != nil {
				continue
			}

			v, err := confCheck(v, config)
			if err == nil {
				v, err = confWriter(v)
			} else if err.GetCode() == ErrBadHostnameTrace {
				var newErr Error
				v, newErr = confWriter(v)
				if newErr != nil {
					err = newErr
				}
			}

			var vPlus = struct {
				ExtHost      string
				IntHost      string
				IntIP        string
				IntPort      int
				Encrypted    bool
				StripHeaders []string
				Error        string
			}{
				ExtHost:      v.ExtHost,
				IntHost:      v.IntHost,
				IntIP:        v.IntIP,
				IntPort:      v.IntPort,
				Encrypted:    v.Encrypted,
				StripHeaders: v.StripHeaders,
			}

			if err != nil {
				l.Println(err.LogError(r))
				vPlus.Error = err.Error()
			}

			if err := tBody.Execute(w, vPlus); err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				l.Println(err.Error())
				return
			}
		}
		tEnd.Execute(w, emptyInterface)
	}
}

// StaticHandler - creates and returns a Handler to simply respond with a static response to every request
func StaticHandler(config HandlerConfig, l *log.Logger) http.HandlerFunc {
	res, err := ioutil.ReadFile(config.resFile)
	if err != nil {
		l.Printf("bad static response file %s - %v", config.resFile, err)
		return InvalidHandler("no data", http.StatusInternalServerError)
	}

	return func(w http.ResponseWriter, r *http.Request) {
		if _, err := w.Write(res); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
}

func InvalidHandler(msg string, code int) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, msg, code)
	}
}
<|endoftext|>


<commit_before>package irc

import (
	irc "github.com/fluffle/goirc/client"
	"fmt"
	"log"
	"strings"
	"time"
	"ircflu/app"
	"ircflu/auth"
	"ircflu/msgsystem"
)

type IrcSubSystem struct {
	name string
	messagesIn chan msgsystem.Message
	messagesOut chan msgsystem.Message

	// channel signaling irc connection status
	chConnected chan bool

	// setup IRC client:
	client *irc.Conn

	irchost     string
	ircnick     string
	ircpassword string
	ircssl      bool
	ircchannel  string
}

func (h *IrcSubSystem) Name() string {
	return h.name
}

func (h *IrcSubSystem) MessageInChan() chan msgsystem.Message {
	return h.messagesIn
}

func (h *IrcSubSystem) SetMessageInChan(channel chan msgsystem.Message) {
	h.messagesIn = channel
}

func (h *IrcSubSystem) MessageOutChan() chan msgsystem.Message {
	return h.messagesOut
}

func (h *IrcSubSystem) SetMessageOutChan(channel chan msgsystem.Message) {
	h.messagesOut = channel
}

func (h *IrcSubSystem) Join(channel string) {
	h.client.Join(channel)
}

func (h *IrcSubSystem) Part(channel string) {
	h.client.Part(channel)
}

func (h *IrcSubSystem) Run() {
	// channel signaling irc connection status
	h.chConnected = make(chan bool)

	// setup IRC client:
	h.client = irc.SimpleClient(h.ircnick, "ircflu", "ircflu")
	h.client.SSL = h.ircssl

	h.client.AddHandler(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		h.chConnected <- true
	})
	h.client.AddHandler(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) {
		h.chConnected <- false
	})
	h.client.AddHandler("PRIVMSG", func(conn *irc.Conn, line *irc.Line) {
		channel := line.Args[0]
		if channel == h.client.Me.Nick {
			// TODO: check if source is in main chan, else return
			log.Println("Got via PM from " + line.Src)
			channel = line.Src // replies go via PM too.
		} else {
			log.Println("Got via channel " + line.Args[0] + " from " + line.Src)
		}

		msg := msgsystem.Message{
			To: []string{channel},
			Msg: line.Args[1],
			Source: line.Src,
			Authed: auth.IsAuthed(line.Src),
		}
		h.messagesIn <- msg
	})

	// loop on IRC dis/connected events
	go func() {
		for {
			log.Println("Connecting to IRC...")
			err := h.client.Connect(h.irchost, h.ircpassword)
			if err != nil {
				log.Println("Failed to connect to IRC")
				log.Println(err)
				continue
			}
			for {
				status := <-h.chConnected
				if status {
					log.Println("Connected to IRC")
					h.client.Join(h.ircchannel)
				} else {
					log.Println("Disconnected from IRC")
					break
				}
			}
			time.Sleep(5 * time.Second)
		}
	}()

	go func() {
		for {
			cm := <-h.messagesOut
			fmt.Println("Sending:", cm.To, cm.Msg)
			if len(cm.To) == 0 {
				h.client.Privmsg(h.ircchannel, cm.Msg)
			} else {
				for _, to := range cm.To {
					recv := to
					if strings.Index(recv, "!~") > 0 {
						recv = recv[0:strings.Index(recv, "!~")]
					}
					h.client.Privmsg(recv, cm.Msg)
				}
			}
		}
	}()
}

func init() {
	irc := IrcSubSystem{name: "irc"}

	app.AddFlags([]app.CliFlag{
		app.CliFlag{&irc.irchost, "irchost", "localhost:6667", "Hostname of IRC server, eg: irc.example.org:6667"},
		app.CliFlag{&irc.ircnick, "ircnick", "ircflu", "Nickname to use for IRC"},
		app.CliFlag{&irc.ircpassword, "ircpassword", "", "Password to use to connect to IRC server"},
		app.CliFlag{&irc.ircchannel, "ircchannel", "#ircflutest", "Which channel to join"},
	//	app.CliFlag{&irc.ircssl, "ircssl", false, "Use SSL for IRC connection"},
	})

	msgsystem.RegisterSubSystem(&irc)
}
<commit_msg>* Auth makes this comment obsolete.<commit_after>package irc

import (
	irc "github.com/fluffle/goirc/client"
	"fmt"
	"log"
	"strings"
	"time"
	"ircflu/app"
	"ircflu/auth"
	"ircflu/msgsystem"
)

type IrcSubSystem struct {
	name string
	messagesIn chan msgsystem.Message
	messagesOut chan msgsystem.Message

	// channel signaling irc connection status
	chConnected chan bool

	// setup IRC client:
	client *irc.Conn

	irchost     string
	ircnick     string
	ircpassword string
	ircssl      bool
	ircchannel  string
}

func (h *IrcSubSystem) Name() string {
	return h.name
}

func (h *IrcSubSystem) MessageInChan() chan msgsystem.Message {
	return h.messagesIn
}

func (h *IrcSubSystem) SetMessageInChan(channel chan msgsystem.Message) {
	h.messagesIn = channel
}

func (h *IrcSubSystem) MessageOutChan() chan msgsystem.Message {
	return h.messagesOut
}

func (h *IrcSubSystem) SetMessageOutChan(channel chan msgsystem.Message) {
	h.messagesOut = channel
}

func (h *IrcSubSystem) Join(channel string) {
	h.client.Join(channel)
}

func (h *IrcSubSystem) Part(channel string) {
	h.client.Part(channel)
}

func (h *IrcSubSystem) Run() {
	// channel signaling irc connection status
	h.chConnected = make(chan bool)

	// setup IRC client:
	h.client = irc.SimpleClient(h.ircnick, "ircflu", "ircflu")
	h.client.SSL = h.ircssl

	h.client.AddHandler(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		h.chConnected <- true
	})
	h.client.AddHandler(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) {
		h.chConnected <- false
	})
	h.client.AddHandler("PRIVMSG", func(conn *irc.Conn, line *irc.Line) {
		channel := line.Args[0]
		if channel == h.client.Me.Nick {
			log.Println("PM from " + line.Src)
			channel = line.Src // replies go via PM too.
		} else {
			log.Println("Message in channel " + line.Args[0] + " from " + line.Src)
		}

		msg := msgsystem.Message{
			To: []string{channel},
			Msg: line.Args[1],
			Source: line.Src,
			Authed: auth.IsAuthed(line.Src),
		}
		h.messagesIn <- msg
	})

	// loop on IRC dis/connected events
	go func() {
		for {
			log.Println("Connecting to IRC...")
			err := h.client.Connect(h.irchost, h.ircpassword)
			if err != nil {
				log.Println("Failed to connect to IRC")
				log.Println(err)
				continue
			}
			for {
				status := <-h.chConnected
				if status {
					log.Println("Connected to IRC")
					h.client.Join(h.ircchannel)
				} else {
					log.Println("Disconnected from IRC")
					break
				}
			}
			time.Sleep(5 * time.Second)
		}
	}()

	go func() {
		for {
			cm := <-h.messagesOut
			fmt.Println("Sending:", cm.To, cm.Msg)
			if len(cm.To) == 0 {
				h.client.Privmsg(h.ircchannel, cm.Msg)
			} else {
				for _, to := range cm.To {
					recv := to
					if strings.Index(recv, "!~") > 0 {
						recv = recv[0:strings.Index(recv, "!~")]
					}
					h.client.Privmsg(recv, cm.Msg)
				}
			}
		}
	}()
}

func init() {
	irc := IrcSubSystem{name: "irc"}

	app.AddFlags([]app.CliFlag{
		app.CliFlag{&irc.irchost, "irchost", "localhost:6667", "Hostname of IRC server, eg: irc.example.org:6667"},
		app.CliFlag{&irc.ircnick, "ircnick", "ircflu", "Nickname to use for IRC"},
		app.CliFlag{&irc.ircpassword, "ircpassword", "", "Password to use to connect to IRC server"},
		app.CliFlag{&irc.ircchannel, "ircchannel", "#ircflutest", "Which channel to join"},
	//	app.CliFlag{&irc.ircssl, "ircssl", false, "Use SSL for IRC connection"},
	})

	msgsystem.RegisterSubSystem(&irc)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	_ "github.com/dotcloud/docker"
	"github.com/dotcloud/docker/api"
	"github.com/dotcloud/docker/dockerversion"
	"github.com/dotcloud/docker/engine"
	flag "github.com/dotcloud/docker/pkg/mflag"
	"github.com/dotcloud/docker/pkg/opts"
	"github.com/dotcloud/docker/sysinit"
	"github.com/dotcloud/docker/utils"
)

func main() {
	if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
		// Running in init mode
		sysinit.SysInit()
		return
	}

	var (
		flVersion            = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
		flDaemon             = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
		flDebug              = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
		flAutoRestart        = flag.Bool([]string{"r", "-restart"}, true, "Restart previously running containers")
		bridgeName           = flag.String([]string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
		bridgeIp             = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
		pidfile              = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
		flRoot               = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the docker runtime")
		flEnableCors         = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
		flDns                = opts.NewListOpts(opts.ValidateIp4Address)
		flEnableIptables     = flag.Bool([]string{"#iptables", "-iptables"}, true, "Disable docker's addition of iptables rules")
		flEnableIpForward    = flag.Bool([]string{"#ip-forward", "-ip-forward"}, true, "Disable enabling of net.ipv4.ip_forward")
		flDefaultIp          = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
		flInterContainerComm = flag.Bool([]string{"#icc", "-icc"}, true, "Enable inter-container communication")
		flGraphDriver        = flag.String([]string{"s", "-storage-driver"}, "", "Force the docker runtime to use a specific storage driver")
		flHosts              = opts.NewListOpts(api.ValidateHost)
		flMtu                = flag.Int([]string{"#mtu", "-mtu"}, 0, "Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if not default route is available")
	)
	flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers")
	flag.Var(&flHosts, []string{"H", "-host"}, "tcp://host:port, unix://path/to/socket, fd://* or fd://socketfd to use in daemon mode. Multiple sockets can be specified")

	flag.Parse()

	if *flVersion {
		showVersion()
		return
	}
	if flHosts.Len() == 0 {
		defaultHost := os.Getenv("DOCKER_HOST")

		if defaultHost == "" || *flDaemon {
			// If we do not have a host, default to unix socket
			defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
		}
		flHosts.Set(defaultHost)
	}

	if *bridgeName != "" && *bridgeIp != "" {
		log.Fatal("You specified -b & --bip, mutually exclusive options. Please specify only one.")
	}

	if *flDebug {
		os.Setenv("DEBUG", "1")
	}
	if *flDaemon {
		if flag.NArg() != 0 {
			flag.Usage()
			return
		}

		eng, err := engine.New(*flRoot)
		if err != nil {
			log.Fatal(err)
		}
		// Load plugin: httpapi
		job := eng.Job("initserver")
		job.Setenv("Pidfile", *pidfile)
		job.Setenv("Root", *flRoot)
		job.SetenvBool("AutoRestart", *flAutoRestart)
		job.SetenvList("Dns", flDns.GetAll())
		job.SetenvBool("EnableIptables", *flEnableIptables)
		job.SetenvBool("EnableIpForward", *flEnableIpForward)
		job.Setenv("BridgeIface", *bridgeName)
		job.Setenv("BridgeIP", *bridgeIp)
		job.Setenv("DefaultIp", *flDefaultIp)
		job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
		job.Setenv("GraphDriver", *flGraphDriver)
		job.SetenvInt("Mtu", *flMtu)
		if err := job.Run(); err != nil {
			log.Fatal(err)
		}
		// Serve api
		job = eng.Job("serveapi", flHosts.GetAll()...)
		job.SetenvBool("Logging", true)
		job.SetenvBool("EnableCors", *flEnableCors)
		job.Setenv("Version", dockerversion.VERSION)
		if err := job.Run(); err != nil {
			log.Fatal(err)
		}
	} else {
		if flHosts.Len() > 1 {
			log.Fatal("Please specify only one -H")
		}
		protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2)
		if err := api.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
			if sterr, ok := err.(*utils.StatusError); ok {
				if sterr.Status != "" {
					log.Println(sterr.Status)
				}
				os.Exit(sterr.StatusCode)
			}
			log.Fatal(err)
		}
	}
}

func showVersion() {
	fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
}
<commit_msg>Fix DOCKER_HOST=tcp:// panic<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	_ "github.com/dotcloud/docker"
	"github.com/dotcloud/docker/api"
	"github.com/dotcloud/docker/dockerversion"
	"github.com/dotcloud/docker/engine"
	flag "github.com/dotcloud/docker/pkg/mflag"
	"github.com/dotcloud/docker/pkg/opts"
	"github.com/dotcloud/docker/sysinit"
	"github.com/dotcloud/docker/utils"
)

func main() {
	if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
		// Running in init mode
		sysinit.SysInit()
		return
	}

	var (
		flVersion            = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
		flDaemon             = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
		flDebug              = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
		flAutoRestart        = flag.Bool([]string{"r", "-restart"}, true, "Restart previously running containers")
		bridgeName           = flag.String([]string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
		bridgeIp             = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
		pidfile              = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
		flRoot               = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the docker runtime")
		flEnableCors         = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
		flDns                = opts.NewListOpts(opts.ValidateIp4Address)
		flEnableIptables     = flag.Bool([]string{"#iptables", "-iptables"}, true, "Disable docker's addition of iptables rules")
		flEnableIpForward    = flag.Bool([]string{"#ip-forward", "-ip-forward"}, true, "Disable enabling of net.ipv4.ip_forward")
		flDefaultIp          = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
		flInterContainerComm = flag.Bool([]string{"#icc", "-icc"}, true, "Enable inter-container communication")
		flGraphDriver        = flag.String([]string{"s", "-storage-driver"}, "", "Force the docker runtime to use a specific storage driver")
		flHosts              = opts.NewListOpts(api.ValidateHost)
		flMtu                = flag.Int([]string{"#mtu", "-mtu"}, 0, "Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if not default route is available")
	)
	flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers")
	flag.Var(&flHosts, []string{"H", "-host"}, "tcp://host:port, unix://path/to/socket, fd://* or fd://socketfd to use in daemon mode. Multiple sockets can be specified")

	flag.Parse()

	if *flVersion {
		showVersion()
		return
	}
	if flHosts.Len() == 0 {
		defaultHost := os.Getenv("DOCKER_HOST")

		if defaultHost == "" || *flDaemon {
			// If we do not have a host, default to unix socket
			defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
		}
		if _, err := api.ValidateHost(defaultHost); err != nil {
			log.Fatal(err)
		}
		flHosts.Set(defaultHost)
	}

	if *bridgeName != "" && *bridgeIp != "" {
		log.Fatal("You specified -b & --bip, mutually exclusive options. Please specify only one.")
	}

	if *flDebug {
		os.Setenv("DEBUG", "1")
	}
	if *flDaemon {
		if flag.NArg() != 0 {
			flag.Usage()
			return
		}

		eng, err := engine.New(*flRoot)
		if err != nil {
			log.Fatal(err)
		}
		// Load plugin: httpapi
		job := eng.Job("initserver")
		job.Setenv("Pidfile", *pidfile)
		job.Setenv("Root", *flRoot)
		job.SetenvBool("AutoRestart", *flAutoRestart)
		job.SetenvList("Dns", flDns.GetAll())
		job.SetenvBool("EnableIptables", *flEnableIptables)
		job.SetenvBool("EnableIpForward", *flEnableIpForward)
		job.Setenv("BridgeIface", *bridgeName)
		job.Setenv("BridgeIP", *bridgeIp)
		job.Setenv("DefaultIp", *flDefaultIp)
		job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
		job.Setenv("GraphDriver", *flGraphDriver)
		job.SetenvInt("Mtu", *flMtu)
		if err := job.Run(); err != nil {
			log.Fatal(err)
		}
		// Serve api
		job = eng.Job("serveapi", flHosts.GetAll()...)
		job.SetenvBool("Logging", true)
		job.SetenvBool("EnableCors", *flEnableCors)
		job.Setenv("Version", dockerversion.VERSION)
		if err := job.Run(); err != nil {
			log.Fatal(err)
		}
	} else {
		if flHosts.Len() > 1 {
			log.Fatal("Please specify only one -H")
		}
		protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2)
		if err := api.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
			if sterr, ok := err.(*utils.StatusError); ok {
				if sterr.Status != "" {
					log.Println(sterr.Status)
				}
				os.Exit(sterr.StatusCode)
			}
			log.Fatal(err)
		}
	}
}

func showVersion() {
	fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
}
<|endoftext|>