<commit_before>// Copyright 2022 Google LLC
//
// 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 alloydbapi

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"google.golang.org/api/googleapi"
	"google.golang.org/api/option"
	htransport "google.golang.org/api/transport/http"
)

type InstanceGetResponse struct {
	ServerResponse googleapi.ServerResponse
	Name           string `json:"name"`
	State          string `json:"state"`
	IPAddress      string `json:"ipAddress"`
}

type GenerateClientCertificateRequest struct {
	PemCSR string `json:"pemCsr"`
}

type GenerateClientCertificateResponse struct {
	ServerResponse      googleapi.ServerResponse
	PemCertificate      string   `json:"pemCertificate"`
	PemCertificateChain []string `json:"pemCertificateChain"`
}

// baseURL is the production API endpoint of the AlloyDB Admin API
// TODO: replace this with production.
const baseURL = "https://staging-alloydb.sandbox.googleapis.com"

type Client struct {
	client *http.Client
	// endpoint is the base URL for the AlloyDB Admin API (e.g.
	// https://alloydb.googleapis.com/v1)
	endpoint string
}

func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
	os := append([]option.ClientOption{
		option.WithEndpoint(baseURL),
	}, opts...) // allow for overriding the endpoint
	os = append(os,
		// do not allow for overriding the scopes
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	client, endpoint, err := htransport.NewClient(ctx, os...)
	if err != nil {
		return nil, err
	}
	return &Client{client: client, endpoint: endpoint}, nil
}

func (c *Client) InstanceGet(ctx context.Context, project, region, cluster, instance string) (InstanceGetResponse, error) {
	u := fmt.Sprintf(
		"%s/v1alpha1/projects/%s/locations/%s/clusters/%s/instances/%s",
		c.endpoint, project, region, cluster, instance,
	)
	req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
	if err != nil {
		return InstanceGetResponse{}, err
	}
	res, err := c.client.Do(req)
	if err != nil {
		return InstanceGetResponse{}, err
	}
	if res != nil && res.StatusCode == http.StatusNotModified {
		var body []byte
		if res.Body != nil {
			defer res.Body.Close()
			body, err = ioutil.ReadAll(res.Body)
			if err != nil {
				return InstanceGetResponse{}, err
			}
		}

		return InstanceGetResponse{}, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
			Body:   string(body),
		}
	}
	if err != nil {
		return InstanceGetResponse{}, err
	}
	defer res.Body.Close()
	ret := InstanceGetResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	if err := json.NewDecoder(res.Body).Decode(&ret); err != nil {
		return InstanceGetResponse{}, err
	}
	return ret, nil
}

func (c *Client) GenerateClientCert(ctx context.Context, project, region, cluster string, csr []byte) (GenerateClientCertificateResponse, error) {
	u := fmt.Sprintf(
		"%s/v1alpha1/projects/%s/locations/%s/clusters/%s:generateClientCertificate",
		c.endpoint, project, region, cluster,
	)
	body, err := json.Marshal(GenerateClientCertificateRequest{PemCSR: string(csr)})
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	req, err := http.NewRequestWithContext(ctx, "POST", u, bytes.NewReader(body))
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	res, err := c.client.Do(req.WithContext(ctx))
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	defer res.Body.Close()
	ret := GenerateClientCertificateResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	if err := json.NewDecoder(res.Body).Decode(&ret); err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	return ret, nil
}
<commit_msg>feat: switch to prod endpoint (#13)<commit_after>// Copyright 2022 Google LLC
//
// 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 alloydbapi

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"google.golang.org/api/googleapi"
	"google.golang.org/api/option"
	htransport "google.golang.org/api/transport/http"
)

type InstanceGetResponse struct {
	ServerResponse googleapi.ServerResponse
	Name           string `json:"name"`
	State          string `json:"state"`
	IPAddress      string `json:"ipAddress"`
}

type GenerateClientCertificateRequest struct {
	PemCSR string `json:"pemCsr"`
}

type GenerateClientCertificateResponse struct {
	ServerResponse      googleapi.ServerResponse
	PemCertificate      string   `json:"pemCertificate"`
	PemCertificateChain []string `json:"pemCertificateChain"`
}

// baseURL is the production API endpoint of the AlloyDB Admin API
const baseURL = "https://alloydb.googleapis.com"

type Client struct {
	client *http.Client
	// endpoint is the base URL for the AlloyDB Admin API (e.g.
	// https://alloydb.googleapis.com)
	endpoint string
}

func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
	os := append([]option.ClientOption{
		option.WithEndpoint(baseURL),
	}, opts...) // allow for overriding the endpoint
	os = append(os,
		// do not allow for overriding the scopes
		option.WithScopes("https://www.googleapis.com/auth/cloud-platform"),
	)
	client, endpoint, err := htransport.NewClient(ctx, os...)
	if err != nil {
		return nil, err
	}
	return &Client{client: client, endpoint: endpoint}, nil
}

func (c *Client) InstanceGet(ctx context.Context, project, region, cluster, instance string) (InstanceGetResponse, error) {
	u := fmt.Sprintf(
		"%s/v1alpha1/projects/%s/locations/%s/clusters/%s/instances/%s",
		c.endpoint, project, region, cluster, instance,
	)
	req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
	if err != nil {
		return InstanceGetResponse{}, err
	}
	res, err := c.client.Do(req)
	if err != nil {
		return InstanceGetResponse{}, err
	}
	if res != nil && res.StatusCode == http.StatusNotModified {
		var body []byte
		if res.Body != nil {
			defer res.Body.Close()
			body, err = ioutil.ReadAll(res.Body)
			if err != nil {
				return InstanceGetResponse{}, err
			}
		}

		return InstanceGetResponse{}, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
			Body:   string(body),
		}
	}
	if err != nil {
		return InstanceGetResponse{}, err
	}
	defer res.Body.Close()
	ret := InstanceGetResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	if err := json.NewDecoder(res.Body).Decode(&ret); err != nil {
		return InstanceGetResponse{}, err
	}
	return ret, nil
}

func (c *Client) GenerateClientCert(ctx context.Context, project, region, cluster string, csr []byte) (GenerateClientCertificateResponse, error) {
	u := fmt.Sprintf(
		"%s/v1alpha1/projects/%s/locations/%s/clusters/%s:generateClientCertificate",
		c.endpoint, project, region, cluster,
	)
	body, err := json.Marshal(GenerateClientCertificateRequest{PemCSR: string(csr)})
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	req, err := http.NewRequestWithContext(ctx, "POST", u, bytes.NewReader(body))
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	res, err := c.client.Do(req.WithContext(ctx))
	if err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	defer res.Body.Close()
	ret := GenerateClientCertificateResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	if err := json.NewDecoder(res.Body).Decode(&ret); err != nil {
		return GenerateClientCertificateResponse{}, err
	}
	return ret, nil
}
<|endoftext|>


<commit_before>package restic

import (
	"path/filepath"
	"syscall"

	"golang.org/x/sys/unix"

	"github.com/restic/restic/internal/errors"

	"github.com/restic/restic/internal/fs"
)

func (node Node) restoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error {
	dir, err := fs.Open(filepath.Dir(path))
	defer dir.Close()
	if err != nil {
		return errors.Wrap(err, "Open")
	}

	times := []unix.Timespec{
		{Sec: utimes[0].Sec, Nsec: utimes[0].Nsec},
		{Sec: utimes[1].Sec, Nsec: utimes[1].Nsec},
	}

	err = unix.UtimesNanoAt(int(dir.Fd()), filepath.Base(path), times, unix.AT_SYMLINK_NOFOLLOW)

	if err != nil {
		return errors.Wrap(err, "UtimesNanoAt")
	}

	return nil
}

func (node Node) device() int {
	return int(node.Device)
}

func (s statUnix) atim() syscall.Timespec { return s.Atim }
func (s statUnix) mtim() syscall.Timespec { return s.Mtim }
func (s statUnix) ctim() syscall.Timespec { return s.Ctim }
<commit_msg>internal/restic: close os.File after checking for error<commit_after>package restic

import (
	"path/filepath"
	"syscall"

	"golang.org/x/sys/unix"

	"github.com/restic/restic/internal/errors"

	"github.com/restic/restic/internal/fs"
)

func (node Node) restoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error {
	dir, err := fs.Open(filepath.Dir(path))
	if err != nil {
		return errors.Wrap(err, "Open")
	}
	defer dir.Close()

	times := []unix.Timespec{
		{Sec: utimes[0].Sec, Nsec: utimes[0].Nsec},
		{Sec: utimes[1].Sec, Nsec: utimes[1].Nsec},
	}

	err = unix.UtimesNanoAt(int(dir.Fd()), filepath.Base(path), times, unix.AT_SYMLINK_NOFOLLOW)

	if err != nil {
		return errors.Wrap(err, "UtimesNanoAt")
	}

	return nil
}

func (node Node) device() int {
	return int(node.Device)
}

func (s statUnix) atim() syscall.Timespec { return s.Atim }
func (s statUnix) mtim() syscall.Timespec { return s.Mtim }
func (s statUnix) ctim() syscall.Timespec { return s.Ctim }
<|endoftext|>


<commit_before>package template

var (
	Makefile = `
GOPATH:=$(shell go env GOPATH)

.PHONY: proto test docker

{{if ne .Type "web"}}
proto:
	protoc --proto_path=${GOPATH}/src:. --micro_out=. --go_out=. proto/example/example.proto

build: proto
{{else}}
build:
{{end}}
	go build -o {{.Alias}}-{{.Type}} main.go plugin.go

test:
	go test -v ./... -cover

docker:
	docker build . -t {{.Alias}}-{{.Type}}:latest
`
)
<commit_msg>remove white spaces from makefile<commit_after>package template

var (
	Makefile = `
GOPATH:=$(shell go env GOPATH)

.PHONY: proto test docker

{{if ne .Type "web"}}
proto:
	protoc --proto_path=${GOPATH}/src:. --micro_out=. --go_out=. proto/example/example.proto

build: proto
{{else}}
build:
{{end}}
	go build -o {{.Alias}}-{{.Type}} main.go plugin.go

test:
	go test -v ./... -cover

docker:
	docker build . -t {{.Alias}}-{{.Type}}:latest
`
)
<|endoftext|>


<commit_before>package timespec

/*
#include <time.h>
*/
import "C"

import (
	"unsafe"

	"golang.org/x/sys/unix"
)

// Timespec behaves similarly to C's struct timespec.
// Timespec is used to retain fidelity to the C based file systems
// apis that could be lossy with the use of Go time types.
type Timespec unix.Timespec

// CTimespecPtr is an unsafe pointer wrapping C's `struct timespec`.
type CTimespecPtr unsafe.Pointer

// CStructToTimespec creates a new Timespec for the C 'struct timespec'.
func CStructToTimespec(cts CTimespecPtr) Timespec {
	t := (*C.struct_timespec)(cts)

	return Timespec{
		Sec:  int64(t.tv_sec),
		Nsec: int64(t.tv_nsec),
	}
}
<commit_msg>timespec: add a helper function to convert from Timespec to C<commit_after>package timespec

/*
#include <time.h>
*/
import "C"

import (
	"unsafe"

	"golang.org/x/sys/unix"
)

// Timespec behaves similarly to C's struct timespec.
// Timespec is used to retain fidelity to the C based file systems
// apis that could be lossy with the use of Go time types.
type Timespec unix.Timespec

// CTimespecPtr is an unsafe pointer wrapping C's `struct timespec`.
type CTimespecPtr unsafe.Pointer

// CStructToTimespec creates a new Timespec for the C 'struct timespec'.
func CStructToTimespec(cts CTimespecPtr) Timespec {
	t := (*C.struct_timespec)(cts)

	return Timespec{
		Sec:  int64(t.tv_sec),
		Nsec: int64(t.tv_nsec),
	}
}

// CopyToCStruct copies the time values from a Timespec to a previously
// allocated C `struct timespec`. Due to restrictions on Cgo the C pointer
// must be passed via the CTimespecPtr wrapper.
func CopyToCStruct(ts Timespec, cts CTimespecPtr) {
	t := (*C.struct_timespec)(cts)
	t.tv_sec = C.time_t(ts.Sec)
	t.tv_nsec = C.long(ts.Nsec)
}
<|endoftext|>


