<commit_before>package controller

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"time"

	ct "github.com/flynn/flynn-controller/types"
	"github.com/flynn/rpcplus"
)

func New(uri string) (*Client, error) {
	u, err := url.Parse(uri)
	if err != nil {
		return nil, err
	}
	return &Client{url: uri, addr: u.Host}, nil
}

type Client struct {
	url  string
	addr string
}

var ErrNotFound = errors.New("controller: not found")

func (c *Client) send(method, path string, in, out interface{}) error {
	data, err := json.Marshal(in)
	if err != nil {
		return err
	}
	req, err := http.NewRequest(method, c.url+path, bytes.NewBuffer(data))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return fmt.Errorf("controller: unexpected status %d", res.StatusCode)
	}
	if out != nil {
		return json.NewDecoder(res.Body).Decode(out)
	}
	return nil
}

func (c *Client) put(path string, in, out interface{}) error {
	return c.send("PUT", path, in, out)
}

func (c *Client) post(path string, in, out interface{}) error {
	return c.send("POST", path, in, out)
}

func (c *Client) get(path string, out interface{}) error {
	res, err := http.Get(c.url + path)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 404 {
			return ErrNotFound
		}
		return fmt.Errorf("controller: unexpected status %d", res.StatusCode)
	}
	return json.NewDecoder(res.Body).Decode(out)
}

func (c *Client) StreamFormations(since *time.Time) (<-chan *ct.ExpandedFormation, *error) {
	if since == nil {
		*since = time.Unix(0, 0)
	}
	// TODO: handle TLS
	client, err := rpcplus.DialHTTP("tcp", c.addr)
	if err != nil {
		return nil, &err
	}
	ch := make(chan *ct.ExpandedFormation)
	return ch, &client.StreamGo("Controller.StreamFormations", since, ch).Error
}

func (c *Client) CreateArtifact(artifact *ct.Artifact) error {
	return c.post("/artifacts", artifact, artifact)
}

func (c *Client) CreateRelease(release *ct.Release) error {
	return c.post("/releases", release, release)
}

func (c *Client) CreateApp(app *ct.App) error {
	return c.post("/apps", app, app)
}

func (c *Client) CreateProvider(provider *ct.Provider) error {
	return c.post("/providers", provider, provider)
}

func (c *Client) ProvisionResource(req *ct.ResourceReq) (*ct.Resource, error) {
	if req.ProviderID == "" {
		return nil, errors.New("controller: missing provider id")
	}
	res := &ct.Resource{}
	err := c.post(fmt.Sprintf("/providers/%s/resources", req.ProviderID), req, res)
	return res, err
}

func (c *Client) PutResource(resource *ct.Resource) error {
	if resource.ID == "" || resource.ProviderID == "" {
		return errors.New("controller: missing id and/or provider id")
	}
	return c.put(fmt.Sprintf("/providers/%s/resources/%s", resource.ProviderID, resource.ID), resource, resource)
}

func (c *Client) PutFormation(formation *ct.Formation) error {
	if formation.AppID == "" || formation.ReleaseID == "" {
		return errors.New("controller: missing app id and/or release id")
	}
	return c.put(fmt.Sprintf("/apps/%s/formations/%s", formation.AppID, formation.ReleaseID), formation, formation)
}

func (c *Client) SetAppRelease(appID, releaseID string) error {
	return c.put("/apps/"+appID+"/release", &ct.Release{ID: releaseID}, nil)
}

func (c *Client) GetAppRelease(appID string) (*ct.Release, error) {
	release := &ct.Release{}
	return release, c.get("/apps/"+appID+"/release", release)
}
<commit_msg>controller/client: Add CreateRoute<commit_after>package controller

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"time"

	ct "github.com/flynn/flynn-controller/types"
	"github.com/flynn/rpcplus"
	"github.com/flynn/strowger/types"
)

func New(uri string) (*Client, error) {
	u, err := url.Parse(uri)
	if err != nil {
		return nil, err
	}
	return &Client{url: uri, addr: u.Host}, nil
}

type Client struct {
	url  string
	addr string
}

var ErrNotFound = errors.New("controller: not found")

func (c *Client) send(method, path string, in, out interface{}) error {
	data, err := json.Marshal(in)
	if err != nil {
		return err
	}
	req, err := http.NewRequest(method, c.url+path, bytes.NewBuffer(data))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return fmt.Errorf("controller: unexpected status %d", res.StatusCode)
	}
	if out != nil {
		return json.NewDecoder(res.Body).Decode(out)
	}
	return nil
}

func (c *Client) put(path string, in, out interface{}) error {
	return c.send("PUT", path, in, out)
}

func (c *Client) post(path string, in, out interface{}) error {
	return c.send("POST", path, in, out)
}

func (c *Client) get(path string, out interface{}) error {
	res, err := http.Get(c.url + path)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		if res.StatusCode == 404 {
			return ErrNotFound
		}
		return fmt.Errorf("controller: unexpected status %d", res.StatusCode)
	}
	return json.NewDecoder(res.Body).Decode(out)
}

func (c *Client) StreamFormations(since *time.Time) (<-chan *ct.ExpandedFormation, *error) {
	if since == nil {
		*since = time.Unix(0, 0)
	}
	// TODO: handle TLS
	client, err := rpcplus.DialHTTP("tcp", c.addr)
	if err != nil {
		return nil, &err
	}
	ch := make(chan *ct.ExpandedFormation)
	return ch, &client.StreamGo("Controller.StreamFormations", since, ch).Error
}

func (c *Client) CreateArtifact(artifact *ct.Artifact) error {
	return c.post("/artifacts", artifact, artifact)
}

func (c *Client) CreateRelease(release *ct.Release) error {
	return c.post("/releases", release, release)
}

func (c *Client) CreateApp(app *ct.App) error {
	return c.post("/apps", app, app)
}

func (c *Client) CreateProvider(provider *ct.Provider) error {
	return c.post("/providers", provider, provider)
}

func (c *Client) ProvisionResource(req *ct.ResourceReq) (*ct.Resource, error) {
	if req.ProviderID == "" {
		return nil, errors.New("controller: missing provider id")
	}
	res := &ct.Resource{}
	err := c.post(fmt.Sprintf("/providers/%s/resources", req.ProviderID), req, res)
	return res, err
}

func (c *Client) PutResource(resource *ct.Resource) error {
	if resource.ID == "" || resource.ProviderID == "" {
		return errors.New("controller: missing id and/or provider id")
	}
	return c.put(fmt.Sprintf("/providers/%s/resources/%s", resource.ProviderID, resource.ID), resource, resource)
}

func (c *Client) PutFormation(formation *ct.Formation) error {
	if formation.AppID == "" || formation.ReleaseID == "" {
		return errors.New("controller: missing app id and/or release id")
	}
	return c.put(fmt.Sprintf("/apps/%s/formations/%s", formation.AppID, formation.ReleaseID), formation, formation)
}

func (c *Client) SetAppRelease(appID, releaseID string) error {
	return c.put(fmt.Sprintf("/apps/%s/release", appID), &ct.Release{ID: releaseID}, nil)
}

func (c *Client) GetAppRelease(appID string) (*ct.Release, error) {
	release := &ct.Release{}
	return release, c.get(fmt.Sprintf("/apps/%s/release", appID), release)
}

func (c *Client) CreateRoute(appID string, route *strowger.Route) error {
	return c.post(fmt.Sprintf("/apps/%s/routes", appID), route, route)
}
<|endoftext|>


<commit_before>package client

