<commit_before>package annotator

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"
)

//test request syntax validation
func TestValidate(t *testing.T) {
	tests := []struct {
		ip       string
		time     string
		res      string
		time_num int64
	}{
		{"1.10.128.0", "625600", "", 625600},
		{"2620:0:1003:1008:dc7a:13d4:dfb3:d622", "625600", "", 625600},
		{"2620:0:1003:1008:DC7A:13D4:DFB3:D622", "625600", "", 625600},
		{"2620:0:1003:1008:dC7A:13d4:dfb3:d622", "625600", "", 625600},
		{"199.666.666.6666", "0", "NOT A RECOGNIZED IP FORMAT!", 0},
		{"199.666.666.66f", "0", "NOT A RECOGNIZED IP FORMAT!", 0},
		{"199.666.666.666", "f", "INVALID TIME!", 0},
		{"199.666.666.6666", "", "INVALID TIME!", 0},
		{"199.666.666.6666", "46d", "INVALID TIME!", 0},
	}
	for _, test := range tests {
		w := httptest.NewRecorder()

		r := &http.Request{}
		r.URL, _ = url.Parse("/annotate?ip_addr=" + url.QueryEscape(test.ip) + "&since_epoch=" + url.QueryEscape(test.time))

		//overrides default metrics
		/*i, d := false, false
		metrics_activeRequests = gaugeMock{&i, &d}
		obc := 0
		metrics_requestTimes = summaryMock{&obc}*/

		validate(w, r)

		/*metGauge, _ := metrics_activeRequests.(gaugeMock)
		metSum, _ := metrics_requestTimes.(summaryMock)
		if !(*metGauge.i && *metGauge.d) {
			t.Errorf("DIDN'T DO GAUGE METRICS CORRECTLY %t & %t!", *metGauge.i, *metGauge.d)
		}
		if *metSum.observeCount == 0 {
			t.Error("NEVER CALLED OBSERVE!!")
		}*/

		body := w.Body.String()
		if string(body) != test.res {
			t.Errorf("Got \"%s\", expected \"%s\".", body, test.res)
		}
	}

}

func TestAnnotation(t *testing.T) {
	tests := []struct {
		ip       string
		time     string
		res      string
		time_num int64
	}{
		{"1.4.128.0", "625600", "[\n  {\"ip\": \"1.4.128.0\", \"type\": \"STRING\"},\n  {\"country\": \"Thailand\", \"type\": \"STRING\"},\n  {\"countryAbrv\": \"TH\", \"type\": \"STRING\"},\n]", 625600},
		{"1.32.128.1", "625600", "[\n  {\"ip\": \"1.32.128.1\", \"type\": \"STRING\"},\n  {\"country\": \"Singapore\", \"type\": \"STRING\"},\n  {\"countryAbrv\": \"SG\", \"type\": \"STRING\"},\n]", 625600},
		{"MEMEMEME", "625600", "NOT A RECOGNIZED IP FORMAT!", 625600},
	}
	for _, test := range tests {
		w := httptest.NewRecorder()

		r := &http.Request{}
		r.URL, _ = url.Parse("/annotate?ip_addr=" + url.QueryEscape(test.ip) + "&since_epoch=" + url.QueryEscape(test.time))

		annotate(w, r)

		body := w.Body.String()

		if string(body) != test.res {
			t.Errorf("\nGot\n__%s__\nexpected\n__%s__\n", body, test.res)
		}
	}
}
<commit_msg>Delete route_test.go<commit_after><|endoftext|>


<commit_before>package restrictedendpoints

import (
	"fmt"
	"io"
	"net"
	"reflect"

	"k8s.io/klog"

	"k8s.io/apiserver/pkg/admission"
	"k8s.io/apiserver/pkg/admission/initializer"
	"k8s.io/apiserver/pkg/authorization/authorizer"
	kapi "k8s.io/kubernetes/pkg/apis/core"

	configlatest "github.com/openshift/origin/pkg/cmd/server/apis/config/latest"
	"github.com/openshift/origin/pkg/network/admission/apis/restrictedendpoints"
)

const RestrictedEndpointsPluginName = "network.openshift.io/RestrictedEndpointsAdmission"

func RegisterRestrictedEndpoints(plugins *admission.Plugins) {
	plugins.Register(RestrictedEndpointsPluginName,
		func(config io.Reader) (admission.Interface, error) {
			pluginConfig, err := readConfig(config)
			if err != nil {
				return nil, err
			}
			if pluginConfig == nil {
				klog.Infof("Admission plugin %q is not configured so it will be disabled.", RestrictedEndpointsPluginName)
				return nil, nil
			}
			restrictedNetworks, err := ParseSimpleCIDRRules(pluginConfig.RestrictedCIDRs)
			if err != nil {
				// should have been caught with validation
				return nil, err
			}

			return NewRestrictedEndpointsAdmission(restrictedNetworks), nil
		})
}

func readConfig(reader io.Reader) (*restrictedendpoints.RestrictedEndpointsAdmissionConfig, error) {
	if reader == nil || reflect.ValueOf(reader).IsNil() {
		return nil, nil
	}
	obj, err := configlatest.ReadYAML(reader)
	if err != nil {
		return nil, err
	}
	if obj == nil {
		return nil, nil
	}
	config, ok := obj.(*restrictedendpoints.RestrictedEndpointsAdmissionConfig)
	if !ok {
		return nil, fmt.Errorf("unexpected config object: %#v", obj)
	}
	// No validation needed since config is just list of strings
	return config, nil
}

type restrictedEndpointsAdmission struct {
	*admission.Handler

	authorizer         authorizer.Authorizer
	restrictedNetworks []*net.IPNet
}

var _ = initializer.WantsAuthorizer(&restrictedEndpointsAdmission{})
var _ = admission.ValidationInterface(&restrictedEndpointsAdmission{})

// ParseSimpleCIDRRules parses a list of CIDR strings
func ParseSimpleCIDRRules(rules []string) (networks []*net.IPNet, err error) {
	for _, s := range rules {
		_, cidr, err := net.ParseCIDR(s)
		if err != nil {
			return nil, err
		}
		networks = append(networks, cidr)
	}
	return networks, nil
}

// NewRestrictedEndpointsAdmission creates a new endpoints admission plugin.
func NewRestrictedEndpointsAdmission(restrictedNetworks []*net.IPNet) *restrictedEndpointsAdmission {
	return &restrictedEndpointsAdmission{
		Handler:            admission.NewHandler(admission.Create, admission.Update),
		restrictedNetworks: restrictedNetworks,
	}
}

func (r *restrictedEndpointsAdmission) SetAuthorizer(a authorizer.Authorizer) {
	r.authorizer = a
}

func (r *restrictedEndpointsAdmission) ValidateInitialization() error {
	if r.authorizer == nil {
		return fmt.Errorf("missing authorizer")
	}
	return nil
}

func (r *restrictedEndpointsAdmission) findRestrictedIP(ep *kapi.Endpoints) string {
	for _, subset := range ep.Subsets {
		for _, addr := range subset.Addresses {
			ip := net.ParseIP(addr.IP)
			if ip == nil {
				continue
			}
			for _, net := range r.restrictedNetworks {
				if net.Contains(ip) {
					return addr.IP
				}
			}
		}
	}
	return ""
}

func (r *restrictedEndpointsAdmission) checkAccess(attr admission.Attributes) (bool, error) {
	authzAttr := authorizer.AttributesRecord{
		User:            attr.GetUserInfo(),
		Verb:            "create",
		Namespace:       attr.GetNamespace(),
		Resource:        "endpoints",
		Subresource:     "restricted",
		APIGroup:        kapi.GroupName,
		Name:            attr.GetName(),
		ResourceRequest: true,
	}
	authorized, _, err := r.authorizer.Authorize(authzAttr)
	return authorized == authorizer.DecisionAllow, err
}

// Admit determines if the endpoints object should be admitted
func (r *restrictedEndpointsAdmission) Validate(a admission.Attributes) error {
	if a.GetResource().GroupResource() != kapi.Resource("endpoints") {
		return nil
	}
	ep, ok := a.GetObject().(*kapi.Endpoints)
	if !ok {
		return nil
	}
	old, ok := a.GetOldObject().(*kapi.Endpoints)
	if ok && reflect.DeepEqual(ep.Subsets, old.Subsets) {
		return nil
	}

	restrictedIP := r.findRestrictedIP(ep)
	if restrictedIP == "" {
		return nil
	}

	allow, err := r.checkAccess(a)
	if err != nil {
		return err
	}
	if !allow {
		return admission.NewForbidden(a, fmt.Errorf("endpoint address %s is not allowed", restrictedIP))
	}
	return nil
}
<commit_msg>Make the RestrictedEndpointsAdmission controller reject the MCS port<commit_after>package restrictedendpoints

import (
	"fmt"
	"io"
	"net"
	"reflect"

	"k8s.io/klog"

	"k8s.io/apiserver/pkg/admission"
	"k8s.io/apiserver/pkg/admission/initializer"
	"k8s.io/apiserver/pkg/authorization/authorizer"
	kapi "k8s.io/kubernetes/pkg/apis/core"

	configlatest "github.com/openshift/origin/pkg/cmd/server/apis/config/latest"
	"github.com/openshift/origin/pkg/network/admission/apis/restrictedendpoints"
)

const RestrictedEndpointsPluginName = "network.openshift.io/RestrictedEndpointsAdmission"

func RegisterRestrictedEndpoints(plugins *admission.Plugins) {
	plugins.Register(RestrictedEndpointsPluginName,
		func(config io.Reader) (admission.Interface, error) {
			pluginConfig, err := readConfig(config)
			if err != nil {
				return nil, err
			}
			if pluginConfig == nil {
				klog.Infof("Admission plugin %q is not configured so it will be disabled.", RestrictedEndpointsPluginName)
				return nil, nil
			}
			restrictedNetworks, err := ParseSimpleCIDRRules(pluginConfig.RestrictedCIDRs)
			if err != nil {
				// should have been caught with validation
				return nil, err
			}

			return NewRestrictedEndpointsAdmission(restrictedNetworks), nil
		})
}

func readConfig(reader io.Reader) (*restrictedendpoints.RestrictedEndpointsAdmissionConfig, error) {
	if reader == nil || reflect.ValueOf(reader).IsNil() {
		return nil, nil
	}
	obj, err := configlatest.ReadYAML(reader)
	if err != nil {
		return nil, err
	}
	if obj == nil {
		return nil, nil
	}
	config, ok := obj.(*restrictedendpoints.RestrictedEndpointsAdmissionConfig)
	if !ok {
		return nil, fmt.Errorf("unexpected config object: %#v", obj)
	}
	// No validation needed since config is just list of strings
	return config, nil
}

type restrictedEndpointsAdmission struct {
	*admission.Handler

	authorizer         authorizer.Authorizer
	restrictedNetworks []*net.IPNet
	restrictedPorts    []kapi.EndpointPort
}

var _ = initializer.WantsAuthorizer(&restrictedEndpointsAdmission{})
var _ = admission.ValidationInterface(&restrictedEndpointsAdmission{})