<commit_before>package mock

import (
	"sync"

	"github.com/btcsuite/btcd/wire"

	"github.com/lightningnetwork/lnd/chainntnfs"
)

// SpendNotifier extends the mock.ChainNotifier so that spend
// notifications can be triggered and delivered to subscribers.
type SpendNotifier struct {
	*ChainNotifier
	spendMap map[wire.OutPoint][]chan *chainntnfs.SpendDetail
	spends   map[wire.OutPoint]*chainntnfs.SpendDetail
	mtx      sync.Mutex
}

// MakeMockSpendNotifier creates a SpendNotifier.
func MakeMockSpendNotifier() *SpendNotifier {
	return &SpendNotifier{
		ChainNotifier: &ChainNotifier{
			SpendChan: make(chan *chainntnfs.SpendDetail),
			EpochChan: make(chan *chainntnfs.BlockEpoch),
			ConfChan:  make(chan *chainntnfs.TxConfirmation),
		},
		spendMap: make(map[wire.OutPoint][]chan *chainntnfs.SpendDetail),
		spends:   make(map[wire.OutPoint]*chainntnfs.SpendDetail),
	}
}

// RegisterSpendNtfn registers a spend notification for a specified outpoint.
func (s *SpendNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
	_ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {

	s.mtx.Lock()
	defer s.mtx.Unlock()

	spendChan := make(chan *chainntnfs.SpendDetail, 1)
	if detail, ok := s.spends[*outpoint]; ok {
		// Deliver spend immediately if details are already known.
		spendChan <- &chainntnfs.SpendDetail{
			SpentOutPoint:     detail.SpentOutPoint,
			SpendingHeight:    detail.SpendingHeight,
			SpendingTx:        detail.SpendingTx,
			SpenderTxHash:     detail.SpenderTxHash,
			SpenderInputIndex: detail.SpenderInputIndex,
		}
	} else {
		// Otherwise, queue the notification for delivery if the spend
		// is ever received.
		s.spendMap[*outpoint] = append(s.spendMap[*outpoint], spendChan)
	}

	return &chainntnfs.SpendEvent{
		Spend:  spendChan,
		Cancel: func() {},
	}, nil
}

// Spend dispatches SpendDetails to all subscribers of the outpoint. The details
// will includethe transaction and height provided by the caller.
func (s *SpendNotifier) Spend(outpoint *wire.OutPoint, height int32,
	txn *wire.MsgTx) {

	s.mtx.Lock()
	defer s.mtx.Unlock()

	txnHash := txn.TxHash()
	details := &chainntnfs.SpendDetail{
		SpentOutPoint:     outpoint,
		SpendingHeight:    height,
		SpendingTx:        txn,
		SpenderTxHash:     &txnHash,
		SpenderInputIndex: outpoint.Index,
	}

	// Cache details in case of late registration.
	if _, ok := s.spends[*outpoint]; !ok {
		s.spends[*outpoint] = details
	}

	// Deliver any backlogged spend notifications.
	if spendChans, ok := s.spendMap[*outpoint]; ok {
		delete(s.spendMap, *outpoint)
		for _, spendChan := range spendChans {
			spendChan <- &chainntnfs.SpendDetail{
				SpentOutPoint:     details.SpentOutPoint,
				SpendingHeight:    details.SpendingHeight,
				SpendingTx:        details.SpendingTx,
				SpenderTxHash:     details.SpenderTxHash,
				SpenderInputIndex: details.SpenderInputIndex,
			}
		}
	}
}
<commit_msg>lntest/mock: set input index on spend event<commit_after>package mock

import (
	"sync"

	"github.com/btcsuite/btcd/wire"

	"github.com/lightningnetwork/lnd/chainntnfs"
)

// SpendNotifier extends the mock.ChainNotifier so that spend
// notifications can be triggered and delivered to subscribers.
type SpendNotifier struct {
	*ChainNotifier
	spendMap map[wire.OutPoint][]chan *chainntnfs.SpendDetail
	spends   map[wire.OutPoint]*chainntnfs.SpendDetail
	mtx      sync.Mutex
}

// MakeMockSpendNotifier creates a SpendNotifier.
func MakeMockSpendNotifier() *SpendNotifier {
	return &SpendNotifier{
		ChainNotifier: &ChainNotifier{
			SpendChan: make(chan *chainntnfs.SpendDetail),
			EpochChan: make(chan *chainntnfs.BlockEpoch),
			ConfChan:  make(chan *chainntnfs.TxConfirmation),
		},
		spendMap: make(map[wire.OutPoint][]chan *chainntnfs.SpendDetail),
		spends:   make(map[wire.OutPoint]*chainntnfs.SpendDetail),
	}
}

// RegisterSpendNtfn registers a spend notification for a specified outpoint.
func (s *SpendNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
	_ []byte, heightHint uint32) (*chainntnfs.SpendEvent, error) {

	s.mtx.Lock()
	defer s.mtx.Unlock()

	spendChan := make(chan *chainntnfs.SpendDetail, 1)
	if detail, ok := s.spends[*outpoint]; ok {
		// Deliver spend immediately if details are already known.
		spendChan <- &chainntnfs.SpendDetail{
			SpentOutPoint:     detail.SpentOutPoint,
			SpendingHeight:    detail.SpendingHeight,
			SpendingTx:        detail.SpendingTx,
			SpenderTxHash:     detail.SpenderTxHash,
			SpenderInputIndex: detail.SpenderInputIndex,
		}
	} else {
		// Otherwise, queue the notification for delivery if the spend
		// is ever received.
		s.spendMap[*outpoint] = append(s.spendMap[*outpoint], spendChan)
	}

	return &chainntnfs.SpendEvent{
		Spend:  spendChan,
		Cancel: func() {},
	}, nil
}

// Spend dispatches SpendDetails to all subscribers of the outpoint. The details
// will includethe transaction and height provided by the caller.
func (s *SpendNotifier) Spend(outpoint *wire.OutPoint, height int32,
	txn *wire.MsgTx) {

	s.mtx.Lock()
	defer s.mtx.Unlock()

	var inputIndex uint32
	for i, in := range txn.TxIn {
		if in.PreviousOutPoint == *outpoint {
			inputIndex = uint32(i)
		}
	}

	txnHash := txn.TxHash()
	details := &chainntnfs.SpendDetail{
		SpentOutPoint:     outpoint,
		SpendingHeight:    height,
		SpendingTx:        txn,
		SpenderTxHash:     &txnHash,
		SpenderInputIndex: inputIndex,
	}

	// Cache details in case of late registration.
	if _, ok := s.spends[*outpoint]; !ok {
		s.spends[*outpoint] = details
	}

	// Deliver any backlogged spend notifications.
	if spendChans, ok := s.spendMap[*outpoint]; ok {
		delete(s.spendMap, *outpoint)
		for _, spendChan := range spendChans {
			spendChan <- &chainntnfs.SpendDetail{
				SpentOutPoint:     details.SpentOutPoint,
				SpendingHeight:    details.SpendingHeight,
				SpendingTx:        details.SpendingTx,
				SpenderTxHash:     details.SpenderTxHash,
				SpenderInputIndex: details.SpenderInputIndex,
			}
		}
	}
}
<|endoftext|>


<commit_before>package loadbalancer

import (
	"github.com/stretchr/testify/assert"
	"github.com/xtracdev/xavi/config"
	"testing"
	"net/http/httptest"
	"net/http"
	"net/url"
	"github.com/xtracdev/xavi/kvstore"
	"net"
	"context"
	"io/ioutil"
	"strconv"
)

func TestLBUtilsBuildFromConfig(t *testing.T) {
	kvs := config.BuildKVStoreTestConfig(t)
	assert.NotNil(t, kvs)
	sc, err := config.ReadServiceConfig("listener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("hello-backend")
	assert.Nil(t, err)
	assert.NotNil(t, lb)

	assert.Equal(t, "hello-backend", lb.BackendConfig.Name)
	assert.Equal(t, "", lb.BackendConfig.CACertPath)
	assert.Equal(t, 2, len(lb.BackendConfig.ServerNames))

	h, _ := lb.LoadBalancer.GetEndpoints()
	if assert.True(t, len(h) == 2) {
		assert.Equal(t, "localhost:3000", h[0])
		assert.Equal(t, "localhost:3100", h[1])
	}
}

func TestLBUtilsNoSuchBackend(t *testing.T) {
	kvs := config.BuildKVStoreTestConfig(t)
	assert.NotNil(t, kvs)
	sc, err := config.ReadServiceConfig("listener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("no-such-backed")
	assert.Nil(t, lb)
	assert.NotNil(t, err)
	assert.Equal(t, ErrBackendNotFound, err)
}

func buildTestConfigForLBCall(t *testing.T, urlStr string)kvstore.KVStore {
	kvs, _ := kvstore.NewHashKVStore("")

	url,_ := url.Parse(urlStr)
	host,port,err := net.SplitHostPort(url.Host)
	assert.Nil(t,err)

	portVal,err := strconv.Atoi(port)
	assert.Nil(t,err)

	ln := &config.ListenerConfig{"lbclistener", []string{"lbcroute1"}}
	err = ln.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	serverConfig1 := &config.ServerConfig{"lbcserver1", host, portVal, "/hello", "none", 0, 0}
	err = serverConfig1.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	r := &config.RouteConfig{
		Name:     "lbcroute1",
		URIRoot:  "/hello",
		Backends: []string{"lbcbackend"},
		Plugins:  []string{"Logging"},
		MsgProps: "",
	}
	err = r.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	b := &config.BackendConfig{
		Name:        "lbcbackend",
		ServerNames: []string{"lbcserver1"},
	}
	err = b.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	return kvs
}

func TestLBUtilsCallSvc(t *testing.T) {

	serverResp := "Hello, client"
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(serverResp))
	}))
	defer ts.Close()

	kvs := buildTestConfigForLBCall(t, ts.URL)
	sc, err := config.ReadServiceConfig("lbclistener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("lbcbackend")
	assert.Nil(t, err)

	req,err := http.NewRequest("GET","/foo",nil)
	assert.Nil(t,err)
	resp, err := lb.DoWithLoadbalancer(context.Background(), req, false)
	if assert.Nil(t, err) {
		defer resp.Body.Close()
		b,err := ioutil.ReadAll(resp.Body)
		assert.Nil(t,err)
		assert.Equal(t, serverResp,string(b))
	}
}
<commit_msg>Added two servers and check of round robin behavior in lb call test<commit_after>package loadbalancer

import (
	"github.com/stretchr/testify/assert"
	"github.com/xtracdev/xavi/config"
	"testing"
	"net/http/httptest"
	"net/http"
	"net/url"
	"github.com/xtracdev/xavi/kvstore"
	"net"
	"context"
	"io/ioutil"
	"strconv"
)