import (
	"errors"
	"log"

	pb "github.com/c-fs/cfs/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

type Client struct {
	conn *grpc.ClientConn
}

func New(address string) *Client {
	conn, err := grpc.Dial(address)
	if err != nil {
		log.Fatalf("Cannot connect: %v", err)
	}
	return &Client{conn: conn}
}

func (c *Client) Write(
	ctx context.Context, name string, offset int64, data []byte, isAppend bool,
) (int64, error) {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.Write(
		ctx,
		&pb.WriteRequest{Name: name, Offset: offset, Data: data, Append: isAppend},
	)

	if err != nil {
		return 0, err
	}
	return reply.BytesWritten, pbErr2GoErr(reply.Error)
}

func (c *Client) Read(
	ctx context.Context, name string, offset, length int64, checkSum uint32,
) (int64, []byte, uint32, error) {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.Read(
		ctx,
		&pb.ReadRequest{
			Name: name, Offset: offset, Length: length, ExpChecksum: checkSum,
		},
	)

	if err != nil {
		return 0, nil, 0, err
	}
	return reply.BytesRead, reply.Data, reply.Checksum, pbErr2GoErr(reply.Error)
}

func (c *Client) Rename(ctx context.Context, oldName, newName string) error {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.Rename(
		ctx,
		&pb.RenameRequest{Oldname: oldName, Newname: newName},
	)

	if err != nil {
		return err
	}
	return pbErr2GoErr(reply.Error)
}

func (c *Client) Remove(ctx context.Context, name string, all bool) error {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.Remove(ctx, &pb.RemoveRequest{Name: name, All: all})

	if err != nil {
		return err
	}
	return pbErr2GoErr(reply.Error)
}

func (c *Client) ReadDir(ctx context.Context, name string) ([]*pb.FileInfo, error) {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.ReadDir(ctx, &pb.ReadDirRequest{Name: name})

	if err != nil {
		return nil, err
	}
	return reply.FileInfos, pbErr2GoErr(reply.Error)
}

func (c *Client) Mkdir(ctx context.Context, name string, all bool) error {
	pbClient := pb.NewCfsClient(c.conn)
	reply, err := pbClient.Mkdir(ctx, &pb.MkdirRequest{Name: name, All: all})

	if err != nil {
		return err
	}
	return pbErr2GoErr(reply.Error)
}

func (c *Client) Close() {
	c.conn.Close()
}

func pbErr2GoErr(pbErr *pb.Error) error {
	return errors.New(pbErr.String())
}
<commit_msg>changes based on Xiang's comments<commit_after>package client

import (
	"errors"

	pb "github.com/c-fs/cfs/proto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

type Client struct {
	grpcConn   *grpc.ClientConn
	grpcClient pb.CfsClient
}

func New(address string) (*Client, error) {
	conn, err := grpc.Dial(address)
	if err != nil {
		return nil, err
	}
	pbClient := pb.NewCfsClient(conn)
	return &Client{grpcConn: conn, grpcClient: pbClient}, nil
}

func (c *Client) Write(ctx context.Context, name string, offset int64, data []byte, isAppend bool) (int64, error) {
	reply, err := c.grpcClient.Write(
		ctx,
		&pb.WriteRequest{Name: name, Offset: offset, Data: data, Append: isAppend},
	)

	if err != nil {
		return 0, err
	}
	return reply.BytesWritten, parseErr(reply.Error)
}

func (c *Client) Read(ctx context.Context, name string, offset, length int64, checkSum uint32,
) (int64, []byte, uint32, error) {
	reply, err := c.grpcClient.Read(
		ctx,
		&pb.ReadRequest{
			Name: name, Offset: offset, Length: length, ExpChecksum: checkSum,
		},
	)

	if err != nil {
		return 0, nil, 0, err
	}
	return reply.BytesRead, reply.Data, reply.Checksum, parseErr(reply.Error)
}

func (c *Client) Rename(ctx context.Context, oldName, newName string) error {
	reply, err := c.grpcClient.Rename(
		ctx,
		&pb.RenameRequest{Oldname: oldName, Newname: newName},
	)

	if err != nil {
		return err
	}
	return parseErr(reply.Error)
}

func (c *Client) Remove(ctx context.Context, name string, all bool) error {
	reply, err := c.grpcClient.Remove(ctx, &pb.RemoveRequest{Name: name, All: all})

	if err != nil {
		return err
	}
	return parseErr(reply.Error)
}

func (c *Client) ReadDir(ctx context.Context, name string) ([]*pb.FileInfo, error) {
	reply, err := c.grpcClient.ReadDir(ctx, &pb.ReadDirRequest{Name: name})

	if err != nil {
		return nil, err
	}
	return reply.FileInfos, parseErr(reply.Error)
}

func (c *Client) Mkdir(ctx context.Context, name string, all bool) error {
	reply, err := c.grpcClient.Mkdir(ctx, &pb.MkdirRequest{Name: name, All: all})

	if err != nil {
		return err
	}
	return parseErr(reply.Error)
}

func (c *Client) Close() {
	c.grpcConn.Close()
}

func parseErr(pbErr *pb.Error) error {
	return errors.New(pbErr.String())
}
<|endoftext|>


<commit_before>package client

import (
	"io"
	"net/http"
	"time"
)

// Client - Minio client interface
type Client interface {
	Get(bucket, object string) (body io.ReadCloser, size int64, err error)
	GetPartial(bucket, key string, offset, length int64) (body io.ReadCloser, size int64, err error)
	Put(bucket, object string, size int64, body io.ReadCloser) error
	Stat(bucket, object string) (size int64, date time.Time, err error)
	PutBucket(bucket string) error
	ListBuckets() ([]*Bucket, error)
	ListObjects(bucket string, startAt, prefix, delimiter string, maxKeys int) (items []*Item, prefixes []*Prefix, err error)
}

// Bucket - carries s3 bucket reply header
type Bucket struct {
	Name         string
	CreationDate XMLTime // 2006-02-03T16:45:09.000Z
}

// Item - object item list
type Item struct {
	Key          string
	LastModified XMLTime
	Size         int64
}

// Prefix - common prefix
type Prefix struct {
	Prefix string
}

// Meta holds Amazon S3 client credentials and flags.
type Meta struct {
	*Auth                       // AWS auth credentials
	Transport http.RoundTripper // or nil for the default behavior
}

// Auth - see http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
type Auth struct {
	AccessKeyID     string
	SecretAccessKey string

	// Used for SSL transport layer
	CertPEM string
	KeyPEM  string
}

// TLSConfig - TLS cert and key configuration
type TLSConfig struct {
	CertPEMBlock []byte
	KeyPEMBlock  []byte
}

const (
	Maxkeys = 1000
)
<commit_msg>Comment for Maxkeys<commit_after>package client

import (
	"io"
	"net/http"
	"time"
)

// Client - Minio client interface
type Client interface {
	Get(bucket, object string) (body io.ReadCloser, size int64, err error)
	GetPartial(bucket, key string, offset, length int64) (body io.ReadCloser, size int64, err error)
	Put(bucket, object string, size int64, body io.ReadCloser) error
	Stat(bucket, object string) (size int64, date time.Time, err error)
	PutBucket(bucket string) error
	ListBuckets() ([]*Bucket, error)
	ListObjects(bucket string, startAt, prefix, delimiter string, maxKeys int) (items []*Item, prefixes []*Prefix, err error)
}

// Bucket - carries s3 bucket reply header
type Bucket struct {
	Name         string
	CreationDate XMLTime // 2006-02-03T16:45:09.000Z
}

// Item - object item list
type Item struct {
	Key          string
	LastModified XMLTime
	Size         int64
}

// Prefix - common prefix
type Prefix struct {
	Prefix string
}

// Meta holds Amazon S3 client credentials and flags.
type Meta struct {
	*Auth                       // AWS auth credentials
	Transport http.RoundTripper // or nil for the default behavior
}

// Auth - see http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
type Auth struct {
	AccessKeyID     string
	SecretAccessKey string

	// Used for SSL transport layer
	CertPEM string
	KeyPEM  string
}

// TLSConfig - TLS cert and key configuration
type TLSConfig struct {
	CertPEMBlock []byte
	KeyPEMBlock  []byte
}

// Maxkeys listed per ListObjects()
const (
	Maxkeys = 1000
)
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	fqdn "github.com/ShowMax/go-fqdn"
	"github.com/justinas/alice"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/vjeantet/bitfan/core/config"
)

var (
	metrics     Metrics
	myScheduler *scheduler
	myStore     *memory

	availableProcessorsFactory map[string]ProcessorFactory = map[string]ProcessorFactory{}
	dataLocation               string                      = "data"

	pipelines map[int]*Pipeline = map[int]*Pipeline{}
)

type FnMux func(sm *http.ServeMux)

func init() {
	metrics = &MetricsVoid{}
	myScheduler = newScheduler()
	myScheduler.Start()
	//Init Store
	myStore = NewMemory(dataLocation)
}

// RegisterProcessor is called by the processor loader when the program starts
// each processor give its name and factory func()
func RegisterProcessor(name string, procFact ProcessorFactory) {
	Log().Debugf("%s processor registered", name)
	availableProcessorsFactory[name] = procFact
}

func SetMetrics(s Metrics) {
	metrics = s
}

func SetDataLocation(location string) error {
	dataLocation = location
	fileInfo, err := os.Stat(dataLocation)
	if err != nil {
		err = os.MkdirAll(dataLocation, os.ModePerm)
		if err != nil {
			Log().Errorf("%s - %s", dataLocation, err)
		} else {
			Log().Debugf("created folder %s", dataLocation)
		}
	} else {
		if !fileInfo.IsDir() {
			Log().Errorf("data path %s is not a directory", dataLocation)
		}
	}
	Log().Debugf("data location : %s", location)
	return err
}

// DataLocation returns the bitfan's data filepath
func DataLocation() string {
	return dataLocation
}

func WebHookServer() FnMux {
	whPrefixURL = "/"
	return func(sm *http.ServeMux) {
		commonHandlers := alice.New(loggingHandler, recoverHandler)
		sm.Handle(whPrefixURL, commonHandlers.ThenFunc(routerHandler))
		Log().Debugf("serving %s to webHooks", whPrefixURL)
	}
}

func ApiServer(s http.Handler) FnMux {
	return func(sm *http.ServeMux) {
		sm.Handle("/api/v1/", s)
		Log().Debugf("serving /api/v1/ to api")
	}
}

func PrometheusServer(path string) FnMux {
	SetMetrics(NewPrometheus())
	return func(sm *http.ServeMux) {
		sm.Handle(path, prometheus.Handler())
		Log().Debugf("serving %s to prometheus", path)
	}
}

func ListenAndServe(addr string, hs ...FnMux) {
	httpServerMux := http.NewServeMux()
	for _, h := range hs {
		h(httpServerMux)
	}
	go http.ListenAndServe(addr, httpServerMux)

	addrSpit := strings.Split(addr, ":")
	if addrSpit[0] == "0.0.0.0" {
		addrSpit[0] = fqdn.Get()
	}

	baseURL = fmt.Sprintf("http://%s:%s", addrSpit[0], addrSpit[1])

	Log().Infof("Ready to serve on %s", baseURL)
}

// StartPipeline load all agents form a configPipeline and returns pipeline's ID
func StartPipeline(configPipeline *config.Pipeline, configAgents []config.Agent) (int, error) {
	p, err := newPipeline(configPipeline, configAgents)
	if err != nil {
		return 0, err
	}
	pipelines[p.ID] = p

	err = p.start()

	return p.ID, err
}

func StopPipeline(ID int) error {
	var err error
	if p, ok := pipelines[ID]; ok {
		err = p.stop()
	} else {
		err = fmt.Errorf("Pipeline %d not found", ID)
	}

	if err != nil {
		return err
	}

	delete(pipelines, ID)
	return nil
}

// Stop each pipeline
func Stop() error {
	var IDS = []int{}
	for ID := range pipelines {
		IDS = append(IDS, ID)
	}
	for _, ID := range IDS {
		err := StopPipeline(ID)
		if err != nil {
			Log().Error(err)
		}
	}

	myStore.close()

	return nil
}

func Pipelines() map[int]*Pipeline {
	return pipelines
}
<commit_msg>core : fix a race condition<commit_after>package core

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	"golang.org/x/sync/syncmap"

	fqdn "github.com/ShowMax/go-fqdn"
	"github.com/justinas/alice"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/vjeantet/bitfan/core/config"
)

var (
	metrics     Metrics
	myScheduler *scheduler
	myStore     *memory

	availableProcessorsFactory map[string]ProcessorFactory = map[string]ProcessorFactory{}
	dataLocation               string                      = "data"

	pipelines syncmap.Map = syncmap.Map{}
)

type FnMux func(sm *http.ServeMux)

func init() {
	metrics = &MetricsVoid{}
	myScheduler = newScheduler()
	myScheduler.Start()
	//Init Store
	myStore = NewMemory(dataLocation)
}

// RegisterProcessor is called by the processor loader when the program starts
// each processor give its name and factory func()
func RegisterProcessor(name string, procFact ProcessorFactory) {
	Log().Debugf("%s processor registered", name)
	availableProcessorsFactory[name] = procFact
}

func SetMetrics(s Metrics) {
	metrics = s
}

func SetDataLocation(location string) error {
	dataLocation = location
	fileInfo, err := os.Stat(dataLocation)
	if err != nil {
		err = os.MkdirAll(dataLocation, os.ModePerm)
		if err != nil {
			Log().Errorf("%s - %s", dataLocation, err)
		} else {
			Log().Debugf("created folder %s", dataLocation)
		}
	} else {
		if !fileInfo.IsDir() {
			Log().Errorf("data path %s is not a directory", dataLocation)
		}
	}
	Log().Debugf("data location : %s", location)
	return err
}

// DataLocation returns the bitfan's data filepath
func DataLocation() string {
	return dataLocation
}

func WebHookServer() FnMux {
	whPrefixURL = "/"
	return func(sm *http.ServeMux) {
		commonHandlers := alice.New(loggingHandler, recoverHandler)
		sm.Handle(whPrefixURL, commonHandlers.ThenFunc(routerHandler))
		Log().Debugf("serving %s to webHooks", whPrefixURL)
	}
}

func ApiServer(s http.Handler) FnMux {
	return func(sm *http.ServeMux) {
		sm.Handle("/api/v1/", s)
		Log().Debugf("serving /api/v1/ to api")
	}
}

func PrometheusServer(path string) FnMux {
	SetMetrics(NewPrometheus())
	return func(sm *http.ServeMux) {
		sm.Handle(path, prometheus.Handler())
		Log().Debugf("serving %s to prometheus", path)
	}
}

func ListenAndServe(addr string, hs ...FnMux) {
	httpServerMux := http.NewServeMux()
	for _, h := range hs {
		h(httpServerMux)
	}
	go http.ListenAndServe(addr, httpServerMux)

	addrSpit := strings.Split(addr, ":")
	if addrSpit[0] == "0.0.0.0" {
		addrSpit[0] = fqdn.Get()
	}

	baseURL = fmt.Sprintf("http://%s:%s", addrSpit[0], addrSpit[1])

	Log().Infof("Ready to serve on %s", baseURL)
}

// StartPipeline load all agents form a configPipeline and returns pipeline's ID
func StartPipeline(configPipeline *config.Pipeline, configAgents []config.Agent) (int, error) {
	p, err := newPipeline(configPipeline, configAgents)
	if err != nil {
		return 0, err
	}
	pipelines.Store(p.ID, p)

	err = p.start()

	return p.ID, err
}

func StopPipeline(ID int) error {
	var err error
	if p, ok := pipelines.Load(ID); ok {
		err = p.(*Pipeline).stop()
	} else {
		err = fmt.Errorf("Pipeline %d not found", ID)
	}

	if err != nil {
		return err
	}

	pipelines.Delete(ID)
	return nil
}

// Stop each pipeline
func Stop() error {
	var IDS = []int{}
	pipelines.Range(func(key, value interface{}) bool {
		IDS = append(IDS, key.(int))
		return true
	})

	for _, ID := range IDS {
		err := StopPipeline(ID)
		if err != nil {
			Log().Error(err)
		}
	}

	myStore.close()

	return nil
}

func Pipelines() map[int]*Pipeline {
	pps := map[int]*Pipeline{}
	pipelines.Range(func(key, value interface{}) bool {
		pps[key.(int)] = value.(*Pipeline)
		return true
	})
	return pps
}
<|endoftext|>


<commit_before>// +build !windows, !appengine

package maxminddb

import (
	"syscall"
)

func mmap(fd int, length int) (data []byte, err error) {
	return syscall.Mmap(fd, 0, length, syscall.PROT_READ, syscall.MAP_SHARED)
}

func munmap(b []byte) (err error) {
	return syscall.Munmap(b)
}
<commit_msg>Fix for compilation issue on Windows<commit_after>// +build !windows,!appengine

package maxminddb

import (
	"syscall"
)

func mmap(fd int, length int) (data []byte, err error) {
	return syscall.Mmap(fd, 0, length, syscall.PROT_READ, syscall.MAP_SHARED)
}

func munmap(b []byte) (err error) {
	return syscall.Munmap(b)
}
<|endoftext|>


<commit_before>package gitmediaclient