// ParseSimpleCIDRRules parses a list of CIDR strings
func ParseSimpleCIDRRules(rules []string) (networks []*net.IPNet, err error) {
	for _, s := range rules {
		_, cidr, err := net.ParseCIDR(s)
		if err != nil {
			return nil, err
		}
		networks = append(networks, cidr)
	}
	return networks, nil
}

// NewRestrictedEndpointsAdmission creates a new endpoints admission plugin.
func NewRestrictedEndpointsAdmission(restrictedNetworks []*net.IPNet) *restrictedEndpointsAdmission {
	return &restrictedEndpointsAdmission{
		Handler:            admission.NewHandler(admission.Create, admission.Update),
		restrictedNetworks: restrictedNetworks,
		restrictedPorts: []kapi.EndpointPort{
			{Protocol: kapi.ProtocolTCP, Port: 22623},
			{Protocol: kapi.ProtocolTCP, Port: 22624},
		},
	}
}

func (r *restrictedEndpointsAdmission) SetAuthorizer(a authorizer.Authorizer) {
	r.authorizer = a
}

func (r *restrictedEndpointsAdmission) ValidateInitialization() error {
	if r.authorizer == nil {
		return fmt.Errorf("missing authorizer")
	}
	return nil
}

func (r *restrictedEndpointsAdmission) findRestrictedIP(ep *kapi.Endpoints) error {
	for _, subset := range ep.Subsets {
		for _, addr := range subset.Addresses {
			ip := net.ParseIP(addr.IP)
			if ip == nil {
				continue
			}
			for _, net := range r.restrictedNetworks {
				if net.Contains(ip) {
					return fmt.Errorf("endpoint address %s is not allowed", addr.IP)
				}
			}
		}
	}
	return nil
}

func (r *restrictedEndpointsAdmission) findRestrictedPort(ep *kapi.Endpoints) error {
	for _, subset := range ep.Subsets {
		for _, port := range subset.Ports {
			for _, restricted := range r.restrictedPorts {
				if port.Protocol == restricted.Protocol && port.Port == restricted.Port {
					return fmt.Errorf("endpoint port %s:%d is not allowed", string(port.Protocol), port.Port)
				}
			}
		}
	}
	return nil
}

func (r *restrictedEndpointsAdmission) checkAccess(attr admission.Attributes) (bool, error) {
	authzAttr := authorizer.AttributesRecord{
		User:            attr.GetUserInfo(),
		Verb:            "create",
		Namespace:       attr.GetNamespace(),
		Resource:        "endpoints",
		Subresource:     "restricted",
		APIGroup:        kapi.GroupName,
		Name:            attr.GetName(),
		ResourceRequest: true,
	}
	authorized, _, err := r.authorizer.Authorize(authzAttr)
	return authorized == authorizer.DecisionAllow, err
}

// Admit determines if the endpoints object should be admitted
func (r *restrictedEndpointsAdmission) Validate(a admission.Attributes) error {
	if a.GetResource().GroupResource() != kapi.Resource("endpoints") {
		return nil
	}
	ep, ok := a.GetObject().(*kapi.Endpoints)
	if !ok {
		return nil
	}
	old, ok := a.GetOldObject().(*kapi.Endpoints)
	if ok && reflect.DeepEqual(ep.Subsets, old.Subsets) {
		return nil
	}

	restrictedErr := r.findRestrictedIP(ep)
	if restrictedErr == nil {
		restrictedErr = r.findRestrictedPort(ep)
	}
	if restrictedErr == nil {
		return nil
	}

	allow, err := r.checkAccess(a)
	if err != nil {
		return err
	}
	if !allow {
		return admission.NewForbidden(a, restrictedErr)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"path"
	"path/filepath"
	"time"

	"github.com/intelsdilabs/pulse/control"
)

var (
	// PulsePath is the local file path to a pulse build
	PulsePath = os.Getenv("PULSE_PATH")
	// CollectorPath is the path to collector plugins within a pulse build
	CollectorPath = path.Join(PulsePath, "plugin", "collector")
)

func checkError(e error) {
	if e != nil {
		panic(e)
	}
}

func isExecutable(p os.FileMode) bool {
	return (p & 0111) != 0
}

func main() {
	if PulsePath == "" {
		log.Fatalln("PULSE_PATH not set")
		os.Exit(1)
	}

	log.Println("Startup")
	// TODO ERROR missing PULSE_PATH
	// fmt.Println(PulsePath)

	pluginControl := control.New()
	pluginControl.Start()
	defer pluginControl.Stop()

	// fmt.Println(pluginControl)
	// fmt.Println(CollectorPath)

	m, err := filepath.Glob(CollectorPath + "/pulse-collector-*")
	checkError(err)
	for _, d := range m {
		f, err := os.Stat(d)
		checkError(err)
		// Ignore directories
		if f.Mode().IsDir() {
			continue
		}
		// Ignore file without executable permission
		if !isExecutable(f.Mode().Perm()) {
			log.Printf("The plugin [%s] is not executable\n", d)
			continue
		}
		pluginControl.Load(d)
	}

	for {
		time.Sleep(time.Second * 1)
	}
	// err := pluginControl.Load(collectorPath)

}
<commit_msg>Initial pass at version printing and setting Max Processors<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	//	"path"
	//	"path/filepath"
	//	"time"

	//	"github.com/intelsdilabs/pulse/control"
)

var version = flag.Bool("version", false, "print Pulse version")
var maxProcs = flag.Int("max_procs", 0, "max number of CPUs that can be used simultaneously. Default is use all cores.")

type Pulse struct{} //Will hold what modules start and stop

func main() {
	//TODO: Parse startup arguments for pulse
	flag.Parse()

	if *version {
		//TODO: Pass in version during build
		fmt.Println("Pulse version 1.0.0-alpha\n")
		os.Exit(0)
	}
	setMaxProcs()

	os.Exit(0)
}

func setMaxProcs() {
	var _maxProcs int
	numProcs := runtime.NumCPU()
	if *maxProcs == 0 {
		_maxProcs = numProcs
	} else if *maxProcs > numProcs {
		log.Printf("WARNING: Not allowed to set GOMAXPROCS above number of processors in system. Setting GOMAXPROCS to %v", numProcs)
		_maxProcs = numProcs
	} else {
		_maxProcs = *maxProcs
	}
	log.Printf("Setting GOMAXPROCS to %v\n", _maxProcs)
	runtime.GOMAXPROCS(_maxProcs)

	//Verify setting worked
	actualNumProcs := runtime.GOMAXPROCS(0)
	if actualNumProcs != _maxProcs {
		log.Println("WARNING: Specified max procs of %v but using %v", _maxProcs, actualNumProcs)
	}
}

//var (
// PulsePath is the local file path to a pulse build
//	PulsePath = os.Getenv("PULSE_PATH")
// CollectorPath is the path to collector plugins within a pulse build
//	CollectorPath = path.Join(PulsePath, "plugin", "collector")
//)

//func checkError(e error) {
//	if e != nil {
//		panic(e)
//	}
//}

//func isExecutable(p os.FileMode) bool {
//	return (p & 0111) != 0
//}

//func main() {
//	if PulsePath == "" {
//		log.Fatalln("PULSE_PATH not set")
//		os.Exit(1)
//	}
//
//	log.Println("Startup")
// TODO ERROR missing PULSE_PATH
// fmt.Println(PulsePath)

//	pluginControl := control.New()
//	pluginControl.Start()
//	defer pluginControl.Stop()

// fmt.Println(pluginControl)
// fmt.Println(CollectorPath)

//	m, err := filepath.Glob(CollectorPath + "/pulse-collector-*")
//	checkError(err)
//	for _, d := range m {
//		f, err := os.Stat(d)
//		checkError(err)
//		// Ignore directories
//		if f.Mode().IsDir() {
//			continue
//		}
//		// Ignore file without executable permission
//		if !isExecutable(f.Mode().Perm()) {
//			log.Printf("The plugin [%s] is not executable\n", d)
//			continue
//		}
//		pluginControl.Load(d)
//	}
//
//	for {
//		time.Sleep(time.Second * 1)
//	}
//	// err := pluginControl.Load(collectorPath)
//
//}
<|endoftext|>


<commit_before>package distributor

import (
	"errors"
	"fmt"
	"log"

	components "github.com/LoRaWanSoFa/LoRaWanSoFa/Components"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/Core/MessageConverter"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/Core/restUplinkConnector"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/DBC/DatabaseConnector"
)

type Distributor interface {
	InputUplink(components.MessageUplinkI) (components.MessageUplinkI, error)
	InputDownlink(components.MessageDownLink)
}

type distributor struct {
	messageConverter    MessageConverter.MessageConverter
	restUplinkConnector restUplink.RestUplinkConnector
}

func New() Distributor {
	dist := new(distributor)
	dist.messageConverter = MessageConverter.New()
	config := components.GetConfiguration().Rest
	fmt.Println(config)
	dist.restUplinkConnector = restUplink.NewRestUplinkConnector(config.Ip, config.ApiKey)
	return dist
}

func (d *distributor) InputUplink(message components.MessageUplinkI) (components.MessageUplinkI, error) {
	if d.deduplicate(message) {
		newMessage := d.convertMessage(message)
		err := DatabaseConnector.StoreMessagePayloads(newMessage)
		if err != nil {
			log.Fatal(err)
		}
		d.restUplinkConnector.NewData(newMessage.GetDevEUI(), newMessage)
		return newMessage, nil
	} else {
		err := errors.New("message was a duplicate")
		return nil, err
	}
}

func (d *distributor) InputDownlink(message components.MessageDownLink) {

}

//The deduplicate method should deduplicate messages that come in once from the
//TTN side of things(semi-private) as well as our own private backend and return
// true only if the message has not been received yet.
func (d *distributor) deduplicate(message components.MessageUplinkI) bool {
	// TODO: deduplicate messages that could come in checking with the database
	// or createing a small cache for it.
	return true
}

func (d *distributor) convertMessage(message components.MessageUplinkI) components.MessageUplinkI {
	bytePayloads := message.GetPayloads()
	message.RemovePayloads()
	for i := range bytePayloads {
		payload, ok := bytePayloads[i].GetPayload().([]byte)
		if ok {
			sensor := bytePayloads[i].GetSensor()
			payloadS, err := d.messageConverter.ConvertSingleValue(payload, sensor.DataType)
			if err != nil {
				log.Fatal(err)
			} else {
				message.AddPayloadString(payloadS, sensor)
			}
		}
	}
	return message
}
<commit_msg>remove logging<commit_after>package distributor

import (
	"errors"
	"log"

	components "github.com/LoRaWanSoFa/LoRaWanSoFa/Components"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/Core/MessageConverter"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/Core/restUplinkConnector"
	"github.com/LoRaWanSoFa/LoRaWanSoFa/DBC/DatabaseConnector"
)

type Distributor interface {
	InputUplink(components.MessageUplinkI) (components.MessageUplinkI, error)
	InputDownlink(components.MessageDownLink)
}