func TestLBUtilsBuildFromConfig(t *testing.T) {
	kvs := config.BuildKVStoreTestConfig(t)
	assert.NotNil(t, kvs)
	sc, err := config.ReadServiceConfig("listener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("hello-backend")
	assert.Nil(t, err)
	assert.NotNil(t, lb)

	assert.Equal(t, "hello-backend", lb.BackendConfig.Name)
	assert.Equal(t, "", lb.BackendConfig.CACertPath)
	assert.Equal(t, 2, len(lb.BackendConfig.ServerNames))

	h, _ := lb.LoadBalancer.GetEndpoints()
	if assert.True(t, len(h) == 2) {
		assert.Equal(t, "localhost:3000", h[0])
		assert.Equal(t, "localhost:3100", h[1])
	}
}

func TestLBUtilsNoSuchBackend(t *testing.T) {
	kvs := config.BuildKVStoreTestConfig(t)
	assert.NotNil(t, kvs)
	sc, err := config.ReadServiceConfig("listener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("no-such-backed")
	assert.Nil(t, lb)
	assert.NotNil(t, err)
	assert.Equal(t, ErrBackendNotFound, err)
}

func buildTestConfigForLBCall(t *testing.T, server1Url, server2Url string)kvstore.KVStore {
	kvs, _ := kvstore.NewHashKVStore("")

	//Define listener
	ln := &config.ListenerConfig{"lbclistener", []string{"lbcroute1"}}
	err := ln.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	//Define server 1
	url,_ := url.Parse(server1Url)
	host,port,err := net.SplitHostPort(url.Host)
	assert.Nil(t,err)

	portVal,err := strconv.Atoi(port)
	assert.Nil(t,err)

	serverConfig1 := &config.ServerConfig{"lbcserver1", host, portVal, "/hello", "none", 0, 0}
	err = serverConfig1.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	//Define server 2
	url,_ = url.Parse(server2Url)
	host,port,err = net.SplitHostPort(url.Host)
	assert.Nil(t,err)

	portVal,err = strconv.Atoi(port)
	assert.Nil(t,err)

	serverConfig2 := &config.ServerConfig{"lbcserver2", host, portVal, "/hello", "none", 0, 0}
	err = serverConfig2.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	//Define route
	r := &config.RouteConfig{
		Name:     "lbcroute1",
		URIRoot:  "/hello",
		Backends: []string{"lbcbackend"},
		Plugins:  []string{"Logging"},
		MsgProps: "",
	}
	err = r.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	b := &config.BackendConfig{
		Name:        "lbcbackend",
		ServerNames: []string{"lbcserver1","lbcserver2"},
	}
	err = b.Store(kvs)
	if err != nil {
		t.Fatal(err)
	}

	return kvs
}

func TestLBUtilsCallSvc(t *testing.T) {

	serverResp := "Hello, client"
	var server1Called, server2Called bool

	server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		server1Called = true
		w.Write([]byte(serverResp))
	}))
	defer server1.Close()

	server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		server2Called = true
		w.Write([]byte(serverResp))
	}))
	defer server2.Close()

	kvs := buildTestConfigForLBCall(t, server1.URL, server2.URL)
	sc, err := config.ReadServiceConfig("lbclistener", kvs)
	assert.Nil(t, err)
	assert.NotNil(t, sc)

	config.RecordActiveConfig(sc)

	lb, err := NewBackendLoadBalancer("lbcbackend")
	assert.Nil(t, err)

	req,err := http.NewRequest("GET","/foo",nil)
	assert.Nil(t,err)

	//Call 1
	resp, err := lb.DoWithLoadbalancer(context.Background(), req, false)
	if assert.Nil(t, err) {
		defer resp.Body.Close()
		b,err := ioutil.ReadAll(resp.Body)
		assert.Nil(t,err)
		assert.Equal(t, serverResp,string(b))
	}

	//Call 2
	resp, err = lb.DoWithLoadbalancer(context.Background(), req, false)
	if assert.Nil(t, err) {
		defer resp.Body.Close()
		b,err := ioutil.ReadAll(resp.Body)
		assert.Nil(t,err)
		assert.Equal(t, serverResp,string(b))
	}

	//Make sure both servers were called
	assert.True(t, server1Called, "Expected server 1 to be called")
	assert.True(t, server2Called, "Expected server 2 to be called")
}
<|endoftext|>


<commit_before>package main

import (
	"log"
    "sync"
	"reflect"
    "time"
	"math"
)

type T interface{}

func makeChannel(t reflect.Type, chanDir reflect.ChanDir, buffer int) reflect.Value {
	ctype := reflect.ChanOf(chanDir, t)
	return reflect.MakeChan(ctype, buffer)
}

type TChan chan T
type TOutChan <- chan T

func chanFromValues(data ...T) TOutChan {
	out := make(chan T)

	go func() {
        for _, d := range data {
            out <- d
        }
        close(out)
    }()

    return out
}

func chanFromSlice(array T) TOutChan {
	value := reflect.ValueOf(array)
	if value.Kind() != reflect.Slice {
		panic("Parameter must be a slice")
	}

	out := make(chan T)

	go func() {
		for i := 0; i != value.Len(); i++ {
			out <- value.Index(i).Interface()
		}
		close(out)
	}()

	return out
}

func chanFromInts(nums ...int) <-chan int {
	out := make(chan int)

	go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()

    return out
}

func chanFromFloats(nums ...float64) <-chan float64 {
	out := make(chan float64)

	go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()

    return out
}

func chanFromStrings(stringi ...string) <-chan string {
	out := make(chan string)

	go func() {
        for _, n := range stringi {
            out <- n
        }
        close(out)
    }()

    return out
}

type Tuple struct {
	Key interface{}
	Value interface{}
	Meta interface{}
}

func checkRunFunction(f T) (vf reflect.Value) {
	vf = reflect.ValueOf(f)
	ftype := vf.Type()

	if ftype.Kind() != reflect.Func {
		log.Panicf("`f` should be %s but got %s", reflect.Func, ftype.Kind())
	}
	if ftype.NumIn() != 1 {
		log.Panicf("`f` should have 1 parameter but it has %d parameters", ftype.NumIn())
	}
	if ftype.NumOut() != 1 {
		log.Panicf("`f` should return 1 value but it returns %d values", ftype.NumOut())
	}

	return
}

func checkRunTuple(xs TupleOutChan) {
	vxs := reflect.ValueOf(xs)
	xstype := vxs.Type()

	if xstype.Kind() != reflect.Chan {
		log.Panicf("`f` should be %s but got %s", reflect.Chan, xstype.Kind())
	}

	return
}