import (
	".."
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

func Put(filename string) error {
	oid := filepath.Base(filename)
	stat, err := os.Stat(filename)
	if err != nil {
		return err
	}

	file, err := os.Open(filename)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("PUT", oid)
	if err != nil {
		return err
	}

	req.Body = file
	req.ContentLength = stat.Size()

	res, err := doRequest(req, creds)
	if err != nil {
		return err
	}

	fmt.Printf("Sending %s from %s: %d\n", oid, filename, res.StatusCode)
	return nil
}

func Get(filename string) (io.ReadCloser, error) {
	oid := filepath.Base(filename)
	if stat, err := os.Stat(filename); err != nil || stat == nil {
		req, creds, err := clientRequest("GET", oid)
		if err != nil {
			return nil, err
		}

		req.Header.Set("Accept", "application/vnd.git-media")
		res, err := doRequest(req, creds)

		if err != nil {
			return nil, err
		}

		return res.Body, nil
	}

	return os.Open(filename)
}

func doRequest(req *http.Request, creds Creds) (*http.Response, error) {
	res, err := http.DefaultClient.Do(req)

	if err == nil {
		if res.StatusCode > 299 {
			execCreds(creds, "reject")

			apierr := &Error{}
			dec := json.NewDecoder(res.Body)
			if err := dec.Decode(apierr); err != nil {
				return res, err
			}

			return res, apierr
		}
	} else {
		execCreds(creds, "approve")
	}

	return res, err
}

func clientRequest(method, oid string) (*http.Request, Creds, error) {
	u := ObjectUrl(oid)
	req, err := http.NewRequest(method, u.String(), nil)
	if err == nil {
		creds, err := credentials(u)
		if err != nil {
			return req, nil, err
		}

		token := fmt.Sprintf("%s:%s", creds["username"], creds["password"])
		auth := "Basic " + base64.URLEncoding.EncodeToString([]byte(token))
		req.Header.Set("Authorization", auth)
		return req, creds, nil
	}

	return req, nil, err
}

func ObjectUrl(oid string) *url.URL {
	c := gitmedia.Config()
	u, _ := url.Parse(c.Endpoint)
	u.Path = filepath.Join(u.Path, "/objects/"+oid)
	return u
}

type Error struct {
	Message   string `json:"message"`
	RequestId string `json:"request_id,omitempty"`
}

func (e *Error) Error() string {
	return e.Message
}
<commit_msg>When the client gets media and the media file doesn't exist, ensure it is created<commit_after>package gitmediaclient

import (
	".."
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
)

func Put(filename string) error {
	oid := filepath.Base(filename)
	stat, err := os.Stat(filename)
	if err != nil {
		return err
	}

	file, err := os.Open(filename)
	if err != nil {
		return err
	}

	req, creds, err := clientRequest("PUT", oid)
	if err != nil {
		return err
	}

	req.Body = file
	req.ContentLength = stat.Size()

	res, err := doRequest(req, creds)
	if err != nil {
		return err
	}

	fmt.Printf("Sending %s from %s: %d\n", oid, filename, res.StatusCode)
	return nil
}

func Get(filename string) (io.ReadCloser, error) {
	oid := filepath.Base(filename)
	if stat, err := os.Stat(filename); err != nil || stat == nil {
		req, creds, err := clientRequest("GET", oid)
		if err != nil {
			return nil, err
		}

		req.Header.Set("Accept", "application/vnd.git-media")
		res, err := doRequest(req, creds)
		defer res.Body.Close()

		if err != nil {
			return nil, err
		}

		mediafile, err := os.Create(filename)
		defer mediafile.Close()

		if err != nil {
			return nil, err
		}

		_, err = io.Copy(mediafile, res.Body)
		if err != nil {
			return nil, err
		}
	}

	return os.Open(filename)
}

func doRequest(req *http.Request, creds Creds) (*http.Response, error) {
	res, err := http.DefaultClient.Do(req)

	if err == nil {
		if res.StatusCode > 299 {
			execCreds(creds, "reject")

			apierr := &Error{}
			dec := json.NewDecoder(res.Body)
			if err := dec.Decode(apierr); err != nil {
				return res, err
			}

			return res, apierr
		}
	} else {
		execCreds(creds, "approve")
	}

	return res, err
}

func clientRequest(method, oid string) (*http.Request, Creds, error) {
	u := ObjectUrl(oid)
	req, err := http.NewRequest(method, u.String(), nil)
	if err == nil {
		creds, err := credentials(u)
		if err != nil {
			return req, nil, err
		}

		token := fmt.Sprintf("%s:%s", creds["username"], creds["password"])
		auth := "Basic " + base64.URLEncoding.EncodeToString([]byte(token))
		req.Header.Set("Authorization", auth)
		return req, creds, nil
	}

	return req, nil, err
}

func ObjectUrl(oid string) *url.URL {
	c := gitmedia.Config()
	u, _ := url.Parse(c.Endpoint)
	u.Path = filepath.Join(u.Path, "/objects/"+oid)
	return u
}

type Error struct {
	Message   string `json:"message"`
	RequestId string `json:"request_id,omitempty"`
}

func (e *Error) Error() string {
	return e.Message
}
<|endoftext|>


<commit_before>package client

import (
	"bufio"
	"fmt"
	"net"
	"nntpd/config"
	"strings"
	"io"
	"nntpd/rawio"
)

const EOF = "\r\n"

type Conn struct {
	LoggedIn   bool
	Cmds       int

	conn net.Conn
	r    *bufio.Reader
	w    *bufio.Writer
}

func (c *Conn) Send(cmd string) error {
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) >> %s", c.RemoteAddr(), cmd))
	}
	_, e := c.w.WriteString(cmd + EOF)
	if e != nil {
		return e
	}
	return c.w.Flush()
}

func (c *Conn) ReadLine() ([]string, error) {
	s, e := c.r.ReadString('\n')
	if e != nil {
		return nil, e
	}
	s = s[:len(s)-2] // Strip \r\n
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) << %s", c.RemoteAddr(), s))
	}
	tok := strings.Split(s, " ")
	return tok, nil
}

func (c *Conn) RemoteAddr() string {
	return c.conn.RemoteAddr().String()
}

func (c *Conn) LocalAddr() string {
	return c.conn.LocalAddr().String()
}

// Get DotReader
func (c *Conn) GetReader() io.Reader {
	return rawio.New(c.r)
}

func (c *Conn) GetWriter() io.Writer {
	return c.w
}

func (c *Conn) Close() error {
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) CLOSED", c.RemoteAddr()))
	}
	return c.conn.Close()
}

func New(conn net.Conn) *Conn {
	return &Conn{
		conn:      conn,
		r:         bufio.NewReader(conn),
		w:         bufio.NewWriter(conn),
	}
}
<commit_msg>Bugfix. Remove ref to nntpd<commit_after>package client

import (
	"bufio"
	"fmt"
	"net"
	"spool-mock/config"
	"strings"
	"io"
	"spool-mock/dotreader"
)

const EOF = "\r\n"

type Conn struct {
	LoggedIn   bool
	Cmds       int

	conn net.Conn
	r    *bufio.Reader
	w    *bufio.Writer
}

func (c *Conn) Send(cmd string) error {
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) >> %s", c.RemoteAddr(), cmd))
	}
	_, e := c.w.WriteString(cmd + EOF)
	if e != nil {
		return e
	}
	return c.w.Flush()
}

func (c *Conn) ReadLine() ([]string, error) {
	s, e := c.r.ReadString('\n')
	if e != nil {
		return nil, e
	}
	s = s[:len(s)-2] // Strip \r\n
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) << %s", c.RemoteAddr(), s))
	}
	tok := strings.Split(s, " ")
	return tok, nil
}

func (c *Conn) RemoteAddr() string {
	return c.conn.RemoteAddr().String()
}

func (c *Conn) LocalAddr() string {
	return c.conn.LocalAddr().String()
}

// Get DotReader
func (c *Conn) GetReader() io.Reader {
	return dotreader.New(c.r)
}

func (c *Conn) GetWriter() io.Writer {
	return c.w
}

func (c *Conn) Close() error {
	if config.Verbose {
		fmt.Println(fmt.Sprintf("C(%s) CLOSED", c.RemoteAddr()))
	}
	return c.conn.Close()
}

func New(conn net.Conn) *Conn {
	return &Conn{
		conn:      conn,
		r:         bufio.NewReader(conn),
		w:         bufio.NewWriter(conn),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	kingpin "gopkg.in/alecthomas/kingpin.v2"

	"github.com/ShowMax/go-fqdn"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/prometheus/common/promlog"
	"github.com/prometheus/common/promlog/flag"
	"github.com/robustperception/pushprox/util"
)

var (
	myFqdn   = kingpin.Flag("fqdn", "FQDN to register with").Default(fqdn.Get()).String()
	proxyURL = kingpin.Flag("proxy-url", "Push proxy to talk to.").Required().String()
)

type Coordinator struct {
	logger log.Logger
}

func (c *Coordinator) doScrape(request *http.Request, client *http.Client) {
	logger := log.With(c.logger, "scrape_id", request.Header.Get("id"))
	ctx, _ := context.WithTimeout(request.Context(), util.GetScrapeTimeout(request.Header))
	request = request.WithContext(ctx)
	// We cannot handle http requests at the proxy, as we would only
	// see a CONNECT, so use a URL parameter to trigger it.
	params := request.URL.Query()
	if params.Get("_scheme") == "https" {
		request.URL.Scheme = "https"
		params.Del("_scheme")
		request.URL.RawQuery = params.Encode()
	}

	scrapeResp, err := client.Do(request)
	if err != nil {
		msg := fmt.Sprintf("Failed to scrape %s: %s", request.URL.String(), err)
		level.Warn(logger).Log("msg", "Failed to scrape", "Request URL", request.URL.String(), "err", err)
		resp := &http.Response{
			StatusCode: 500,
			Header:     http.Header{},
			Body:       ioutil.NopCloser(strings.NewReader(msg)),
		}
		err = c.doPush(resp, request, client)
		if err != nil {
			level.Warn(logger).Log("msg", "Failed to push failed scrape response:", "err", err)
			return
		}
		level.Info(logger).Log("msg", "Pushed failed scrape response")
		return
	}
	level.Info(logger).Log("msg", "Retrieved scrape response")
	err = c.doPush(scrapeResp, request, client)
	if err != nil {
		level.Warn(logger).Log("msg", "Failed to push scrape response:", "err", err)
		return
	}
	level.Info(logger).Log("msg", "Pushed scrape result")
}

// Report the result of the scrape back up to the proxy.
func (c *Coordinator) doPush(resp *http.Response, origRequest *http.Request, client *http.Client) error {
	resp.Header.Set("id", origRequest.Header.Get("id")) // Link the request and response
	// Remaining scrape deadline.
	deadline, _ := origRequest.Context().Deadline()
	resp.Header.Set("X-Prometheus-Scrape-Timeout", fmt.Sprintf("%f", float64(time.Until(deadline))/1e9))

	base, err := url.Parse(*proxyURL)
	if err != nil {
		return err
	}
	u, err := url.Parse("/post")
	if err != nil {
		return err
	}
	url := base.ResolveReference(u)

	buf := &bytes.Buffer{}
	resp.Write(buf)
	request := &http.Request{
		Method:        "POST",
		URL:           url,
		Body:          ioutil.NopCloser(buf),
		ContentLength: int64(buf.Len()),
	}
	request = request.WithContext(origRequest.Context())
	_, err = client.Do(request)
	if err != nil {
		return err
	}
	return nil
}

func loop(c Coordinator) {
	client := &http.Client{}
	base, err := url.Parse(*proxyURL)
	if err != nil {
		level.Error(c.logger).Log("msg", "Error parsing url:", "err", err)
		return
	}
	u, err := url.Parse("/poll")
	if err != nil {
		level.Error(c.logger).Log("msg", "Error parsing url:", "err", err)
		return
	}
	url := base.ResolveReference(u)
	resp, err := client.Post(url.String(), "", strings.NewReader(*myFqdn))
	if err != nil {
		level.Error(c.logger).Log("msg", "Error polling:", "err", err)
		time.Sleep(time.Second) // Don't pound the server. TODO: Randomised exponential backoff.
		return
	}
	defer resp.Body.Close()
	request, _ := http.ReadRequest(bufio.NewReader(resp.Body))
	level.Info(c.logger).Log("msg", "Got scrape request", "scrape_id", request.Header.Get("id"), "url", request.URL)

	request.RequestURI = ""

	go c.doScrape(request, client)
}

func main() {
	allowedLevel := promlog.AllowedLevel{}
	flag.AddFlags(kingpin.CommandLine, &allowedLevel)
	kingpin.HelpFlag.Short('h')
	kingpin.Parse()
	logger := promlog.New(allowedLevel)
	coordinator := Coordinator{logger: logger}
	if *proxyURL == "" {
		level.Error(coordinator.logger).Log("msg", "-proxy-url flag must be specified.")
		os.Exit(1)
	}
	level.Info(coordinator.logger).Log("msg", "URL and FQDN info", "proxy_url", *proxyURL, "Using FQDN of", *myFqdn)
	for {
		loop(coordinator)
	}
}
<commit_msg>Fix client push path<commit_after>package main

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	kingpin "gopkg.in/alecthomas/kingpin.v2"

	"github.com/ShowMax/go-fqdn"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/prometheus/common/promlog"
	"github.com/prometheus/common/promlog/flag"
	"github.com/robustperception/pushprox/util"
)