type distributor struct {
	messageConverter    MessageConverter.MessageConverter
	restUplinkConnector restUplink.RestUplinkConnector
}

func New() Distributor {
	dist := new(distributor)
	dist.messageConverter = MessageConverter.New()
	config := components.GetConfiguration().Rest
	dist.restUplinkConnector = restUplink.NewRestUplinkConnector(config.Ip, config.ApiKey)
	return dist
}

func (d *distributor) InputUplink(message components.MessageUplinkI) (components.MessageUplinkI, error) {
	if d.deduplicate(message) {
		newMessage := d.convertMessage(message)
		err := DatabaseConnector.StoreMessagePayloads(newMessage)
		if err != nil {
			log.Fatal(err)
		}
		d.restUplinkConnector.NewData(newMessage.GetDevEUI(), newMessage)
		return newMessage, nil
	} else {
		err := errors.New("message was a duplicate")
		return nil, err
	}
}

func (d *distributor) InputDownlink(message components.MessageDownLink) {

}

//The deduplicate method should deduplicate messages that come in once from the
//TTN side of things(semi-private) as well as our own private backend and return
// true only if the message has not been received yet.
func (d *distributor) deduplicate(message components.MessageUplinkI) bool {
	// TODO: deduplicate messages that could come in checking with the database
	// or createing a small cache for it.
	return true
}

func (d *distributor) convertMessage(message components.MessageUplinkI) components.MessageUplinkI {
	bytePayloads := message.GetPayloads()
	message.RemovePayloads()
	for i := range bytePayloads {
		payload, ok := bytePayloads[i].GetPayload().([]byte)
		if ok {
			sensor := bytePayloads[i].GetSensor()
			payloadS, err := d.messageConverter.ConvertSingleValue(payload, sensor.DataType)
			if err != nil {
				log.Fatal(err)
			} else {
				message.AddPayloadString(payloadS, sensor)
			}
		}
	}
	return message
}
<|endoftext|>


<commit_before>package rpc

import (
	"encoding/json"

	"github.com/gopherjs/websocket"
)

type Call struct {
	ServiceMethod string
	Args, Reply   interface{}
	Error         error
	Done          chan *Call
}

type request struct {
	Method string         `json:"method"`
	ID     uint           `json:"id"`
	Params [1]interface{} `json:"params"`
}

type Client struct {
	ws     *websocket.Websocket
	nextID uint
	reqs   map[uint]func(json.RawMessage, error)
}

func Dial(addr string) (*Client, error) {
	w, err := websocket.New(addr)
	if err != nil {
		return nil, err
	}
	reqs := make(map[uint]func(json.RawMessage, error))
	w.AddEventListener("message", false, func(e *js.Object) {
		var (
			r request
			m json.RawMessage
		)
		r.Params[0] = &m
		err := json.UnmarshalString(e.Get("data").String(), &r)
		f, ok := reqs[r.ID]
		if ok {
			delete(reqs, r.ID)
			f(m, err)
		}
	})
	return &Client{
		ws:   w,
		reqs: reqs,
	}, nil
}

func (c *Client) Call(method string, args interface{}, reply interface{}) error {
	call := <-c.Go(method, args, reply, make(chan *Call, 1)).Done
	return call.Error
}

func (c *Client) Close() error {
	return c.w.Close()
}

func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
	call := &Call{
		ServiceMethod: method,
		Args:          args,
		Reply:         reply,
	}
	if done == nil {
		call.Done = make(chan *Call, 1)
	} else {
		call.Done = done
	}
	c.nextID++
	id := c.nextID
	c.reqs[id] = func(rm json.RawMessage, err error) {
		if err != nil {
			call.Error = err
		} else if err = json.Unmarshal(rm, reply); err != nil {
			call.Error = err
		}
		call.Done <- call
	}
	return call
}
<commit_msg>Go now sends the data<commit_after>package rpc

import (
	"encoding/json"

	"github.com/gopherjs/websocket"
)

type Call struct {
	ServiceMethod string
	Args, Reply   interface{}
	Error         error
	Done          chan *Call
}

type request struct {
	Method string         `json:"method"`
	ID     uint           `json:"id"`
	Params [1]interface{} `json:"params"`
}

type Client struct {
	ws     *websocket.Websocket
	nextID uint
	reqs   map[uint]func(json.RawMessage, error)
}

func Dial(addr string) (*Client, error) {
	w, err := websocket.New(addr)
	if err != nil {
		return nil, err
	}
	reqs := make(map[uint]func(json.RawMessage, error))
	w.AddEventListener("message", false, func(e *js.Object) {
		var (
			r request
			m json.RawMessage
		)
		r.Params[0] = &m
		err := json.UnmarshalString(e.Get("data").String(), &r)
		f, ok := reqs[r.ID]
		if ok {
			delete(reqs, r.ID)
			f(m, err)
		}
	})
	return &Client{
		ws:   w,
		reqs: reqs,
	}, nil
}

func (c *Client) Call(method string, args interface{}, reply interface{}) error {
	call := <-c.Go(method, args, reply, make(chan *Call, 1)).Done
	return call.Error
}

func (c *Client) Close() error {
	return c.w.Close()
}

func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
	call := &Call{
		ServiceMethod: method,
		Args:          args,
		Reply:         reply,
	}
	if done == nil {
		call.Done = make(chan *Call, 1)
	} else {
		if cap(done) < 1 {
			panic("invalid channel capacity")
		}
		call.Done = done
	}
	str, err := json.MarshalString(request{
		Method: method,
		ID:     c.nextID,
		Params: [1]interface{}{args},
	})
	if err == nil {
		err = c.ws.Send(str)
	}
	if err != nil {
		call.Error = err
		call.Done <- call
		return call
	}
	c.reqs[c.nextID] = func(rm json.RawMessage, err error) {
		if err != nil {
			call.Error = err
		} else if err = json.Unmarshal(rm, reply); err != nil {
			call.Error = err
		}
		call.Done <- call
	}
	c.nextID++
	return call
}
<|endoftext|>


<commit_before>package rpc

import (
	"bufio"
	"context"
	"encoding/gob"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"reflect"
	"sync"
	"unicode"
	"unicode/utf8"
)

var debugLog = false

var typeOfError = reflect.TypeOf((*error)(nil)).Elem()

const (
	// Defaults used by HandleHTTP
	DefaultRPCPath   = "/_goRPC_"
	DefaultDebugPath = "/debug/rpc"
)

type JsonRequest struct {
	Cmd    uint32           `json:"cmd"`
	Seq    uint32           `json:"seq"`
	Params *json.RawMessage `json:"params"`
}

func (r *JsonRequest) reset() {
	r.Cmd = 0
	r.Seq = 0
	r.Params = nil
}

type JsonResponse struct {
	Cmd    uint32      `json:"cmd"`
	Seq    uint32      `json:"seq"`
	Error  string      `json:"error"`
	Result interface{} `json:"result"`
}

// Request is a header written before every RPC call.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Request struct {
	Cmd  uint32
	Seq  uint32   // sequence number chosen by client
	next *Request // for free list in Server
}

// Response is a header written before every RPC return.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Response struct {
	Cmd   uint32    // echoes that of the Request
	Seq   uint32    // echoes that of the request
	Error uint32    // error, if any.
	next  *Response // for free list in Server
}

// Server represents an RPC Server.
type Server struct {
	// mu         sync.RWMutex // protects the serviceMap
	method   map[uint32]*methodType
	reqLock  sync.Mutex // protects freeReq
	freeReq  *Request
	respLock sync.Mutex // protects freeResp
	freeResp *Response
}

// NewServer returns a new Server.
func NewServer() *Server {
	return &Server{method: make(map[uint32]*methodType)}
}

var DefaultServer = NewServer()

type Error uint32

func (e Error) Error() string {
	return fmt.Sprintf("%d", uint32(e))
}

type ServerCodec interface {
	ReadRequestHeader(*Request) error
	ReadRequestBody(interface{}) error
	WriteResponse(*Response, interface{}) error
	Close() error
}

type methodType struct {
	// method    reflect.Method
	Func      reflect.Value
	ArgType   reflect.Type
	ReplyType reflect.Type
}

// Is this an exported - upper case - name?
func isExported(name string) bool {
	rune, _ := utf8.DecodeRuneInString(name)
	return unicode.IsUpper(rune)
}

// Is this type exported or a builtin?
func isExportedOrBuiltinType(t reflect.Type) bool {
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	// PkgPath will be non-empty even for an exported type,
	// so we need to check the type name as well.
	return isExported(t.Name()) || t.PkgPath() == ""
}

func (server *Server) readRequestHeader(codec ServerCodec) (mtype *methodType, req *Request, keepReading bool, err error) {
	// Grab the request header.
	req = server.getRequest()
	err = codec.ReadRequestHeader(req)
	if err != nil {
		req = nil
		if err == io.EOF || err == io.ErrUnexpectedEOF {
			return
		}
		err = errors.New("rpc: server cannot decode request: " + err.Error())
		return
	}

	// We read the header successfully.  If we see an error now,
	// we can still recover and move on to the next request.
	keepReading = true

	mtype = server.method[req.Cmd]
	if mtype == nil {
		err = errors.New("rpc: can't find method")
	}
	return
}

func (server *Server) getRequest() *Request {
	server.reqLock.Lock()
	req := server.freeReq
	if req == nil {
		req = new(Request)
	} else {
		server.freeReq = req.next
		*req = Request{}
	}
	server.reqLock.Unlock()
	return req
}

func (server *Server) freeRequest(req *Request) {
	server.reqLock.Lock()
	req.next = server.freeReq
	server.freeReq = req
	server.reqLock.Unlock()
}

func (server *Server) getResponse() *Response {
	server.respLock.Lock()
	resp := server.freeResp
	if resp == nil {
		resp = new(Response)
	} else {
		server.freeResp = resp.next
		*resp = Response{}
	}
	server.respLock.Unlock()
	return resp
}

func (server *Server) freeResponse(resp *Response) {
	server.respLock.Lock()
	resp.next = server.freeResp
	server.freeResp = resp
	server.respLock.Unlock()
}

func (server *Server) readRequest(codec ServerCodec) (mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
	mtype, req, keepReading, err = server.readRequestHeader(codec)
	if err != nil {
		if !keepReading {
			return
		}
		// discard body
		codec.ReadRequestBody(nil)
		return
	}

	// Decode the argument value.
	argIsValue := false // if true, need to indirect before calling.
	if mtype.ArgType.Kind() == reflect.Ptr {
		argv = reflect.New(mtype.ArgType.Elem())
	} else {
		argv = reflect.New(mtype.ArgType)
		argIsValue = true
	}
	// argv guaranteed to be a pointer now.
	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
		return
	}
	if argIsValue {
		argv = argv.Elem()
	}

	replyv = reflect.New(mtype.ReplyType.Elem())
	return
}

type gobServerCodec struct {
	rwc    io.ReadWriteCloser
	dec    *gob.Decoder
	enc    *gob.Encoder
	encBuf *bufio.Writer
	closed bool
}