func runSyncAsyncTupleSingle(xs TupleOutChan, async bool, f T) TupleOutChan {
	vf := checkRunFunction(f)
	checkRunTuple(xs)

	out := make(chan Tuple)

	go func() {
		var wg sync.WaitGroup

		for tup := range xs {
			wg.Add(1)
			fx := func(tup Tuple) {
				valRes := vf.Call([]reflect.Value{ reflect.ValueOf(tup.Value) })[0].Interface()
				out <- NewTupleVal(tup, valRes)
				wg.Done()
			}
			if(async) {
				go fx(tup)
			} else {
				fx(tup)
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func filterSyncAsyncTupleSingle(xs TupleOutChan, async bool, f T) TupleOutChan {
	vf := checkRunFunction(f)
	checkRunTuple(xs)

	out := make(chan Tuple)

	go func() {
		var wg sync.WaitGroup

		for tup := range xs {
			wg.Add(1)
			fx := func(tup Tuple) {
				valRes := vf.Call([]reflect.Value{ reflect.ValueOf(tup.Value) })[0].Interface()
				if valRes.(bool) {
					out <- tup
				}
				wg.Done()
			}
			if(async) {
				go fx(tup)
			} else {
				fx(tup)
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func runSyncAsyncTuple(xs TupleOutChan, async bool, f ...T) TupleOutChan {
	var ch TupleOutChan
	ch = xs
	for m := range f {
		ch = runSyncAsyncTupleSingle(ch, async, f[m])
	}
	return ch
}

func filterSyncAsyncTuple(xs TupleOutChan, async bool, f ...T) TupleOutChan {
	var ch TupleOutChan
	ch = xs
	for m := range f {
		ch = filterSyncAsyncTupleSingle(ch, async, f[m])
	}
	return ch
}

func runSyncAsyncSingle(xs T, f T, async bool) TOutChan {
	vf := reflect.ValueOf(f)
	ftype := vf.Type()
	if ftype.Kind() != reflect.Func {
		log.Panicf("`f` should be %s but got %s", reflect.Func, ftype.Kind())
	}
	if ftype.NumIn() != 1 {
		log.Panicf("`f` should have 1 parameter but it has %d parameters", ftype.NumIn())
	}
	if ftype.NumOut() != 1 {
		log.Panicf("`f` should return 1 value but it returns %d values", ftype.NumOut())
	}

	vxs := reflect.ValueOf(xs)
	xstype := vxs.Type()

	if xstype.Kind() != reflect.Chan {
		log.Panicf("`f` should be %s but got %s", reflect.Chan, xstype.Kind())
	}

	// elIn := vf.Type().In(0)
	// // elOut := vf.Type().Out(0)

	// elemType := xstype.Elem()

	// if elemType != elIn {
	// 	log.Panicf("`f` parameter must be %s but got %s", elemType, elIn)
	// }

	out := make(chan T)

	go func() {
		var wg sync.WaitGroup

		for ok := true; ok; {
			var elem reflect.Value
			if elem, ok = vxs.Recv(); ok {
				wg.Add(1)
				fx := func(elem reflect.Value) {
					// rx := vf.Call([]reflect.Value{ elem })[0].Interface()
					// elem.Interface()
					out <- vf.Call([]reflect.Value{ reflect.ValueOf(elem.Interface()) })[0].Interface()
					wg.Done()
				}
				if(async) {
					go fx(elem)
				} else {
					fx(elem)
				}
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func runSyncAsync(xs T, async bool, f ...T) TOutChan {
	var ch interface{}
	ch = xs
	for m := range f {
		ch = runSyncAsyncSingle(ch, f[m], async)
	}
	return ch.(TOutChan)
}

type TupleChan chan Tuple
type TupleOutChan <- chan Tuple

func NewTuple(k interface{}, v interface{}) Tuple {
	return Tuple{k, v, nil}
}

func NewTupleVal(t Tuple, v interface{}) Tuple {
	return Tuple{t.Key, v, t.Meta}
}

func MakeTupleChan(data ...T) TupleOutChan {
	out := make(chan Tuple)

	go func() {
		i := 0

		for _, d := range data {
			out <- NewTuple(i, d)
			i++
		}

		close(out)
	}()

	return out
}

func MakeTupleChanFromChan(data interface{}) TupleOutChan {
	out := make(chan Tuple)

	dataVal := reflect.ValueOf(data)
	if dataVal.Kind() != reflect.Chan {
		panic("data parameter must be a chan")
	}

	go func() {
		i := 0

		var elem reflect.Value
		for ok := true; ok; {
			if elem, ok = dataVal.Recv(); ok {
				out <- NewTuple(i, elem.Interface())
				i++
			}
		}

		close(out)
	}()

	return out
}

func MakeTupleChanFromSlice(array T) TupleOutChan {
	value := reflect.ValueOf(array)
	if value.Kind() != reflect.Slice {
		panic("Parameter must be a slice")
	}

	out := make(chan Tuple)

	go func() {
		for i := 0; i != value.Len(); i++ {
			out <- NewTuple(i, value.Index(i).Interface())
		}
		close(out)
	}()

	return out
}

func MakeTupleFloat64Chan(data ...float64) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleFloat32Chan(data ...float32) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleInt64Chan(data ...int64) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleInt32Chan(data ...int32) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleIntChan(data ...int) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleStringChan(data ...string) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleBoolChan(data ...bool) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func (ch TupleOutChan) Apply(f T) TupleOutChan {
	return runSyncAsyncTuple(ch, true, f)
}

func (ch TupleOutChan) ApplyAll(f ...T) TupleOutChan {
	return runSyncAsyncTuple(ch, true, f...)
}

func (ch TupleOutChan) Filter(f T) TupleOutChan {
	return filterSyncAsyncTuple(ch, true, f)
}

func (ch TupleOutChan) FilterAll(f ...T) TupleOutChan {
	return filterSyncAsyncTuple(ch, true, f...)
}

func ApplyStream(s StreamI) StreamI {
	out := make(chan Tuple)

	go func() {
		s.Run()
		close(out)
	}()

	<- out

	return s
}

func RunStreams(data ...StreamI) <- chan StreamI {
	dataStream := make(chan StreamI)
	out := make(chan StreamI)

	go func() {
        for _, d := range data {
            dataStream <- d
        }
        close(dataStream)
    }()

    go func() {
    	for s := range runSyncAsync(dataStream, true, ApplyStream) {
    		out <- s.(StreamI)
    	}
    	close(out)
    }()

    return out
}

func RunStreamsAndWait(data ...StreamI) {
	for _ = range RunStreams(data...) {}
}

type StreamFunction func ()
type StreamProcessFunction interface{}

type Stream struct {
	id T
	function StreamFunction
	in 	*TupleOutChan
	out TupleChan
}

func (s Stream) Id() interface{} {
	return s.id
}

func (s Stream) SetData(data *TupleOutChan) {
	s.in = data
}

func (s Stream) Items() <- chan Tuple {
	return s.out
}

func (s Stream) Run() {
	s.function()
}

func NewStream(id T, f StreamFunction) Stream {
	return Stream{ id, f, nil, make(TupleChan) }
}

type StreamProcess struct {
	Stream
	function StreamProcessFunction
}

func (s StreamProcess) Run() {
	for x := range runSyncAsyncTuple(*s.in, true, s.function) {
		s.out <- x
	}
}

func NewStreamProcess(id T, data TupleOutChan, f StreamProcessFunction) StreamProcess {
	s := StreamProcess{}
	s.id = id
	s.in = &data
	s.out = make(TupleChan)
	s.function = f
	return s
}

type StreamReaderFunction func(t Tuple)

type StreamReader struct {
	stream StreamI
	function StreamReaderFunction
}

func (sr StreamReader) ReadStream(s StreamI) {
	for t := range s.Items() {
		sr.OnRead(t)
	}
}

func (sr StreamReader) OnRead(t Tuple) {
	sr.function(t)
}

func NewStreamReader(f StreamReaderFunction) StreamReader {
	return StreamReader{nil, f}
}

func ReadStream(s StreamI, f StreamReaderFunction) {
	NewStreamReader(f).ReadStream(s)
}

type StreamReaderI interface {
	ReadStream(s StreamI)
	OnRead(t Tuple)
}

type StreamI interface {
	Id() interface{}
	Items() <- chan Tuple
	Run()
}<commit_msg>Initial commit<commit_after>package main

import (
	"log"
    "sync"
	"reflect"
)

type T interface{}

func makeChannel(t reflect.Type, chanDir reflect.ChanDir, buffer int) reflect.Value {
	ctype := reflect.ChanOf(chanDir, t)
	return reflect.MakeChan(ctype, buffer)
}

type TChan chan T
type TOutChan <- chan T

func chanFromValues(data ...T) TOutChan {
	out := make(chan T)

	go func() {
        for _, d := range data {
            out <- d
        }
        close(out)
    }()

    return out
}

func chanFromSlice(array T) TOutChan {
	value := reflect.ValueOf(array)
	if value.Kind() != reflect.Slice {
		panic("Parameter must be a slice")
	}

	out := make(chan T)

	go func() {
		for i := 0; i != value.Len(); i++ {
			out <- value.Index(i).Interface()
		}
		close(out)
	}()

	return out
}

func chanFromInts(nums ...int) <-chan int {
	out := make(chan int)

	go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()

    return out
}

func chanFromFloats(nums ...float64) <-chan float64 {
	out := make(chan float64)

	go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()

    return out
}

func chanFromStrings(stringi ...string) <-chan string {
	out := make(chan string)

	go func() {
        for _, n := range stringi {
            out <- n
        }
        close(out)
    }()

    return out
}

type Tuple struct {
	Key interface{}
	Value interface{}
	Meta interface{}
}

func checkRunFunction(f T) (vf reflect.Value) {
	vf = reflect.ValueOf(f)
	ftype := vf.Type()

	if ftype.Kind() != reflect.Func {
		log.Panicf("`f` should be %s but got %s", reflect.Func, ftype.Kind())
	}
	if ftype.NumIn() != 1 {
		log.Panicf("`f` should have 1 parameter but it has %d parameters", ftype.NumIn())
	}
	if ftype.NumOut() != 1 {
		log.Panicf("`f` should return 1 value but it returns %d values", ftype.NumOut())
	}

	return
}

func checkRunTuple(xs TupleOutChan) {
	vxs := reflect.ValueOf(xs)
	xstype := vxs.Type()

	if xstype.Kind() != reflect.Chan {
		log.Panicf("`f` should be %s but got %s", reflect.Chan, xstype.Kind())
	}

	return
}

func runSyncAsyncTupleSingle(xs TupleOutChan, async bool, f T) TupleOutChan {
	vf := checkRunFunction(f)
	checkRunTuple(xs)

	out := make(chan Tuple)

	go func() {
		var wg sync.WaitGroup

		for tup := range xs {
			wg.Add(1)
			fx := func(tup Tuple) {
				valRes := vf.Call([]reflect.Value{ reflect.ValueOf(tup.Value) })[0].Interface()
				out <- NewTupleVal(tup, valRes)
				wg.Done()
			}
			if(async) {
				go fx(tup)
			} else {
				fx(tup)
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func filterSyncAsyncTupleSingle(xs TupleOutChan, async bool, f T) TupleOutChan {
	vf := checkRunFunction(f)
	checkRunTuple(xs)

	out := make(chan Tuple)

	go func() {
		var wg sync.WaitGroup

		for tup := range xs {
			wg.Add(1)
			fx := func(tup Tuple) {
				valRes := vf.Call([]reflect.Value{ reflect.ValueOf(tup.Value) })[0].Interface()
				if valRes.(bool) {
					out <- tup
				}
				wg.Done()
			}
			if(async) {
				go fx(tup)
			} else {
				fx(tup)
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func runSyncAsyncTuple(xs TupleOutChan, async bool, f ...T) TupleOutChan {
	var ch TupleOutChan
	ch = xs
	for m := range f {
		ch = runSyncAsyncTupleSingle(ch, async, f[m])
	}
	return ch
}

func filterSyncAsyncTuple(xs TupleOutChan, async bool, f ...T) TupleOutChan {
	var ch TupleOutChan
	ch = xs
	for m := range f {
		ch = filterSyncAsyncTupleSingle(ch, async, f[m])
	}
	return ch
}

func runSyncAsyncSingle(xs T, f T, async bool) TOutChan {
	vf := reflect.ValueOf(f)
	ftype := vf.Type()
	if ftype.Kind() != reflect.Func {
		log.Panicf("`f` should be %s but got %s", reflect.Func, ftype.Kind())
	}
	if ftype.NumIn() != 1 {
		log.Panicf("`f` should have 1 parameter but it has %d parameters", ftype.NumIn())
	}
	if ftype.NumOut() != 1 {
		log.Panicf("`f` should return 1 value but it returns %d values", ftype.NumOut())
	}

	vxs := reflect.ValueOf(xs)
	xstype := vxs.Type()

	if xstype.Kind() != reflect.Chan {
		log.Panicf("`f` should be %s but got %s", reflect.Chan, xstype.Kind())
	}

	// elIn := vf.Type().In(0)
	// // elOut := vf.Type().Out(0)

	// elemType := xstype.Elem()

	// if elemType != elIn {
	// 	log.Panicf("`f` parameter must be %s but got %s", elemType, elIn)
	// }

	out := make(chan T)

	go func() {
		var wg sync.WaitGroup

		for ok := true; ok; {
			var elem reflect.Value
			if elem, ok = vxs.Recv(); ok {
				wg.Add(1)
				fx := func(elem reflect.Value) {
					// rx := vf.Call([]reflect.Value{ elem })[0].Interface()
					// elem.Interface()
					out <- vf.Call([]reflect.Value{ reflect.ValueOf(elem.Interface()) })[0].Interface()
					wg.Done()
				}
				if(async) {
					go fx(elem)
				} else {
					fx(elem)
				}
			}
		}

		wg.Wait()
		close(out)
	}()

	return out
}

func runSyncAsync(xs T, async bool, f ...T) TOutChan {
	var ch interface{}
	ch = xs
	for m := range f {
		ch = runSyncAsyncSingle(ch, f[m], async)
	}
	return ch.(TOutChan)
}

type TupleChan chan Tuple
type TupleOutChan <- chan Tuple

func NewTuple(k interface{}, v interface{}) Tuple {
	return Tuple{k, v, nil}
}

func NewTupleVal(t Tuple, v interface{}) Tuple {
	return Tuple{t.Key, v, t.Meta}
}

func MakeTupleChan(data ...T) TupleOutChan {
	out := make(chan Tuple)

	go func() {
		i := 0

		for _, d := range data {
			out <- NewTuple(i, d)
			i++
		}

		close(out)
	}()

	return out
}

func MakeTupleChanFromChan(data interface{}) TupleOutChan {
	out := make(chan Tuple)

	dataVal := reflect.ValueOf(data)
	if dataVal.Kind() != reflect.Chan {
		panic("data parameter must be a chan")
	}

	go func() {
		i := 0

		var elem reflect.Value
		for ok := true; ok; {
			if elem, ok = dataVal.Recv(); ok {
				out <- NewTuple(i, elem.Interface())
				i++
			}
		}

		close(out)
	}()

	return out
}

func MakeTupleChanFromSlice(array T) TupleOutChan {
	value := reflect.ValueOf(array)
	if value.Kind() != reflect.Slice {
		panic("Parameter must be a slice")
	}

	out := make(chan Tuple)

	go func() {
		for i := 0; i != value.Len(); i++ {
			out <- NewTuple(i, value.Index(i).Interface())
		}
		close(out)
	}()

	return out
}

func MakeTupleFloat64Chan(data ...float64) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleFloat32Chan(data ...float32) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleInt64Chan(data ...int64) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleInt32Chan(data ...int32) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleIntChan(data ...int) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleStringChan(data ...string) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func MakeTupleBoolChan(data ...bool) TupleOutChan {
	return MakeTupleChanFromSlice(data)
}

func (ch TupleOutChan) Apply(f T) TupleOutChan {
	return runSyncAsyncTuple(ch, true, f)
}

func (ch TupleOutChan) ApplyAll(f ...T) TupleOutChan {
	return runSyncAsyncTuple(ch, true, f...)
}

func (ch TupleOutChan) Filter(f T) TupleOutChan {
	return filterSyncAsyncTuple(ch, true, f)
}

func (ch TupleOutChan) FilterAll(f ...T) TupleOutChan {
	return filterSyncAsyncTuple(ch, true, f...)
}

func ApplyStream(s StreamI) StreamI {
	out := make(chan Tuple)

	go func() {
		s.Run()
		close(out)
	}()

	<- out

	return s
}

func RunStreams(data ...StreamI) <- chan StreamI {
	dataStream := make(chan StreamI)
	out := make(chan StreamI)

	go func() {
        for _, d := range data {
            dataStream <- d
        }
        close(dataStream)
    }()

    go func() {
    	for s := range runSyncAsync(dataStream, true, ApplyStream) {
    		out <- s.(StreamI)
    	}
    	close(out)
    }()

    return out
}

func RunStreamsAndWait(data ...StreamI) {
	for _ = range RunStreams(data...) {}
}

type StreamFunction func ()
type StreamProcessFunction interface{}

type Stream struct {
	id T
	function StreamFunction
	in 	*TupleOutChan
	out TupleChan
}

func (s Stream) Id() interface{} {
	return s.id
}

func (s Stream) SetData(data *TupleOutChan) {
	s.in = data
}

func (s Stream) Items() <- chan Tuple {
	return s.out
}

func (s Stream) Run() {
	s.function()
}

func NewStream(id T, f StreamFunction) Stream {
	return Stream{ id, f, nil, make(TupleChan) }
}

type StreamProcess struct {
	Stream
	function StreamProcessFunction
}

func (s StreamProcess) Run() {
	for x := range runSyncAsyncTuple(*s.in, true, s.function) {
		s.out <- x
	}
}

func NewStreamProcess(id T, data TupleOutChan, f StreamProcessFunction) StreamProcess {
	s := StreamProcess{}
	s.id = id
	s.in = &data
	s.out = make(TupleChan)
	s.function = f
	return s
}

type StreamReaderFunction func(t Tuple)

type StreamReader struct {
	stream StreamI
	function StreamReaderFunction
}

func (sr StreamReader) ReadStream(s StreamI) {
	for t := range s.Items() {
		sr.OnRead(t)
	}
}

func (sr StreamReader) OnRead(t Tuple) {
	sr.function(t)
}

func NewStreamReader(f StreamReaderFunction) StreamReader {
	return StreamReader{nil, f}
}

func ReadStream(s StreamI, f StreamReaderFunction) {
	NewStreamReader(f).ReadStream(s)
}

type StreamReaderI interface {
	ReadStream(s StreamI)
	OnRead(t Tuple)
}

type StreamI interface {
	Id() interface{}
	Items() <- chan Tuple
	Run()
}<|endoftext|>


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

package com

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

// AppendStr appends string to slice with no duplicates.
func AppendStr(strs []string, str string) []string {
	for _, s := range strs {
		if s == str {
			return strs
		}
	}
	return append(strs, str)
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements and order are both the same.
func CompareSliceStr(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		if s1[i] != s2[i] {
			return false
		}
	}

	return true
}

// CompareSliceStrU compares two 'string' type slices.
// It returns true if elements are the same, and ignores the order.
func CompareSliceStrU(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		for j := len(s2) - 1; j >= 0; j-- {
			if s1[i] == s2[j] {
				s2 = append(s2[:j], s2[j+1:]...)
				break
			}
		}
	}
	if len(s2) > 0 {
		return false
	}
	return true
}

// IsSliceContainsStr returns true if the string exists in given slice.
func IsSliceContainsStr(sl []string, str string) bool {
	str = strings.ToLower(str)
	for _, s := range sl {
		if strings.ToLower(s) == str {
			return true
		}
	}
	return false
}

// IsSliceContainsInt64 returns true if the int64 exists in given slice.
func IsSliceContainsInt64(sl []int64, i int64) bool {
	for _, s := range sl {
		if s == i {
			return true
		}
	}
	return false
}

// ==============================
type reducetype func(interface{}) interface{}
type filtertype func(interface{}) bool

func InSlice(v string, sl []string) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InSliceIface(v interface{}, sl []interface{}) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func SliceRandList(min, max int) []int {
	if max < min {
		min, max = max, min
	}
	length := max - min + 1
	t0 := time.Now()
	rand.Seed(int64(t0.Nanosecond()))
	list := rand.Perm(length)
	for index := range list {
		list[index] += min
	}
	return list
}

func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) {
	c = append(slice1, slice2...)
	return
}

func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) {
	for _, v := range slice {
		dslice = append(dslice, a(v))
	}
	return
}

func SliceRand(a []interface{}) (b interface{}) {
	randnum := rand.Intn(len(a))
	b = a[randnum]
	return
}

func SliceSum(intslice []int64) (sum int64) {
	for _, v := range intslice {
		sum += v
	}
	return
}

func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) {
	for _, v := range slice {
		if a(v) {
			ftslice = append(ftslice, v)
		}
	}
	return
}

func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) {
	for _, v := range slice1 {
		if !InSliceIface(v, slice2) {
			diffslice = append(diffslice, v)
		}
	}
	return
}

func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) {
	for _, v := range slice1 {
		if !InSliceIface(v, slice2) {
			diffslice = append(diffslice, v)
		}
	}
	return
}

func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) {
	if size >= len(slice) {
		chunkslice = append(chunkslice, slice)
		return
	}
	end := size
	for i := 0; i <= (len(slice) - size); i += size {
		chunkslice = append(chunkslice, slice[i:end])
		end += size
	}
	return
}

func SliceRange(start, end, step int64) (intslice []int64) {
	for i := start; i <= end; i += step {
		intslice = append(intslice, i)
	}
	return
}

func SlicePad(slice []interface{}, size int, val interface{}) []interface{} {
	if size <= len(slice) {
		return slice
	}
	for i := 0; i < (size - len(slice)); i++ {
		slice = append(slice, val)
	}
	return slice
}

func SliceUnique(slice []interface{}) (uniqueslice []interface{}) {
	for _, v := range slice {
		if !InSliceIface(v, uniqueslice) {
			uniqueslice = append(uniqueslice, v)
		}
	}
	return
}

func SliceShuffle(slice []interface{}) []interface{} {
	for i := 0; i < len(slice); i++ {
		a := rand.Intn(len(slice))
		b := rand.Intn(len(slice))
		slice[a], slice[b] = slice[b], slice[a]
	}
	return slice
}

func SliceInsert(slice, insertion []interface{}, index int) []interface{} {
	result := make([]interface{}, len(slice)+len(insertion))
	at := copy(result, slice[:index])
	at += copy(result[at:], insertion)
	copy(result[at:], slice[index:])
	return result
}

//SliceRemove SliceRomove(a,4,5) //a[4]
func SliceRemove(slice []interface{}, start int, args ...int) []interface{} {
	var end int
	if len(args) == 0 {
		end = start + 1
	} else {
		end = args[0]
	}
	if end > len(slice)-1 {
		return slice[:start]
	}
	return append(slice[:start], slice[end:]...)
}

// SliceRemoveCallback : 根据条件删除
// a=[]int{1,2,3,4,5,6}
// SliceRemoveCallback(len(a), func(i int) func(bool)error{
//	if a[i]!=4 {
//	 	return nil
// 	}
// 	return func(inside bool)error{
//		if inside {
//			a=append(a[0:i],a[i+1:]...)
// 		}else{
//			a=a[0:i]
//		}
//		return nil
// 	}
//})
func SliceRemoveCallback(length int, callback func(int) func(bool) error) error {
	for i, j := 0, length-1; i <= j; i++ {
		if removeFunc := callback(i); removeFunc != nil {
			var err error
			if i+1 <= j {
				err = removeFunc(true)
			} else {
				err = removeFunc(false)
			}
			if err != nil {
				return err
			}
			i--
			j--
		}
	}
	return nil
}
<commit_msg>update<commit_after>// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package com

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

// AppendStr appends string to slice with no duplicates.
func AppendStr(strs []string, str string) []string {
	for _, s := range strs {
		if s == str {
			return strs
		}
	}
	return append(strs, str)
}

// CompareSliceStr compares two 'string' type slices.
// It returns true if elements and order are both the same.
func CompareSliceStr(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		if s1[i] != s2[i] {
			return false
		}
	}

	return true
}

// CompareSliceStrU compares two 'string' type slices.
// It returns true if elements are the same, and ignores the order.
func CompareSliceStrU(s1, s2 []string) bool {
	if len(s1) != len(s2) {
		return false
	}

	for i := range s1 {
		for j := len(s2) - 1; j >= 0; j-- {
			if s1[i] == s2[j] {
				s2 = append(s2[:j], s2[j+1:]...)
				break
			}
		}
	}
	if len(s2) > 0 {
		return false
	}
	return true
}

// IsSliceContainsStr returns true if the string exists in given slice.
func IsSliceContainsStr(sl []string, str string) bool {
	str = strings.ToLower(str)
	for _, s := range sl {
		if strings.ToLower(s) == str {
			return true
		}
	}
	return false
}

// IsSliceContainsInt64 returns true if the int64 exists in given slice.
func IsSliceContainsInt64(sl []int64, i int64) bool {
	for _, s := range sl {
		if s == i {
			return true
		}
	}
	return false
}

// ==============================
type reducetype func(interface{}) interface{}
type filtertype func(interface{}) bool

func InSlice(v string, sl []string) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InSliceIface(v interface{}, sl []interface{}) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InStringSlice(v string, sl []string) bool {
	return InSlice(v, sl)
}

func InInterfaceSlice(v interface{}, sl []interface{}) bool {
	return InSliceIface(v, sl)
}

func InIntSlice(v int, sl []int) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InInt32Slice(v int32, sl []int32) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InInt16Slice(v int16, sl []int16) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InInt64Slice(v int64, sl []int64) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InUintSlice(v uint, sl []uint) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InUint32Slice(v uint32, sl []uint32) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InUint16Slice(v uint16, sl []uint16) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func InUint64Slice(v uint64, sl []uint64) bool {
	for _, vv := range sl {
		if vv == v {
			return true
		}
	}
	return false
}

func SliceRandList(min, max int) []int {
	if max < min {
		min, max = max, min
	}
	length := max - min + 1
	t0 := time.Now()
	rand.Seed(int64(t0.Nanosecond()))
	list := rand.Perm(length)
	for index := range list {
		list[index] += min
	}
	return list
}

func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) {
	c = append(slice1, slice2...)
	return
}

func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) {
	for _, v := range slice {
		dslice = append(dslice, a(v))
	}
	return
}

func SliceRand(a []interface{}) (b interface{}) {
	randnum := rand.Intn(len(a))
	b = a[randnum]
	return
}

func SliceSum(intslice []int64) (sum int64) {
	for _, v := range intslice {
		sum += v
	}
	return
}

func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) {
	for _, v := range slice {
		if a(v) {
			ftslice = append(ftslice, v)
		}
	}
	return
}

func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) {
	for _, v := range slice1 {
		if !InSliceIface(v, slice2) {
			diffslice = append(diffslice, v)
		}
	}
	return
}

func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) {
	for _, v := range slice1 {
		if !InSliceIface(v, slice2) {
			diffslice = append(diffslice, v)
		}
	}
	return
}

func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) {
	if size >= len(slice) {
		chunkslice = append(chunkslice, slice)
		return
	}
	end := size
	for i := 0; i <= (len(slice) - size); i += size {
		chunkslice = append(chunkslice, slice[i:end])
		end += size
	}
	return
}

func SliceRange(start, end, step int64) (intslice []int64) {
	for i := start; i <= end; i += step {
		intslice = append(intslice, i)
	}
	return
}

func SlicePad(slice []interface{}, size int, val interface{}) []interface{} {
	if size <= len(slice) {
		return slice
	}
	for i := 0; i < (size - len(slice)); i++ {
		slice = append(slice, val)
	}
	return slice
}

func SliceUnique(slice []interface{}) (uniqueslice []interface{}) {
	for _, v := range slice {
		if !InSliceIface(v, uniqueslice) {
			uniqueslice = append(uniqueslice, v)
		}
	}
	return
}

func SliceShuffle(slice []interface{}) []interface{} {
	for i := 0; i < len(slice); i++ {
		a := rand.Intn(len(slice))
		b := rand.Intn(len(slice))
		slice[a], slice[b] = slice[b], slice[a]
	}
	return slice
}

func SliceInsert(slice, insertion []interface{}, index int) []interface{} {
	result := make([]interface{}, len(slice)+len(insertion))
	at := copy(result, slice[:index])
	at += copy(result[at:], insertion)
	copy(result[at:], slice[index:])
	return result
}

//SliceRemove SliceRomove(a,4,5) //a[4]
func SliceRemove(slice []interface{}, start int, args ...int) []interface{} {
	var end int
	if len(args) == 0 {
		end = start + 1
	} else {
		end = args[0]
	}
	if end > len(slice)-1 {
		return slice[:start]
	}
	return append(slice[:start], slice[end:]...)
}

// SliceRemoveCallback : 根据条件删除
// a=[]int{1,2,3,4,5,6}
// SliceRemoveCallback(len(a), func(i int) func(bool)error{
//	if a[i]!=4 {
//	 	return nil
// 	}
// 	return func(inside bool)error{
//		if inside {
//			a=append(a[0:i],a[i+1:]...)
// 		}else{
//			a=a[0:i]
//		}
//		return nil
// 	}
//})
func SliceRemoveCallback(length int, callback func(int) func(bool) error) error {
	for i, j := 0, length-1; i <= j; i++ {
		if removeFunc := callback(i); removeFunc != nil {
			var err error
			if i+1 <= j {
				err = removeFunc(true)
			} else {
				err = removeFunc(false)
			}
			if err != nil {
				return err
			}
			i--
			j--
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2012, Hailiang Wang. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package socks implements a SOCKS (SOCKS4, SOCKS4A and SOCKS5) proxy client.

A complete example using this package:
	package main

	import (
		"h12.me/socks"
		"fmt"
		"net/http"
		"io/ioutil"
	)

	func main() {
		dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, "127.0.0.1:1080")
		tr := &http.Transport{Dial: dialSocksProxy}
		httpClient := &http.Client{Transport: tr}

		bodyText, err := TestHttpsGet(httpClient, "https://h12.me/about")
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Print(bodyText)
	}

	func TestHttpsGet(c *http.Client, url string) (bodyText string, err error) {
		resp, err := c.Get(url)
		if err != nil { return }
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil { return }
		bodyText = string(body)
		return
	}
*/
package socks

import (
	"errors"
	"fmt"
	"net"
	"strconv"
)

// Constants to choose which version of SOCKS protocol to use.
const (
	SOCKS4 = iota
	SOCKS4A
	SOCKS5
)

// DialSocksProxy returns the dial function to be used in http.Transport object.
// Argument socksType should be one of SOCKS4, SOCKS4A and SOCKS5.
// Argument proxy should be in this format "127.0.0.1:1080".
func DialSocksProxy(socksType int, proxy string) func(string, string) (net.Conn, error) {
	if socksType == SOCKS5 {
		return func(_, targetAddr string) (conn net.Conn, err error) {
			return dialSocks5(proxy, targetAddr)
		}
	}

	// SOCKS4, SOCKS4A
	return func(_, targetAddr string) (conn net.Conn, err error) {
		return dialSocks4(socksType, proxy, targetAddr)
	}
}

func dialSocks5(proxy, targetAddr string) (conn net.Conn, err error) {
	// dial TCP
	conn, err = net.Dial("tcp", proxy)
	if err != nil {
		return
	}

	// version identifier/method selection request
	req := []byte{
		5, // version number
		1, // number of methods
		0, // method 0: no authentication (only anonymous access supported for now)
	}
	resp, err := sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 2 {
		err = errors.New("Server does not respond properly.")
	} else if resp[0] != 5 {
		err = errors.New("Server does not support Socks 5.")
	} else if resp[1] != 0 { // no auth
		err = errors.New("socks method negotiation failed.")
		return
	}

	// detail request
	host, port, err := splitHostPort(targetAddr)
	req = []byte{
		5,               // version number
		1,               // connect command
		0,               // reserved, must be zero
		3,               // address type, 3 means domain name
		byte(len(host)), // address length
	}
	req = append(req, []byte(host)...)
	req = append(req, []byte{
		byte(port >> 8), // higher byte of destination port
		byte(port),      // lower byte of destination port (big endian)
	}...)
	resp, err = sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 10 {
		err = errors.New("Server does not respond properly.")
	} else if resp[1] != 0 {
		err = errors.New("Can't complete SOCKS5 connection.")
	}

	return
}

func dialSocks4(socksType int, proxy, targetAddr string) (conn net.Conn, err error) {
	// dial TCP
	conn, err = net.Dial("tcp", proxy)
	if err != nil {
		return
	}

	// connection request
	host, port, err := splitHostPort(targetAddr)
	if err != nil {
		return
	}
	ip := net.IPv4(0, 0, 0, 1).To4()
	if socksType == SOCKS4 {
		ip, err = lookupIP(host)
		if err != nil {
			return
		}
	}
	req := []byte{
		4,                          // version number
		1,                          // command CONNECT
		byte(port >> 8),            // higher byte of destination port
		byte(port),                 // lower byte of destination port (big endian)
		ip[0], ip[1], ip[2], ip[3], // special invalid IP address to indicate the host name is provided
		0, // user id is empty, anonymous proxy only
	}
	if socksType == SOCKS4A {
		req = append(req, []byte(host+"\x00")...)
	}

	resp, err := sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 8 {
		err = errors.New("Server does not respond properly.")
	}
	switch resp[1] {
	case 90:
		// request granted
	case 91:
		err = errors.New("Socks connection request rejected or failed.")
	case 92:
		err = errors.New("Socks connection request rejected becasue SOCKS server cannot connect to identd on the client.")
	case 93:
		err = errors.New("Socks connection request rejected because the client program and identd report different user-ids.")
	default:
		err = errors.New("Socks connection request failed, unknown error.")
	}
	return
}

func sendReceive(conn net.Conn, req []byte) (resp []byte, err error) {
	_, err = conn.Write(req)
	if err != nil {
		return
	}
	resp, err = readAll(conn)
	return
}

func readAll(conn net.Conn) (resp []byte, err error) {
	resp = make([]byte, 1024)
	n, err := conn.Read(resp)
	resp = resp[:n]
	return
}

func lookupIP(host string) (ip net.IP, err error) {
	ips, err := net.LookupIP(host)
	if err != nil {
		return
	}
	if len(ips) == 0 {
		err = errors.New(fmt.Sprintf("Cannot resolve host: %s.", host))
		return
	}
	ip = ips[0].To4()
	if len(ip) != net.IPv4len {
		fmt.Println(len(ip), ip)
		err = errors.New("IPv6 is not supported by SOCKS4.")
		return
	}
	return
}

func splitHostPort(addr string) (host string, port uint16, err error) {
	host, portStr, err := net.SplitHostPort(addr)
	portInt, err := strconv.ParseUint(portStr, 10, 16)
	port = uint16(portInt)
	return
}
<commit_msg>feat: timeout functionality<commit_after>// Copyright 2012, Hailiang Wang. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package socks implements a SOCKS (SOCKS4, SOCKS4A and SOCKS5) proxy client.

A complete example using this package:
	package main

	import (
		"h12.me/socks"
		"fmt"
		"net/http"
		"io/ioutil"
	)

	func main() {
		dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, "127.0.0.1:1080")
		tr := &http.Transport{Dial: dialSocksProxy}
		httpClient := &http.Client{Transport: tr}

		bodyText, err := TestHttpsGet(httpClient, "https://h12.me/about")
		if err != nil {
			fmt.Println(err.Error())
		}
		fmt.Print(bodyText)
	}

	func TestHttpsGet(c *http.Client, url string) (bodyText string, err error) {
		resp, err := c.Get(url)
		if err != nil { return }
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil { return }
		bodyText = string(body)
		return
	}
*/
package socks

import (
	"errors"
	"fmt"
	"net"
	"strconv"
	"time"
)

// Constants to choose which version of SOCKS protocol to use.
const (
	SOCKS4 = iota
	SOCKS4A
	SOCKS5
)

// DialSocksProxy returns the dial function to be used in http.Transport object.
// Argument socksType should be one of SOCKS4, SOCKS4A and SOCKS5.
// Argument proxy should be in this format "127.0.0.1:1080".
// This method does not specify a timeout
func DialSocksProxy(socksType int, proxy string) func(string, string) (net.Conn, error) {
	return DialSocksProxyTimeout(socksType, proxy, 0)
}

// DialSocksProxy returns the dial function to be used in http.Transport object.
// Argument socksType should be one of SOCKS4, SOCKS4A and SOCKS5.
// Argument proxy should be in this format "127.0.0.1:1080".
// Argument timeout the time.Duration after which the request should time out
func DialSocksProxyTimeout(socksType int, proxy string, timeout time.Duration) func(string, string) (net.Conn, error) {
	if socksType == SOCKS5 {
		return func(_, targetAddr string) (conn net.Conn, err error) {
			return dialSocks5(proxy, targetAddr, timeout)
		}
	}

	// SOCKS4, SOCKS4A
	return func(_, targetAddr string) (conn net.Conn, err error) {
		return dialSocks4(socksType, proxy, targetAddr, timeout)
	}
}

func dialSocks5(proxy, targetAddr string, timeout time.Duration) (conn net.Conn, err error) {
	// dial TCP

	if timeout > 0 {
		deadline := time.Now().Add(timeout)
		conn, err = net.DialTimeout("tcp", proxy, timeout)
		if err != nil {
			return
		}
		conn.SetDeadline(deadline)
	} else {
		conn, err = net.Dial("tcp", proxy)
		if err != nil {
			return
		}
	}

	// version identifier/method selection request
	req := []byte{
		5, // version number
		1, // number of methods
		0, // method 0: no authentication (only anonymous access supported for now)
	}
	resp, err := sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 2 {
		err = errors.New("Server does not respond properly.")
	} else if resp[0] != 5 {
		err = errors.New("Server does not support Socks 5.")
	} else if resp[1] != 0 { // no auth
		err = errors.New("socks method negotiation failed.")
		return
	}

	// detail request
	host, port, err := splitHostPort(targetAddr)
	req = []byte{
		5,               // version number
		1,               // connect command
		0,               // reserved, must be zero
		3,               // address type, 3 means domain name
		byte(len(host)), // address length
	}
	req = append(req, []byte(host)...)
	req = append(req, []byte{
		byte(port >> 8), // higher byte of destination port
		byte(port),      // lower byte of destination port (big endian)
	}...)
	resp, err = sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 10 {
		err = errors.New("Server does not respond properly.")
	} else if resp[1] != 0 {
		err = errors.New("Can't complete SOCKS5 connection.")
	}

	return
}

func dialSocks4(socksType int, proxy, targetAddr string, timeout time.Duration) (conn net.Conn, err error) {
	if timeout > 0 {
		conn, err = net.DialTimeout("tcp", proxy, timeout)
	} else {
		conn, err = net.Dial("tcp", proxy)
	}

	if err != nil {
		return
	}

	// connection request
	host, port, err := splitHostPort(targetAddr)
	if err != nil {
		return
	}
	ip := net.IPv4(0, 0, 0, 1).To4()
	if socksType == SOCKS4 {
		ip, err = lookupIP(host)
		if err != nil {
			return
		}
	}
	req := []byte{
		4,                          // version number
		1,                          // command CONNECT
		byte(port >> 8),            // higher byte of destination port
		byte(port),                 // lower byte of destination port (big endian)
		ip[0], ip[1], ip[2], ip[3], // special invalid IP address to indicate the host name is provided
		0, // user id is empty, anonymous proxy only
	}
	if socksType == SOCKS4A {
		req = append(req, []byte(host+"\x00")...)
	}

	resp, err := sendReceive(conn, req)
	if err != nil {
		return
	} else if len(resp) != 8 {
		err = errors.New("Server does not respond properly.")
	}
	switch resp[1] {
	case 90:
		// request granted
	case 91:
		err = errors.New("Socks connection request rejected or failed.")
	case 92:
		err = errors.New("Socks connection request rejected becasue SOCKS server cannot connect to identd on the client.")
	case 93:
		err = errors.New("Socks connection request rejected because the client program and identd report different user-ids.")
	default:
		err = errors.New("Socks connection request failed, unknown error.")
	}
	return
}

func sendReceive(conn net.Conn, req []byte) (resp []byte, err error) {
	_, err = conn.Write(req)
	if err != nil {
		return
	}
	resp, err = readAll(conn)
	return
}

func readAll(conn net.Conn) (resp []byte, err error) {
	resp = make([]byte, 1024)
	n, err := conn.Read(resp)
	resp = resp[:n]
	return
}

func lookupIP(host string) (ip net.IP, err error) {
	ips, err := net.LookupIP(host)
	if err != nil {
		return
	}
	if len(ips) == 0 {
		err = errors.New(fmt.Sprintf("Cannot resolve host: %s.", host))
		return
	}
	ip = ips[0].To4()
	if len(ip) != net.IPv4len {
		fmt.Println(len(ip), ip)
		err = errors.New("IPv6 is not supported by SOCKS4.")
		return
	}
	return
}

func splitHostPort(addr string) (host string, port uint16, err error) {
	host, portStr, err := net.SplitHostPort(addr)
	portInt, err := strconv.ParseUint(portStr, 10, 16)
	port = uint16(portInt)
	return
}
<|endoftext|>


<commit_before>// Package solve provides algorithms like A*, IDA* and Depth-first
package solve

import (
	"math"
)

// Context can be used to interact with the solver and to maintain a custom context
// during the search.
type Context struct {
	Custom interface{}
}

// The State representing a state in the search tree
//
// An implementation of this interface represents the problem. It tells the algorithm how
// to get from one state to another, how much it costs to reach the state etc.
type State interface {
	// The costs to reach this state
	Cost(ctx Context) float64

	// Returns true if this is a goal state
	IsGoal(ctx Context) bool

	// Expands this state in zero or more child states
	Expand(ctx Context) []State

	// Estimated costs to reach a goal. Use 0 for no heuristic. Most algorithms will
	// find the optimal solution if the heuristic is admissible, meaning it will never
	// over-estimate the costs to reach a goal
	Heuristic(ctx Context) float64
}

// Result of the search
type Result struct {
	// The list of states leading from the root state to the goal state. If no solution
	// is found this list will be empty
	Solution []State

	// Number of nodes visited (dequeued) by the algorithm
	Visited int

	// Number of nodes expanded (enqueued) by the algorithm
	Expanded int
}

// Convenience method to test if the result yields a solution
func (r Result) Solved() bool {
	return len(r.Solution) > 0
}

// Convenience method to get the goal state. Can only be called if r.Solved() == true
func (r Result) GoalState() State {
	return r.Solution[len(r.Solution)-1]
}

type node struct {
	parent *node
	state  State
	value  float64
}

type result struct {
	node     *node
	contour  float64
	visited  int
	expanded int

	next *func() result
}

func generalSearch(queue strategy, visited int, expanded int, constr iconstraint, ubound float64, limit float64, contour float64, context Context) result {
	for {
		n := queue.Take()
		if n == nil {
			return result{nil, contour, visited, expanded, nil}
		}
		visited++
		if constr.onVisit(n) {
			continue
		}
		if n.state.IsGoal(context) && n.value > ubound {
			next := func() result {
				return generalSearch(queue, visited, expanded, constr, ubound, limit, contour, context)
			}
			return result{n, contour, visited, expanded, &next}
		}
		for _, child := range n.state.Expand(context) {
			childNode := &node{n, child, math.Max(n.value, child.Cost(context)+child.Heuristic(context))}
			if constr.onExpand(childNode) {
				continue
			}
			if childNode.value > limit {
				contour = math.Min(contour, childNode.value)
				continue
			}
			queue.Add(childNode)
			expanded++
		}
	}
}

func startGeneralSearch(queue strategy, constr iconstraint, limit float64, context Context) result {
	return generalSearch(queue, 0, 0, constr, -1.0, limit, math.Inf(1), context)
}

func idaStar(rootState State, constraint iconstraint, contour float64, ubound float64, limit float64, context Context, nextfn *func() result) result {
	visited := 0
	expanded := 0
	for true {
		var lastResult result
		if nextfn == nil {
			// start with new iteration
			s := depthFirst()
			s.Add(&node{nil, rootState, rootState.Cost(context) + rootState.Heuristic(context)})
			constraint.reset()
			lastResult = generalSearch(s, visited, expanded, constraint, ubound, contour, math.Inf(1), context)
		} else {
			// continue previous iteration
			fn := *nextfn
			nextfn = nil
			lastResult = fn()
		}
		if lastResult.node != nil {
			// Found a solution
			underlyingNextFn := lastResult.next
			nextIdaStarFn := func() result {
				return idaStar(rootState, constraint, contour, ubound, limit, context, underlyingNextFn)
			}
			lastResult.next = &nextIdaStarFn
			return lastResult
		}
		lastResult.next = nil
		if lastResult.contour > limit || math.IsInf(lastResult.contour, 1) || math.IsNaN(lastResult.contour) {
			// no (more) solutions
			return lastResult
		}
		ubound = contour
		visited = lastResult.visited
		expanded = lastResult.expanded
		contour = lastResult.contour
	}
	panic("Shouldn't be reached")
}

func startIdaStar(rootState State, constraint iconstraint, limit float64, context Context) result {
	return idaStar(rootState, constraint, 0.0, -1.0, limit, context, nil)
}

func toSlice(node *node) []State {
	if node == nil {
		return make([]State, 0)
	}
	return append(toSlice(node.parent), node.state)
}

func toResult(r *result) Result {
	return Result{toSlice(r.node), r.visited, r.expanded}
}

type solver struct {
	rootState  State
	algorithm  Algorithm
	constraint Constraint
	limit      float64
	context    interface{}

	started bool
	result  *result
}

func solve(ss *solver) Result {
	if ss.started {
		if ss.result.next == nil {
			// no more possible solutions
			return Result{[]State{}, ss.result.visited, ss.result.expanded}
		}
		nextResult := (*ss.result.next)()
		ss.result = &nextResult
		return toResult(ss.result)
	}
	ss.started = true
	context := Context{ss.context}
	constraint := ss.constraint.(iconstraint)
	if ss.algorithm == IDAstar {
		nextResult := startIdaStar(ss.rootState, constraint, ss.limit, context)
		ss.result = &nextResult
		return toResult(ss.result)
	}
	var s strategy
	switch ss.algorithm {
	case Astar:
		s = aStar()
	case DepthFirst:
		s = depthFirst()
	case BreadthFirst:
		s = breadthFirst()
	}
	s.Add(&node{nil, ss.rootState, ss.rootState.Cost(context) + ss.rootState.Heuristic(context)})

	constraint.reset()
	nextResult := startGeneralSearch(s, constraint, ss.limit, context)
	ss.result = &nextResult
	return toResult(ss.result)
}

// Solver to solve the problem.
type Solver interface {
	// The algorithm to use, defaults to IDAstar
	Algorithm(algorithm Algorithm) Solver

	// The constraint to use, defaults to NONE
	Constraint(constraint Constraint) Solver

	// The limit to use. The problem will not be exanded beyond this limit. Defaults
	// to math.Inf(1).
	Limit(limit float64) Solver

	// Custom context which is passed to the methods of the state. Can contain for example precalculated data that
	// is used to speed up calculations. Be careful with state in the context though.
	Context(context interface{}) Solver

	// Solves the problem returning the result
	Solve() Result

	// Convenience method for finding all solutions. The solutions are put in the
	// given channel. The channel is closed when the solver is completed.
	SolveAll(solutions chan<- Result)

	// True if the search is completed
	Completed() bool
}

func (s *solver) Algorithm(algorithm Algorithm) Solver {
	s.algorithm = algorithm
	return s
}

func (s *solver) Constraint(constraint Constraint) Solver {
	s.constraint = constraint
	return s
}

func (s *solver) Limit(limit float64) Solver {
	s.limit = limit
	return s
}

func (s *solver) Context(context interface{}) Solver {
	s.context = context
	return s
}

func (s *solver) Solve() Result {
	return solve(s)
}

func (s *solver) SolveAll(solutions chan<- Result) {
	defer close(solutions)
	for result := s.Solve(); result.Solved(); result = s.Solve() {
		solutions <- result
	}
}

func (s *solver) Completed() bool {
	return s.started && s.result.next == nil
}

// NewSolver creates a new solver
func NewSolver(rootState State) Solver {
	return &solver{rootState, Astar, NoConstraint(), math.Inf(1), nil, false, nil}
}
<commit_msg>Documentation<commit_after>// Package solve provides algorithms like A*, IDA* and Depth-first
package solve

import (
	"math"
)

// Context can be used to interact with the solver and to maintain a custom context
// during the search.
type Context struct {
	Custom interface{}
}

// The State representing a state in the search tree
//
// An implementation of this interface represents the problem. It tells the algorithm how
// to get from one state to another, how much it costs to reach the state etc.
type State interface {
	// The costs to reach this state
	Cost(ctx Context) float64

	// Returns true if this is a goal state
	IsGoal(ctx Context) bool

	// Expands this state in zero or more child states
	Expand(ctx Context) []State

	// Estimated costs to reach a goal. Use 0 for no heuristic. Most algorithms will
	// find the optimal solution if the heuristic is admissible, meaning it will never
	// over-estimate the costs to reach a goal
	Heuristic(ctx Context) float64
}

// Result of the search
type Result struct {
	// The list of states leading from the root state to the goal state. If no solution
	// is found this list will be empty
	Solution []State

	// Number of nodes visited (dequeued) by the algorithm
	Visited int

	// Number of nodes expanded (enqueued) by the algorithm
	Expanded int
}

// Solved returns true if the result yields a solution
func (r Result) Solved() bool {
	return len(r.Solution) > 0
}

// GoalState returns the last state of Solution(). Can only be called if r.Solved() == true
func (r Result) GoalState() State {
	return r.Solution[len(r.Solution)-1]
}

type node struct {
	parent *node
	state  State
	value  float64
}

type result struct {
	node     *node
	contour  float64
	visited  int
	expanded int

	next *func() result
}

func generalSearch(queue strategy, visited int, expanded int, constr iconstraint, ubound float64, limit float64, contour float64, context Context) result {
	for {
		n := queue.Take()
		if n == nil {
			return result{nil, contour, visited, expanded, nil}
		}
		visited++
		if constr.onVisit(n) {
			continue
		}
		if n.state.IsGoal(context) && n.value > ubound {
			next := func() result {
				return generalSearch(queue, visited, expanded, constr, ubound, limit, contour, context)
			}
			return result{n, contour, visited, expanded, &next}
		}
		for _, child := range n.state.Expand(context) {
			childNode := &node{n, child, math.Max(n.value, child.Cost(context)+child.Heuristic(context))}
			if constr.onExpand(childNode) {
				continue
			}
			if childNode.value > limit {
				contour = math.Min(contour, childNode.value)
				continue
			}
			queue.Add(childNode)
			expanded++
		}
	}
}

func startGeneralSearch(queue strategy, constr iconstraint, limit float64, context Context) result {
	return generalSearch(queue, 0, 0, constr, -1.0, limit, math.Inf(1), context)
}

func idaStar(rootState State, constraint iconstraint, contour float64, ubound float64, limit float64, context Context, nextfn *func() result) result {
	visited := 0
	expanded := 0
	for true {
		var lastResult result
		if nextfn == nil {
			// start with new iteration
			s := depthFirst()
			s.Add(&node{nil, rootState, rootState.Cost(context) + rootState.Heuristic(context)})
			constraint.reset()
			lastResult = generalSearch(s, visited, expanded, constraint, ubound, contour, math.Inf(1), context)
		} else {
			// continue previous iteration
			fn := *nextfn
			nextfn = nil
			lastResult = fn()
		}
		if lastResult.node != nil {
			// Found a solution
			underlyingNextFn := lastResult.next
			nextIdaStarFn := func() result {
				return idaStar(rootState, constraint, contour, ubound, limit, context, underlyingNextFn)
			}
			lastResult.next = &nextIdaStarFn
			return lastResult
		}
		lastResult.next = nil
		if lastResult.contour > limit || math.IsInf(lastResult.contour, 1) || math.IsNaN(lastResult.contour) {
			// no (more) solutions
			return lastResult
		}
		ubound = contour
		visited = lastResult.visited
		expanded = lastResult.expanded
		contour = lastResult.contour
	}
	panic("Shouldn't be reached")
}

func startIdaStar(rootState State, constraint iconstraint, limit float64, context Context) result {
	return idaStar(rootState, constraint, 0.0, -1.0, limit, context, nil)
}

func toSlice(node *node) []State {
	if node == nil {
		return make([]State, 0)
	}
	return append(toSlice(node.parent), node.state)
}

func toResult(r *result) Result {
	return Result{toSlice(r.node), r.visited, r.expanded}
}

type solver struct {
	rootState  State
	algorithm  Algorithm
	constraint Constraint
	limit      float64
	context    interface{}

	started bool
	result  *result
}

func solve(ss *solver) Result {
	if ss.started {
		if ss.result.next == nil {
			// no more possible solutions
			return Result{[]State{}, ss.result.visited, ss.result.expanded}
		}
		nextResult := (*ss.result.next)()
		ss.result = &nextResult
		return toResult(ss.result)
	}
	ss.started = true
	context := Context{ss.context}
	constraint := ss.constraint.(iconstraint)
	if ss.algorithm == IDAstar {
		nextResult := startIdaStar(ss.rootState, constraint, ss.limit, context)
		ss.result = &nextResult
		return toResult(ss.result)
	}
	var s strategy
	switch ss.algorithm {
	case Astar:
		s = aStar()
	case DepthFirst:
		s = depthFirst()
	case BreadthFirst:
		s = breadthFirst()
	}
	s.Add(&node{nil, ss.rootState, ss.rootState.Cost(context) + ss.rootState.Heuristic(context)})

	constraint.reset()
	nextResult := startGeneralSearch(s, constraint, ss.limit, context)
	ss.result = &nextResult
	return toResult(ss.result)
}

// Solver to solve the problem.
type Solver interface {
	// The algorithm to use, defaults to IDAstar
	Algorithm(algorithm Algorithm) Solver

	// The constraint to use, defaults to NONE
	Constraint(constraint Constraint) Solver

	// The limit to use. The problem will not be exanded beyond this limit. Defaults
	// to math.Inf(1).
	Limit(limit float64) Solver

	// Custom context which is passed to the methods of the state. Can contain for example precalculated data that
	// is used to speed up calculations. Be careful with state in the context though.
	Context(context interface{}) Solver

	// Solves the problem returning the result
	Solve() Result

	// Convenience method for finding all solutions. The solutions are put in the
	// given channel. The channel is closed when the solver is completed.
	SolveAll(solutions chan<- Result)

	// True if the search is completed
	Completed() bool
}

func (s *solver) Algorithm(algorithm Algorithm) Solver {
	s.algorithm = algorithm
	return s
}

func (s *solver) Constraint(constraint Constraint) Solver {
	s.constraint = constraint
	return s
}

func (s *solver) Limit(limit float64) Solver {
	s.limit = limit
	return s
}

func (s *solver) Context(context interface{}) Solver {
	s.context = context
	return s
}

func (s *solver) Solve() Result {
	return solve(s)
}

func (s *solver) SolveAll(solutions chan<- Result) {
	defer close(solutions)
	for result := s.Solve(); result.Solved(); result = s.Solve() {
		solutions <- result
	}
}

func (s *solver) Completed() bool {
	return s.started && s.result.next == nil
}

// NewSolver creates a new solver
func NewSolver(rootState State) Solver {
	return &solver{rootState, Astar, NoConstraint(), math.Inf(1), nil, false, nil}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

var (
	address = flag.String("address", "0.0.0.0", "Listening address")
	port    = flag.String("port", "8080", "Listening port")
	sslPort = flag.String("sslPort", "10433", "SSL listening port")
	path    = flag.String("path", "/", "URL path")
	deny    = flag.String("deny", "", "Sesitive directory or file patterns to be denied when listing path (comma sperated)")
	status  = flag.Int("status", 200, "Returned HTTP status code")
	cert    = flag.String("cert", "cert.pem", "SSL certificate path")
	key     = flag.String("key", "key.pem", "SSL private Key path")
)

type bytesHandler []byte

func (h bytesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.WriteHeader(*status)
	w.Write(h)
}

func isDenied(path, denyList string) bool {
	if len(denyList) == 0 {
		return false
	}
	for _, pathElement := range strings.Split(path, string(filepath.Separator)) {
		for _, denyElement := range strings.Split(denyList, ",") {
			match, err := filepath.Match(strings.TrimSpace(denyElement), pathElement)
			if err != nil {
				log.Print("error matching file path element: ", err)
			}
			if match {
				return true
			}
		}
	}
	return false
}

type protectdFileSystem struct {
	fs http.FileSystem
}

func (pfs protectdFileSystem) Open(path string) (http.File, error) {
	if isDenied(path, *deny) {
		return nil, os.ErrPermission
	}
	return pfs.fs.Open(path)
}

func main() {
	flag.Parse()
	listen := *address + ":" + *port
	listenTLS := *address + ":" + *sslPort
	body := flag.Arg(0)
	if body == "" {
		body = "."
	}
	var handler http.Handler
	if fi, err := os.Stat(body); err == nil {
		switch mode := fi.Mode(); {
		case mode.IsDir():
			handler = http.StripPrefix(*path, http.FileServer(protectdFileSystem{http.Dir(body)}))
		case mode.IsRegular():
			if content, err := ioutil.ReadFile(body); err != nil {
				log.Fatal("Error reading file: ", err)
			} else {
				handler = bytesHandler(content)
			}
		}
	} else {
		handler = bytesHandler(body)
	}
	http.Handle(*path, handler)
	go func() {
		if _, err := os.Stat(*cert); err != nil {
			return
		}
		if _, err := os.Stat(*key); err != nil {
			return
		}
		log.Fatal(http.ListenAndServeTLS(listenTLS, *cert, *key, nil))
	}()
	log.Printf("Serving %s on %s%s...", body, listen, *path)
	log.Fatal(http.ListenAndServe(listen, nil))
}
<commit_msg>waring on serving unfiltered path<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

var (
	address = flag.String("address", "0.0.0.0", "Listening address")
	port    = flag.String("port", "8080", "Listening port")
	sslPort = flag.String("sslPort", "10433", "SSL listening port")
	path    = flag.String("path", "/", "URL path")
	deny    = flag.String("deny", "", "Sesitive directory or file patterns to be denied when serving directory (comma sperated)")
	status  = flag.Int("status", 200, "Returned HTTP status code")
	cert    = flag.String("cert", "cert.pem", "SSL certificate path")
	key     = flag.String("key", "key.pem", "SSL private Key path")
)

type bytesHandler []byte

func (h bytesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.WriteHeader(*status)
	w.Write(h)
}

func isDenied(path, denyList string) bool {
	if len(denyList) == 0 {
		return false
	}
	for _, pathElement := range strings.Split(path, string(filepath.Separator)) {
		for _, denyElement := range strings.Split(denyList, ",") {
			match, err := filepath.Match(strings.TrimSpace(denyElement), pathElement)
			if err != nil {
				log.Print("error matching file path element: ", err)
			}
			if match {
				return true
			}
		}
	}
	return false
}

type protectdFileSystem struct {
	fs http.FileSystem
}

func (pfs protectdFileSystem) Open(path string) (http.File, error) {
	if isDenied(path, *deny) {
		return nil, os.ErrPermission
	}
	return pfs.fs.Open(path)
}

func main() {
	flag.Parse()
	listen := *address + ":" + *port
	listenTLS := *address + ":" + *sslPort
	body := flag.Arg(0)
	if body == "" {
		body = "."
	}
	var handler http.Handler
	if fi, err := os.Stat(body); err == nil {
		switch mode := fi.Mode(); {
		case mode.IsDir():
			if *deny == "" {
				log.Print("Warning: serving files without any filter!")
			}
			handler = http.StripPrefix(*path, http.FileServer(protectdFileSystem{http.Dir(body)}))
		case mode.IsRegular():
			if content, err := ioutil.ReadFile(body); err != nil {
				log.Fatal("Error reading file: ", err)
			} else {
				handler = bytesHandler(content)
			}
		}
	} else {
		handler = bytesHandler(body)
	}
	http.Handle(*path, handler)
	go func() {
		if _, err := os.Stat(*cert); err != nil {
			return
		}
		if _, err := os.Stat(*key); err != nil {
			return
		}
		log.Fatal(http.ListenAndServeTLS(listenTLS, *cert, *key, nil))
	}()
	log.Printf("Serving %s on %s%s...", body, listen, *path)
	log.Fatal(http.ListenAndServe(listen, nil))
}
<|endoftext|>


<commit_before>package mqtt

import (
	"crypto/tls"
)

////////////////////Interface//////////////////////////////

type Stack interface {
	CreateTransport(network string, address string, port int, tlsc *tls.Config) Transport
	GetTransports() []Transport
	DeleteTransport(t Transport)

	CreateProvider() Provider
	GetProviders() []Provider
	DeleteProvider(p Provider)

	Run()
	Stop()
}

////////////////////Implementation////////////////////////

var stackSingleton Stack

func GetStack() Stack {
	if stackSingleton == nil {
		stackSingleton = newStack()
	}
	return stackSingleton
}

type stack struct {
	transports map[Transport]*transport
	providers  map[Provider]*provider
}

func newStack() Stack {
	this := &stack{}

	this.transports = make(map[Transport]*transport)
	this.providers = make(map[Provider]*provider)

	return this
}

func (this *stack) CreateTransport(network string, address string, port int, tlsc *tls.Config) Transport {
	t := newTransport(network, address, port, tlsc)

	this.transports[t] = t

	return t
}

func (this *stack) GetTransports() []Transport {
	transports := make([]Transport, len(this.transports))

	l := 0
	for _, value := range this.transports {
		transports[l] = value
		l++
	}

	return transports
}

func (this *stack) DeleteTransport(t Transport) {
	delete(this.transports, t)
}

func (this *stack) CreateProvider() Provider {
	p := newProvider()

	this.providers[p] = p

	return p
}

func (this *stack) GetProviders() []Provider {
	providers := make([]Provider, len(this.providers))

	l := 0
	for _, value := range this.providers {
		providers[l] = value
		l++
	}

	return providers
}

func (this *stack) DeleteProvider(p Provider) {
	delete(this.providers, p)
}

func (this *stack) Run() {
	for _, p := range this.providers {
		p.Run()
	}
}

func (this *stack) Stop() {
	for _, p := range this.providers {
		p.Stop()
	}
}
<commit_msg>make p.Run() to goroutine<commit_after>package mqtt

import (
	"crypto/tls"
)

////////////////////Interface//////////////////////////////

type Stack interface {
	CreateTransport(network string, address string, port int, tlsc *tls.Config) Transport
	GetTransports() []Transport
	DeleteTransport(t Transport)

	CreateProvider() Provider
	GetProviders() []Provider
	DeleteProvider(p Provider)

	Run()
	Stop()
}

////////////////////Implementation////////////////////////

var stackSingleton Stack

func GetStack() Stack {
	if stackSingleton == nil {
		stackSingleton = newStack()
	}
	return stackSingleton
}

type stack struct {
	transports map[Transport]*transport
	providers  map[Provider]*provider
}

func newStack() Stack {
	this := &stack{}

	this.transports = make(map[Transport]*transport)
	this.providers = make(map[Provider]*provider)

	return this
}

func (this *stack) CreateTransport(network string, address string, port int, tlsc *tls.Config) Transport {
	t := newTransport(network, address, port, tlsc)

	this.transports[t] = t

	return t
}

func (this *stack) GetTransports() []Transport {
	transports := make([]Transport, len(this.transports))

	l := 0
	for _, value := range this.transports {
		transports[l] = value
		l++
	}

	return transports
}

func (this *stack) DeleteTransport(t Transport) {
	delete(this.transports, t)
}

func (this *stack) CreateProvider() Provider {
	p := newProvider()

	this.providers[p] = p

	return p
}

func (this *stack) GetProviders() []Provider {
	providers := make([]Provider, len(this.providers))

	l := 0
	for _, value := range this.providers {
		providers[l] = value
		l++
	}

	return providers
}

func (this *stack) DeleteProvider(p Provider) {
	delete(this.providers, p)
}

func (this *stack) Run() {
	for _, p := range this.providers {
		go p.Run()
	}
}

func (this *stack) Stop() {
	for _, p := range this.providers {
		p.Stop()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
)

var opt Options

var countDirs int
var countFiles int

func update(f os.FileInfo) {
	if f.IsDir() {
		countDirs++
	} else {
		countFiles++
	}
}

func visit(path string, f os.FileInfo, err error) error {
	if err != nil {
		fmt.Println("[-]", err)
	}
	if opt.excludeEmptyFiles && !f.IsDir() && f.Size() == 0 {
		return nil
	}
	if opt.excludeEmptyDir && f.IsDir() {
		files, err := ioutil.ReadDir(f.Name())
		if err != nil {
			fmt.Println("[-]", err)
		}
		if len(files) == 0 {
			return nil
		}
	}
	update(f)

	fmt.Printf("[+] Analyzed: %v directories and %v files\r",
		countDirs, countFiles)
	return nil
}

// Start the program with the current options. Options param is read only
func Start(options Options) {
	opt = options
	fmt.Println("[+] Starting in directory:", opt.currentDir)
	err := filepath.Walk(opt.currentDir, visit)

	if err != nil {
		fmt.Println("[-]", err)
	}
	fmt.Println()
}
<commit_msg>check when the file or directory is hidden<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var opt Options

var countDirs int
var countFiles int

func update(f os.FileInfo) {
	if f.IsDir() {
		countDirs++
	} else {
		countFiles++
	}
}

func visit(path string, f os.FileInfo, err error) error {
	if err != nil {
		fmt.Println("[-]", err)
	}
	if opt.excludeEmptyFiles && !f.IsDir() && f.Size() == 0 {
		return nil
	}
	if opt.excludeEmptyDir && f.IsDir() {
		files, err := ioutil.ReadDir(path)
		if err != nil {
			fmt.Println("[-]", err)
		}
		if len(files) == 0 {
			return nil
		}
	}
	if opt.excludeHiddenFiles && strings.HasPrefix(f.Name(), ".") {
		// hidden file or directory
		return nil
	}

	update(f)

	fmt.Printf("[+] Analyzed: %v directories and %v files\r",
		countDirs, countFiles)
	return nil
}

// Start the program with the current options. Options param is read only
func Start(options Options) {
	opt = options
	fmt.Println("[+] Starting in directory:", opt.currentDir)
	err := filepath.Walk(opt.currentDir, visit)

	if err != nil {
		fmt.Println("[-]", err)
	}
	fmt.Println()
}
<|endoftext|>