var (
	myFqdn   = kingpin.Flag("fqdn", "FQDN to register with").Default(fqdn.Get()).String()
	proxyURL = kingpin.Flag("proxy-url", "Push proxy to talk to.").Required().String()
)

type Coordinator struct {
	logger log.Logger
}

func (c *Coordinator) doScrape(request *http.Request, client *http.Client) {
	logger := log.With(c.logger, "scrape_id", request.Header.Get("id"))
	ctx, _ := context.WithTimeout(request.Context(), util.GetScrapeTimeout(request.Header))
	request = request.WithContext(ctx)
	// We cannot handle http requests at the proxy, as we would only
	// see a CONNECT, so use a URL parameter to trigger it.
	params := request.URL.Query()
	if params.Get("_scheme") == "https" {
		request.URL.Scheme = "https"
		params.Del("_scheme")
		request.URL.RawQuery = params.Encode()
	}

	scrapeResp, err := client.Do(request)
	if err != nil {
		msg := fmt.Sprintf("Failed to scrape %s: %s", request.URL.String(), err)
		level.Warn(logger).Log("msg", "Failed to scrape", "Request URL", request.URL.String(), "err", err)
		resp := &http.Response{
			StatusCode: 500,
			Header:     http.Header{},
			Body:       ioutil.NopCloser(strings.NewReader(msg)),
		}
		err = c.doPush(resp, request, client)
		if err != nil {
			level.Warn(logger).Log("msg", "Failed to push failed scrape response:", "err", err)
			return
		}
		level.Info(logger).Log("msg", "Pushed failed scrape response")
		return
	}
	level.Info(logger).Log("msg", "Retrieved scrape response")
	err = c.doPush(scrapeResp, request, client)
	if err != nil {
		level.Warn(logger).Log("msg", "Failed to push scrape response:", "err", err)
		return
	}
	level.Info(logger).Log("msg", "Pushed scrape result")
}

// Report the result of the scrape back up to the proxy.
func (c *Coordinator) doPush(resp *http.Response, origRequest *http.Request, client *http.Client) error {
	resp.Header.Set("id", origRequest.Header.Get("id")) // Link the request and response
	// Remaining scrape deadline.
	deadline, _ := origRequest.Context().Deadline()
	resp.Header.Set("X-Prometheus-Scrape-Timeout", fmt.Sprintf("%f", float64(time.Until(deadline))/1e9))

	base, err := url.Parse(*proxyURL)
	if err != nil {
		return err
	}
	u, err := url.Parse("/push")
	if err != nil {
		return err
	}
	url := base.ResolveReference(u)

	buf := &bytes.Buffer{}
	resp.Write(buf)
	request := &http.Request{
		Method:        "POST",
		URL:           url,
		Body:          ioutil.NopCloser(buf),
		ContentLength: int64(buf.Len()),
	}
	request = request.WithContext(origRequest.Context())
	_, err = client.Do(request)
	if err != nil {
		return err
	}
	return nil
}

func loop(c Coordinator) {
	client := &http.Client{}
	base, err := url.Parse(*proxyURL)
	if err != nil {
		level.Error(c.logger).Log("msg", "Error parsing url:", "err", err)
		return
	}
	u, err := url.Parse("/poll")
	if err != nil {
		level.Error(c.logger).Log("msg", "Error parsing url:", "err", err)
		return
	}
	url := base.ResolveReference(u)
	resp, err := client.Post(url.String(), "", strings.NewReader(*myFqdn))
	if err != nil {
		level.Error(c.logger).Log("msg", "Error polling:", "err", err)
		time.Sleep(time.Second) // Don't pound the server. TODO: Randomised exponential backoff.
		return
	}
	defer resp.Body.Close()
	request, _ := http.ReadRequest(bufio.NewReader(resp.Body))
	level.Info(c.logger).Log("msg", "Got scrape request", "scrape_id", request.Header.Get("id"), "url", request.URL)

	request.RequestURI = ""

	go c.doScrape(request, client)
}

func main() {
	allowedLevel := promlog.AllowedLevel{}
	flag.AddFlags(kingpin.CommandLine, &allowedLevel)
	kingpin.HelpFlag.Short('h')
	kingpin.Parse()
	logger := promlog.New(allowedLevel)
	coordinator := Coordinator{logger: logger}
	if *proxyURL == "" {
		level.Error(coordinator.logger).Log("msg", "-proxy-url flag must be specified.")
		os.Exit(1)
	}
	level.Info(coordinator.logger).Log("msg", "URL and FQDN info", "proxy_url", *proxyURL, "Using FQDN of", *myFqdn)
	for {
		loop(coordinator)
	}
}
<|endoftext|>


<commit_before>package libcmdline

import (
	"github.com/codegangsta/cli"
	"github.com/keybase/go/libkb"
	"regexp"
	"strings"
)

type Command interface {
	libkb.Command
	ParseArgv(*cli.Context) error // A command-specific parse-args
	Run() error                   // Actually run the command (finally!)
	RunClient() error             // Run in client mode
}

type CommandLine struct {
	app        *cli.App
	ctx        *cli.Context
	cmd        Command
	name       string // the name of the chosen command
	defaultCmd string
}

func (p CommandLine) GetHome() string {
	return p.GetGString("home")
}
func (p CommandLine) GetServerUri() string {
	return p.GetGString("server")
}
func (p CommandLine) GetConfigFilename() string {
	return p.GetGString("config")
}
func (p CommandLine) GetSessionFilename() string {
	return p.GetGString("session")
}
func (p CommandLine) GetDbFilename() string {
	return p.GetGString("db")
}
func (p CommandLine) GetDebug() (bool, bool) {
	return p.GetBool("debug", true)
}
func (p CommandLine) GetUsername() string {
	return p.GetGString("username")
}
func (p CommandLine) GetUid() *libkb.UID {
	if s := p.GetGString("uid"); len(s) == 0 {
		return nil
	} else if i, e := libkb.UidFromHex(s); e == nil {
		return i
	} else {
		return nil
	}
}
func (p CommandLine) GetPgpFingerprint() *libkb.PgpFingerprint {
	return libkb.PgpFingerprintFromHexNoError(p.GetGString("fingerprint"))
}
func (p CommandLine) GetEmail() string {
	return p.GetGString("email")
}
func (p CommandLine) GetProxy() string {
	return p.GetGString("proxy")
}
func (p CommandLine) GetPlainLogging() (bool, bool) {
	return p.GetBool("plain-logging", true)
}
func (p CommandLine) GetPgpDir() string {
	return p.GetGString("pgpdir")
}
func (p CommandLine) GetApiDump() (bool, bool) {
	return p.GetBool("api-dump", true)
}
func (p CommandLine) GetPinentry() string {
	return p.GetGString("pinentry")
}
func (p CommandLine) GetGString(s string) string {
	return p.ctx.GlobalString(s)
}
func (p CommandLine) GetGInt(s string) int {
	return p.ctx.GlobalInt(s)
}
func (p CommandLine) GetGpg() string {
	return p.GetGString("gpg")
}
func (p CommandLine) GetSecretKeyring() string {
	return p.GetGString("secret-keyring")
}
func (p CommandLine) GetSocketFile() string {
	return p.GetGString("socket-file")
}
func (p CommandLine) GetPerDeviceKID() string {
	return p.GetGString("device-kid")
}
func (p CommandLine) GetDeviceId() string {
	return p.GetGString("device-id")
}
func (p CommandLine) GetGpgOptions() []string {
	var ret []string
	s := p.GetGString("gpg-options")
	if len(s) > 0 {
		ret = regexp.MustCompile(`\s+`).Split(s, -1)
	}
	return ret
}
func (p CommandLine) GetMerkleKeyFingerprints() []string {
	s := p.GetGString("merkle-key-fingerprints")
	if len(s) != 0 {
		return strings.Split(s, ":")
	} else {
		return nil
	}
}
func (p CommandLine) GetUserCacheSize() (int, bool) {
	ret := p.GetGInt("user-cache-size")
	if ret != 0 {
		return ret, true
	} else {
		return 0, false
	}
}
func (p CommandLine) GetProofCacheSize() (int, bool) {
	ret := p.GetGInt("proof-cache-size")
	if ret != 0 {
		return ret, true
	} else {
		return 0, false
	}
}
func (p CommandLine) GetDaemonPort() (ret int, set bool) {
	if ret = p.GetGInt("daemon-port"); ret != 0 {
		set = true
	}
	return
}

func (p CommandLine) GetStandalone() (bool, bool) {
	return p.GetBool("standalone", true)
}

func (p CommandLine) GetLocalRpcDebug() string {
	return p.GetGString("local-rpc-debug")
}

func (p CommandLine) GetBool(s string, glbl bool) (bool, bool) {
	var v bool
	if glbl {
		v = p.ctx.GlobalBool(s)
	} else {
		v = p.ctx.Bool(s)
	}
	return v, v
}

type CmdBaseHelp struct {
	ctx *cli.Context
}

func (c *CmdBaseHelp) GetUsage() libkb.Usage {
	return libkb.Usage{}
}
func (c *CmdBaseHelp) ParseArgv(*cli.Context) error { return nil }

type CmdGeneralHelp struct {
	CmdBaseHelp
}

func (c *CmdBaseHelp) RunClient() error { return c.Run() }

func (c *CmdBaseHelp) Run() error {
	cli.ShowAppHelp(c.ctx)
	return nil
}

type CmdSpecificHelp struct {
	CmdBaseHelp
	name string
}

func (c CmdSpecificHelp) Run() error {
	cli.ShowCommandHelp(c.ctx, c.name)
	return nil
}

func NewCommandLine(addHelp bool) *CommandLine {
	app := cli.NewApp()
	ret := &CommandLine{app: app}
	ret.PopulateApp(addHelp)
	return ret
}

func (cl *CommandLine) PopulateApp(addHelp bool) {
	app := cl.app
	app.Name = "keybase"
	app.Version = libkb.CLIENT_VERSION
	app.Usage = "control keybase either with 1-off commands, " +
		"or start a daemon"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "home, H",
			Usage: "specify an (alternate) home directory",
		},
		cli.StringFlag{
			Name: "server, s",
			Usage: "specify server API " +
				"(default: https://api.keybase.io:443/)",
		},
		cli.StringFlag{
			Name:  "config, c",
			Usage: "specify an (alternate) master config file",
		},
		cli.StringFlag{
			Name:  "session",
			Usage: "specify an alternate session data file",
		},
		cli.StringFlag{
			Name:  "db",
			Usage: "specify an alternate local DB location",
		},
		cli.StringFlag{
			Name:  "api-uri-path-prefix",
			Usage: "specify an alternate API URI path prefix",
		},
		cli.StringFlag{
			Name:  "username, u",
			Usage: "specify Keybase username of the current user",
		},
		cli.StringFlag{
			Name:  "uid, i",
			Usage: "specify Keybase UID for current user",
		},
		cli.StringFlag{
			Name:  "pinentry",
			Usage: "specify a path to find a pinentry program",
		},
		cli.StringFlag{
			Name:  "secret-keyring",
			Usage: "location of the Keybase secret-keyring (P3SKB-encoded)",
		},
		cli.StringFlag{
			Name:  "socket-file",
			Usage: "location of the keybased socket-file",
		},
		cli.StringFlag{
			Name: "proxy",
			Usage: "specify an HTTP(s) proxy to ship all Web " +
				"requests over",
		},
		cli.BoolFlag{
			Name:  "debug, d",
			Usage: "enable debugging mode",
		},
		cli.StringFlag{
			Name:  "email",
			Usage: "specify your email address for login/signup purposes",
		},
		cli.BoolFlag{
			Name:  "plain-logging, L",
			Usage: "plain logging mode (no colors)",
		},
		cli.StringFlag{
			Name:  "pgpdir, gpgdir",
			Usage: "specify a PGP directory (default is ~/.gnupg)",
		},
		cli.BoolFlag{
			Name:  "api-dump",
			Usage: "dump API call internals",
		},
		cli.StringFlag{
			Name:  "merkle-key-fingerprints",
			Usage: "Set of admissable Merkle Tree fingerprints (colon-separated)",
		},
		cli.IntFlag{
			Name:  "user-cache-size",
			Usage: "number of User entries to cache",
		},
		cli.IntFlag{
			Name:  "proof-cache-size",
			Usage: "number of proof entries to cache",
		},
		cli.StringFlag{
			Name:  "gpg",
			Usage: "Path to GPG client (optional for exporting keys)",
		},
		cli.StringFlag{
			Name:  "gpg-options",
			Usage: "Options to use when calling GPG",
		},
		cli.IntFlag{
			Name:  "daemon-port",
			Usage: "specify a daemon port on 127.0.0.1",
		},
		cli.BoolFlag{
			Name:  "standalone",
			Usage: "use the client without any daemon support",
		},
		cli.StringFlag{
			Name:  "local-rpc-debug",
			Usage: "use to debug local RPC",
		},
		cli.StringFlag{
			Name:  "device-kid",
			Usage: "specify per-device KID",
		},
		cli.StringFlag{
			Name:  "device-id",
			Usage: "specify the device ID",
		},
	}

	// Finally, add help if we asked for it
	if addHelp {
		app.Action = func(c *cli.Context) {
			cl.cmd = &CmdGeneralHelp{CmdBaseHelp{c}}
			cl.ctx = c
			cl.name = "help"
		}
	}
}