func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
	return c.dec.Decode(r)
}

func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
	return c.dec.Decode(body)
}

func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
	if err = c.enc.Encode(r); err != nil {
		if c.encBuf.Flush() == nil {
			// Gob couldn't encode the header. Should not happen, so if it does,
			// shut down the connection to signal that the connection is broken.
			log.Println("rpc: gob error encoding response:", err)
			c.Close()
		}
		return
	}
	if err = c.enc.Encode(body); err != nil {
		if c.encBuf.Flush() == nil {
			// Was a gob problem encoding the body but the header has been written.
			// Shut down the connection to signal that the connection is broken.
			log.Println("rpc: gob error encoding body:", err)
			c.Close()
		}
		return
	}
	return c.encBuf.Flush()
}

func (c *gobServerCodec) Close() error {
	if c.closed {
		// Only call c.rwc.Close once; otherwise the semantics are undefined.
		return nil
	}
	c.closed = true
	return c.rwc.Close()
}

// ServeConn runs the server on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection.  To use an alternate codec, use ServeCodec.
func (server *Server) ServeConn(ctx context.Context, conn io.ReadWriteCloser) {
	buf := bufio.NewWriter(conn)
	srv := &gobServerCodec{
		rwc:    conn,
		dec:    gob.NewDecoder(conn),
		enc:    gob.NewEncoder(buf),
		encBuf: buf,
	}
	server.ServeCodec(ctx, srv)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
func (server *Server) ServeCodec(ctx context.Context, codec ServerCodec) {
	sending := new(sync.Mutex)
	arg1 := reflect.ValueOf(ctx)
	for {
		mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
		if err != nil {
			if debugLog && err != io.EOF {
				log.Println("rpc:", err)
			}
			if !keepReading {
				break
			}
			// send a response if we actually managed to read a header.
			if req != nil {
				server.sendResponse(sending, req, invalidRequest, codec, err)
				server.freeRequest(req)
			}
			continue
		}
		go server.call(sending, mtype, req, arg1, argv, replyv, codec)
	}
	codec.Close()
}

// test
type PendingCall struct {
	sending *sync.Mutex
	mtype   *methodType
	req     *Request
	arg1    reflect.Value
	argv    reflect.Value
	replyv  reflect.Value
	codec   ServerCodec
}

// test
func (server *Server) ServeCodec2(ctx context.Context, codec ServerCodec) {
	sending := new(sync.Mutex)
	arg1 := reflect.ValueOf(ctx)
	ch := make(chan *PendingCall, 1024)
	go server.callWithChan(ch)
	for {
		mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
		if err != nil {
			if debugLog && err != io.EOF {
				log.Println("rpc:", err)
			}
			if !keepReading {
				break
			}
			// send a response if we actually managed to read a header.
			if req != nil {
				server.sendResponse(sending, req, invalidRequest, codec, err)
				server.freeRequest(req)
			}
			continue
		}
		ch <- &PendingCall{
			sending: sending,
			mtype:   mtype,
			req:     req,
			arg1:    arg1,
			argv:    argv,
			replyv:  replyv,
			codec:   codec,
		}
		// go server.call(sending, mtype, req, arg1, argv, replyv, codec)
	}
	codec.Close()
}

// test
func (server *Server) callWithChan(ch chan *PendingCall) {
	for {
		call := <-ch
		server.call(call.sending, call.mtype, call.req, call.arg1, call.argv, call.replyv, call.codec)
	}
}

// A value sent as a placeholder for the server's response value when the server
// receives an invalid request. It is never decoded by the client since the Response
// contains an error when it is used.
var invalidRequest = struct{}{}

func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg error) {
	resp := server.getResponse()
	// Encode the response header
	resp.Cmd = req.Cmd
	if errmsg != nil {
		errcode, ok := errmsg.(Error)
		if ok {
			resp.Error = uint32(errcode)
		} else {
			resp.Error = uint32(0xFFFFFFFF)
		}
	}
	resp.Seq = req.Seq
	sending.Lock()
	err := codec.WriteResponse(resp, reply)
	if debugLog && err != nil {
		log.Println("rpc: writing response:", err)
	}
	sending.Unlock()
	server.freeResponse(resp)
}

func (server *Server) call(sending *sync.Mutex, mtype *methodType, req *Request, arg1, argv, replyv reflect.Value, codec ServerCodec) {
	function := mtype.Func
	// Invoke the method, providing a new value for the reply.
	returnValues := function.Call([]reflect.Value{arg1, argv, replyv})
	// The return value for the method is an error.
	errInter := returnValues[0].Interface()
	var err error
	if errInter != nil {
		err = errInter.(error)
	}
	server.sendResponse(sending, req, replyv.Interface(), codec, err)
	server.freeRequest(req)
}

func (server *Server) Register(cmd uint32, function interface{}) error {
	mtype := reflect.TypeOf(function)
	// Method needs three ins: receiver, *args, *reply.
	if mtype.NumIn() != 3 {
		return errors.New("method has wrong number of ins")
	}
	// First arg need not be a pointer.
	argType := mtype.In(1)
	if !isExportedOrBuiltinType(argType) {
		return errors.New("argument type not exported")
	}
	// Second arg must be a pointer.
	replyType := mtype.In(2)
	if replyType.Kind() != reflect.Ptr {
		return errors.New("reply type not a pointer")
	}
	// Reply type must be exported.
	if !isExportedOrBuiltinType(replyType) {
		return errors.New("reply type not exported")
	}
	// Method needs one out.
	if mtype.NumOut() != 1 {
		return errors.New("has wrong number of outs:")
	}
	// The return type of the method must be error.
	if returnType := mtype.Out(0); returnType != typeOfError {
		return errors.New("not error")
	}
	server.method[cmd] = &methodType{Func: reflect.ValueOf(function), ArgType: argType, ReplyType: replyType}
	return nil
}

// ServeConn runs the DefaultServer on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection.  To use an alternate codec, use ServeCodec.
func ServeConn(conn io.ReadWriteCloser) {
	DefaultServer.ServeConn(context.Background(), conn)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
func ServeCodec(codec ServerCodec) {
	DefaultServer.ServeCodec(context.Background(), codec)
}

// Register publishes the receiver's methods in the DefaultServer.
func Register(cmd uint32, function interface{}) error { return DefaultServer.Register(cmd, function) }

// Can connect to RPC service using HTTP CONNECT to rpcPath.
var connected = "200 Connected to Go RPC"
<commit_msg>improve & test<commit_after>package rpc

import (
	"bufio"
	"context"
	"encoding/gob"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"reflect"
	"sync"
	"unicode"
	"unicode/utf8"
)

var debugLog = false

var typeOfError = reflect.TypeOf((*error)(nil)).Elem()

const (
	// Defaults used by HandleHTTP
	DefaultRPCPath   = "/_goRPC_"
	DefaultDebugPath = "/debug/rpc"
)

type JsonRequest struct {
	Cmd    uint32           `json:"cmd"`
	Seq    uint32           `json:"seq"`
	Params *json.RawMessage `json:"params"`
}

func (r *JsonRequest) reset() {
	r.Cmd = 0
	r.Seq = 0
	r.Params = nil
}

type JsonResponse struct {
	Cmd    uint32      `json:"cmd"`
	Seq    uint32      `json:"seq"`
	Error  string      `json:"error"`
	Result interface{} `json:"result"`
}

// Request is a header written before every RPC call.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Request struct {
	Cmd  uint32
	Seq  uint32   // sequence number chosen by client
	next *Request // for free list in Server
}

// Response is a header written before every RPC return.  It is used internally
// but documented here as an aid to debugging, such as when analyzing
// network traffic.
type Response struct {
	Cmd   uint32    // echoes that of the Request
	Seq   uint32    // echoes that of the request
	Error uint32    // error, if any.
	next  *Response // for free list in Server
}

// Server represents an RPC Server.
type Server struct {
	// mu         sync.RWMutex // protects the serviceMap
	method   map[uint32]*methodType
	reqLock  sync.Mutex // protects freeReq
	freeReq  *Request
	respLock sync.Mutex // protects freeResp
	freeResp *Response
}

// NewServer returns a new Server.
func NewServer() *Server {
	return &Server{method: make(map[uint32]*methodType)}
}

var DefaultServer = NewServer()

type Error uint32

func (e Error) Error() string {
	return fmt.Sprintf("%d", uint32(e))
}

type ServerCodec interface {
	ReadRequestHeader(*Request) error
	ReadRequestBody(interface{}) error
	WriteResponse(*Response, interface{}) error
	Close() error
}

type methodType struct {
	// method    reflect.Method
	Func      reflect.Value
	ArgType   reflect.Type
	ReplyType reflect.Type
}

// Is this an exported - upper case - name?
func isExported(name string) bool {
	rune, _ := utf8.DecodeRuneInString(name)
	return unicode.IsUpper(rune)
}

// Is this type exported or a builtin?
func isExportedOrBuiltinType(t reflect.Type) bool {
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	// PkgPath will be non-empty even for an exported type,
	// so we need to check the type name as well.
	return isExported(t.Name()) || t.PkgPath() == ""
}

func (server *Server) readRequestHeader(codec ServerCodec) (mtype *methodType, req *Request, keepReading bool, err error) {
	// Grab the request header.
	req = server.getRequest()
	err = codec.ReadRequestHeader(req)
	if err != nil {
		req = nil
		if err == io.EOF || err == io.ErrUnexpectedEOF {
			return
		}
		err = errors.New("rpc: server cannot decode request: " + err.Error())
		return
	}

	// We read the header successfully.  If we see an error now,
	// we can still recover and move on to the next request.
	keepReading = true

	mtype = server.method[req.Cmd]
	if mtype == nil {
		err = errors.New("rpc: can't find method")
	}
	return
}

func (server *Server) getRequest() *Request {
	server.reqLock.Lock()
	req := server.freeReq
	if req == nil {
		req = new(Request)
	} else {
		server.freeReq = req.next
		*req = Request{}
	}
	server.reqLock.Unlock()
	return req
}

func (server *Server) freeRequest(req *Request) {
	server.reqLock.Lock()
	req.next = server.freeReq
	server.freeReq = req
	server.reqLock.Unlock()
}

func (server *Server) getResponse() *Response {
	server.respLock.Lock()
	resp := server.freeResp
	if resp == nil {
		resp = new(Response)
	} else {
		server.freeResp = resp.next
		*resp = Response{}
	}
	server.respLock.Unlock()
	return resp
}

func (server *Server) freeResponse(resp *Response) {
	server.respLock.Lock()
	resp.next = server.freeResp
	server.freeResp = resp
	server.respLock.Unlock()
}