func (cl *CommandLine) AddCommands(cmds []cli.Command) {
	cl.app.Commands = cmds
}

func (cl *CommandLine) SetDefaultCommand(name string, cmd Command) {
	cl.defaultCmd = name
	cl.app.Action = func(c *cli.Context) {
		cl.cmd = cmd
		cl.ctx = c
		cl.name = name
	}
}

// Called back from inside our subcommands, when they're picked...
func (p *CommandLine) ChooseCommand(cmd Command, name string, ctx *cli.Context) {
	p.cmd = cmd
	p.name = name
	p.ctx = ctx
}

func (p *CommandLine) Parse(args []string) (cmd Command, err error) {
	// This is suboptimal, but the default help action when there are
	// no args crashes.
	// (cli sets HelpPrinter to nil when p.app.Run(...) returns.)
	if len(args) == 1 && p.defaultCmd == "help" {
		args = append(args, p.defaultCmd)
	}

	// Actually pick a command
	err = p.app.Run(args)

	// Should not be populated
	cmd = p.cmd

	if err != nil || cmd == nil {
		return
	}

	// cli.HelpPrinter is nil here...anything that needs it will panic.

	// If we failed to parse arguments properly, switch to the help command
	if err = p.cmd.ParseArgv(p.ctx); err != nil {
		libkb.G.Log.Error("In '%s': %s", p.name, err.Error())
		cmd = &CmdSpecificHelp{CmdBaseHelp{p.ctx}, p.name}
	}

	return
}
<commit_msg>added a hack to create a cli.HelpPrinter if it is nil. Fixes crash when command doesn't exist.<commit_after>package libcmdline

import (
	"github.com/codegangsta/cli"
	"github.com/keybase/go/libkb"
	"regexp"
	"strings"
	"text/tabwriter"
	"text/template"
)

type Command interface {
	libkb.Command
	ParseArgv(*cli.Context) error // A command-specific parse-args
	Run() error                   // Actually run the command (finally!)
	RunClient() error             // Run in client mode
}

type CommandLine struct {
	app        *cli.App
	ctx        *cli.Context
	cmd        Command
	name       string // the name of the chosen command
	defaultCmd string
}

func (p CommandLine) GetHome() string {
	return p.GetGString("home")
}
func (p CommandLine) GetServerUri() string {
	return p.GetGString("server")
}
func (p CommandLine) GetConfigFilename() string {
	return p.GetGString("config")
}
func (p CommandLine) GetSessionFilename() string {
	return p.GetGString("session")
}
func (p CommandLine) GetDbFilename() string {
	return p.GetGString("db")
}
func (p CommandLine) GetDebug() (bool, bool) {
	return p.GetBool("debug", true)
}
func (p CommandLine) GetUsername() string {
	return p.GetGString("username")
}
func (p CommandLine) GetUid() *libkb.UID {
	if s := p.GetGString("uid"); len(s) == 0 {
		return nil
	} else if i, e := libkb.UidFromHex(s); e == nil {
		return i
	} else {
		return nil
	}
}
func (p CommandLine) GetPgpFingerprint() *libkb.PgpFingerprint {
	return libkb.PgpFingerprintFromHexNoError(p.GetGString("fingerprint"))
}
func (p CommandLine) GetEmail() string {
	return p.GetGString("email")
}
func (p CommandLine) GetProxy() string {
	return p.GetGString("proxy")
}
func (p CommandLine) GetPlainLogging() (bool, bool) {
	return p.GetBool("plain-logging", true)
}
func (p CommandLine) GetPgpDir() string {
	return p.GetGString("pgpdir")
}
func (p CommandLine) GetApiDump() (bool, bool) {
	return p.GetBool("api-dump", true)
}
func (p CommandLine) GetPinentry() string {
	return p.GetGString("pinentry")
}
func (p CommandLine) GetGString(s string) string {
	return p.ctx.GlobalString(s)
}
func (p CommandLine) GetGInt(s string) int {
	return p.ctx.GlobalInt(s)
}
func (p CommandLine) GetGpg() string {
	return p.GetGString("gpg")
}
func (p CommandLine) GetSecretKeyring() string {
	return p.GetGString("secret-keyring")
}
func (p CommandLine) GetSocketFile() string {
	return p.GetGString("socket-file")
}
func (p CommandLine) GetPerDeviceKID() string {
	return p.GetGString("device-kid")
}
func (p CommandLine) GetDeviceId() string {
	return p.GetGString("device-id")
}
func (p CommandLine) GetGpgOptions() []string {
	var ret []string
	s := p.GetGString("gpg-options")
	if len(s) > 0 {
		ret = regexp.MustCompile(`\s+`).Split(s, -1)
	}
	return ret
}
func (p CommandLine) GetMerkleKeyFingerprints() []string {
	s := p.GetGString("merkle-key-fingerprints")
	if len(s) != 0 {
		return strings.Split(s, ":")
	} else {
		return nil
	}
}
func (p CommandLine) GetUserCacheSize() (int, bool) {
	ret := p.GetGInt("user-cache-size")
	if ret != 0 {
		return ret, true
	} else {
		return 0, false
	}
}
func (p CommandLine) GetProofCacheSize() (int, bool) {
	ret := p.GetGInt("proof-cache-size")
	if ret != 0 {
		return ret, true
	} else {
		return 0, false
	}
}
func (p CommandLine) GetDaemonPort() (ret int, set bool) {
	if ret = p.GetGInt("daemon-port"); ret != 0 {
		set = true
	}
	return
}

func (p CommandLine) GetStandalone() (bool, bool) {
	return p.GetBool("standalone", true)
}

func (p CommandLine) GetLocalRpcDebug() string {
	return p.GetGString("local-rpc-debug")
}

func (p CommandLine) GetBool(s string, glbl bool) (bool, bool) {
	var v bool
	if glbl {
		v = p.ctx.GlobalBool(s)
	} else {
		v = p.ctx.Bool(s)
	}
	return v, v
}

type CmdBaseHelp struct {
	ctx *cli.Context
}

func (c *CmdBaseHelp) GetUsage() libkb.Usage {
	return libkb.Usage{}
}
func (c *CmdBaseHelp) ParseArgv(*cli.Context) error { return nil }

type CmdGeneralHelp struct {
	CmdBaseHelp
}

func (c *CmdBaseHelp) RunClient() error { return c.Run() }

// This is a hack to work around codegangsta/cli destroying the HelpPrinter
// object.
func (c *CmdBaseHelp) MakeHelpPrinter() {
	if cli.HelpPrinter != nil {
		return
	}

	cli.HelpPrinter = func(templ string, data interface{}) {
		w := tabwriter.NewWriter(c.ctx.App.Writer, 0, 8, 1, '\t', 0)
		t := template.Must(template.New("help").Parse(templ))
		err := t.Execute(w, data)
		if err != nil {
			panic(err)
		}
		w.Flush()
	}
}

func (c *CmdBaseHelp) Run() error {
	c.MakeHelpPrinter()
	cli.ShowAppHelp(c.ctx)
	return nil
}

type CmdSpecificHelp struct {
	CmdBaseHelp
	name string
}

func (c CmdSpecificHelp) Run() error {
	cli.ShowCommandHelp(c.ctx, c.name)
	return nil
}

func NewCommandLine(addHelp bool) *CommandLine {
	app := cli.NewApp()
	ret := &CommandLine{app: app}
	ret.PopulateApp(addHelp)
	return ret
}

func (cl *CommandLine) PopulateApp(addHelp bool) {
	app := cl.app
	app.Name = "keybase"
	app.Version = libkb.CLIENT_VERSION
	app.Usage = "control keybase either with 1-off commands, " +
		"or start a daemon"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "home, H",
			Usage: "specify an (alternate) home directory",
		},
		cli.StringFlag{
			Name: "server, s",
			Usage: "specify server API " +
				"(default: https://api.keybase.io:443/)",
		},
		cli.StringFlag{
			Name:  "config, c",
			Usage: "specify an (alternate) master config file",
		},
		cli.StringFlag{
			Name:  "session",
			Usage: "specify an alternate session data file",
		},
		cli.StringFlag{
			Name:  "db",
			Usage: "specify an alternate local DB location",
		},
		cli.StringFlag{
			Name:  "api-uri-path-prefix",
			Usage: "specify an alternate API URI path prefix",
		},
		cli.StringFlag{
			Name:  "username, u",
			Usage: "specify Keybase username of the current user",
		},
		cli.StringFlag{
			Name:  "uid, i",
			Usage: "specify Keybase UID for current user",
		},
		cli.StringFlag{
			Name:  "pinentry",
			Usage: "specify a path to find a pinentry program",
		},
		cli.StringFlag{
			Name:  "secret-keyring",
			Usage: "location of the Keybase secret-keyring (P3SKB-encoded)",
		},
		cli.StringFlag{
			Name:  "socket-file",
			Usage: "location of the keybased socket-file",
		},
		cli.StringFlag{
			Name: "proxy",
			Usage: "specify an HTTP(s) proxy to ship all Web " +
				"requests over",
		},
		cli.BoolFlag{
			Name:  "debug, d",
			Usage: "enable debugging mode",
		},
		cli.StringFlag{
			Name:  "email",
			Usage: "specify your email address for login/signup purposes",
		},
		cli.BoolFlag{
			Name:  "plain-logging, L",
			Usage: "plain logging mode (no colors)",
		},
		cli.StringFlag{
			Name:  "pgpdir, gpgdir",
			Usage: "specify a PGP directory (default is ~/.gnupg)",
		},
		cli.BoolFlag{
			Name:  "api-dump",
			Usage: "dump API call internals",
		},
		cli.StringFlag{
			Name:  "merkle-key-fingerprints",
			Usage: "Set of admissable Merkle Tree fingerprints (colon-separated)",
		},
		cli.IntFlag{
			Name:  "user-cache-size",
			Usage: "number of User entries to cache",
		},
		cli.IntFlag{
			Name:  "proof-cache-size",
			Usage: "number of proof entries to cache",
		},
		cli.StringFlag{
			Name:  "gpg",
			Usage: "Path to GPG client (optional for exporting keys)",
		},
		cli.StringFlag{
			Name:  "gpg-options",
			Usage: "Options to use when calling GPG",
		},
		cli.IntFlag{
			Name:  "daemon-port",
			Usage: "specify a daemon port on 127.0.0.1",
		},
		cli.BoolFlag{
			Name:  "standalone",
			Usage: "use the client without any daemon support",
		},
		cli.StringFlag{
			Name:  "local-rpc-debug",
			Usage: "use to debug local RPC",
		},
		cli.StringFlag{
			Name:  "device-kid",
			Usage: "specify per-device KID",
		},
		cli.StringFlag{
			Name:  "device-id",
			Usage: "specify the device ID",
		},
	}

	// Finally, add help if we asked for it
	if addHelp {
		app.Action = func(c *cli.Context) {
			cl.cmd = &CmdGeneralHelp{CmdBaseHelp{c}}
			cl.ctx = c
			cl.name = "help"
		}
	}
}