func (server *Server) readRequest(codec ServerCodec) (mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
	mtype, req, keepReading, err = server.readRequestHeader(codec)
	if err != nil {
		if !keepReading {
			return
		}
		// discard body
		codec.ReadRequestBody(nil)
		return
	}

	// Decode the argument value.
	argIsValue := false // if true, need to indirect before calling.
	if mtype.ArgType.Kind() == reflect.Ptr {
		argv = reflect.New(mtype.ArgType.Elem())
	} else {
		argv = reflect.New(mtype.ArgType)
		argIsValue = true
	}
	// argv guaranteed to be a pointer now.
	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
		return
	}
	if argIsValue {
		argv = argv.Elem()
	}

	replyv = reflect.New(mtype.ReplyType.Elem())
	return
}

type gobServerCodec struct {
	rwc    io.ReadWriteCloser
	dec    *gob.Decoder
	enc    *gob.Encoder
	encBuf *bufio.Writer
	closed bool
}

func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
	return c.dec.Decode(r)
}

func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
	return c.dec.Decode(body)
}

func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
	if err = c.enc.Encode(r); err != nil {
		if c.encBuf.Flush() == nil {
			// Gob couldn't encode the header. Should not happen, so if it does,
			// shut down the connection to signal that the connection is broken.
			log.Println("rpc: gob error encoding response:", err)
			c.Close()
		}
		return
	}
	if err = c.enc.Encode(body); err != nil {
		if c.encBuf.Flush() == nil {
			// Was a gob problem encoding the body but the header has been written.
			// Shut down the connection to signal that the connection is broken.
			log.Println("rpc: gob error encoding body:", err)
			c.Close()
		}
		return
	}
	return c.encBuf.Flush()
}

func (c *gobServerCodec) Close() error {
	if c.closed {
		// Only call c.rwc.Close once; otherwise the semantics are undefined.
		return nil
	}
	c.closed = true
	return c.rwc.Close()
}

// ServeConn runs the server on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection.  To use an alternate codec, use ServeCodec.
func (server *Server) ServeConn(ctx context.Context, conn io.ReadWriteCloser) {
	buf := bufio.NewWriter(conn)
	srv := &gobServerCodec{
		rwc:    conn,
		dec:    gob.NewDecoder(conn),
		enc:    gob.NewEncoder(buf),
		encBuf: buf,
	}
	server.ServeCodec(ctx, srv)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
func (server *Server) ServeCodec(ctx context.Context, codec ServerCodec) {
	sending := new(sync.Mutex)
	arg1 := reflect.ValueOf(ctx)
	for {
		mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
		if err != nil {
			if debugLog && err != io.EOF {
				log.Println("rpc:", err)
			}
			if !keepReading {
				break
			}
			// send a response if we actually managed to read a header.
			if req != nil {
				server.sendResponse(sending, req, invalidRequest, codec, err)
				server.freeRequest(req)
			}
			continue
		}
		go server.call(sending, mtype, req, arg1, argv, replyv, codec)
	}
	codec.Close()
}

// test
type PendingCall struct {
	sending *sync.Mutex
	mtype   *methodType
	req     *Request
	arg1    reflect.Value
	argv    reflect.Value
	replyv  reflect.Value
	codec   ServerCodec
}

func (pc *PendingCall) Context() context.Context {
	return pc.arg1.Interface().(context.Context)
}

// test
func (server *Server) ServeCodec2(ctx context.Context, codec ServerCodec, ch chan interface{}) {
	sending := new(sync.Mutex)
	arg1 := reflect.ValueOf(ctx)
	for {
		mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
		if err != nil {
			if debugLog && err != io.EOF {
				log.Println("rpc:", err)
			}
			if !keepReading {
				break
			}
			// send a response if we actually managed to read a header.
			if req != nil {
				server.sendResponse(sending, req, invalidRequest, codec, err)
				server.freeRequest(req)
			}
			continue
		}
		ch <- &PendingCall{
			sending: sending,
			mtype:   mtype,
			req:     req,
			arg1:    arg1,
			argv:    argv,
			replyv:  replyv,
			codec:   codec,
		}
		// go server.call(sending, mtype, req, arg1, argv, replyv, codec)
	}
	codec.Close()
}

// test
func (server *Server) Call(pc interface{}) {
	call := pc.(*PendingCall)
	server.call(call.sending, call.mtype, call.req, call.arg1, call.argv, call.replyv, call.codec)
}

// test
// func (server *Server) callWithChan(ch chan *PendingCall) {
// 	for {
// 		call := <-ch
// 		server.call(call.sending, call.mtype, call.req, call.arg1, call.argv, call.replyv, call.codec)
// 	}
// }

// A value sent as a placeholder for the server's response value when the server
// receives an invalid request. It is never decoded by the client since the Response
// contains an error when it is used.
var invalidRequest = struct{}{}

func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg error) {
	resp := server.getResponse()
	// Encode the response header
	resp.Cmd = req.Cmd
	if errmsg != nil {
		errcode, ok := errmsg.(Error)
		if ok {
			resp.Error = uint32(errcode)
		} else {
			resp.Error = uint32(0xFFFFFFFF)
		}
	}
	resp.Seq = req.Seq
	sending.Lock()
	err := codec.WriteResponse(resp, reply)
	if debugLog && err != nil {
		log.Println("rpc: writing response:", err)
	}
	sending.Unlock()
	server.freeResponse(resp)
}

func (server *Server) call(sending *sync.Mutex, mtype *methodType, req *Request, arg1, argv, replyv reflect.Value, codec ServerCodec) {
	function := mtype.Func
	// Invoke the method, providing a new value for the reply.
	returnValues := function.Call([]reflect.Value{arg1, argv, replyv})
	// The return value for the method is an error.
	errInter := returnValues[0].Interface()
	var err error
	if errInter != nil {
		err = errInter.(error)
	}
	server.sendResponse(sending, req, replyv.Interface(), codec, err)
	server.freeRequest(req)
}

func (server *Server) Register(cmd uint32, function interface{}) error {
	mtype := reflect.TypeOf(function)
	// Method needs three ins: receiver, *args, *reply.
	if mtype.NumIn() != 3 {
		return errors.New("method has wrong number of ins")
	}
	// First arg need not be a pointer.
	argType := mtype.In(1)
	if !isExportedOrBuiltinType(argType) {
		return errors.New("argument type not exported")
	}
	// Second arg must be a pointer.
	replyType := mtype.In(2)
	if replyType.Kind() != reflect.Ptr {
		return errors.New("reply type not a pointer")
	}
	// Reply type must be exported.
	if !isExportedOrBuiltinType(replyType) {
		return errors.New("reply type not exported")
	}
	// Method needs one out.
	if mtype.NumOut() != 1 {
		return errors.New("has wrong number of outs:")
	}
	// The return type of the method must be error.
	if returnType := mtype.Out(0); returnType != typeOfError {
		return errors.New("not error")
	}
	server.method[cmd] = &methodType{Func: reflect.ValueOf(function), ArgType: argType, ReplyType: replyType}
	return nil
}

// ServeConn runs the DefaultServer on a single connection.
// ServeConn blocks, serving the connection until the client hangs up.
// The caller typically invokes ServeConn in a go statement.
// ServeConn uses the gob wire format (see package gob) on the
// connection.  To use an alternate codec, use ServeCodec.
func ServeConn(conn io.ReadWriteCloser) {
	DefaultServer.ServeConn(context.Background(), conn)
}

// ServeCodec is like ServeConn but uses the specified codec to
// decode requests and encode responses.
func ServeCodec(codec ServerCodec) {
	DefaultServer.ServeCodec(context.Background(), codec)
}

// Register publishes the receiver's methods in the DefaultServer.
func Register(cmd uint32, function interface{}) error { return DefaultServer.Register(cmd, function) }

// Can connect to RPC service using HTTP CONNECT to rpcPath.
var connected = "200 Connected to Go RPC"
<|endoftext|>


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

package main

import (
  "bufio"
  "flag"
  "fmt"
  "lc-lib/admin"
  "lc-lib/core"
  "os"
  "os/signal"
  "strings"
  "text/scanner"
  "time"
)

type CommandError struct {
  message string
}

func (c *CommandError) Error() string {
  return c.message
}

var CommandEOF *CommandError = &CommandError{"EOF"}
var CommandTooManyArgs *CommandError = &CommandError{"Too many arguments"}

type Admin struct {
  client        *admin.Client
  connected     bool
  quiet         bool
  admin_connect string
  scanner       scanner.Scanner
  scanner_err   error
}

func NewAdmin(quiet bool, admin_connect string) *Admin {
  return &Admin{
    quiet:         quiet,
    admin_connect: admin_connect,
  }
}

func (a *Admin) connect() error {
  if !a.connected {
    var err error

    if !a.quiet {
      fmt.Printf("Attempting connection to %s...\n", a.admin_connect)
    }

    if a.client, err = admin.NewClient(a.admin_connect); err != nil {
      fmt.Printf("Failed to connect: %s\n", err)
      return err
    }

    if !a.quiet {
      fmt.Printf("Connected\n\n")
    }

    a.connected = true
  }

  return nil
}

func (a *Admin) ProcessCommand(command string) bool {
  var reconnected bool

  for {
    if !a.connected {
      if err := a.connect(); err != nil {
        return false
      }

      reconnected = true
    }

    var err error

    a.initScanner(command)
    if command, err = a.scanIdent(); err != nil {
      goto Error
    }

    switch command {
    case "reload":
      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      err = a.client.Reload()
      if err != nil {
        break
      }

      fmt.Printf("Configuration reload successful\n")
    case "status":
      var format string
      format, err = a.scanIdent()
      if err != nil && err != CommandEOF {
        break
      }

      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      var snaps *core.Snapshot
      snaps, err = a.client.FetchSnapshot()
      if err != nil {
        break
      }

      a.renderSnap(format, snaps)
    case "help":
      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      PrintHelp()
    default:
      err = &CommandError{fmt.Sprintf("Unknown command: %s", command)}
    }

    if err == nil {
      return true
    }

  Error:
    if _, ok := err.(*CommandError); ok {
      fmt.Printf("Parse error: %s\n", err)
      return false
    } else if _, ok := err.(*admin.ErrorResponse); ok {
      fmt.Printf("Log Courier returned an error: %s\n", err)
      return false
    } else {
      a.connected = false
      fmt.Printf("Connection error: %s\n", err)
    }

    if reconnected {
      break
    }
  }

  return false
}

func (a *Admin) initScanner(command string) {
  a.scanner.Init(strings.NewReader(command))
  a.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings
  a.scanner.Whitespace = 1<<' '

  a.scanner.Error = func(s *scanner.Scanner, msg string) {
    a.scanner_err = &CommandError{msg}
  }

  a.scanner.IsIdentRune = func(ch rune, i int) bool {
    if ch >= 'a' && ch <= 'z' {
      return true
    }
    if ch >= 'A' && ch <= 'Z' {
      return true
    }
    return false
  }
}

func (a *Admin) scanIdent() (string, error) {
  r := a.scanner.Scan()
  if a.scanner_err != nil {
    return "", a.scanner_err
  }
  switch r {
  case scanner.Ident:
    return a.scanner.TokenText(), nil
  case scanner.EOF:
    return "", CommandEOF
  }
  return "", &CommandError{"Invalid token"}
}

func (a *Admin) scanEOF() bool {
  r := a.scanner.Scan()
  if a.scanner_err == nil && r == scanner.EOF {
    return true
  }
  return false
}

func (a *Admin) renderSnap(format string, snap *core.Snapshot) {
  switch format {
  case "json":
    fmt.Printf("{\n")
    a.renderSnapJSON("\t", snap)
    fmt.Printf("}\n")
  default:
    a.renderSnapYAML("", snap)
  }
}

func (a *Admin) renderSnapJSON(indent string, snap *core.Snapshot) {
  if snap.NumEntries() != 0 {
    for i, j := 0, snap.NumEntries(); i < j; i = i+1 {
      k, v := snap.Entry(i)
      switch t := v.(type) {
      case string:
        fmt.Printf(indent + "%q: %q", k, t)
      case int8, int16, int32, int64, uint8, uint16, uint32, uint64:
        fmt.Printf(indent + "%q: %d", k, t)
      case float32, float64:
        fmt.Printf(indent + "%q: %.2f", k, t)
      case time.Time:
        fmt.Printf(indent + "%q: %q", k, t.Format("_2 Jan 2006 15.04.05"))
      case time.Duration:
        fmt.Printf(indent + "%q: %q", k, (t-(t%time.Second)).String())
      default:
        fmt.Printf(indent + "%q: %q", k, fmt.Sprintf("%v", t))
      }
      if i + 1 < j || snap.NumSubs() != 0 {
        fmt.Printf(",\n")
      } else {
        fmt.Printf("\n")
      }
    }
  }
  if snap.NumSubs() != 0 {
    for i, j := 0, snap.NumSubs(); i < j; i = i+1 {
      sub_snap := snap.Sub(i)
      fmt.Printf(indent + "%q: {\n", sub_snap.Description())
      a.renderSnapJSON(indent + "\t", sub_snap)
      if i + 1 < j {
        fmt.Printf(indent + "},\n")
      } else {
        fmt.Printf(indent + "}\n")
      }
    }
  }
}

func (a *Admin) renderSnapYAML(indent string, snap *core.Snapshot) {
  if snap.NumEntries() != 0 {
    for i, j := 0, snap.NumEntries(); i < j; i = i+1 {
      k, v := snap.Entry(i)
      switch t := v.(type) {
      case string:
        fmt.Printf(indent + "%s: %s\n", k, t)
      case int, int8, int16, int32, int64, uint8, uint16, uint32, uint64:
        fmt.Printf(indent + "%s: %d\n", k, t)
      case float32, float64:
        fmt.Printf(indent + "%s: %.2f\n", k, t)
      case time.Time:
        fmt.Printf(indent + "%s: %s\n", k, t.Format("_2 Jan 2006 15.04.05"))
      case time.Duration:
        fmt.Printf(indent + "%s: %s\n", k, (t-(t%time.Second)).String())
      default:
        fmt.Printf(indent + "%s: %v\n", k, t)
      }
    }
  }
  if snap.NumSubs() != 0 {
    for i, j := 0, snap.NumSubs(); i < j; i = i+1 {
      sub_snap := snap.Sub(i)
      fmt.Printf(indent + "%s:\n", sub_snap.Description())
      a.renderSnapYAML(indent + "  ", sub_snap)
    }
  }
}

func (a *Admin) Run() {
  signal_chan := make(chan os.Signal, 1)
  signal.Notify(signal_chan, os.Interrupt)

  command_chan := make(chan string)
  go func() {
    var discard bool
    reader := bufio.NewReader(os.Stdin)
    for {
      line, prefix, err := reader.ReadLine()
      if err != nil {
        break
      } else if prefix {
        discard = true
      } else if discard {
        fmt.Printf("Line too long!\n")
        discard = false
      } else {
        command_chan <- string(line)
      }
    }
  }()

CommandLoop:
  for {
    fmt.Printf("> ")
    select {
    case command := <-command_chan:
      if command == "exit" {
        break CommandLoop
      }
      a.ProcessCommand(command)
    case <-signal_chan:
      fmt.Printf("\n> exit\n")
      break CommandLoop
    }
  }
}

func (a *Admin) argsCommand(args []string, watch bool) bool {
  var signal_chan chan os.Signal

  if watch {
    signal_chan = make(chan os.Signal, 1)
    signal.Notify(signal_chan, os.Interrupt)
  }

WatchLoop:
  for {
    if !a.ProcessCommand(strings.Join(args, " ")) {
      if !watch {
        return false
      }
    }

    if !watch {
      break
    }

    // Gap between repeats
    fmt.Printf("\n")

    select {
    case <-signal_chan:
      break WatchLoop
    case <-time.After(time.Second):
    }
  }

  return true
}

func PrintHelp() {
  fmt.Printf("Available commands:\n")
  fmt.Printf("  reload    Reload configuration\n")
  fmt.Printf("  status    Display the current shipping status\n")
  fmt.Printf("  exit      Exit\n")
}