func (cl *CommandLine) AddCommands(cmds []cli.Command) {
	cl.app.Commands = cmds
}

func (cl *CommandLine) SetDefaultCommand(name string, cmd Command) {
	cl.defaultCmd = name
	cl.app.Action = func(c *cli.Context) {
		cl.cmd = cmd
		cl.ctx = c
		cl.name = name
	}
}

// Called back from inside our subcommands, when they're picked...
func (p *CommandLine) ChooseCommand(cmd Command, name string, ctx *cli.Context) {
	p.cmd = cmd
	p.name = name
	p.ctx = ctx
}

func (p *CommandLine) Parse(args []string) (cmd Command, err error) {
	// This is suboptimal, but the default help action when there are
	// no args crashes.
	// (cli sets HelpPrinter to nil when p.app.Run(...) returns.)
	if len(args) == 1 && p.defaultCmd == "help" {
		args = append(args, p.defaultCmd)
	}

	// Actually pick a command
	err = p.app.Run(args)

	// Should not be populated
	cmd = p.cmd

	if err != nil || cmd == nil {
		return
	}

	// cli.HelpPrinter is nil here...anything that needs it will panic.

	// If we failed to parse arguments properly, switch to the help command
	if err = p.cmd.ParseArgv(p.ctx); err != nil {
		libkb.G.Log.Error("In '%s': %s", p.name, err.Error())
		cmd = &CmdSpecificHelp{CmdBaseHelp{p.ctx}, p.name}
	}

	return
}
<|endoftext|>


<commit_before>package client

import (
	// Stdlib
	"fmt"
	"log"
	"strings"
	"time"

	// Vendor
	"github.com/pkg/errors"
)

//We check whether there is a voter on the list of those who have already voted
func (api *Client) Verify_Voter_Weight(author, permlink, voter string, weight int) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Voter: "))
		return false
	} else {
		for _, v := range ans {
			if v.Voter == voter && v.Percent == weight {
				return true
			}
		}
		return false
	}
}

func (api *Client) Verify_Voter(author, permlink, voter string) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Voter: "))
		return false
	} else {
		for _, v := range ans {
			if v.Voter == voter {
				return true
			}
		}
		return false
	}
}

//We check whether there are voted
func (api *Client) Verify_Votes(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Votes: "))
		return false
	} else {
		if len(ans) > 0 {
			return true
		} else {
			return false
		}
	}
}

func (api *Client) Verify_Comments(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetContentReplies(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Comments: "))
		return false
	} else {
		if len(ans) > 0 {
			return true
		} else {
			return false
		}
	}
}

func (api *Client) Verify_Reblogs(author, permlink, rebloger string) bool {
	ans, err := api.Rpc.Follow.GetRebloggedBy(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Reblogs: "))
		return false
	} else {
		for _, v := range ans {
			if v == rebloger {
				return true
			}
		}
		return false
	}
}

func (api *Client) Verify_Follow(follower, following string) bool {
	ans, err := api.Rpc.Follow.GetFollowing(follower, following, "blog", 1)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Follow: "))
		return false
	} else {
		for _, v := range ans {
			if (v.Follower == follower) && (v.Following == following) {
				return true
			} else {
				return false
			}
		}
		return false
	}
}

func (api *Client) Verify_Post(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetContent(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Post: "))
		return false
	} else {
		if (ans.Author == author) && (ans.Permlink == permlink) {
			return true
		} else {
			return false
		}
		return false
	}
}

func (api *Client) Verify_Delegate_Posting_Key_Sign(from, to string) bool {
	acc, err := api.Rpc.Database.GetAccounts([]string{from})
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Delegate Vote Sign: "))
		return false
	} else if len(acc) == 1 {
		for _, v := range acc[0].Posting.AccountAuths {
			tu := strings.Split(strings.Replace(strings.Replace(fmt.Sprintf("%v", v), "[", "", -1), "]", "", -1), " ")
			if tu[0] == to {
				if tu[1] == fmt.Sprintf("%v", acc[0].Posting.WeightThreshold) {
					return true
				}
			}
		}
		return false
	} else {
		return false
	}
}

func (api *Client) Verify_First_Post(username string) bool {
	d := time.Now()
	cont, err := api.Rpc.Database.GetDiscussionsByAuthorBeforeDate(username, "", d.Format("2006-01-02T00:00:00"), 100)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify First Post: "))
		return false
	} else {
		if len(cont) > 1 {
			return false
		} else {
			return true
		}
		return false
	}
}
<commit_msg>edit function<commit_after>package client

import (
	// Stdlib
	"fmt"
	"log"
	"strings"
	"time"

	// Vendor
	"github.com/pkg/errors"
)

//We check whether there is a voter on the list of those who have already voted
func (api *Client) Verify_Voter_Weight(author, permlink, voter string, weight int) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Voter: "))
		return false
	} else {
		for _, v := range ans {
			if v.Voter == voter && v.Percent == weight {
				return true
			}
		}
		return false
	}
}

func (api *Client) Verify_Voter(author, permlink, voter string) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Voter: "))
		return false
	} else {
		for _, v := range ans {
			if v.Voter == voter {
				return true
			}
		}
		return false
	}
}

//We check whether there are voted
func (api *Client) Verify_Votes(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetActiveVotes(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Votes: "))
		return false
	} else {
		if len(ans) > 0 {
			return true
		} else {
			return false
		}
	}
}

func (api *Client) Verify_Comments(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetContentReplies(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Comments: "))
		return false
	} else {
		if len(ans) > 0 {
			return true
		} else {
			return false
		}
	}
}

func (api *Client) Verify_Reblogs(author, permlink, rebloger string) bool {
	ans, err := api.Rpc.Follow.GetRebloggedBy(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Reblogs: "))
		return false
	} else {
		for _, v := range ans {
			if v == rebloger {
				return true
			}
		}
		return false
	}
}

func (api *Client) Verify_Follow(follower, following string) bool {
	ans, err := api.Rpc.Follow.GetFollowing(follower, following, "blog", 1)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Follow: "))
		return false
	} else {
		for _, v := range ans {
			if (v.Follower == follower) && (v.Following == following) {
				return true
			} else {
				return false
			}
		}
		return false
	}
}

func (api *Client) Verify_Post(author, permlink string) bool {
	ans, err := api.Rpc.Database.GetContent(author, permlink)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Post: "))
		return false
	} else {
		if (ans.Author == author) && (ans.Permlink == permlink) {
			return true
		} else {
			return false
		}
		return false
	}
}

func (api *Client) Verify_Delegate_Posting_Key_Sign(from_user, to_user string) bool {
	acc, err := api.Rpc.Database.GetAccounts([]string{from_user})
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify Delegate Vote Sign: "))
		return false
	} else if len(acc) == 1 {
		for _, v := range acc[0].Posting.AccountAuths {
			tu := strings.Split(strings.Replace(strings.Replace(fmt.Sprintf("%v", v), "[", "", -1), "]", "", -1), " ")
			if tu[0] == to_user {
				if tu[1] == fmt.Sprintf("%v", acc[0].Posting.WeightThreshold) {
					return true
				}
			}
		}
		return false
	} else {
		return false
	}
}

func (api *Client) Verify_First_Post(username string) bool {
	d := time.Now()
	cont, err := api.Rpc.Database.GetDiscussionsByAuthorBeforeDate(username, "", d.Format("2006-01-02T00:00:00"), 100)
	if err != nil {
		log.Println(errors.Wrapf(err, "Error Verify First Post: "))
		return false
	} else {
		if len(cont) > 1 {
			return false
		} else {
			return true
		}
		return false
	}
}
<|endoftext|>


<commit_before>package mock

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"path"
	"regexp"
	"strconv"
	"strings"

	"github.com/bukalapak/snowboard/api"
	"github.com/naoina/denco"
)

type MockTransaction struct {
	Path        string
	Pattern     string
	Method      string
	StatusCode  int
	ContentType string
	Body        string
}

type mockRecord struct {
	Pattern      string
	Method       string
	Transactions []*MockTransaction
}

type mockRouter struct {
	routers map[string]*denco.Router
}

func (mr mockRouter) Router(method string) *denco.Router {
	if r, ok := mr.routers[method]; ok {
		return r
	}

	return nil
}

type MockTransactions []*MockTransaction

func (ms MockTransactions) Router() *mockRouter {
	mr := map[string]*mockRecord{}

	for _, m := range ms {
		s := fmt.Sprintf("%s#%s", m.Method, m.Path)

		if r, ok := mr[s]; ok {
			r.Transactions = append(r.Transactions, m)
		} else {
			mr[s] = &mockRecord{
				Pattern:      m.Path,
				Method:       m.Method,
				Transactions: []*MockTransaction{m},
			}
		}
	}

	mc := map[string][]denco.Record{}

	for _, m := range mr {
		d := denco.Record{
			Key:   m.Pattern,
			Value: m,
		}

		if _, ok := mc[m.Method]; ok {
			mc[m.Method] = append(mc[m.Method], d)
		} else {
			mc[m.Method] = []denco.Record{d}
		}
	}

	mx := map[string]*denco.Router{}

	for k, c := range mc {
		r := denco.New()
		r.Build(c)
		mx[k] = r
	}

	return &mockRouter{mx}
}

func Mock(b *api.API) []*MockTransaction {
	ms := []*MockTransaction{}

	for _, g := range b.ResourceGroups {
		for _, x := range g.Resources {
			for _, t := range x.Transitions {
				for _, n := range t.Transactions {
					p := transformURL(t.URL, b.Host())
					m := &MockTransaction{
						Path:        urlPath(p),
						Pattern:     p,
						Method:      n.Request.Method,
						StatusCode:  n.Response.StatusCode,
						ContentType: n.Response.Body.ContentType,
						Body:        n.Response.Body.Body,
					}

					ms = append(ms, m)
				}
			}
		}
	}

	return ms
}

func MockMulti(bs []*api.API) []MockTransactions {
	ms := make([]MockTransactions, len(bs))

	for i := range bs {
		ms[i] = Mock(bs[i])
	}

	return ms
}

func MockHandler(ms []MockTransactions) http.Handler {
	mr := make([]*mockRouter, len(ms))

	for i := range ms {
		mr[i] = ms[i].Router()
	}

	fn := func(w http.ResponseWriter, r *http.Request) {
		var n *MockTransaction

		var found bool
		var data interface{}

		for _, q := range mr {
			router := q.Router(r.Method)

			if !found {
				data, _, found = router.Lookup(r.URL.Path)
			}
		}

		if !found {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		m := data.(*mockRecord)
		s := preferStatusCode(r)

		if s == "" {
			for _, t := range m.Transactions {
				if t.StatusCode >= http.StatusOK && t.StatusCode < http.StatusBadRequest {
					n = t
				}
			}
		} else {
			for _, t := range m.Transactions {
				if s == strconv.Itoa(t.StatusCode) {
					n = t
				}
			}
		}

		if n == nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		log.Printf("%s\t%d\t%s\n", n.Method, n.StatusCode, n.Path)

		w.Header().Set("Content-Type", n.ContentType)
		w.WriteHeader(n.StatusCode)
		io.WriteString(w, n.Body)
	}

	return http.HandlerFunc(fn)
}

func preferStatusCode(r *http.Request) string {
	var c string

	for _, v := range strings.Split(r.Header.Get("Prefer"), ",") {
		if z := strings.SplitN(v, "=", 2); z[0] == "status" {
			c = z[1]
		}
	}

	if c == "" {
		c = r.Header.Get("X-Status-Code")
	}

	return c
}

func transformURL(u, h string) string {
	paramPattern := regexp.MustCompile(`\{\?[\w,]+\}`)
	queryPattern := regexp.MustCompile(`\{([\w,]+)\}`)

	u = queryPattern.ReplaceAllString(u, ":${1}")
	u = paramPattern.ReplaceAllLiteralString(u, "")
	u = strings.Replace(u, h, "", 1)
	u = path.Join("/", u)

	return u
}

func urlPath(u string) string {
	if x, err := url.Parse(u); err == nil {
		return x.Path
	}

	return u
}
<commit_msg>updated OPTIONS handling; fix #48<commit_after>package mock

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"path"
	"regexp"
	"strconv"
	"strings"

	"github.com/bukalapak/snowboard/api"
	"github.com/naoina/denco"
)

type MockTransaction struct {
	Path        string
	Pattern     string
	Method      string
	StatusCode  int
	ContentType string
	Body        string
}

type mockRecord struct {
	Pattern      string
	Method       string
	Transactions []*MockTransaction
}

type mockRouter struct {
	routers map[string]*denco.Router
}

func (mr mockRouter) Router(method string) *denco.Router {
	if r, ok := mr.routers[method]; ok {
		return r
	}

	return nil
}

type MockTransactions []*MockTransaction

func (ms MockTransactions) Router() *mockRouter {
	mr := map[string]*mockRecord{}

	for _, m := range ms {
		s := fmt.Sprintf("%s#%s", m.Method, m.Path)

		if r, ok := mr[s]; ok {
			r.Transactions = append(r.Transactions, m)
		} else {
			mr[s] = &mockRecord{
				Pattern:      m.Path,
				Method:       m.Method,
				Transactions: []*MockTransaction{m},
			}
		}
	}

	mc := map[string][]denco.Record{}

	for _, m := range mr {
		d := denco.Record{
			Key:   m.Pattern,
			Value: m,
		}

		if _, ok := mc[m.Method]; ok {
			mc[m.Method] = append(mc[m.Method], d)
		} else {
			mc[m.Method] = []denco.Record{d}
		}
	}

	mx := map[string]*denco.Router{}

	for k, c := range mc {
		r := denco.New()
		r.Build(c)
		mx[k] = r
	}

	return &mockRouter{mx}
}

func Mock(b *api.API) []*MockTransaction {
	ms := []*MockTransaction{}

	for _, g := range b.ResourceGroups {
		for _, x := range g.Resources {
			for _, t := range x.Transitions {
				for _, n := range t.Transactions {
					p := transformURL(t.URL, b.Host())
					m := &MockTransaction{
						Path:        urlPath(p),
						Pattern:     p,
						Method:      n.Request.Method,
						StatusCode:  n.Response.StatusCode,
						ContentType: n.Response.Body.ContentType,
						Body:        n.Response.Body.Body,
					}

					ms = append(ms, m)
				}
			}
		}
	}

	return ms
}

func MockMulti(bs []*api.API) []MockTransactions {
	ms := make([]MockTransactions, len(bs))

	for i := range bs {
		ms[i] = Mock(bs[i])
	}

	return ms
}

func MockHandler(ms []MockTransactions) http.Handler {
	mr := make([]*mockRouter, len(ms))

	for i := range ms {
		mr[i] = ms[i].Router()
	}

	fn := func(w http.ResponseWriter, r *http.Request) {
		var n *MockTransaction

		var found bool
		var data interface{}

		for _, q := range mr {
			if router := q.Router(r.Method); router != nil {
				data, _, found = router.Lookup(r.URL.Path)
			}
		}

		if !found {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		m := data.(*mockRecord)
		s := preferStatusCode(r)

		if s == "" {
			for _, t := range m.Transactions {
				if t.StatusCode >= http.StatusOK && t.StatusCode < http.StatusBadRequest {
					n = t
				}
			}
		} else {
			for _, t := range m.Transactions {
				if s == strconv.Itoa(t.StatusCode) {
					n = t
				}
			}
		}

		if n == nil {
			w.WriteHeader(http.StatusNotFound)
			return
		}

		log.Printf("%s\t%d\t%s\n", n.Method, n.StatusCode, n.Path)

		w.Header().Set("Content-Type", n.ContentType)
		w.WriteHeader(n.StatusCode)
		io.WriteString(w, n.Body)
	}

	return http.HandlerFunc(fn)
}

func preferStatusCode(r *http.Request) string {
	var c string

	for _, v := range strings.Split(r.Header.Get("Prefer"), ",") {
		if z := strings.SplitN(v, "=", 2); z[0] == "status" {
			c = z[1]
		}
	}

	if c == "" {
		c = r.Header.Get("X-Status-Code")
	}

	return c
}

func transformURL(u, h string) string {
	paramPattern := regexp.MustCompile(`\{\?[\w,]+\}`)
	queryPattern := regexp.MustCompile(`\{([\w,]+)\}`)

	u = queryPattern.ReplaceAllString(u, ":${1}")
	u = paramPattern.ReplaceAllLiteralString(u, "")
	u = strings.Replace(u, h, "", 1)
	u = path.Join("/", u)

	return u
}

func urlPath(u string) string {
	if x, err := url.Parse(u); err == nil {
		return x.Path
	}

	return u
}
<|endoftext|>


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

// Package topology host, TOR definitions.
package topology

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"net"
	"strings"

	"github.com/romana/core/common"

	_ "github.com/go-sql-driver/mysql"
)

type Tor struct {
	Id         uint64 `sql:"AUTO_INCREMENT"`
	datacenter *common.Datacenter
}

// Backing store
type topoStore struct {
	common.DbStore
}

func (topoStore *topoStore) Entities() []interface{} {
	retval := make([]interface{}, 2)
	retval[0] = &common.Host{}
	retval[1] = &common.Datacenter{}
	return retval
}

func (topoStore *topoStore) CreateSchemaPostProcess() error {
	return nil
}

func (topoStore *topoStore) findHost(id uint64) (common.Host, error) {
	host := common.Host{}
	topoStore.DbStore.Db.Where("id = ?", id).First(&host)
	err := common.MakeMultiError(topoStore.DbStore.Db.GetErrors())
	if err != nil {
		return host, err
	}
	return host, nil
}

func (topoStore *topoStore) listHosts() ([]common.Host, error) {
	var hosts []common.Host
	log.Println("In listHosts()")
	topoStore.DbStore.Db.Find(&hosts)
	err := common.MakeMultiError(topoStore.DbStore.Db.GetErrors())
	if err != nil {
		return nil, err
	}
	log.Println("listHosts(): found hosts:", hosts)
	return hosts, nil
}

// findFirstAvaiableID finds the first available ID
// for the given list of hostID's. This is mainly to
// reuse the hostID if the host gets deletes and use
// use the same subnet in process, since subnet is
// generated based on id as shown in getNetworkFromID.
func findFirstAvaiableID(arr []uint64) uint64 {
	for i := 0; i < len(arr)-1; i++ {
		if arr[i+1]-arr[i] > 1 {
			return arr[i] + 1
		}
	}
	return arr[len(arr)-1] + 1
}

// getNetworkFromID calculates a subnet equivalent to id
// specified, from the avaiable romana cidr.
// Currently only IPv4 is supported.
func getNetworkFromID(id uint64, hostBits uint) (string, error) {
	if id == 0 || id > uint64(1<<hostBits) {
		return "", fmt.Errorf("error: invalid id passed or max subnets already allocated.")
	}
	if hostBits >= 24 {
		return "", fmt.Errorf("error: invalid number of bits alloacted for hosts.")
	}

	var hostIP uint32 = 0x0A << hostBits
	hostIP += uint32(id) - 1
	hostIP <<= 24 - hostBits

	bufHostIP := new(bytes.Buffer)
	err := binary.Write(bufHostIP, binary.BigEndian, hostIP)
	if err != nil {
		return "", fmt.Errorf("error: subnet ip calculation (%s) failed.", err)
	}
	var hostIPNet net.IPNet
	for i := range hostIPNet.IP {
		hostIPNet.IP[i] = bufHostIP.Bytes()[i]
	}

	var hostMask uint32
	for i := uint(0); i < hostBits+8; i++ {
		hostMask |= 1 << i
	}
	hostMask <<= 24 - hostBits
	bufHostMask := new(bytes.Buffer)
	err = binary.Write(bufHostMask, binary.BigEndian, hostMask)
	if err != nil {
		return "", fmt.Errorf("error: subnet mask calculation (%s) failed.", err)
	}
	for i := range hostIPNet.Mask {
		hostIPNet.Mask[i] = bufHostMask.Bytes()[i]
	}

	return hostIPNet.String(), nil
}

func (topoStore *topoStore) addHost(dc *common.Datacenter, host *common.Host) error {
	var count uint
	db := topoStore.DbStore.Db.Count(&count)
	if db.Error != nil {
		return db.Error
	}
	err := common.MakeMultiError(topoStore.DbStore.Db.GetErrors())
	if err != nil {
		return err
	}
	if count >= 1<<dc.PortBits {
		return fmt.Errorf("error: max number (%d) of hosts exceeded.", count)
	}

	romanaIP := strings.TrimSpace(host.RomanaIp)
	if romanaIP == "" {
		tx := topoStore.DbStore.Db.Begin()

		var allHostsID []uint64
		if err := tx.Select("id").Find(&allHostsID).Error; err != nil {
			tx.Rollback()
			return err
		}

		id := findFirstAvaiableID(allHostsID)
		host.RomanaIp, err = getNetworkFromID(id, dc.PortBits)
		if err != nil {
			tx.Rollback()
			return err
		}

		if err := tx.Create(host).Error; err != nil {
			tx.Rollback()
			return err
		}
		tx.Commit()
	} else {
		topoStore.DbStore.Db.NewRecord(*host)
		db := topoStore.DbStore.Db.Create(host)
		err := common.GetDbErrors(db)
		if err != nil {
			log.Printf("topology.store.addHost(%v): %v", host, err)
			return "", err
		}
	}
	return nil
}
<commit_msg>topology: make getNetworkFromID flexible enough for all cidrs.<commit_after>// Copyright (c) 2016 Pani Networks
// All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Package topology host, TOR definitions.
package topology

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"net"
	"strconv"
	"strings"

	"github.com/romana/core/common"

	_ "github.com/go-sql-driver/mysql"
)

var (
	BITS_IN_BYTE uint = 8
)

type Tor struct {
	Id         uint64 `sql:"AUTO_INCREMENT"`
	datacenter *common.Datacenter
}

// Backing store
type topoStore struct {
	common.DbStore
}

func (topoStore *topoStore) Entities() []interface{} {
	retval := make([]interface{}, 2)
	retval[0] = &common.Host{}
	retval[1] = &common.Datacenter{}
	return retval
}

func (topoStore *topoStore) CreateSchemaPostProcess() error {
	return nil
}

func (topoStore *topoStore) findHost(id uint64) (common.Host, error) {
	host := common.Host{}
	topoStore.DbStore.Db.Where("id = ?", id).First(&host)
	err := common.MakeMultiError(topoStore.DbStore.Db.GetErrors())
	if err != nil {
		return host, err
	}
	return host, nil
}

func (topoStore *topoStore) listHosts() ([]common.Host, error) {
	var hosts []common.Host
	log.Println("In listHosts()")
	topoStore.DbStore.Db.Find(&hosts)
	err := common.MakeMultiError(topoStore.DbStore.Db.GetErrors())
	if err != nil {
		return nil, err
	}
	log.Println("listHosts(): found hosts:", hosts)
	return hosts, nil
}

// findFirstAvaiableID finds the first available ID
// for the given list of hostIDs. This is mainly to
// reuse the hostID if the host gets deleted and
// use the same subnet in process, since subnet is
// generated based on id as shown in getNetworkFromID.
func findFirstAvaiableID(arr []uint64) uint64 {
	for i := 0; i < len(arr)-1; i++ {
		if arr[i+1]-arr[i] > 1 {
			return arr[i] + 1
		}
	}
	return arr[len(arr)-1] + 1
}