func main() {
  var version bool
  var quiet bool
  var watch bool
  var admin_connect string

  flag.BoolVar(&version, "version", false, "display the Log Courier client version")
  flag.BoolVar(&quiet, "quiet", false, "quietly execute the command line argument and output only the result")
  flag.BoolVar(&watch, "watch", false, "repeat the command specified on the command line every second")
  flag.StringVar(&admin_connect, "connect", "tcp:127.0.0.1:1234", "the Log Courier instance to connect to (default tcp:127.0.0.1:1234)")

  flag.Parse()

  if version {
    fmt.Printf("Log Courier version %s\n", core.Log_Courier_Version)
    os.Exit(0)
  }

  if !quiet {
    fmt.Printf("Log Courier version %s client\n\n", core.Log_Courier_Version)
  }

  args := flag.Args()

  if len(args) != 0 {
    // Don't require a connection to display the help message
    if args[0] == "help" {
      PrintHelp()
      os.Exit(0)
    }

    admin := NewAdmin(quiet, admin_connect)
    if admin.argsCommand(args, watch) {
      os.Exit(0)
    }
    os.Exit(1)
  }

  if quiet {
    fmt.Printf("No command specified on the command line for quiet execution\n")
    os.Exit(1)
  }

  if watch {
    fmt.Printf("No command specified on the command line to watch\n")
    os.Exit(1)
  }

  admin := NewAdmin(quiet, admin_connect)
  if err := admin.connect(); err != nil {
    return
  }

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

package main

import (
  "bufio"
  "flag"
  "fmt"
  "lc-lib/admin"
  "lc-lib/core"
  "os"
  "os/signal"
  "strings"
  "text/scanner"
  "time"
)

type CommandError struct {
  message string
}

func (c *CommandError) Error() string {
  return c.message
}

var CommandEOF *CommandError = &CommandError{"EOF"}
var CommandTooManyArgs *CommandError = &CommandError{"Too many arguments"}

type Admin struct {
  client        *admin.Client
  connected     bool
  quiet         bool
  admin_connect string
  scanner       scanner.Scanner
  scanner_err   error
}

func NewAdmin(quiet bool, admin_connect string) *Admin {
  return &Admin{
    quiet:         quiet,
    admin_connect: admin_connect,
  }
}

func (a *Admin) connect() error {
  if !a.connected {
    var err error

    if !a.quiet {
      fmt.Printf("Attempting connection to %s...\n", a.admin_connect)
    }

    if a.client, err = admin.NewClient(a.admin_connect); err != nil {
      fmt.Printf("Failed to connect: %s\n", err)
      return err
    }

    if !a.quiet {
      fmt.Printf("Connected\n\n")
    }

    a.connected = true
  }

  return nil
}

func (a *Admin) ProcessCommand(command string) bool {
  var reconnected bool

  for {
    if !a.connected {
      if err := a.connect(); err != nil {
        return false
      }

      reconnected = true
    }

    var err error

    a.initScanner(command)
    if command, err = a.scanIdent(); err != nil {
      goto Error
    }

    switch command {
    case "reload":
      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      err = a.client.Reload()
      if err != nil {
        break
      }

      fmt.Printf("Configuration reload successful\n")
    case "status":
      var format string
      format, err = a.scanIdent()
      if err != nil && err != CommandEOF {
        break
      }

      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      var snaps *core.Snapshot
      snaps, err = a.client.FetchSnapshot()
      if err != nil {
        break
      }

      a.renderSnap(format, snaps)
    case "help":
      if !a.scanEOF() {
        err = CommandTooManyArgs
        break
      }

      PrintHelp()
    default:
      err = &CommandError{fmt.Sprintf("Unknown command: %s", command)}
    }

    if err == nil {
      return true
    }

  Error:
    if _, ok := err.(*CommandError); ok {
      fmt.Printf("Parse error: %s\n", err)
      return false
    } else if _, ok := err.(*admin.ErrorResponse); ok {
      fmt.Printf("Log Courier returned an error: %s\n", err)
      return false
    } else {
      a.connected = false
      fmt.Printf("Connection error: %s\n", err)
    }

    if reconnected {
      break
    }
  }

  return false
}

func (a *Admin) initScanner(command string) {
  a.scanner.Init(strings.NewReader(command))
  a.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings
  a.scanner.Whitespace = 1<<' '

  a.scanner.Error = func(s *scanner.Scanner, msg string) {
    a.scanner_err = &CommandError{msg}
  }
}

func (a *Admin) scanIdent() (string, error) {
  r := a.scanner.Scan()
  if a.scanner_err != nil {
    return "", a.scanner_err
  }
  switch r {
  case scanner.Ident:
    return a.scanner.TokenText(), nil
  case scanner.EOF:
    return "", CommandEOF
  }
  return "", &CommandError{"Invalid token"}
}

func (a *Admin) scanEOF() bool {
  r := a.scanner.Scan()
  if a.scanner_err == nil && r == scanner.EOF {
    return true
  }
  return false
}

func (a *Admin) renderSnap(format string, snap *core.Snapshot) {
  switch format {
  case "json":
    fmt.Printf("{\n")
    a.renderSnapJSON("\t", snap)
    fmt.Printf("}\n")
  default:
    a.renderSnapYAML("", snap)
  }
}

func (a *Admin) renderSnapJSON(indent string, snap *core.Snapshot) {
  if snap.NumEntries() != 0 {
    for i, j := 0, snap.NumEntries(); i < j; i = i+1 {
      k, v := snap.Entry(i)
      switch t := v.(type) {
      case string:
        fmt.Printf(indent + "%q: %q", k, t)
      case int8, int16, int32, int64, uint8, uint16, uint32, uint64:
        fmt.Printf(indent + "%q: %d", k, t)
      case float32, float64:
        fmt.Printf(indent + "%q: %.2f", k, t)
      case time.Time:
        fmt.Printf(indent + "%q: %q", k, t.Format("_2 Jan 2006 15.04.05"))
      case time.Duration:
        fmt.Printf(indent + "%q: %q", k, (t-(t%time.Second)).String())
      default:
        fmt.Printf(indent + "%q: %q", k, fmt.Sprintf("%v", t))
      }
      if i + 1 < j || snap.NumSubs() != 0 {
        fmt.Printf(",\n")
      } else {
        fmt.Printf("\n")
      }
    }
  }
  if snap.NumSubs() != 0 {
    for i, j := 0, snap.NumSubs(); i < j; i = i+1 {
      sub_snap := snap.Sub(i)
      fmt.Printf(indent + "%q: {\n", sub_snap.Description())
      a.renderSnapJSON(indent + "\t", sub_snap)
      if i + 1 < j {
        fmt.Printf(indent + "},\n")
      } else {
        fmt.Printf(indent + "}\n")
      }
    }
  }
}

func (a *Admin) renderSnapYAML(indent string, snap *core.Snapshot) {
  if snap.NumEntries() != 0 {
    for i, j := 0, snap.NumEntries(); i < j; i = i+1 {
      k, v := snap.Entry(i)
      switch t := v.(type) {
      case string:
        fmt.Printf(indent + "%s: %s\n", k, t)
      case int, int8, int16, int32, int64, uint8, uint16, uint32, uint64:
        fmt.Printf(indent + "%s: %d\n", k, t)
      case float32, float64:
        fmt.Printf(indent + "%s: %.2f\n", k, t)
      case time.Time:
        fmt.Printf(indent + "%s: %s\n", k, t.Format("_2 Jan 2006 15.04.05"))
      case time.Duration:
        fmt.Printf(indent + "%s: %s\n", k, (t-(t%time.Second)).String())
      default:
        fmt.Printf(indent + "%s: %v\n", k, t)
      }
    }
  }
  if snap.NumSubs() != 0 {
    for i, j := 0, snap.NumSubs(); i < j; i = i+1 {
      sub_snap := snap.Sub(i)
      fmt.Printf(indent + "%s:\n", sub_snap.Description())
      a.renderSnapYAML(indent + "  ", sub_snap)
    }
  }
}

func (a *Admin) Run() {
  signal_chan := make(chan os.Signal, 1)
  signal.Notify(signal_chan, os.Interrupt)

  command_chan := make(chan string)
  go func() {
    var discard bool
    reader := bufio.NewReader(os.Stdin)
    for {
      line, prefix, err := reader.ReadLine()
      if err != nil {
        break
      } else if prefix {
        discard = true
      } else if discard {
        fmt.Printf("Line too long!\n")
        discard = false
      } else {
        command_chan <- string(line)
      }
    }
  }()

CommandLoop:
  for {
    fmt.Printf("> ")
    select {
    case command := <-command_chan:
      if command == "exit" {
        break CommandLoop
      }
      a.ProcessCommand(command)
    case <-signal_chan:
      fmt.Printf("\n> exit\n")
      break CommandLoop
    }
  }
}

func (a *Admin) argsCommand(args []string, watch bool) bool {
  var signal_chan chan os.Signal

  if watch {
    signal_chan = make(chan os.Signal, 1)
    signal.Notify(signal_chan, os.Interrupt)
  }

WatchLoop:
  for {
    if !a.ProcessCommand(strings.Join(args, " ")) {
      if !watch {
        return false
      }
    }

    if !watch {
      break
    }

    // Gap between repeats
    fmt.Printf("\n")

    select {
    case <-signal_chan:
      break WatchLoop
    case <-time.After(time.Second):
    }
  }

  return true
}

func PrintHelp() {
  fmt.Printf("Available commands:\n")
  fmt.Printf("  reload    Reload configuration\n")
  fmt.Printf("  status    Display the current shipping status\n")
  fmt.Printf("  exit      Exit\n")
}

func main() {
  var version bool
  var quiet bool
  var watch bool
  var admin_connect string

  flag.BoolVar(&version, "version", false, "display the Log Courier client version")
  flag.BoolVar(&quiet, "quiet", false, "quietly execute the command line argument and output only the result")
  flag.BoolVar(&watch, "watch", false, "repeat the command specified on the command line every second")
  flag.StringVar(&admin_connect, "connect", "tcp:127.0.0.1:1234", "the Log Courier instance to connect to (default tcp:127.0.0.1:1234)")

  flag.Parse()

  if version {
    fmt.Printf("Log Courier version %s\n", core.Log_Courier_Version)
    os.Exit(0)
  }

  if !quiet {
    fmt.Printf("Log Courier version %s client\n\n", core.Log_Courier_Version)
  }

  args := flag.Args()

  if len(args) != 0 {
    // Don't require a connection to display the help message
    if args[0] == "help" {
      PrintHelp()
      os.Exit(0)
    }

    admin := NewAdmin(quiet, admin_connect)
    if admin.argsCommand(args, watch) {
      os.Exit(0)
    }
    os.Exit(1)
  }

  if quiet {
    fmt.Printf("No command specified on the command line for quiet execution\n")
    os.Exit(1)
  }

  if watch {
    fmt.Printf("No command specified on the command line to watch\n")
    os.Exit(1)
  }

  admin := NewAdmin(quiet, admin_connect)
  if err := admin.connect(); err != nil {
    return
  }

  admin.Run()
}
<|endoftext|>


<commit_before>package sn

func countingStepNumbers(low, hi int) []int {
    return []int{}
}
<commit_msg>feat: use brute force got tle<commit_after>package sn

import "strconv"

func countingStepNumbers(low, hi int) []int {
    return bruteForce(low, hi)
}

func bruteForce(low, hi int) []int {
    res := make([]int, 0, hi-low)
    if low == hi {
        res = append(res, low)
        return res
    }
    res = append(res, low)
    for i := low + 1; i < hi; i++ {
        if isStepping(i) {
            res = append(res, i)
        }
    }
    res = append(res, hi)
    return res
}

func isStepping(i int) bool {
    sb := strconv.Itoa(i)
    var prev, cur int
    for i := 0; i < len(sb)-1; i++ {
        //fmt.Printf("sb[i] is %d, sb[i+1] is %d\n", int(sb[i]-'0'), int(sb[i+1]-'0'))
        prev, cur = int(sb[i]-'0'), int(sb[i+1]-'0')
        if prev-cur != -1 && prev-cur != 1 {
            return false
        }
    }
    return true
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

// An interface defines behaviour of an object. In go an interface is a type
// that specifies one or more method signatures collectively called method set.
// Interfaces are wholly abstract, so it is not possible to instantiate an interface.
// A variable of interface type can store a value of any type with a method set
// that is any superset of the interface. Such a type is said to implement the
// interface. The value of an uninitialized variable of interface type is nil.

// The interface{} type is the interface that specifies the empty set of methods.
// Every value satisfies the interface{} type whether the value has methods or
// not, if a value does have methods, its set of methods includes the empty set
// of methods as well as the methods it actually has. This is why the interface{}
// type can be used for anyvalue.

// A type doesn’t have to state explicitly that it implements an interface:
// interfaces are satisfied implicitly.
// Multiple types can implement the same interface.
// A type that implements an interface can also have other functions. A type can
// implement many interfaces.
// An interface type can contain a reference to an instance of any of the types
// that implement the interface (an interface has what is called a dynamic type)

type shaper interface {
	area() float64
	perimeter() float64
}

type enlarger interface {
	enlarge(float64)
}

type circle struct {
	radius float64
}

type rectangle struct {
	length, width float64
}

type square struct {
	rectangle //anonymous field (embedding)
}

type triangle struct {
	a, b, c float64 //side of a triangle
}

// The methods area and perimeter on types circle, and rectangle are defined
// with a value reciever since these methods do not mutate (modify) the state of
// their respective types.
func (c circle) area() float64 {
	return math.Pi * c.radius * c.radius
}

func (c circle) perimeter() float64 {
	return 2 * math.Pi * c.radius
}

// enlarge method is defined with a pointer reciever since it mutates (modifies)
// the passed values state. If the reciver was defined as value then the chnage
// to the state of the value will not visible.
func (c *circle) enlarge(by float64) {
	c.radius += by
}

// notice that we have not defined the area and perimeter methods for the square type
// If an embedded field has methods we can call them on the containing struct,
// and only the embedded field will be passed as the methods’ receiver.
func (r rectangle) area() float64 {
	return r.length * r.width
}

func (r rectangle) perimeter() float64 {
	return 2 * (r.length + r.width)
}

func (r *rectangle) enlarge(by float64) {
	r.length += by
	r.width += by
}

// geometry takes any values that satisfy the shaper interface and is able
// dynamically dispatch the call to correct area and perimeter methods
func geometry(s shaper) {
	fmt.Printf("Area of %#v is %.2f\n", s, s.area())
	fmt.Printf("Perimeter of %#v is %.2f\n", s, s.perimeter())
}

func main() {
	c := circle{2.12}
	r := rectangle{4.3, 3.5}
	s := square{rectangle{4.6, 4.6}}

	geometry(c)
	geometry(r)
	geometry(s)

	fmt.Printf("Before enlarge %#v\n", c)
	// Since the circle type is addressable Go would automatically modify the
	// call to enlarge method by passing a pointer to c i.e. it would modify
	// the method call to read (&c).enlarge(1.1)
	c.enlarge(1.1)
	fmt.Printf("After enlarge %#v\n", c)

	// declare t if of type interface{}
	var t interface{}
	t = triangle{1.0, 2.0, 3.0}

	// we can use type assertion to check at runtime if a type satifies an interface
	_, ok := t.(shaper)
	if !ok {
		fmt.Printf("%#v does not statisfy shaper interface\n", t)
	}

	// Go would generate a compile time error if we were pass t1 to geomerty function
	// because the triangle type does not implement the methods called out in the
	// shaper interface.
	// uncomment next two lines to see the error in action
	//t1 := triangle{1.0, 10.2, 13.0}
	//geometry(t1)
}
<commit_msg>complete the sample<commit_after>package main

import (
	"fmt"
	"math"
)

// An interface defines behaviour of an object. In go an interface is a type
// that specifies one or more method signatures collectively called method set.
// Interfaces are wholly abstract, so it is not possible to instantiate an interface.
// A variable of interface type can store a value of any type with a method set
// that is any superset of the interface. Such a type is said to implement the
// interface. The value of an uninitialized variable of interface type is nil.

// The interface{} type is the interface that specifies the empty set of methods.
// Every value satisfies the interface{} type whether the value has methods or
// not, if a value does have methods, its set of methods includes the empty set
// of methods as well as the methods it actually has. This is why the interface{}
// type can be used for anyvalue.

// A type doesn’t have to state explicitly that it implements an interface:
// interfaces are satisfied implicitly.
// Multiple types can implement the same interface.
// A type that implements an interface can also have other functions. A type can
// implement many interfaces.
// An interface type can contain a reference to an instance of any of the types
// that implement the interface (an interface has what is called a dynamic type)

type shaper interface {
	area() float64
	perimeter() float64
}

type enlarger interface {
	enlarge(float64)
}

type circle struct {
	radius float64
}

type rectangle struct {
	length, width float64
}

type square struct {
	rectangle //anonymous field (embedding)
}

type triangle struct {
	a, b, c float64 //side of a triangle
}

// The methods area and perimeter on types circle, and rectangle are defined
// with a value reciever since these methods do not mutate (modify) the state of
// their respective types.
func (c circle) area() float64 {
	return math.Pi * c.radius * c.radius
}

func (c circle) perimeter() float64 {
	return 2 * math.Pi * c.radius
}

// enlarge method is defined with a pointer reciever since it mutates (modifies)
// the passed values state. If the reciver was defined as value then the chnage
// to the state of the value will not visible.
func (c *circle) enlarge(by float64) {
	c.radius += by
}

// notice that we have not defined the area and perimeter methods for the square type
// If an embedded field has methods we can call them on the containing struct,
// and only the embedded field will be passed as the methods’ receiver.
func (r rectangle) area() float64 {
	return r.length * r.width
}

func (r rectangle) perimeter() float64 {
	return 2 * (r.length + r.width)
}

func (r *rectangle) enlarge(by float64) {
	r.length += by
	r.width += by
}

// geometry takes any values that satisfy the shaper interface and is able
// dynamically dispatch the call to correct area and perimeter methods
func geometry(s shaper) {
	fmt.Printf("Area of %#v is %.2f\n", s, s.area())
	fmt.Printf("Perimeter of %#v is %.2f\n", s, s.perimeter())
}

func main() {
	c := circle{2.12}
	r := rectangle{4.3, 3.5}
	s := square{rectangle{4.6, 4.6}}

	geometry(c)
	geometry(r)
	geometry(s)

	fmt.Printf("Before enlarge %#v\n", c)
	// Since the circle type is addressable Go would automatically modify the
	// call to enlarge method by passing a pointer to c i.e. it would modify
	// the method call to read (&c).enlarge(1.1)
	c.enlarge(1.1)
	fmt.Printf("After enlarge %#v\n", c)

	// declare t if of type interface{}
	var t interface{}
	t = triangle{1.0, 2.0, 3.0}

	// we can use type assertion to check at runtime if a type satifies an interface
	_, ok := t.(shaper)
	if !ok {
		fmt.Printf("%#v does not statisfy shaper interface\n", t)
	}

	// Go would generate a compile time error if we were pass t1 to geometry function
	// because the triangle type does not implement the methods called out in the
	// shaper interface.
	// uncomment next two lines to see the error in action
	//t1 := triangle{1.0, 10.2, 13.0}
	//geometry(t1)
}
<|endoftext|>


<commit_before>// +build windows

package filesystem

import (
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/spf13/afero"
)

type OsFs struct {
	afero.Fs
}

func NewOsFs() afero.Fs {
	return &OsFs{}
}

func (OsFs) Name() string { return "OsFs" }

func (OsFs) Create(name string) (afero.File, error) {
	f, e := os.Create(normalizePath(name))
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(normalizePath(name), perm)
}

func (OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(normalizePath(path), perm)
}

func (OsFs) Open(name string) (afero.File, error) {
	f, e := os.Open(normalizePath(name))
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
	f, e := os.OpenFile(normalizePath(name), flag, perm)
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) Remove(name string) error {
	return os.Remove(normalizePath(name))
}

func (OsFs) RemoveAll(path string) error {
	return os.RemoveAll(normalizePath(path))
}

func (OsFs) Rename(oldname, newname string) error {
	return os.Rename(normalizePath(oldname), normalizePath(newname))
}

func (OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(normalizePath(name))
}

func (OsFs) Chmod(name string, mode os.FileMode) error {
	return os.Chmod(normalizePath(name), mode)
}

func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
	return os.Chtimes(normalizePath(name), atime, mtime)
}

func normalizePath(path string) string {
	if filepath.IsAbs(path) || len(path) < 227 {
		return path
	}

	if absPath, err := filepath.Abs(path); err == nil {
		return absPath
	} else {
		log.Printf("Could not determine absolute path for %s - this can lead to misbehaviour\n", path)
		return path
	}
}

func (fs *OsFs) Close() {
	// osfs does not need to be closed
}
<commit_msg>corrected down longest relative filename to 200 because of errors with 227<commit_after>// +build windows

package filesystem

import (
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/spf13/afero"
)

type OsFs struct {
	afero.Fs
}

func NewOsFs() afero.Fs {
	return &OsFs{}
}

func (OsFs) Name() string { return "OsFs" }

func (OsFs) Create(name string) (afero.File, error) {
	f, e := os.Create(normalizePath(name))
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(normalizePath(name), perm)
}

func (OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(normalizePath(path), perm)
}

func (OsFs) Open(name string) (afero.File, error) {
	f, e := os.Open(normalizePath(name))
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
	f, e := os.OpenFile(normalizePath(name), flag, perm)
	if f == nil {
		// while this looks strange, we need to return a bare nil (of type nil) not
		// a nil value of type *os.File or nil won't be nil
		return nil, e
	}
	return f, e
}

func (OsFs) Remove(name string) error {
	return os.Remove(normalizePath(name))
}

func (OsFs) RemoveAll(path string) error {
	return os.RemoveAll(normalizePath(path))
}

func (OsFs) Rename(oldname, newname string) error {
	return os.Rename(normalizePath(oldname), normalizePath(newname))
}

func (OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(normalizePath(name))
}

func (OsFs) Chmod(name string, mode os.FileMode) error {
	return os.Chmod(normalizePath(name), mode)
}

func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
	return os.Chtimes(normalizePath(name), atime, mtime)
}

func normalizePath(path string) string {
	if filepath.IsAbs(path) || len(path) < 200 {
		return path
	}

	if absPath, err := filepath.Abs(path); err == nil {
		return absPath
	} else {
		log.Printf("Could not determine absolute path for %s - this can lead to misbehaviour\n", path)
		return path
	}
}

func (fs *OsFs) Close() {
	// osfs does not need to be closed
}
<|endoftext|>


<commit_before>package sdl

// #cgo pkg-config: sdl2
// #cgo LDFLAGS: -lSDL2_image
//
// #include "SDL.h"
import "C"

// Window Handling

type WindowFlag uint32

const (
	WindowFullscreen WindowFlag = 1 << iota
	WindowOpenGL
	WindowShown
	WindowHidden
	WindowBorderless
	WindowResizable
	WindowMinimized
	WindowMaximized
	WindowInputGrabbed
	WindowInputFocus
	WindowMouseFocus
	WindowForeign
	_
	WindowAllowHighDpi
	WindowFullscreenDesktop = 0x00001001
)

const WindowPosUndefined = 0x1FFF0000
const WindowPosCentered = 0x2FFF0000

type renderer struct {
	r *C.SDL_Renderer
}

type RendererFlags uint32

const (
	RendererSoftware = 1 << iota
	RendererAccelerated
	RendererPresentVsync
	RendererTargetTexture
)

type Window struct {
	w        *C.SDL_Window
	Renderer *renderer
}

// Create a new window
func NewWindow(title string, x, y, w, h int, flags WindowFlag) (Window, error) {
	if window := C.SDL_CreateWindow(C.CString(title), C.int(x), C.int(y), C.int(w), C.int(h),
		C.Uint32(flags)); window != nil {

		return Window{window, nil}, nil
	}

	return Window{}, getError()
}

// Get the window's surface
func (w *Window) GetSurface() Surface {
	return Surface{C.SDL_GetWindowSurface(w.w)}
}

func (w *Window) Destroy() {
	C.SDL_DestroyWindow(w.w)
}

// Renderer stuff

func NewRenderer(window *Window, index int, flags uint32) (renderer, error) {
	if r := C.SDL_CreateRenderer(window.w, C.int(index), C.Uint32(flags)); r != nil {
		return renderer{r}, nil
	}

	return renderer{}, getError()
}

func (w *Window) GetRenderer() (renderer, error) {
	if r := C.SDL_GetRenderer(w.w); r != nil {
		return renderer{r}, nil
	}

	return renderer{}, getError()
}
<commit_msg>Add RendererInfo and make Renderer public again<commit_after>package sdl

// #cgo pkg-config: sdl2
// #cgo LDFLAGS: -lSDL2_image
//
// #include "SDL.h"
import "C"

import (
	"unsafe"
	"reflect"
)

// Window Handling

type WindowFlag uint32

const (
	WindowFullscreen WindowFlag = 1 << iota
	WindowOpenGL
	WindowShown
	WindowHidden
	WindowBorderless
	WindowResizable
	WindowMinimized
	WindowMaximized
	WindowInputGrabbed
	WindowInputFocus
	WindowMouseFocus
	WindowForeign
	_
	WindowAllowHighDpi
	WindowFullscreenDesktop = 0x00001001
)

const WindowPosUndefined = 0x1FFF0000
const WindowPosCentered = 0x2FFF0000

type Renderer struct {
	r *C.SDL_Renderer
}

type RendererFlags uint32

const (
	RendererSoftware RendererFlags = 1 << iota
	RendererAccelerated
	RendererPresentVsync
	RendererTargetTexture
)

const TextureFormatsSize int = 16

type RendererInfo struct {
	Name string
	Flags RendererFlags
	NumTextureFormats uint32
	TextureFormats []PixelFormat
	MaxTextureWidth int
	MaxTextureHeight int
}

type Window struct {
	w        *C.SDL_Window
	r *Renderer
}

// Create a new window
func NewWindow(title string, x, y, w, h int, flags WindowFlag) (Window, error) {
	if window := C.SDL_CreateWindow(C.CString(title), C.int(x), C.int(y), C.int(w), C.int(h),
		C.Uint32(flags)); window != nil {

		return Window{window, nil}, nil
	}

	return Window{}, getError()
}

// Get the window's surface
func (w *Window) GetSurface() Surface {
	return Surface{C.SDL_GetWindowSurface(w.w)}
}

func (w *Window) Destroy() {
	C.SDL_DestroyWindow(w.w)
}

// Renderer functions

func NewRenderer(window *Window, index int, flags uint32) (Renderer, error) {
	if r := C.SDL_CreateRenderer(window.w, C.int(index), C.Uint32(flags)); r != nil {
		return Renderer{r}, nil
	}

	return Renderer{}, getError()
}

func (w *Window) GetRenderer() (Renderer, error) {
	if r := C.SDL_GetRenderer(w.w); r != nil {
		return Renderer{r}, nil
	}

	return Renderer{}, getError()
}

func (r *Renderer) GetRendererInfo() (i *RendererInfo, e error) {
	var info C.SDL_RendererInfo
	if retCode := C.SDL_GetRendererInfo(r.r, &info); retCode != 0 {
		return &RendererInfo{}, getError()
	}

	var textureFormats []PixelFormat
	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&textureFormats)))
	sliceHeader.Cap = TextureFormatsSize
	sliceHeader.Len = TextureFormatsSize
	sliceHeader.Data = uintptr(unsafe.Pointer(&info.texture_formats[0]))

	return &RendererInfo{C.GoString(info.name), RendererFlags(info.flags),
		uint32(info.num_texture_formats), textureFormats, int(info.max_texture_width),
		int(info.max_texture_height)}, nil
}

func (r *Renderer) Destroy() {
	C.SDL_DestroyRenderer(r.r)
}
<|endoftext|>