// getNetworkFromID calculates a subnet equivalent to id
// specified, from the avaiable romana cidr. Currently
// only IPv4 is supported.
func getNetworkFromID(id uint64, hostBits uint, cidr string) (string, error) {
	if id == 0 || id > uint64(1<<hostBits) {
		return "", fmt.Errorf("error: invalid id passed or max subnets already allocated.")
	}

	networkBits := strings.Split(cidr, "/")
	if len(networkBits) != 2 {
		return "", fmt.Errorf("error: parsing romana cidr (%s) failed.", cidr)
	}

	networkBits[0] = strings.TrimSpace(networkBits[0])
	romanaPrefix := net.ParseIP(networkBits[0])
	if romanaPrefix == nil {
		return "", fmt.Errorf("error: parsing romana cidr (%s) failed.", networkBits[0])
	}

	networkBits[1] = strings.TrimSpace(networkBits[1])
	romanaPrefixBits, err := strconv.ParseUint(networkBits[1], 10, 64)
	if err != nil {
		return "", fmt.Errorf("error: parsing romana cidr (%s) failed.", networkBits[1])
	}

	var romanaPrefixUint32 uint32
	byteRomanaPrefix := romanaPrefix.To4()
	bufRomanaPrefix := bytes.NewReader(byteRomanaPrefix)
	err = binary.Read(bufRomanaPrefix, binary.BigEndian, &romanaPrefixUint32)
	if err != nil {
		return "", fmt.Errorf("error: parsing romana cidr (%s) failed.", romanaPrefix)
	}

	// since this function is limited to IPv4, handle romanaPrefixBits accordingly.
	if hostBits >= (net.IPv4len*BITS_IN_BYTE - uint(romanaPrefixBits)) {
		return "", fmt.Errorf("error: invalid number of bits allocated for hosts.")
	}

	var hostIP uint32
	hostIP = (romanaPrefixUint32 >> (net.IPv4len*BITS_IN_BYTE - uint(romanaPrefixBits))) << hostBits
	hostIP += uint32(id) - 1
	hostIP <<= (net.IPv4len*BITS_IN_BYTE - uint(romanaPrefixBits)) - hostBits

	bufHostIP := new(bytes.Buffer)
	err = binary.Write(bufHostIP, binary.BigEndian, hostIP)
	if err != nil {
		return "", fmt.Errorf("error: subnet ip calculation (%s) failed.", err)
	}

	var hostIPNet net.IPNet
	hostIPNet.IP = make(net.IP, net.IPv4len)
	hostIPNet.Mask = make(net.IPMask, net.IPv4len)
	for i := range hostIPNet.IP {
		hostIPNet.IP[i] = bufHostIP.Bytes()[i]
	}

	var hostMask uint32
	for i := uint(0); i < hostBits+uint(romanaPrefixBits); i++ {
		hostMask |= 1 << i
	}
	hostMask <<= (net.IPv4len*BITS_IN_BYTE - uint(romanaPrefixBits)) - hostBits
	bufHostMask := new(bytes.Buffer)
	err = binary.Write(bufHostMask, binary.BigEndian, hostMask)
	if err != nil {
		return "", fmt.Errorf("error: subnet mask calculation (%s) failed.", err)
	}
	for i := range hostIPNet.Mask {
		hostIPNet.Mask[i] = bufHostMask.Bytes()[i]
	}

	return hostIPNet.String(), nil
}

// addHost adds a new host to a specific datacenter, it also makes sure
// that if a romana cidr is not assigned, then to create and assign a new
// romana cidr using help of helper functions like findFirstAvaiableID
// and getNetworkFromID.
func (topoStore *topoStore) addHost(dc *common.Datacenter, host *common.Host) error {
	romanaIP := strings.TrimSpace(host.RomanaIp)
	if romanaIP == "" {
		var err error
		tx := topoStore.DbStore.Db.Begin()

		var allHostsID []uint64
		if err := tx.Select("id").Find(&allHostsID).Error; err != nil {
			tx.Rollback()
			return err
		}

		id := findFirstAvaiableID(allHostsID)
		host.RomanaIp, err = getNetworkFromID(id, dc.PortBits, dc.Cidr)
		if err != nil {
			tx.Rollback()
			return err
		}

		if err := tx.Create(host).Error; err != nil {
			tx.Rollback()
			return err
		}
		tx.Commit()
	} else {
		topoStore.DbStore.Db.NewRecord(*host)
		db := topoStore.DbStore.Db.Create(host)
		if err := common.GetDbErrors(db); err != nil {
			log.Printf("topology.store.addHost(%v): %v", host, err)
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2011 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.

// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package net

import (
	"internal/syscall/unix"
	"os"
	"syscall"
)

func dupSocket(f *os.File) (int, error) {
	s, err := dupCloseOnExec(int(f.Fd()))
	if err != nil {
		return -1, err
	}
	if err := syscall.SetNonblock(s, true); err != nil {
		closeFunc(s)
		return -1, os.NewSyscallError("setnonblock", err)
	}
	return s, nil
}

func newFileFD(f *os.File, sa SocketAddr) (*netFD, error) {
	s, err := dupSocket(f)
	if err != nil {
		return nil, err
	}
	var laddr, raddr Addr
	var fd *netFD
	if sa != nil {
		lsa := make([]byte, syscall.SizeofSockaddrAny)
		if err := unix.Getsockname(s, lsa); err != nil {
			lsa = nil
		}
		rsa := make([]byte, syscall.SizeofSockaddrAny)
		if err := unix.Getpeername(s, rsa); err != nil {
			rsa = nil
		}
		laddr = sa.Addr(lsa)
		raddr = sa.Addr(rsa)
		fd, err = newFD(s, -1, -1, laddr.Network())
	} else {
		family := syscall.AF_UNSPEC
		sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE)
		if err != nil {
			closeFunc(s)
			return nil, os.NewSyscallError("getsockopt", err)
		}
		lsa, _ := syscall.Getsockname(s)
		rsa, _ := syscall.Getpeername(s)
		switch lsa.(type) {
		case *syscall.SockaddrInet4:
			family = syscall.AF_INET
		case *syscall.SockaddrInet6:
			family = syscall.AF_INET6
		case *syscall.SockaddrUnix:
			family = syscall.AF_UNIX
		default:
			closeFunc(s)
			return nil, syscall.EPROTONOSUPPORT
		}
		fd, err = newFD(s, family, sotype, "")
		laddr = fd.addrFunc()(lsa)
		raddr = fd.addrFunc()(rsa)
		fd.net = laddr.Network()
	}
	if err != nil {
		closeFunc(s)
		return nil, err
	}
	if err := fd.init(); err != nil {
		fd.Close()
		return nil, err
	}
	fd.setAddr(laddr, raddr)
	return fd, nil
}

func fileConn(f *os.File) (Conn, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch fd.laddr.(type) {
	case *TCPAddr:
		return newTCPConn(fd), nil
	case *UDPAddr:
		return newUDPConn(fd), nil
	case *IPAddr:
		return newIPConn(fd), nil
	case *UnixAddr:
		return newUnixConn(fd), nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func fileListener(f *os.File) (Listener, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch laddr := fd.laddr.(type) {
	case *TCPAddr:
		return &TCPListener{fd}, nil
	case *UnixAddr:
		return &UnixListener{fd, laddr.Name}, nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func filePacketConn(f *os.File) (PacketConn, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch fd.laddr.(type) {
	case *UDPAddr:
		return newUDPConn(fd), nil
	case *IPAddr:
		return newIPConn(fd), nil
	case *UnixAddr:
		return newUnixConn(fd), nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func socketConn(f *os.File, sa SocketAddr) (Conn, error) {
	fd, err := newFileFD(f, sa)
	if err != nil {
		return nil, err
	}
	return &socketFile{conn: conn{fd}, SocketAddr: sa}, nil
}

func socketPacketConn(f *os.File, sa SocketAddr) (PacketConn, error) {
	fd, err := newFileFD(f, sa)
	if err != nil {
		return nil, err
	}
	return &socketFile{conn: conn{fd}, SocketAddr: sa}, nil
}

var (
	_ Conn       = &socketFile{}
	_ PacketConn = &socketFile{}
)

// A socketFile is a placeholder that holds a user-specified socket
// descriptor and a profile of socket address encoding.
// It implements both Conn and PacketConn interfaces.
type socketFile struct {
	conn
	SocketAddr
}

func (c *socketFile) ReadFrom(b []byte) (int, Addr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	from := make([]byte, syscall.SizeofSockaddrAny)
	n, err := c.fd.recvFrom(b, 0, from)
	if err != nil {
		return n, nil, &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, c.SocketAddr.Addr(from), nil
}

func (c *socketFile) WriteTo(b []byte, addr Addr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.fd.sendTo(b, 0, c.SocketAddr.Raw(addr))
	if err != nil {
		return n, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, nil
}
<commit_msg>net: fix undetected set and not used error<commit_after>// Copyright 2011 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.

// +build darwin dragonfly freebsd linux netbsd openbsd solaris

package net

import (
	"internal/syscall/unix"
	"os"
	"syscall"
)

func dupSocket(f *os.File) (int, error) {
	s, err := dupCloseOnExec(int(f.Fd()))
	if err != nil {
		return -1, err
	}
	if err := syscall.SetNonblock(s, true); err != nil {
		closeFunc(s)
		return -1, os.NewSyscallError("setnonblock", err)
	}
	return s, nil
}

func newFileFD(f *os.File, sa SocketAddr) (*netFD, error) {
	s, err := dupSocket(f)
	if err != nil {
		return nil, err
	}
	var laddr, raddr Addr
	var fd *netFD
	if sa != nil {
		lsa := make([]byte, syscall.SizeofSockaddrAny)
		if err := unix.Getsockname(s, lsa); err != nil {
			lsa = nil
		}
		rsa := make([]byte, syscall.SizeofSockaddrAny)
		if err := unix.Getpeername(s, rsa); err != nil {
			rsa = nil
		}
		laddr = sa.Addr(lsa)
		raddr = sa.Addr(rsa)
		fd, err = newFD(s, -1, -1, laddr.Network())
	} else {
		family := syscall.AF_UNSPEC
		var sotype int
		sotype, err = syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE)
		if err != nil {
			closeFunc(s)
			return nil, os.NewSyscallError("getsockopt", err)
		}
		lsa, _ := syscall.Getsockname(s)
		rsa, _ := syscall.Getpeername(s)
		switch lsa.(type) {
		case *syscall.SockaddrInet4:
			family = syscall.AF_INET
		case *syscall.SockaddrInet6:
			family = syscall.AF_INET6
		case *syscall.SockaddrUnix:
			family = syscall.AF_UNIX
		default:
			closeFunc(s)
			return nil, syscall.EPROTONOSUPPORT
		}
		fd, err = newFD(s, family, sotype, "")
		laddr = fd.addrFunc()(lsa)
		raddr = fd.addrFunc()(rsa)
		fd.net = laddr.Network()
	}
	if err != nil {
		closeFunc(s)
		return nil, err
	}
	if err := fd.init(); err != nil {
		fd.Close()
		return nil, err
	}
	fd.setAddr(laddr, raddr)
	return fd, nil
}

func fileConn(f *os.File) (Conn, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch fd.laddr.(type) {
	case *TCPAddr:
		return newTCPConn(fd), nil
	case *UDPAddr:
		return newUDPConn(fd), nil
	case *IPAddr:
		return newIPConn(fd), nil
	case *UnixAddr:
		return newUnixConn(fd), nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func fileListener(f *os.File) (Listener, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch laddr := fd.laddr.(type) {
	case *TCPAddr:
		return &TCPListener{fd}, nil
	case *UnixAddr:
		return &UnixListener{fd, laddr.Name}, nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func filePacketConn(f *os.File) (PacketConn, error) {
	fd, err := newFileFD(f, nil)
	if err != nil {
		return nil, err
	}
	switch fd.laddr.(type) {
	case *UDPAddr:
		return newUDPConn(fd), nil
	case *IPAddr:
		return newIPConn(fd), nil
	case *UnixAddr:
		return newUnixConn(fd), nil
	}
	fd.Close()
	return nil, syscall.EINVAL
}

func socketConn(f *os.File, sa SocketAddr) (Conn, error) {
	fd, err := newFileFD(f, sa)
	if err != nil {
		return nil, err
	}
	return &socketFile{conn: conn{fd}, SocketAddr: sa}, nil
}

func socketPacketConn(f *os.File, sa SocketAddr) (PacketConn, error) {
	fd, err := newFileFD(f, sa)
	if err != nil {
		return nil, err
	}
	return &socketFile{conn: conn{fd}, SocketAddr: sa}, nil
}

var (
	_ Conn       = &socketFile{}
	_ PacketConn = &socketFile{}
)

// A socketFile is a placeholder that holds a user-specified socket
// descriptor and a profile of socket address encoding.
// It implements both Conn and PacketConn interfaces.
type socketFile struct {
	conn
	SocketAddr
}

func (c *socketFile) ReadFrom(b []byte) (int, Addr, error) {
	if !c.ok() {
		return 0, nil, syscall.EINVAL
	}
	from := make([]byte, syscall.SizeofSockaddrAny)
	n, err := c.fd.recvFrom(b, 0, from)
	if err != nil {
		return n, nil, &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, c.SocketAddr.Addr(from), nil
}

func (c *socketFile) WriteTo(b []byte, addr Addr) (int, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.fd.sendTo(b, 0, c.SocketAddr.Raw(addr))
	if err != nil {
		return n, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, nil
}
<|endoftext|>