<commit_before>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package server

import (
	"time"

	"gopherpit.com/gopherpit/services/packages"
	"gopherpit.com/gopherpit/services/user"
)

var (
	changelogActionDisplay = map[packages.Action]string{
		packages.ActionAddDomain:        "added domain",
		packages.ActionUpdateDomain:     "updated domain",
		packages.ActionDeleteDomain:     "deleted domain",
		packages.ActionDomainAddUser:    "added user to domain",
		packages.ActionDomainRemoveUser: "removed user from domain",
		packages.ActionAddPackage:       "added package",
		packages.ActionUpdatePackage:    "updated package",
		packages.ActionDeletePackage:    "deleted package",
	}
)

type changelogRecordChange struct {
	Field    string
	To       *string
	ToInfo   *string
	ToHref   *string
	From     *string
	FromInfo *string
	FromHref *string
}

type changelogAction packages.Action

func (c changelogAction) Display() string {
	return changelogActionDisplay[packages.Action(c)]
}

type changelogRecord struct {
	Time      time.Time
	DomainID  string
	FQDN      string
	PackageID string
	Path      string
	User      *user.User
	Action    changelogAction
	Changes   []changelogRecordChange
}

func (c changelogRecord) ImportPrefix() string {
	if c.FQDN == "" || c.Path == "" {
		return ""
	}
	return c.FQDN + c.Path
}

type changelog struct {
	Records  []changelogRecord
	Domain   packages.Domain
	Previous string
}

type changelogs []changelog

func (c changelogs) Len() int      { return len(c) }
func (c changelogs) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c changelogs) Less(i, j int) bool {
	if len(c[i].Records) == 0 {
		return false
	}
	if len(c[j].Records) == 0 {
		return true
	}
	return c[i].Records[0].Time.After(c[j].Records[0].Time)
}

func (s Server) updateChangelogRecords(u user.User, record packages.ChangelogRecord, records *[]changelogRecord, users *map[string]*user.User) (err error) {
	if _, ok := (*users)[record.UserID]; !ok {
		ru, err := s.UserService.UserByID(record.UserID)
		if err != nil {
			if err != user.UserNotFound {
				(*users)[record.UserID] = nil
			}
			return err
		}
		(*users)[record.UserID] = ru
	}

	r := changelogRecord{
		Time:      record.Time,
		DomainID:  record.DomainID,
		FQDN:      record.FQDN,
		PackageID: record.PackageID,
		Path:      record.Path,
		Action:    changelogAction(record.Action),
		Changes:   []changelogRecordChange{},
	}
	if ru, ok := (*users)[record.UserID]; ok {
		r.User = ru
	}
	if r.User == nil {
		r.User = &user.User{
			ID: record.UserID,
		}
	}

	var c changelogRecordChange
	switch record.Action {
	case packages.ActionAddDomain, packages.ActionUpdateDomain:
	Loop1:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "owner-user-id":
				c.Field = "Owner"
				if change.To != nil {
					if _, ok := (*users)[*change.To]; !ok {
						ru, err := s.UserService.UserByID(*change.To)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.To] = nil
							}
							return err
						}
						(*users)[*change.To] = ru
					}
					if *change.To == u.ID {
						c.To = stringToPtr("You")
					} else {
						if (*users)[*change.To] == nil {
							c.To = change.To
						} else {
							c.To = stringToPtr((*users)[*change.To].Name)
							c.ToHref = stringToPtr("/user/" + *change.To)
							c.ToInfo = stringToPtr("ID: " + *change.To)
						}
					}
				}

				if change.From != nil {
					if _, ok := (*users)[*change.From]; !ok {
						ru, err := s.UserService.UserByID(*change.From)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.From] = nil
							}
							return err
						}
						(*users)[*change.From] = ru
					}
					if *change.From == u.ID {
						c.From = stringToPtr("You")
					} else {
						if (*users)[*change.From] == nil {
							c.From = change.From
						} else {
							c.From = stringToPtr((*users)[*change.From].Name)
							c.FromHref = stringToPtr("/user/" + *change.From)
							c.FromInfo = stringToPtr("ID: " + *change.From)
						}
					}
				}
			case "fqdn":
				c.Field = "FQDN"
				c.To = change.To
				c.From = change.From
			case "certificate-ignore":
				if record.Action == packages.ActionAddDomain {
					continue Loop1
				}
				c.Field = "Ignore TLS Certificate"
				c.To = change.To
				c.From = change.From
			case "disabled":
				c.Field = "Disabled"
				c.To = change.To
				c.From = change.From
			default:
				continue Loop1
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionDeleteDomain:
	case packages.ActionDomainAddUser, packages.ActionDomainRemoveUser:
	Loop2:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "id":
				c.Field = "User"
				if change.To != nil {
					if _, ok := (*users)[*change.To]; !ok {
						ru, err := s.UserService.UserByID(*change.To)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.To] = nil
							}
							return err
						}
						(*users)[*change.To] = ru
					}
					if (*users)[*change.To] == nil {
						c.To = change.To
					} else if *change.To == u.ID {
						c.To = stringToPtr("You")
					} else {
						c.To = stringToPtr((*users)[*change.To].Name)
						c.ToHref = stringToPtr("/user/" + *change.To)
						c.ToInfo = stringToPtr("ID: " + *change.To)
					}
				}

				if change.From != nil {
					if _, ok := (*users)[*change.From]; !ok {
						ru, err := s.UserService.User(*change.From)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.From] = nil
							}
							return err
						}
						(*users)[*change.From] = ru
					}
					if (*users)[*change.From] == nil {
						c.From = change.From
					} else if *change.From == u.ID {
						c.From = stringToPtr("You")
					} else {
						c.From = stringToPtr((*users)[*change.From].Name)
						c.FromHref = stringToPtr("/user/" + *change.From)
						c.FromInfo = stringToPtr("ID: " + *change.From)
					}
				}
			default:
				continue Loop2
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionAddPackage, packages.ActionUpdatePackage:
	Loop3:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "domain-id", "domain-fqdn":
				continue Loop3
			case "path":
				c.Field = "Path"
				c.To = change.To
				c.From = change.From
			case "vcs":
				c.Field = "VCS"
				c.To = change.To
				c.From = change.From
			case "repo-root":
				c.Field = "Repository"
				c.To = change.To
				c.From = change.From
			case "go-source":
				c.Field = "Go Source"
				c.To = change.To
				c.From = change.From
			case "redirect-url":
				c.Field = "Redirect URL"
				c.To = change.To
				c.From = change.From
			default:
				continue Loop3
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionDeletePackage:
	default:
		for _, change := range record.Changes {
			r.Changes = append(r.Changes, changelogRecordChange{
				Field: change.Field,
				From:  change.From,
				To:    change.To,
			})
		}
	}

	*records = append(*records, r)
	return
}

func stringToPtr(s string) *string {
	return &s
}
<commit_msg>Fix displaying package disabled state change in package changelog<commit_after>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package server

import (
	"time"

	"gopherpit.com/gopherpit/services/packages"
	"gopherpit.com/gopherpit/services/user"
)

var (
	changelogActionDisplay = map[packages.Action]string{
		packages.ActionAddDomain:        "added domain",
		packages.ActionUpdateDomain:     "updated domain",
		packages.ActionDeleteDomain:     "deleted domain",
		packages.ActionDomainAddUser:    "added user to domain",
		packages.ActionDomainRemoveUser: "removed user from domain",
		packages.ActionAddPackage:       "added package",
		packages.ActionUpdatePackage:    "updated package",
		packages.ActionDeletePackage:    "deleted package",
	}
)

type changelogRecordChange struct {
	Field    string
	To       *string
	ToInfo   *string
	ToHref   *string
	From     *string
	FromInfo *string
	FromHref *string
}

type changelogAction packages.Action

func (c changelogAction) Display() string {
	return changelogActionDisplay[packages.Action(c)]
}

type changelogRecord struct {
	Time      time.Time
	DomainID  string
	FQDN      string
	PackageID string
	Path      string
	User      *user.User
	Action    changelogAction
	Changes   []changelogRecordChange
}

func (c changelogRecord) ImportPrefix() string {
	if c.FQDN == "" || c.Path == "" {
		return ""
	}
	return c.FQDN + c.Path
}

type changelog struct {
	Records  []changelogRecord
	Domain   packages.Domain
	Previous string
}

type changelogs []changelog

func (c changelogs) Len() int      { return len(c) }
func (c changelogs) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c changelogs) Less(i, j int) bool {
	if len(c[i].Records) == 0 {
		return false
	}
	if len(c[j].Records) == 0 {
		return true
	}
	return c[i].Records[0].Time.After(c[j].Records[0].Time)
}

func (s Server) updateChangelogRecords(u user.User, record packages.ChangelogRecord, records *[]changelogRecord, users *map[string]*user.User) (err error) {
	if _, ok := (*users)[record.UserID]; !ok {
		ru, err := s.UserService.UserByID(record.UserID)
		if err != nil {
			if err != user.UserNotFound {
				(*users)[record.UserID] = nil
			}
			return err
		}
		(*users)[record.UserID] = ru
	}

	r := changelogRecord{
		Time:      record.Time,
		DomainID:  record.DomainID,
		FQDN:      record.FQDN,
		PackageID: record.PackageID,
		Path:      record.Path,
		Action:    changelogAction(record.Action),
		Changes:   []changelogRecordChange{},
	}
	if ru, ok := (*users)[record.UserID]; ok {
		r.User = ru
	}
	if r.User == nil {
		r.User = &user.User{
			ID: record.UserID,
		}
	}

	var c changelogRecordChange
	switch record.Action {
	case packages.ActionAddDomain, packages.ActionUpdateDomain:
	Loop1:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "owner-user-id":
				c.Field = "Owner"
				if change.To != nil {
					if _, ok := (*users)[*change.To]; !ok {
						ru, err := s.UserService.UserByID(*change.To)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.To] = nil
							}
							return err
						}
						(*users)[*change.To] = ru
					}
					if *change.To == u.ID {
						c.To = stringToPtr("You")
					} else {
						if (*users)[*change.To] == nil {
							c.To = change.To
						} else {
							c.To = stringToPtr((*users)[*change.To].Name)
							c.ToHref = stringToPtr("/user/" + *change.To)
							c.ToInfo = stringToPtr("ID: " + *change.To)
						}
					}
				}

				if change.From != nil {
					if _, ok := (*users)[*change.From]; !ok {
						ru, err := s.UserService.UserByID(*change.From)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.From] = nil
							}
							return err
						}
						(*users)[*change.From] = ru
					}
					if *change.From == u.ID {
						c.From = stringToPtr("You")
					} else {
						if (*users)[*change.From] == nil {
							c.From = change.From
						} else {
							c.From = stringToPtr((*users)[*change.From].Name)
							c.FromHref = stringToPtr("/user/" + *change.From)
							c.FromInfo = stringToPtr("ID: " + *change.From)
						}
					}
				}
			case "fqdn":
				c.Field = "FQDN"
				c.To = change.To
				c.From = change.From
			case "certificate-ignore":
				if record.Action == packages.ActionAddDomain {
					continue Loop1
				}
				c.Field = "Ignore TLS Certificate"
				c.To = change.To
				c.From = change.From
			case "disabled":
				c.Field = "Disabled"
				c.To = change.To
				c.From = change.From
			default:
				continue Loop1
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionDeleteDomain:
	case packages.ActionDomainAddUser, packages.ActionDomainRemoveUser:
	Loop2:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "id":
				c.Field = "User"
				if change.To != nil {
					if _, ok := (*users)[*change.To]; !ok {
						ru, err := s.UserService.UserByID(*change.To)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.To] = nil
							}
							return err
						}
						(*users)[*change.To] = ru
					}
					if (*users)[*change.To] == nil {
						c.To = change.To
					} else if *change.To == u.ID {
						c.To = stringToPtr("You")
					} else {
						c.To = stringToPtr((*users)[*change.To].Name)
						c.ToHref = stringToPtr("/user/" + *change.To)
						c.ToInfo = stringToPtr("ID: " + *change.To)
					}
				}

				if change.From != nil {
					if _, ok := (*users)[*change.From]; !ok {
						ru, err := s.UserService.User(*change.From)
						if err != nil {
							if err != user.UserNotFound {
								(*users)[*change.From] = nil
							}
							return err
						}
						(*users)[*change.From] = ru
					}
					if (*users)[*change.From] == nil {
						c.From = change.From
					} else if *change.From == u.ID {
						c.From = stringToPtr("You")
					} else {
						c.From = stringToPtr((*users)[*change.From].Name)
						c.FromHref = stringToPtr("/user/" + *change.From)
						c.FromInfo = stringToPtr("ID: " + *change.From)
					}
				}
			default:
				continue Loop2
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionAddPackage, packages.ActionUpdatePackage:
	Loop3:
		for _, change := range record.Changes {
			c = changelogRecordChange{}
			switch change.Field {
			case "domain-id", "domain-fqdn":
				continue Loop3
			case "path":
				c.Field = "Path"
				c.To = change.To
				c.From = change.From
			case "vcs":
				c.Field = "VCS"
				c.To = change.To
				c.From = change.From
			case "repo-root":
				c.Field = "Repository"
				c.To = change.To
				c.From = change.From
			case "go-source":
				c.Field = "Go Source"
				c.To = change.To
				c.From = change.From
			case "redirect-url":
				c.Field = "Redirect URL"
				c.To = change.To
				c.From = change.From
			case "disabled":
				c.Field = "Disabled"
				c.To = change.To
				c.From = change.From
			default:
				continue Loop3
			}
			r.Changes = append(r.Changes, c)
		}
	case packages.ActionDeletePackage:
	default:
		for _, change := range record.Changes {
			r.Changes = append(r.Changes, changelogRecordChange{
				Field: change.Field,
				From:  change.From,
				To:    change.To,
			})
		}
	}

	*records = append(*records, r)
	return
}

func stringToPtr(s string) *string {
	return &s
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package framework

import (
	"fmt"
	"sync"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/util/wait"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// Convenience method for getting a pod client interface in the framework's namespace.
func (f *Framework) PodClient() *PodClient {
	return &PodClient{
		f:            f,
		PodInterface: f.Client.Pods(f.Namespace.Name),
	}
}

type PodClient struct {
	f *Framework
	unversioned.PodInterface
}

// Create creates a new pod according to the framework specifications (don't wait for it to start).
func (c *PodClient) Create(pod *api.Pod) *api.Pod {
	c.mungeSpec(pod)
	p, err := c.PodInterface.Create(pod)
	ExpectNoError(err, "Error creating Pod")
	return p
}

// CreateSync creates a new pod according to the framework specifications, and wait for it to start.
func (c *PodClient) CreateSync(pod *api.Pod) *api.Pod {
	p := c.Create(pod)
	ExpectNoError(c.f.WaitForPodRunning(p.Name))
	// Get the newest pod after it becomes running, some status may change after pod created, such as pod ip.
	p, err := c.Get(pod.Name)
	ExpectNoError(err)
	return p
}

// CreateBatch create a batch of pods. All pods are created before waiting.
func (c *PodClient) CreateBatch(pods []*api.Pod) []*api.Pod {
	ps := make([]*api.Pod, len(pods))
	var wg sync.WaitGroup
	for i, pod := range pods {
		wg.Add(1)
		go func(i int, pod *api.Pod) {
			defer wg.Done()
			defer GinkgoRecover()
			ps[i] = c.CreateSync(pod)
		}(i, pod)
	}
	wg.Wait()
	return ps
}

// Update updates the pod object. It retries if there is a conflict, throw out error if
// there is any other errors. name is the pod name, updateFn is the function updating the
// pod object.
func (c *PodClient) Update(name string, updateFn func(pod *api.Pod)) {
	ExpectNoError(wait.Poll(time.Millisecond*500, time.Second*30, func() (bool, error) {
		pod, err := c.PodInterface.Get(name)
		if err != nil {
			return false, fmt.Errorf("failed to get pod %q: %v", name, err)
		}
		updateFn(pod)
		_, err = c.PodInterface.Update(pod)
		if err == nil {
			Logf("Successfully updated pod %q", name)
			return true, nil
		}
		if errors.IsConflict(err) {
			Logf("Conflicting update to pod %q, re-get and re-update: %v", name, err)
			return false, nil
		}
		return false, fmt.Errorf("failed to update pod %q: %v", name, err)
	}))
}

// mungeSpec apply test-suite specific transformations to the pod spec.
func (c *PodClient) mungeSpec(pod *api.Pod) {
	if TestContext.NodeName != "" {
		Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
		pod.Spec.NodeName = TestContext.NodeName
	}
}

// TODO(random-liu): Move pod wait function into this file
<commit_msg>Bug fix: Use p.Name instead of pod.Name<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package framework

import (
	"fmt"
	"sync"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/util/wait"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// Convenience method for getting a pod client interface in the framework's namespace.
func (f *Framework) PodClient() *PodClient {
	return &PodClient{
		f:            f,
		PodInterface: f.Client.Pods(f.Namespace.Name),
	}
}

type PodClient struct {
	f *Framework
	unversioned.PodInterface
}

// Create creates a new pod according to the framework specifications (don't wait for it to start).
func (c *PodClient) Create(pod *api.Pod) *api.Pod {
	c.mungeSpec(pod)
	p, err := c.PodInterface.Create(pod)
	ExpectNoError(err, "Error creating Pod")
	return p
}

// CreateSync creates a new pod according to the framework specifications, and wait for it to start.
func (c *PodClient) CreateSync(pod *api.Pod) *api.Pod {
	p := c.Create(pod)
	ExpectNoError(c.f.WaitForPodRunning(p.Name))
	// Get the newest pod after it becomes running, some status may change after pod created, such as pod ip.
	p, err := c.Get(p.Name)
	ExpectNoError(err)
	return p
}

// CreateBatch create a batch of pods. All pods are created before waiting.
func (c *PodClient) CreateBatch(pods []*api.Pod) []*api.Pod {
	ps := make([]*api.Pod, len(pods))
	var wg sync.WaitGroup
	for i, pod := range pods {
		wg.Add(1)
		go func(i int, pod *api.Pod) {
			defer wg.Done()
			defer GinkgoRecover()
			ps[i] = c.CreateSync(pod)
		}(i, pod)
	}
	wg.Wait()
	return ps
}

// Update updates the pod object. It retries if there is a conflict, throw out error if
// there is any other errors. name is the pod name, updateFn is the function updating the
// pod object.
func (c *PodClient) Update(name string, updateFn func(pod *api.Pod)) {
	ExpectNoError(wait.Poll(time.Millisecond*500, time.Second*30, func() (bool, error) {
		pod, err := c.PodInterface.Get(name)
		if err != nil {
			return false, fmt.Errorf("failed to get pod %q: %v", name, err)
		}
		updateFn(pod)
		_, err = c.PodInterface.Update(pod)
		if err == nil {
			Logf("Successfully updated pod %q", name)
			return true, nil
		}
		if errors.IsConflict(err) {
			Logf("Conflicting update to pod %q, re-get and re-update: %v", name, err)
			return false, nil
		}
		return false, fmt.Errorf("failed to update pod %q: %v", name, err)
	}))
}

// mungeSpec apply test-suite specific transformations to the pod spec.
func (c *PodClient) mungeSpec(pod *api.Pod) {
	if TestContext.NodeName != "" {
		Expect(pod.Spec.NodeName).To(Or(BeZero(), Equal(TestContext.NodeName)), "Test misconfigured")
		pod.Spec.NodeName = TestContext.NodeName
	}
}

// TODO(random-liu): Move pod wait function into this file
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

const baseUrl = "http://localhost:8989/api/"

func main() {
	refreshSeries()
}

func refreshSeries() {
	apiKey := readApiKey()
	endpoint := baseUrl + "command?apikey=" + apiKey
	fmt.Println(endpoint)
	data := []byte(`{"name":"RefreshSeries"}`)
	req, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(data))

	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)

	if err != nil {
		fmt.Println(err)
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("submitted!")
	fmt.Printf("%s", body)
}

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

func readApiKey() string {
	key, err := ioutil.ReadFile("api_key")
	check(err)
	return strings.TrimSpace(string(key))
}
<commit_msg>Cleaning things up a little<commit_after>package main

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

const baseUrl = "http://localhost:8989/api/"

func main() {
	refreshSeries()
}

type command struct {
	Name string
}

func refreshSeries() {
	apiKey := readApiKey()
	endpoint := baseUrl + "command?apikey=" + apiKey

	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(command{Name: "RefreshSeries"})
	resp, err := http.Post(endpoint, "application/json", b)

	check(err)

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	check(err)

	fmt.Printf("Response:\n%s", body)
}

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

func readApiKey() string {
	key, err := ioutil.ReadFile("api_key")
	check(err)
	return strings.TrimSpace(string(key))
}
<|endoftext|>


<commit_before>package sflow

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
)

type SFDecoder struct {
	reader io.ReadSeeker
}

type SFDatagram struct {
	Version    uint32 // Datagram version
	IPVersion  uint32 // Data gram sFlow version
	AgentSubId uint32 // Identifies a source of sFlow data
	SequenceNo uint32 // Sequence of sFlow Datagrams
	SysUpTime  uint32 // Current time (in milliseconds since device last booted
	SamplesNo  uint32 // Number of samples

	IPAddress  net.IP // Agent IP address
	FilterType []int
}

type SFSampledHeader struct {
	HeaderProtocol uint32 // (enum SFHeaderProtocol)
	FrameLength    uint32 // Original length of packet before sampling
	Stripped       uint32 // Header/trailer bytes stripped by sender
	HeaderLength   uint32 // Length of sampled header bytes to follow
	HeaderBytes    []byte // Header bytes
}

type SFSample interface {
}

func NewSFDecoder(r io.ReadSeeker) SFDecoder {
	return SFDecoder{r}
}

func (d *SFDecoder) SFDecode() (*SFDatagram, error) {
	var (
		datagram     = &SFDatagram{}
		ipLen    int = 4
		err      error
	)

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.Version); err != nil {
		return nil, err
	}

	if datagram.Version != 5 {
		return nil, fmt.Errorf("sflow version doesn't support")
	}

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.IPVersion); err != nil {
		return nil, err
	}

	// read the agent ip address
	if datagram.IPVersion == 2 {
		ipLen = 16
	}
	buff := make([]byte, ipLen)
	if _, err = d.reader.Read(buff); err != nil {
		return nil, err
	}
	datagram.IPAddress = buff

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.AgentSubId); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SequenceNo); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SysUpTime); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SamplesNo); err != nil {
		return nil, err
	}

	fmt.Printf("%#v\n", datagram)

	return datagram, nil
}
<commit_msg>add format filter, sample loop<commit_after>package sflow

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"
)

const (
	SampleDataFormat  = 1
	CounterDataFormat = 2
	FlowDataFormat    = 3
)

type SFDecoder struct {
	reader io.ReadSeeker
	filter []uint32 // Filter data format(s)
}

type SFDatagram struct {
	Version    uint32 // Datagram version
	IPVersion  uint32 // Data gram sFlow version
	AgentSubId uint32 // Identifies a source of sFlow data
	SequenceNo uint32 // Sequence of sFlow Datagrams
	SysUpTime  uint32 // Current time (in milliseconds since device last booted
	SamplesNo  uint32 // Number of samples

	IPAddress net.IP // Agent IP address
}

type SFSampledHeader struct {
	HeaderProtocol uint32 // (enum SFHeaderProtocol)
	FrameLength    uint32 // Original length of packet before sampling
	Stripped       uint32 // Header/trailer bytes stripped by sender
	HeaderLength   uint32 // Length of sampled header bytes to follow
	HeaderBytes    []byte // Header bytes
}

type SFSample interface {
}

func NewSFDecoder(r io.ReadSeeker, f []uint32) SFDecoder {
	return SFDecoder{
		reader: r,
		filter: f,
	}
}

func (d *SFDecoder) SFDecode() (*SFDatagram, error) {
	var (
		datagram     = &SFDatagram{}
		ipLen    int = 4
		err      error
	)

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.Version); err != nil {
		return nil, err
	}

	if datagram.Version != 5 {
		return nil, fmt.Errorf("sflow version doesn't support")
	}

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.IPVersion); err != nil {
		return nil, err
	}

	// read the agent ip address
	if datagram.IPVersion == 2 {
		ipLen = 16
	}
	buff := make([]byte, ipLen)
	if _, err = d.reader.Read(buff); err != nil {
		return nil, err
	}
	datagram.IPAddress = buff

	if err = binary.Read(d.reader, binary.BigEndian, &datagram.AgentSubId); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SequenceNo); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SysUpTime); err != nil {
		return nil, err
	}
	if err = binary.Read(d.reader, binary.BigEndian, &datagram.SamplesNo); err != nil {
		return nil, err
	}

	fmt.Printf("%#v\n", datagram)

	var (
		format uint32
		length uint32
	)

	for i := uint32(0); i < datagram.SamplesNo; i++ {
		if err = binary.Read(d.reader, binary.BigEndian, &format); err != nil {
			return nil, err
		}
		if err = binary.Read(d.reader, binary.BigEndian, &length); err != nil {
			return nil, err
		}

		if m := d.isFilterMatch(format); m {
			d.reader.Seek(int64(length), 1)
			continue
		}

		// TODO
		println("sample", format, length)
		d.reader.Seek(int64(length), 1)
	}

	return datagram, nil
}

func (d *SFDecoder) isFilterMatch(f uint32) bool {
	for _, v := range d.filter {
		if v == f {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Quick and dirty uploader and serial terminal for LPC8xx chips.
// -jcw, 2015-02-02

package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"github.com/chimera/rs232"
	"golang.org/x/crypto/ssh/terminal"
)

var (
	termFlag   = flag.Bool("t", false, "launch as serial terminal after upload")
	waitFlag   = flag.Bool("w", false, "wait for connection to the boot loader")
	offsetFlag = flag.Int("o", 0, "upload offset (must be a multiple of 1024)")
	idleFlag   = flag.Int("i", 0, "exit terminal after N idle seconds (0: off)")
)

func main() {
	log.SetFlags(0) // no timestamps

	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: lpc8xx ?options? tty ?binfile?")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(2)
	}

	ttyName := flag.Arg(0)
	binFile := ""
	if flag.NArg() > 1 {
		binFile = flag.Arg(1)
	}

	conn := connect(ttyName)

	id := conn.Identify()
	fmt.Printf("found: %X\n", id)

	conn.SendAndWait("N", "0")
	buf := bytes.NewBuffer([]byte{})

	for i := 0; i < 4; i++ {
		b, err := strconv.ParseUint(<-conn.lines, 10, 32)
		Check(err)
		binary.Write(buf, binary.LittleEndian, uint32(b))
	}
	fmt.Printf("hwuid: %X\n", buf.Bytes())

	if binFile != "" {
		data, err := ioutil.ReadFile(binFile)
		Check(err)

		fmt.Print("flash: ")
		for _ = range conn.Program(*offsetFlag, data) {
			fmt.Print(".")
		}
		fmt.Println(" done")
	}

	conn.SetDTR(true) // pulse DTR to reset
	conn.SetDTR(false)

	if *termFlag {
		fmt.Println("entering terminal mode, press <ESC> to quit:\n")
		conn.Terminal()
		fmt.Println()
	}
}

func connect(port string) *connection {
	opt := rs232.Options{BitRate: 115200, DataBits: 8, StopBits: 1}
	dev, err := rs232.Open(port, opt)
	Check(err)

	conn := &connection{dev, make(chan string)}
	go func() {
		scanner := bufio.NewScanner(dev)
		for scanner.Scan() {
			conn.lines <- scanner.Text()
		}
		close(conn.lines)
	}()
	return conn
}

type connection struct {
	*rs232.Port
	lines chan string
}

func (c *connection) ReadReply() string {
	select {
	case reply := <-c.lines:
		return reply
	case <-time.After(500 * time.Millisecond):
		return ""
	}
}

func (c *connection) SendAndWait(cmd string, expect string) {
	c.Write([]byte(cmd + "\r\n"))
	var reply string
	for i := 0; i < 4; i++ {
		reply = c.ReadReply()
		if reply == "" {
			log.Fatal("no response, timeout")
		}
		if reply == expect {
			return
		}
	}
	log.Fatal(reply)
}

func (c *connection) Identify() int {
	c.SetRTS(true) // keep RTS on for ISP mode

	notDone := true
	for notDone {
		c.SetDTR(true) // pulse DTR to reset
		for c.ReadReply() != "" {
			// flush
		}
		c.SetDTR(false)

		c.Write([]byte("?\r\n"))
		notDone = c.ReadReply() != "Synchronized" && *waitFlag
	}

	c.SetRTS(false)

	c.SendAndWait("Synchronized", "OK")
	c.SendAndWait("12000", "OK")
	c.SendAndWait("A 0", "0")

	c.SendAndWait("J", "0")
	id, err := strconv.Atoi(<-c.lines)
	Check(err)

	return id
}

func (c *connection) Program(startAddress int, data []byte) chan int {
	const sectorSize = 1024
	const pageSize = 64

	for len(data)%pageSize != 0 {
		data = append(data, 0xFF)
	}
	firstPage := startAddress / pageSize
	lastPage := firstPage + len(data)/pageSize - 1

	for len(data)%sectorSize != 0 {
		data = append(data, 0xFF)
	}
	firstSector := startAddress / sectorSize
	lastSector := firstSector + len(data)/sectorSize - 1

	if startAddress == 0 {
		fixChecksum(data)
	}

	c.SendAndWait("U 23130", "0") // unlock for programming

	// erase entire range, as 1024-byte sectors
	c.SendAndWait(fmt.Sprint("P ", firstSector, lastSector), "0") // prepare
	c.SendAndWait(fmt.Sprint("E ", firstSector, lastSector), "0") // erase

	r := make(chan int)
	go func() {
		defer close(r)
		// program in 64-byte pages (sectors won't fit in the LPC810's RAM)
		for page := firstPage; page <= lastPage; page++ {
			const RAM_ADDR = 0x10000300
			// write one page of data to RAM
			offset := (page - firstPage) * pageSize
			c.SendAndWait(fmt.Sprint("W ", RAM_ADDR, pageSize), "0")
			c.Write(data[offset : offset+pageSize])
			// prepare and copy the data to flash memory
			sector := (page * pageSize) / sectorSize
			c.SendAndWait(fmt.Sprint("P ", sector, sector), "0")
			destAddr := page * pageSize
			c.SendAndWait(fmt.Sprint("C ", destAddr, RAM_ADDR, pageSize), "0")
			r <- (page - firstPage) + 1
		}
	}()
	return r
}

// fix the checksum to mark code as valid (see UM10398, p.416)
func fixChecksum(data []byte) {
	buf := bytes.NewReader(data)
	values := [7]uint32{}
	err := binary.Read(buf, binary.LittleEndian, values[:])
	Check(err)
	var sum uint32
	for _, v := range values {
		sum -= v
	}
	data[28] = byte(sum)
	data[29] = byte(sum >> 8)
	data[30] = byte(sum >> 16)
	data[31] = byte(sum >> 24)
}

func (c *connection) Terminal() {
	timeout := time.Duration(*idleFlag) * time.Second
	idleTimer := time.NewTimer(timeout)

	// FIXME still in line mode, so only complete lines will be shown
	//  look into bufio.Reader for a possible solution
	go func() {
		for s := range c.lines {
			idleTimer.Reset(timeout)
			fmt.Println(s)
		}
	}()

	// put stdin in raw mode
	oldState, err := terminal.MakeRaw(0)
	Check(err)
	defer terminal.Restore(0, oldState)

	// cleanup when program is terminated via a signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGHUP, syscall.SIGTERM)
	go func() {
		sigMsg := <-sigChan
		terminal.Restore(0, oldState)
		log.Fatal(sigMsg)
	}()

	// cleanup when idle timer fires, and exit cleanly
	if *idleFlag > 0 {
		go func() {
			<-idleTimer.C
			terminal.Restore(0, oldState)
			fmt.Println("\nidle timeout")
			os.Exit(0)
		}()
	}

	// copy key presses to the serial port
	for {
		var b [1]byte
		n, _ := os.Stdin.Read(b[:])
		idleTimer.Reset(timeout)
		if n < 1 || b[0] == 0x1B { // ESC
			break
		}
		c.Write(b[:n])
	}

}

func Check(e error) {
	if e != nil {
		log.Fatal(e)
	}
}
<commit_msg>minor cleanup<commit_after>// Quick and dirty uploader and serial terminal for LPC8xx chips.
// -jcw, 2015-02-02

package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"github.com/chimera/rs232"
	"golang.org/x/crypto/ssh/terminal"
)

var (
	termFlag   = flag.Bool("t", false, "launch as serial terminal after upload")
	waitFlag   = flag.Bool("w", false, "wait for connection to the boot loader")
	offsetFlag = flag.Int("o", 0, "upload offset (must be a multiple of 1024)")
	idleFlag   = flag.Int("i", 0, "exit terminal after N idle seconds (0: off)")
)

func main() {
	log.SetFlags(0) // no timestamps

	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, "Usage: lpc8xx ?options? tty ?binfile?")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() < 1 {
		flag.Usage()
		os.Exit(2)
	}

	ttyName := flag.Arg(0)
	binFile := ""
	if flag.NArg() > 1 {
		binFile = flag.Arg(1)
	}

	conn := connect(ttyName)

	id := conn.Identify()
	fmt.Printf("found: %X\n", id)

	conn.SendAndWait("N", "0")
	buf := bytes.NewBuffer([]byte{})

	for i := 0; i < 4; i++ {
		b, err := strconv.ParseUint(<-conn.lines, 10, 32)
		Check(err)
		binary.Write(buf, binary.LittleEndian, uint32(b))
	}
	fmt.Printf("hwuid: %X\n", buf.Bytes())

	if binFile != "" {
		data, err := ioutil.ReadFile(binFile)
		Check(err)

		fmt.Print("flash: ")
		for _ = range conn.Program(*offsetFlag, data) {
			fmt.Print(".")
		}
		fmt.Println(" done")
	}

	conn.SetDTR(true) // pulse DTR to reset
	conn.SetDTR(false)

	if *termFlag {
		fmt.Println("entering terminal mode, press <ESC> to quit:\n")
		conn.Terminal()
		fmt.Println()
	}
}

func connect(port string) *connection {
	opt := rs232.Options{BitRate: 115200, DataBits: 8, StopBits: 1}
	dev, err := rs232.Open(port, opt)
	Check(err)

	conn := &connection{dev, make(chan string)}
	go func() {
		scanner := bufio.NewScanner(dev)
		for scanner.Scan() {
			conn.lines <- scanner.Text()
		}
		close(conn.lines)
	}()
	return conn
}

type connection struct {
	*rs232.Port
	lines chan string
}

func (c *connection) ReadReply() string {
	select {
	case reply := <-c.lines:
		return reply
	case <-time.After(500 * time.Millisecond):
		return ""
	}
}

func (c *connection) SendAndWait(cmd string, expect string) {
	c.Write([]byte(cmd + "\r\n"))
	var reply string
	for i := 0; i < 4; i++ {
		reply = c.ReadReply()
		if reply == "" {
			log.Fatal("no response, timeout")
		}
		if reply == expect {
			return
		}
	}
	log.Fatal(reply)
}

func (c *connection) Identify() int {
	c.SetRTS(true) // keep RTS on for ISP mode

	for {
		c.SetDTR(true) // pulse DTR to reset
		for c.ReadReply() != "" {
			// flush
		}
		c.SetDTR(false)

		c.Write([]byte("?\r\n"))
		if c.ReadReply() == "Synchronized" || !*waitFlag {
			break
		}
	}

	c.SetRTS(false)

	c.SendAndWait("Synchronized", "OK")
	c.SendAndWait("12000", "OK")
	c.SendAndWait("A 0", "0")

	c.SendAndWait("J", "0")
	id, err := strconv.Atoi(c.ReadReply())
	Check(err)

	return id
}

func (c *connection) Program(startAddress int, data []byte) chan int {
	const sectorSize = 1024
	const pageSize = 64

	for len(data)%pageSize != 0 {
		data = append(data, 0xFF)
	}
	firstPage := startAddress / pageSize
	lastPage := firstPage + len(data)/pageSize - 1

	for len(data)%sectorSize != 0 {
		data = append(data, 0xFF)
	}
	firstSector := startAddress / sectorSize
	lastSector := firstSector + len(data)/sectorSize - 1

	if startAddress == 0 {
		fixChecksum(data)
	}

	c.SendAndWait("U 23130", "0") // unlock for programming

	// erase entire range, as 1024-byte sectors
	c.SendAndWait(fmt.Sprint("P ", firstSector, lastSector), "0") // prepare
	c.SendAndWait(fmt.Sprint("E ", firstSector, lastSector), "0") // erase

	r := make(chan int)
	go func() {
		defer close(r)
		// program in 64-byte pages (sectors won't fit in the LPC810's RAM)
		for page := firstPage; page <= lastPage; page++ {
			const RAM_ADDR = 0x10000300
			// write one page of data to RAM
			offset := (page - firstPage) * pageSize
			c.SendAndWait(fmt.Sprint("W ", RAM_ADDR, pageSize), "0")
			c.Write(data[offset : offset+pageSize])
			// prepare and copy the data to flash memory
			sector := (page * pageSize) / sectorSize
			c.SendAndWait(fmt.Sprint("P ", sector, sector), "0")
			destAddr := page * pageSize
			c.SendAndWait(fmt.Sprint("C ", destAddr, RAM_ADDR, pageSize), "0")
			r <- (page - firstPage) + 1
		}
	}()
	return r
}

// fix the checksum to mark code as valid (see UM10398, p.416)
func fixChecksum(data []byte) {
	buf := bytes.NewReader(data)
	values := [7]uint32{}
	err := binary.Read(buf, binary.LittleEndian, values[:])
	Check(err)
	var sum uint32
	for _, v := range values {
		sum -= v
	}
	data[28] = byte(sum)
	data[29] = byte(sum >> 8)
	data[30] = byte(sum >> 16)
	data[31] = byte(sum >> 24)
}

func (c *connection) Terminal() {
	timeout := time.Duration(*idleFlag) * time.Second
	idleTimer := time.NewTimer(timeout)

	// FIXME still in line mode, so only complete lines will be shown
	//  look into bufio.Reader for a possible solution
	go func() {
		for s := range c.lines {
			idleTimer.Reset(timeout)
			fmt.Println(s)
		}
	}()

	// put stdin in raw mode
	oldState, err := terminal.MakeRaw(0)
	Check(err)
	defer terminal.Restore(0, oldState)

	// cleanup when program is terminated via a signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGHUP, syscall.SIGTERM)
	go func() {
		sigMsg := <-sigChan
		terminal.Restore(0, oldState)
		log.Fatal(sigMsg)
	}()

	// cleanup when idle timer fires, and exit cleanly
	if *idleFlag > 0 {
		go func() {
			<-idleTimer.C
			terminal.Restore(0, oldState)
			fmt.Println("\nidle timeout")
			os.Exit(0)
		}()
	}

	// copy key presses to the serial port
	for {
		var b [1]byte
		n, _ := os.Stdin.Read(b[:])
		idleTimer.Reset(timeout)
		if n < 1 || b[0] == 0x1B { // ESC
			break
		}
		c.Write(b[:n])
	}

}

func Check(e error) {
	if e != nil {
		log.Fatal(e)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/nlopes/slack"
)

func main() {
	api := slack.New("YOUR TOKEN HERE")
	api.SetDebug(true)

	rtm := api.NewRTM()
	go rtm.ManageConnection()

	for {
		select {
		case msg := <-rtm.IncomingEvents:
			fmt.Print("Event Received: ")
			switch ev := msg.Data.(type) {
			case *slack.HelloEvent:
				// Ignore hello

			case *slack.ConnectedEvent:
				fmt.Println("Infos:", ev.Info)
				fmt.Println("Connection counter:", ev.ConnectionCount)
				// Replace #general with your Channel ID
				rtm.SendMessage(rtm.NewOutgoingMessage("Hello world", "#general"))

			case *slack.MessageEvent:
				fmt.Printf("Message: %v\n", ev)

			case *slack.PresenceChangeEvent:
				fmt.Printf("Presence Change: %v\n", ev)

			case *slack.LatencyReport:
				fmt.Printf("Current latency: %v\n", ev.Value)

			case *slack.SlackWSError:
				fmt.Printf("Error: %d - %s\n", ev.Code, ev.Msg)

			default:
				// Ignore other events..
				//fmt.Printf("Unexpected: %v\n", msg.Data)
			}
		}
	}
}
<commit_msg>Fixed example<commit_after>package main

import (
	"fmt"

	"github.com/nlopes/slack"
)

func main() {
	api := slack.New("YOUR TOKEN HERE")
	api.SetDebug(true)

	rtm := api.NewRTM()
	go rtm.ManageConnection()

	for {
		select {
		case msg := <-rtm.IncomingEvents:
			fmt.Print("Event Received: ")
			switch ev := msg.Data.(type) {
			case *slack.HelloEvent:
				// Ignore hello

			case *slack.ConnectedEvent:
				fmt.Println("Infos:", ev.Info)
				fmt.Println("Connection counter:", ev.ConnectionCount)
				// Replace #general with your Channel ID
				rtm.SendMessage(rtm.NewOutgoingMessage("Hello world", "#general"))

			case *slack.MessageEvent:
				fmt.Printf("Message: %v\n", ev)

			case *slack.PresenceChangeEvent:
				fmt.Printf("Presence Change: %v\n", ev)

			case *slack.LatencyReport:
				fmt.Printf("Current latency: %v\n", ev.Value)

			case *slack.SlackWSError:
				fmt.Printf("Error: %s\n", ev.Error())

			default:
				// Ignore other events..
				//fmt.Printf("Unexpected: %v\n", msg.Data)
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
//
//    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 (
	"fmt"
	"git.openstack.org/stackforge/golang-client.git/identity"
	"time"
)

// Authentication examples.
func main() {
	config := getConfig()

	// Authenticate with just a username and password. The returned token is
	// unscoped to a tenant.
	auth, err := identity.AuthUserName(config.Host,
		config.Username,
		config.Password)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
	}

	// Authenticate with a username, password, tenant name.
	auth, err = identity.AuthUserNameTenantName(config.Host,
		config.Username,
		config.Password,
		config.ProjectName)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
	}

	// Authenticate with a username, password, tenant id.
	auth, err = identity.AuthUserNameTenantId(config.Host,
		config.Username,
		config.Password,
		config.ProjectID)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
	}
}
<commit_msg>after errors in main we should return<commit_after>// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
//
//    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 (
	"fmt"
	"git.openstack.org/stackforge/golang-client.git/identity"
	"time"
)

// Authentication examples.
func main() {
	config := getConfig()

	// Authenticate with just a username and password. The returned token is
	// unscoped to a tenant.
	auth, err := identity.AuthUserName(config.Host,
		config.Username,
		config.Password)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
		return
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
		return
	}

	// Authenticate with a username, password, tenant name.
	auth, err = identity.AuthUserNameTenantName(config.Host,
		config.Username,
		config.Password,
		config.ProjectName)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
		return
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
		return
	}

	// Authenticate with a username, password, tenant id.
	auth, err = identity.AuthUserNameTenantId(config.Host,
		config.Username,
		config.Password,
		config.ProjectID)
	if err != nil {
		fmt.Println("There was an error authenticating:", err)
		return
	}
	if !auth.Access.Token.Expires.After(time.Now()) {
		fmt.Println("There was an error. The auth token has an invalid expiration.")
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"strconv"
	"strings"
)

// Each Toastmaster manual contains 5-10 ordered and named speeches.
// The fields min and max are the minimum and maximum speaking times for a Speech.
type speechDetails struct {
	number int
	name   string
	min    int
	max    int
}

// Speech represents the Speech that will be performed for the agenda.
type Speech struct {
	manualCode string
	manualName string
	speechDetails
}

// Factory function to create a Speech using a manual and the Speech number in that manual.
func NewSpeech(manualCode string, num int) Speech {
	manualCode = strings.ToLower(manualCode)
	manual := manualMap[manualCode]

	sp := Speech{
		manualCode: manualCode,
		manualName: manual.manualName,
		speechDetails: speechDetails{
			number: num,
		},
	}

	// Do not fail with invalid input, return with the default values set.
	if num < 1 || num > len(manual.speeches) {
		log.Print("Speech num is invalid for the manual.  Manual code: "+manualCode+" Speech num:", num)
		return sp
	}

	sp.name = manual.speeches[num-1].name
	sp.min = manual.speeches[num-1].min
	sp.max = manual.speeches[num-1].max

	return sp
}

// Info create a string that represents a Speech ex: "#1 Ice Breaker (4-6 mins)."
func (s Speech) info() string {
	return "#" + strconv.Itoa(s.number) + " " + s.name +
		" " + "(" + strconv.Itoa(s.min) + "-" + strconv.Itoa(s.max) + " mins)"
}

// There are 16 Toastmaster manuals a speaker can use at a meeting.
type manual struct {
	manualName string
	speeches   []speechDetails
}

// Representation of the Toasmaters speeches with their code as the key.
var manualMap = map[string]manual{
	"cc": {
		manualName: "Competent Communicator",
		speeches: []speechDetails{
			{number: 1, name: "Ice Breaker", min: 4, max: 6},
			{number: 2, name: "Organize Your Speech", min: 5, max: 7},
			{number: 3, name: "Get to the Point", min: 5, max: 7},
			{number: 4, name: "How to Say It", min: 5, max: 7},
			{number: 5, name: "Your Body Speaks", min: 5, max: 7},
			{number: 6, name: "Vocal Variety", min: 5, max: 7},
			{number: 7, name: "Research Your Topic", min: 5, max: 7},
			{number: 8, name: "Visual Aids", min: 5, max: 7},
			{number: 9, name: "Persuade with Power", min: 5, max: 7},
			{number: 10, name: "Inspire Your Audience", min: 8, max: 10},
		},
	},
	"inform": {
		manualName: "Speaking to Inform",
		speeches: []speechDetails{
			{number: 1, name: "The Speech to Inform", min: 5, max: 7},
			{number: 2, name: "Resources for Informing", min: 5, max: 7},
			{number: 3, name: "The Demonstration Talk", min: 5, max: 7},
			{number: 4, name: "A Fact Finding Report", min: 5, max: 7},
			{number: 5, name: "The Abstract Concept", min: 6, max: 8},
		},
	},
	"interpretive": {
		manualName: "Interpretive Reading",
		speeches: []speechDetails{
			{number: 1, name: "Read a Story", min: 8, max: 10},
			{number: 2, name: "Interpretive Poetry", min: 6, max: 8},
			{number: 3, name: "The Monodrama", min: 5, max: 7},
			{number: 4, name: "The Play", min: 12, max: 15},
			{number: 5, name: "The Oratorical Speech", min: 8, max: 10},
		},
	},
	"mgt": {
		manualName: "Speeches By Management",
		speeches: []speechDetails{
			{number: 1, name: "The Briefing", min: 8, max: 10},
			{number: 2, name: "The Technical Speech", min: 8, max: 10},
			{number: 3, name: "Manage and Motivate", min: 10, max: 12},
			{number: 4, name: "The Status Report", min: 10, max: 12},
			{number: 5, name: "Confrontation", min: 5, max: 15},
		},
	},
	"technical": {
		manualName: "Technical Presentations",
		speeches: []speechDetails{
			{number: 1, name: "Technical Briefing", min: 8, max: 10},
			{number: 2, name: "The Proposal", min: 8, max: 10},
			{number: 3, name: "The Nontechnical Audience", min: 10, max: 12},
			{number: 4, name: "Presenting a Technical Paper", min: 10, max: 12},
			{number: 5, name: "The Team Technical Presentation", min: 20, max: 30},
		},
	},
	"storytelling": {
		manualName: "Storytelling",
		speeches: []speechDetails{
			{number: 1, name: "The Folk Tale", min: 7, max: 9},
			{number: 2, name: "Let's Get Personal", min: 6, max: 8},
			{number: 3, name: "The Moral of the Story", min: 4, max: 6},
			{number: 4, name: "The Touching Story", min: 6, max: 8},
			{number: 5, name: "Bringing History to Life", min: 7, max: 9},
		},
	},
	"specialty": {
		manualName: "Specialty Speeches",
		speeches: []speechDetails{
			{number: 1, name: "Impromptu Speaking", min: 5, max: 7},
			{number: 2, name: "Uplift the Spirit", min: 8, max: 10},
			{number: 3, name: "Sell a product", min: 10, max: 12},
			{number: 4, name: "Read Out Loud", min: 12, max: 15},
			{number: 5, name: "Introduce the speaker", min: 0, max: 0},
		},
	},
	"hpl": {
		manualName: "High Performance Leadership",
		speeches: []speechDetails{
			{number: 1, name: "Share Your Vision", min: 5, max: 6},
			{number: 2, name: "Presenting The Results", min: 5, max: 7},
		},
	},
}
<commit_msg>export structs.<commit_after>package main

import (
	"log"
	"strconv"
	"strings"
)

// Each Toastmaster manual contains 5-10 ordered and named speeches.
// The fields min and max are the minimum and maximum speaking times for a Speech.
type SpeechDetails struct {
	number int
	name   string
	min    int
	max    int
}

// Speech represents the Speech that will be performed for the agenda.
type Speech struct {
	manualCode string
	manualName string
	SpeechDetails
}

// Factory function to create a Speech using a manual code and the Speech number in that manual.
func NewSpeech(manCode string, num int) Speech {
	manCode = strings.ToLower(manCode)
	man := manualMap[manCode]

	sp := Speech{
		manualCode: manCode,
		manualName: man.manualName,
		SpeechDetails: SpeechDetails{
			number: num,
		},
	}

	// Do not fail with invalid input, return with the default values set.
	if num < 1 || num > len(man.speeches) {
		log.Print("Speech num is invalid for the man.  Manual code: "+manCode+" Speech num:", num)
		return sp
	}

	sp.name = man.speeches[num-1].name
	sp.min = man.speeches[num-1].min
	sp.max = man.speeches[num-1].max

	return sp
}

// Info create a string that represents a Speech ex: "#1 Ice Breaker (4-6 mins)."
func (s Speech) info() string {
	return "#" + strconv.Itoa(s.number) + " " + s.name +
		" " + "(" + strconv.Itoa(s.min) + "-" + strconv.Itoa(s.max) + " mins)"
}

// There are 16 Toastmaster manuals a speaker can use at a meeting.
type manual struct {
	manualName string
	speeches   []SpeechDetails
}

// Representation of the Toasmaters speeches with their code as the key.
var manualMap = map[string]manual{
	"cc": {
		manualName: "Competent Communicator",
		speeches: []SpeechDetails{
			{number: 1, name: "Ice Breaker", min: 4, max: 6},
			{number: 2, name: "Organize Your Speech", min: 5, max: 7},
			{number: 3, name: "Get to the Point", min: 5, max: 7},
			{number: 4, name: "How to Say It", min: 5, max: 7},
			{number: 5, name: "Your Body Speaks", min: 5, max: 7},
			{number: 6, name: "Vocal Variety", min: 5, max: 7},
			{number: 7, name: "Research Your Topic", min: 5, max: 7},
			{number: 8, name: "Visual Aids", min: 5, max: 7},
			{number: 9, name: "Persuade with Power", min: 5, max: 7},
			{number: 10, name: "Inspire Your Audience", min: 8, max: 10},
		},
	},
	"inform": {
		manualName: "Speaking to Inform",
		speeches: []SpeechDetails{
			{number: 1, name: "The Speech to Inform", min: 5, max: 7},
			{number: 2, name: "Resources for Informing", min: 5, max: 7},
			{number: 3, name: "The Demonstration Talk", min: 5, max: 7},
			{number: 4, name: "A Fact Finding Report", min: 5, max: 7},
			{number: 5, name: "The Abstract Concept", min: 6, max: 8},
		},
	},
	"interpretive": {
		manualName: "Interpretive Reading",
		speeches: []SpeechDetails{
			{number: 1, name: "Read a Story", min: 8, max: 10},
			{number: 2, name: "Interpretive Poetry", min: 6, max: 8},
			{number: 3, name: "The Monodrama", min: 5, max: 7},
			{number: 4, name: "The Play", min: 12, max: 15},
			{number: 5, name: "The Oratorical Speech", min: 8, max: 10},
		},
	},
	"mgt": {
		manualName: "Speeches By Management",
		speeches: []SpeechDetails{
			{number: 1, name: "The Briefing", min: 8, max: 10},
			{number: 2, name: "The Technical Speech", min: 8, max: 10},
			{number: 3, name: "Manage and Motivate", min: 10, max: 12},
			{number: 4, name: "The Status Report", min: 10, max: 12},
			{number: 5, name: "Confrontation", min: 5, max: 15},
		},
	},
	"technical": {
		manualName: "Technical Presentations",
		speeches: []SpeechDetails{
			{number: 1, name: "Technical Briefing", min: 8, max: 10},
			{number: 2, name: "The Proposal", min: 8, max: 10},
			{number: 3, name: "The Nontechnical Audience", min: 10, max: 12},
			{number: 4, name: "Presenting a Technical Paper", min: 10, max: 12},
			{number: 5, name: "The Team Technical Presentation", min: 20, max: 30},
		},
	},
	"storytelling": {
		manualName: "Storytelling",
		speeches: []SpeechDetails{
			{number: 1, name: "The Folk Tale", min: 7, max: 9},
			{number: 2, name: "Let's Get Personal", min: 6, max: 8},
			{number: 3, name: "The Moral of the Story", min: 4, max: 6},
			{number: 4, name: "The Touching Story", min: 6, max: 8},
			{number: 5, name: "Bringing History to Life", min: 7, max: 9},
		},
	},
	"specialty": {
		manualName: "Specialty Speeches",
		speeches: []SpeechDetails{
			{number: 1, name: "Impromptu Speaking", min: 5, max: 7},
			{number: 2, name: "Uplift the Spirit", min: 8, max: 10},
			{number: 3, name: "Sell a product", min: 10, max: 12},
			{number: 4, name: "Read Out Loud", min: 12, max: 15},
			{number: 5, name: "Introduce the speaker", min: 0, max: 0},
		},
	},
	"hpl": {
		manualName: "High Performance Leadership",
		speeches: []SpeechDetails{
			{number: 1, name: "Share Your Vision", min: 5, max: 6},
			{number: 2, name: "Presenting The Results", min: 5, max: 7},
		},
	},
}
<|endoftext|>


<commit_before>package socks5

import (
	"net"
	"io"
	"log"
	"bytes"
	"errors"
	"strconv"
	"encoding/binary"
	"runtime"
	"golang.org/x/net/proxy"
	"time"
)

//version
const Version = 0x05

//methods
const (
	MethodNoAuthentication = iota
	MethodGSSAPI
	MethodUsernamePassword
	MethodNoAcceptable = 0xff
)

//CMD
const (
	CMDConnect = iota + 0x01
	CMDBind
	CMDUDPAssociate
)

//address type
const (
	AddrTypeIPv4 = iota + 0x01
	AddrTypeDomainName
	AddrTypeIPv6
)

//reply field
const (
	ReplySucceeded = iota
	ReplyGeneralFailure
	ReplyConnectionNotAllowed
	ReplyNetworkUnreachable
	ReplyHostUnreachable
	ReplyConnectionRefused
	ReplyTTLExpired
	ReplyCMDNotSupported
	ReplyAddrTypeNotSupported
)

type Error struct {
	x     byte
	error string
}

func (self Error) Byte() byte {
	return self.x
}

func (self Error) Error() string {
	return self.error
}

type Server struct {
	Dialer proxy.Dialer
}

func (self Server) ListenAndServe(network, address string) (err error) {
	var listener net.Listener
	if listener, err = net.Listen(network, address); err != nil {
		return
	}
	return self.Serve(listener)
}

func (self Server) Serve(listener net.Listener) (err error) {
	for {
		var conn net.Conn
		if conn, err = listener.Accept(); err != nil {
			return
		}

		go self.serve(conn)
	}
	return
}

func (self Server) serve(conn net.Conn) {
	defer func() {
		conn.Close()

		if r := recover(); r != nil {
			log.Println(r)

			buff := make([]byte, 512)
			runtime.Stack(buff, false)
			log.Println(string(buff))
		}
	}()

	var err error
	if err = self.initialize(conn); err != nil {
		log.Println("Socks5 connection initialize failed,", err)
		return
	}

	var proxy net.Conn
	if proxy, err = self.setup(conn); err != nil {
		log.Println("Socks5 connection setup failed,", err)
		return
	}
	defer proxy.Close()

	if err = self.serveloop(conn, proxy); err != nil {
		log.Println("Socks5 loop error,", err)
	}
}

func (self Server) initialize(conn net.Conn) (err error) {
	//read version, methods field
	buff := make([]byte, 2)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}

	ver := buff[0]
	if ver != Version {
		return errors.New("Socks version missmatch")
	}

	//read methods list
	methods := int(buff[1])
	buff = make([]byte, methods)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}
	if ! bytes.Contains(buff, []byte{MethodNoAuthentication}) {
		return errors.New("socks5 methods list invaild")
	}

	//reply
	buff = []byte{Version, MethodNoAuthentication}
	if err = binary.Write(conn, binary.BigEndian, buff); err != nil {
		return
	}

	return
}

func (self Server) readRequest(conn net.Conn) (network, addr string, err error) {
	buff := make([]byte, 4)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}

	//version
	ver := buff[0]
	if ver != Version {
		err = Error{ReplyGeneralFailure, "Socks version missmatch"}
		return
	}

	//cmd
	cmd := buff[1]
	if cmd != CMDConnect {    //Only support CONNECT
		err = Error{ReplyCMDNotSupported, "Socks 5 command not supported"}
		return
	}

	//address type
	atyp := buff[3]

	//read address
	var host string
	switch atyp {
	case 0x01:    //IPv4
		network = "tcp4"

		ip := make(net.IP, 4)
		if err = binary.Read(conn, binary.BigEndian, &ip); err != nil {
			return
		}

		host = ip.String()

	case 0x03:    //domain
		network = "tcp"

		var len byte
		if err = binary.Read(conn, binary.BigEndian, &len); err != nil {
			return
		}

		domain := make([]byte, len)
		if err = binary.Read(conn, binary.BigEndian, &domain); err != nil {
			return
		}

		host = string(domain)

	case 0x04:    //IPv6
		network = "tcp6"

		ip := make(net.IP, 16)
		if err = binary.Read(conn, binary.BigEndian, &ip); err != nil {
			return
		}

		host = ip.String()

	default:
		err = Error{ReplyAddrTypeNotSupported, "socks5 atyp error"}
		return
	}

	var port uint16
	if err = binary.Read(conn, binary.BigEndian, &port); err != err {
		return
	}

	addr = net.JoinHostPort(host, strconv.Itoa(int(port)))

	return
}

func (self Server) writeReply(conn net.Conn, addr net.Addr, e error) (err error) {
	if e != nil {
		if _e, ok := e.(Error); ok {
			return binary.Write(conn, binary.BigEndian, _e.Byte())
		} else {
			return binary.Write(conn, binary.BigEndian, ReplyGeneralFailure)
		}
	}

	var (
		host string
		sport string
	)
	if host, sport, err = net.SplitHostPort(addr.String()); err != nil {
		return
	}

	ip := net.ParseIP(host)

	var atyp byte
	if ip == nil {
		atyp = 0x03        //domain
	} else {
		if ip = ip.To4(); ip != nil {
			atyp = 0x01        //IPv4
		} else if ip = ip.To16(); ip != nil {
			atyp = 0x04        //IPv6
		} else {
			err = errors.New("local address error")
			return
		}
	}

	var nport int
	if nport, err = net.LookupPort(addr.Network(), sport); err != nil {
		return
	}
	port := uint16(nport)

	//write version, rep, reserved, address type
	head := []byte{
		Version,
		ReplySucceeded,
		0x00,
		atyp,
	}
	if err = binary.Write(conn, binary.BigEndian, head); err != nil {
		return
	}

	//write domain or ip
	if ip != nil {
		if err = binary.Write(conn, binary.BigEndian, ip); err != nil {
			return
		}
	} else {
		data := []byte(host)
		if err = binary.Write(conn, binary.BigEndian, byte(len(data))); err != nil {
			return
		}

		if err = binary.Write(conn, binary.BigEndian, data); err != nil {
			return
		}
	}

	//write port
	return binary.Write(conn, binary.BigEndian, port)
}

func (self Server) setup(conn net.Conn) (proxy net.Conn, err error) {
	var network, addr string

	//read
	if network, addr, err = self.readRequest(conn); err == nil {

		//connect
		if proxy, err = self.Dialer.Dial(network, addr); err != nil {
			err = Error{ReplyConnectionRefused, err.Error()}
		}
		defer func() {
			if err != nil && proxy != nil {
				proxy.Close()
				proxy = nil
			}
		}()
	}

	//reply
	var e error
	var laddr net.Addr
	if proxy != nil {
		laddr = proxy.LocalAddr()
	}
	if e = self.writeReply(conn, laddr, err); err == nil && e != nil {
		err = e
	}

	return
}

func (self Server) serveloop(conn, proxy net.Conn) (err error) {
	ch := make(chan error, 2)

	go self.copyLoop(conn, proxy, ch)

	go self.copyLoop(proxy, conn, ch)

	err = <-ch

	conn.SetReadDeadline(time.Now())
	proxy.SetReadDeadline(time.Now())

	<-ch    //Waiting for another exit
	return
}

func (self Server) copyLoop(conn1, conn2 net.Conn, ch chan error) {
	_, err := io.Copy(conn1, conn2)
	ch <- err
}
<commit_msg>修改socks5实现，当代理地址不能解析，返回dummy地址，保障程序运行<commit_after>package socks5

import (
	"net"
	"io"
	"log"
	"bytes"
	"errors"
	"strconv"
	"encoding/binary"
	"runtime"
	"golang.org/x/net/proxy"
	"time"
)

//version
const Version = 0x05

//methods
const (
	MethodNoAuthentication = iota
	MethodGSSAPI
	MethodUsernamePassword
	MethodNoAcceptable = 0xff
)

//CMD
const (
	CMDConnect = iota + 0x01
	CMDBind
	CMDUDPAssociate
)

//address type
const (
	AddrTypeIPv4 = iota + 0x01
	AddrTypeDomainName
	AddrTypeIPv6
)

//reply field
const (
	ReplySucceeded = iota
	ReplyGeneralFailure
	ReplyConnectionNotAllowed
	ReplyNetworkUnreachable
	ReplyHostUnreachable
	ReplyConnectionRefused
	ReplyTTLExpired
	ReplyCMDNotSupported
	ReplyAddrTypeNotSupported
)

type Error struct {
	x     byte
	error string
}

func (self Error) Byte() byte {
	return self.x
}

func (self Error) Error() string {
	return self.error
}

type Server struct {
	Dialer proxy.Dialer
}

func (self Server) ListenAndServe(network, address string) (err error) {
	var listener net.Listener
	if listener, err = net.Listen(network, address); err != nil {
		return
	}
	return self.Serve(listener)
}

func (self Server) Serve(listener net.Listener) (err error) {
	for {
		var conn net.Conn
		if conn, err = listener.Accept(); err != nil {
			return
		}

		go self.serve(conn)
	}
	return
}

func (self Server) serve(conn net.Conn) {
	defer func() {
		conn.Close()

		if r := recover(); r != nil {
			log.Println(r)

			buff := make([]byte, 512)
			runtime.Stack(buff, false)
			log.Println(string(buff))
		}
	}()

	var err error
	if err = self.initialize(conn); err != nil {
		log.Println("Socks5 connection initialize failed,", err)
		return
	}

	var proxy net.Conn
	if proxy, err = self.setup(conn); err != nil {
		log.Println("Socks5 connection setup failed,", err)
		return
	}
	defer proxy.Close()

	if err = self.serveloop(conn, proxy); err != nil {
		log.Println("Socks5 loop error,", err)
	}
}

func (self Server) initialize(conn net.Conn) (err error) {
	//read version, methods field
	buff := make([]byte, 2)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}

	ver := buff[0]
	if ver != Version {
		return errors.New("Socks version missmatch")
	}

	//read methods list
	methods := int(buff[1])
	buff = make([]byte, methods)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}
	if ! bytes.Contains(buff, []byte{MethodNoAuthentication}) {
		return errors.New("socks5 methods list invaild")
	}

	//reply
	buff = []byte{Version, MethodNoAuthentication}
	if err = binary.Write(conn, binary.BigEndian, buff); err != nil {
		return
	}

	return
}

func (self Server) readRequest(conn net.Conn) (network, addr string, err error) {
	buff := make([]byte, 4)
	if err = binary.Read(conn, binary.BigEndian, &buff); err != nil {
		return
	}

	//version
	ver := buff[0]
	if ver != Version {
		err = Error{ReplyGeneralFailure, "Socks version missmatch"}
		return
	}

	//cmd
	cmd := buff[1]
	if cmd != CMDConnect {    //Only support CONNECT
		err = Error{ReplyCMDNotSupported, "Socks 5 command not supported"}
		return
	}

	//address type
	atyp := buff[3]

	//read address
	var host string
	switch atyp {
	case 0x01:    //IPv4
		network = "tcp4"

		ip := make(net.IP, 4)
		if err = binary.Read(conn, binary.BigEndian, &ip); err != nil {
			return
		}

		host = ip.String()

	case 0x03:    //domain
		network = "tcp"

		var len byte
		if err = binary.Read(conn, binary.BigEndian, &len); err != nil {
			return
		}

		domain := make([]byte, len)
		if err = binary.Read(conn, binary.BigEndian, &domain); err != nil {
			return
		}

		host = string(domain)

	case 0x04:    //IPv6
		network = "tcp6"

		ip := make(net.IP, 16)
		if err = binary.Read(conn, binary.BigEndian, &ip); err != nil {
			return
		}

		host = ip.String()

	default:
		err = Error{ReplyAddrTypeNotSupported, "socks5 atyp error"}
		return
	}

	var port uint16
	if err = binary.Read(conn, binary.BigEndian, &port); err != err {
		return
	}

	addr = net.JoinHostPort(host, strconv.Itoa(int(port)))

	return
}

func (self Server) writeReply(conn net.Conn, addr net.Addr, e error) (err error) {
	if e != nil {
		if _e, ok := e.(Error); ok {
			return binary.Write(conn, binary.BigEndian, _e.Byte())
		} else {
			return binary.Write(conn, binary.BigEndian, ReplyGeneralFailure)
		}
	}

	var (
		host string
		ip net.IP
		port uint16

		sport string
		atyp byte
		nport int
	)
	host, sport, err = net.SplitHostPort(addr.String())
	if err != nil {
		//dummy
		atyp = 0x03
		host = addr.String()
		port = 0
	} else {
		ip = net.ParseIP(host)

		if ip == nil {
			atyp = 0x03        //domain
		} else {
			if ip = ip.To4(); ip != nil {
				atyp = 0x01        //IPv4
			} else if ip = ip.To16(); ip != nil {
				atyp = 0x04        //IPv6
			} else {
				err = errors.New("local address error")
				return
			}
		}

		if nport, err = net.LookupPort(addr.Network(), sport); err != nil {
			return
		}
		port = uint16(nport)
	}

	//write version, rep, reserved, address type
	head := []byte{
		Version,
		ReplySucceeded,
		0x00,
		atyp,
	}
	if err = binary.Write(conn, binary.BigEndian, head); err != nil {
		return
	}

	//write domain or ip
	if ip != nil {
		if err = binary.Write(conn, binary.BigEndian, ip); err != nil {
			return
		}
	} else {
		data := []byte(host)
		if err = binary.Write(conn, binary.BigEndian, byte(len(data))); err != nil {
			return
		}

		if err = binary.Write(conn, binary.BigEndian, data); err != nil {
			return
		}
	}

	//write port
	return binary.Write(conn, binary.BigEndian, port)
}

func (self Server) setup(conn net.Conn) (proxy net.Conn, err error) {
	var network, addr string

	//read
	if network, addr, err = self.readRequest(conn); err == nil {

		//connect
		if proxy, err = self.Dialer.Dial(network, addr); err != nil {
			err = Error{ReplyConnectionRefused, err.Error()}
		}
		defer func() {
			if err != nil && proxy != nil {
				proxy.Close()
				proxy = nil
			}
		}()
	}

	//reply
	var e error
	var laddr net.Addr
	if proxy != nil {
		laddr = proxy.LocalAddr()
	}
	if e = self.writeReply(conn, laddr, err); err == nil && e != nil {
		err = e
	}

	return
}

func (self Server) serveloop(conn, proxy net.Conn) (err error) {
	ch := make(chan error, 2)

	go self.copyLoop(conn, proxy, ch)

	go self.copyLoop(proxy, conn, ch)

	err = <-ch

	conn.SetReadDeadline(time.Now())
	proxy.SetReadDeadline(time.Now())

	<-ch    //Waiting for another exit
	return
}

func (self Server) copyLoop(conn1, conn2 net.Conn, ch chan error) {
	_, err := io.Copy(conn1, conn2)
	ch <- err
}
<|endoftext|>


<commit_before>package disruptor

import (
	"math"
	"sync/atomic"
)

type SharedWriter struct {
	capacity           int64
	gate               int64
	shift              uint8
	committedSequences []int32
	readerBarrier      Barrier
	writerCursor       *Cursor
}

func NewSharedWriter(writerCursor *Cursor, capacity int64, readerBarrier Barrier) *SharedWriter {
	assertPowerOfTwo(capacity)

	shift := uint8(math.Log2(float64(capacity)))
	buffer := initializeCommittedSequences(capacity)

	return &SharedWriter{
		capacity:           capacity,
		gate:               InitialSequenceValue,
		shift:              shift,
		committedSequences: buffer,
		readerBarrier:      readerBarrier,
		writerCursor:       writerCursor,
	}
}
func initializeCommittedSequences(capacity int64) []int32 {
	buffer := make([]int32, capacity)
	for i := range buffer {
		buffer[i] = int32(InitialSequenceValue)
	}
	return buffer
}

func (this *SharedWriter) Reserve(count int64) (int64, int64) {
	if count <= 0 {
		panic("Reservation must be a positive number.")
	} else if count > this.capacity {
		panic("Reservation cannot exceed the capacity.")
	}

	for {
		previous := this.writerCursor.Load()
		next := previous + count
		wrap := next - this.capacity

		if wrap > this.gate {
			min := this.readerBarrier.Load()
			if wrap > min {
				return 0, Gating
			}

			this.gate = min
		}

		if atomic.CompareAndSwapInt64(&this.writerCursor.value, previous, next) {
			return previous + 1, next
		}
	}
}

func (this *SharedWriter) Commit(lower, upper int64) {
	for mask := this.capacity - 1; lower <= upper; lower++ {
		this.committedSequences[lower&mask] = int32(lower >> this.shift)
	}
}

func (this *SharedWriter) LoadBarrier(lower, upper int64) int64 {
	for mask := this.capacity - 1; lower <= upper; lower++ {
		if this.committedSequences[lower&mask] < int32(lower>>this.shift) {
			return lower - 1
		}
	}

	return upper
}
<commit_msg>Added TODOs.<commit_after>package disruptor

import (
	"math"
	"sync/atomic"
)

type SharedWriter struct {
	capacity           int64
	gate               int64 // TODO: this will most likely need to be a cursor
	shift              uint8
	committedSequences []int32
	readerBarrier      Barrier
	writerCursor       *Cursor
}

func NewSharedWriter(writerCursor *Cursor, capacity int64, readerBarrier Barrier) *SharedWriter {
	assertPowerOfTwo(capacity)

	shift := uint8(math.Log2(float64(capacity)))
	buffer := initializeCommittedSequences(capacity)

	return &SharedWriter{
		capacity:           capacity,
		gate:               InitialSequenceValue,
		shift:              shift,
		committedSequences: buffer,
		readerBarrier:      readerBarrier,
		writerCursor:       writerCursor,
	}
}
func initializeCommittedSequences(capacity int64) []int32 {
	buffer := make([]int32, capacity)
	for i := range buffer {
		buffer[i] = int32(InitialSequenceValue)
	}
	return buffer
}

func (this *SharedWriter) Reserve(count int64) (int64, int64) {
	if count <= 0 {
		panic("Reservation must be a positive number.")
	} else if count > this.capacity {
		panic("Reservation cannot exceed the capacity.")
	}

	for {
		previous := this.writerCursor.Load()
		next := previous + count
		wrap := next - this.capacity

		if wrap > this.gate {
			min := this.readerBarrier.Load()
			if wrap > min {
				return 0, Gating
			}

			this.gate = min // doesn't matter which write wins, BUT will most likely need to be a Cursor
		}

		if atomic.CompareAndSwapInt64(&this.writerCursor.value, previous, next) {
			return previous + 1, next
		}
	}
}

func (this *SharedWriter) Commit(lower, upper int64) {
	for mask := this.capacity - 1; lower <= upper; lower++ {
		this.committedSequences[lower&mask] = int32(lower >> this.shift)
	}
}

func (this *SharedWriter) LoadBarrier(lower, upper int64) int64 {
	for mask := this.capacity - 1; lower <= upper; lower++ {
		if this.committedSequences[lower&mask] < int32(lower>>this.shift) {
			return lower - 1
		}
	}

	return upper
}
<|endoftext|>


<commit_before>package sexp

// IsReturning returns true for forms that unconditionally
// return from function.
func IsReturning(form Form) bool {
	switch form := form.(type) {
	case *Panic:
		return true

	case *Return:
		return true

	case *Block:
		for _, form := range form.Forms {
			if IsReturning(form) {
				return true
			}
		}

	case *If:
		// If both branches return, whole statement returns.
		return IsReturning(form.Then) && IsReturning(form.Else)

	case CallStmt:
		return form.Fn.IsPanic()

	case *Call:
		return form.Fn.IsPanic()
	}

	return false
}

func IsAtom(form Form) bool {
	switch form.(type) {
	case Bool, Int, Float, String, Symbol:
		return true
	default:
		return false
	}
}<commit_msg>sexp.IsStmt predicate<commit_after>package sexp

// IsStmt returns true for statement form.
func IsStmt(form Form) bool {
	return form.Type() == typVoid
}

// IsReturning returns true for forms that unconditionally
// return from function.
func IsReturning(form Form) bool {
	switch form := form.(type) {
	case *Panic:
		return true

	case *Return:
		return true

	case *Block:
		for _, form := range form.Forms {
			if IsReturning(form) {
				return true
			}
		}

	case *If:
		// If both branches return, whole statement returns.
		return IsReturning(form.Then) && IsReturning(form.Else)

	case CallStmt:
		return form.Fn.IsPanic()

	case *Call:
		return form.Fn.IsPanic()
	}

	return false
}

func IsAtom(form Form) bool {
	switch form.(type) {
	case Bool, Int, Float, String, Symbol:
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package etcdfs

import(
  "log"
  "strings"
  "bytes"

  "github.com/hanwen/go-fuse/fuse"
  "github.com/hanwen/go-fuse/fuse/nodefs"
  "github.com/hanwen/go-fuse/fuse/pathfs"

  "github.com/coreos/go-etcd/etcd"
)

type EtcdFs struct {
  pathfs.FileSystem
  EtcdEndpoint string
}

func (me *EtcdFs) NewEtcdClient() *etcd.Client {
  return etcd.NewClient([]string{me.EtcdEndpoint})
}

func (me *EtcdFs) Unlink(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().Delete(name, false)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().RawDelete(name, true, true)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Set(name, "", 0)

  if err != nil {
    log.Println("Create Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().CreateDir(name, 0)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
  if name == "" {
    return &fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }, fuse.OK
  }

  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    return nil, fuse.ENOENT
  }

  var attr fuse.Attr

  if res.Node.Dir {
    attr = fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }
  } else {
    attr = fuse.Attr{
      Mode: fuse.S_IFREG | 0666, Size: uint64(len(res.Node.Value)),
    }
  }

  return &attr, fuse.OK
}

func (me *EtcdFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("OpenDir Error:", err)
    return nil, fuse.ENOENT
  }

  entries := []fuse.DirEntry{}

  for _, e := range(res.Node.Nodes) {
    chunks := strings.Split(e.Key, "/")
    file := chunks[len(chunks)-1]
    if e.Dir {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFDIR})
    } else {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFREG})
    }
  }

  return entries, fuse.OK
}

func (me *EtcdFs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("Open Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
  etcdClient := me.NewEtcdClient()
  res, err := etcdClient.Get(oldName, false, false)
  originalValue := []byte(res.Node.Value)
  newValue := bytes.NewBuffer(originalValue)
  _, err = etcdClient.Set(newName, newValue.String(), 0)
  _, err = etcdClient.Delete(oldName, false)
  return fuse.OK
}
<commit_msg>Remove unused err.<commit_after>package etcdfs

import(
  "log"
  "strings"
  "bytes"

  "github.com/hanwen/go-fuse/fuse"
  "github.com/hanwen/go-fuse/fuse/nodefs"
  "github.com/hanwen/go-fuse/fuse/pathfs"

  "github.com/coreos/go-etcd/etcd"
)

type EtcdFs struct {
  pathfs.FileSystem
  EtcdEndpoint string
}

func (me *EtcdFs) NewEtcdClient() *etcd.Client {
  return etcd.NewClient([]string{me.EtcdEndpoint})
}

func (me *EtcdFs) Unlink(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().Delete(name, false)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().RawDelete(name, true, true)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Set(name, "", 0)

  if err != nil {
    log.Println("Create Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().CreateDir(name, 0)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
  if name == "" {
    return &fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }, fuse.OK
  }

  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    return nil, fuse.ENOENT
  }

  var attr fuse.Attr

  if res.Node.Dir {
    attr = fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }
  } else {
    attr = fuse.Attr{
      Mode: fuse.S_IFREG | 0666, Size: uint64(len(res.Node.Value)),
    }
  }

  return &attr, fuse.OK
}

func (me *EtcdFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("OpenDir Error:", err)
    return nil, fuse.ENOENT
  }

  entries := []fuse.DirEntry{}

  for _, e := range(res.Node.Nodes) {
    chunks := strings.Split(e.Key, "/")
    file := chunks[len(chunks)-1]
    if e.Dir {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFDIR})
    } else {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFREG})
    }
  }

  return entries, fuse.OK
}

func (me *EtcdFs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("Open Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
  etcdClient := me.NewEtcdClient()
  res,_ := etcdClient.Get(oldName, false, false)
  originalValue := []byte(res.Node.Value)
  newValue := bytes.NewBuffer(originalValue)
  etcdClient.Set(newName, newValue.String(), 0)
  etcdClient.Delete(oldName, false)
  return fuse.OK
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"erlang/dist"
	"flag"
	"fmt"
	"log"
	"net"
	"strconv"
	"time"
)

var listenPort string
var regLimit int
var unregTTL int

func init() {
	flag.StringVar(&listenPort, "port", "4369", "listen port")
	flag.IntVar(&regLimit, "nodes-limit", 1000, "limit size of registration table to prune unregistered nodes")
	flag.IntVar(&unregTTL, "unreg-ttl", 10, "prune unregistered nodes if unregistration older than this value in minutes")
}

type regAns struct {
	reply   []byte
	isClose bool
}

type regReq struct {
	buf     []byte
	replyTo chan regAns
	conn    net.Conn
}

func main() {
	flag.Parse()

	l, err := net.Listen("tcp", net.JoinHostPort("", listenPort))
	if err != nil {
		log.Fatal(err)
	}
	epm := make(chan regReq, 10)
	go epmReg(epm)
	for {
		conn, err := l.Accept()
		log.Printf("Accept new")
		if err != nil {
			log.Printf(err.Error())
		} else {
			go mLoop(conn, epm)
		}
	}
	log.Printf("Exit")
}

type nodeRec struct {
	dist.NodeInfo
	Time  time.Time
	Active bool
	conn  net.Conn
}

func epmReg(in <-chan regReq) {

	var nReg = make(map[string]*nodeRec)

	for {
		select {
		case req := <-in:
			buf := req.buf
			if len(buf) == 0 {
				rs := len(nReg)
				log.Printf("REG %d records", rs)
				now := time.Now()

				for node, rec := range nReg {
					if rec.conn == req.conn {
						log.Printf("Connection for %s dropped", node)
						nReg[node].Active = false
						nReg[node].Time = now
					} else if rs > regLimit && !rec.Active && now.Sub(rec.Time).Minutes() > float64(unregTTL) {
						log.Printf("REG prune %s:%+v", node, rec)
						delete(nReg, node)
					}
				}
				continue
			}
			replyTo := req.replyTo
			log.Printf("IN: %v", buf)
			switch dist.MessageId(buf[0]) {
			case dist.ALIVE2_REQ:
				nConn := req.conn
				nPort := binary.BigEndian.Uint16(buf[1:3])
				nType := buf[3]
				nProto := buf[4]
				highVsn := binary.BigEndian.Uint16(buf[5:7])
				lowVsn := binary.BigEndian.Uint16(buf[7:9])
				nLen := binary.BigEndian.Uint16(buf[9:11])
				offset := (11 + nLen)
				nName := string(buf[11:offset])
				//nELen := binary.BigEndian.Uint16(buf[offset:(offset+2)])
				nExtra := buf[(offset + 2):]
				log.Printf("Alive: N:%s, P:%d, T:%d", nName, nPort, nType)

				reply := make([]byte, 4)
				reply[0] = byte(dist.ALIVE2_RESP)
				reply[1] = 0 // OK

				var data uint16 = 0
				if rec, ok := nReg[nName]; ok {
					log.Printf("Node %s found", nName)
					if rec.Active {
						log.Printf("Node %s is running", nName)
						reply[1] = 1 // ERROR
						data = 99    // CANNOT REGISTER
					} else {
						log.Printf("Node %s is not running", nName)
						rec.conn = nConn
						rec.Port = nPort
						rec.Type = nType
						rec.Protocol = nProto
						rec.HighVsn = highVsn
						rec.LowVsn = lowVsn
						rec.Extra = nExtra
						rec.Creation = (rec.Creation % 3) + 1
						rec.Active = true
						data = rec.Creation
					}
				} else {
					log.Printf("New node %s", nName)
					rec := &nodeRec{
						NodeInfo: dist.NodeInfo{
							Name:     nName,
							Port:     nPort,
							Type:     nType,
							Protocol: nProto,
							HighVsn:  highVsn,
							LowVsn:   lowVsn,
							Extra:    nExtra,
							Creation: 1,
						},
						conn:  nConn,
						Time:  time.Now(),
						Active: true,
					}
					nReg[nName] = rec
					data = rec.Creation
				}

				binary.BigEndian.PutUint16(reply[2:4], data)
				replyTo <- regAns{reply: reply, isClose: false}
			case dist.PORT_PLEASE2_REQ:
				nName := buf[1:]
				var reply []byte
				if rec, ok := nReg[string(nName)]; ok && rec.Active {
					reply = make([]byte, 14+len(nName)+len(rec.Extra))
					reply[0] = byte(dist.PORT2_RESP)
					reply[1] = 0 // OK
					binary.BigEndian.PutUint16(reply[2:4], rec.Port)
					reply[4] = rec.Type
					reply[5] = rec.Protocol
					binary.BigEndian.PutUint16(reply[6:8], rec.HighVsn)
					binary.BigEndian.PutUint16(reply[8:10], rec.LowVsn)
					nLen := len(rec.Name)
					binary.BigEndian.PutUint16(reply[10:12], uint16(nLen))
					offset := (12 + nLen)
					copy(reply[12:offset], rec.Name)
					nELen := len(rec.Extra)
					binary.BigEndian.PutUint16(reply[offset:offset+2], uint16(nELen))
					copy(reply[offset+2:offset+2+nELen], rec.Extra)
				} else {
					reply = make([]byte, 2)
					reply[0] = byte(dist.PORT2_RESP)
					reply[1] = 1 // ERROR
				}
				replyTo <- regAns{reply: reply, isClose: true}
			case dist.NAMES_REQ, dist.DUMP_REQ:
				log.Printf("NAMES_REQ")
				lp, err := strconv.Atoi(listenPort)
				if err != nil {
					log.Printf("Cannot convert %s to integer", listenPort)
					replyTo <- regAns{reply: nil, isClose: true}
				} else {
					log.Printf("Make a reply")

					var replyB bytes.Buffer
					reply := make([]byte, 4)
					binary.BigEndian.PutUint32(reply, uint32(lp))
					replyB.Write(reply)

					for node, rec := range nReg {
						if rec.Active {
							if dist.MessageId(buf[0]) == dist.NAMES_REQ {
								replyB.Write([]byte(fmt.Sprintf("name %s at port %d\n", node, rec.Port)))
							} else {
								if rec.Active {
									replyB.Write([]byte(fmt.Sprintf("active name     <%s> at port %d\n", node, rec.Port)))
								} else {
									replyB.Write([]byte(fmt.Sprintf("old/unused name <%s>, port = %d\n", node, rec.Port)))
								}
							}
						}
					}
					replyTo <- regAns{reply: replyB.Bytes(), isClose: true}
				}
			case dist.KILL_REQ:
				replyTo <- regAns{reply: []byte("OK"), isClose: true}
			default:
				replyTo <- regAns{reply: nil, isClose: true}
			}
		}
	}
}

func mLoop(c net.Conn, epm chan regReq) {
	buf := make([]byte, 1024)
	for {
		n, err := c.Read(buf)
		if err != nil {
			c.Close()
			log.Printf("Stop loop: %v", err)
			epm <- regReq{buf: []byte{}, conn: c}
			return
		}
		length := binary.BigEndian.Uint16(buf[0:2])
		if length != uint16(n-2) {
			log.Printf("Incomplete packet: %d from %d", n, length)
		}
		log.Printf("Read %d, %d: %v", n, length, buf[2:n])
		if isClose := handleMsg(c, buf[2:n], epm); isClose {
			break
		}
	}
	c.Close()
}

func handleMsg(c net.Conn, buf []byte, epm chan regReq) bool {
	myChan := make(chan regAns)
	epm <- regReq{buf: buf, replyTo: myChan, conn: c}
	select {
	case ans := <-myChan:
		log.Printf("Got reply: %+v", ans)
		if ans.reply != nil {
			c.Write(ans.reply)
		}
		return ans.isClose
	}
	return true
}
<commit_msg>Fix condition<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"erlang/dist"
	"flag"
	"fmt"
	"log"
	"net"
	"strconv"
	"time"
)

var listenPort string
var regLimit int
var unregTTL int

func init() {
	flag.StringVar(&listenPort, "port", "4369", "listen port")
	flag.IntVar(&regLimit, "nodes-limit", 1000, "limit size of registration table to prune unregistered nodes")
	flag.IntVar(&unregTTL, "unreg-ttl", 10, "prune unregistered nodes if unregistration older than this value in minutes")
}

type regAns struct {
	reply   []byte
	isClose bool
}

type regReq struct {
	buf     []byte
	replyTo chan regAns
	conn    net.Conn
}

func main() {
	flag.Parse()

	l, err := net.Listen("tcp", net.JoinHostPort("", listenPort))
	if err != nil {
		log.Fatal(err)
	}
	epm := make(chan regReq, 10)
	go epmReg(epm)
	for {
		conn, err := l.Accept()
		log.Printf("Accept new")
		if err != nil {
			log.Printf(err.Error())
		} else {
			go mLoop(conn, epm)
		}
	}
	log.Printf("Exit")
}

type nodeRec struct {
	dist.NodeInfo
	Time  time.Time
	Active bool
	conn  net.Conn
}

func epmReg(in <-chan regReq) {

	var nReg = make(map[string]*nodeRec)

	for {
		select {
		case req := <-in:
			buf := req.buf
			if len(buf) == 0 {
				rs := len(nReg)
				log.Printf("REG %d records", rs)
				now := time.Now()

				for node, rec := range nReg {
					if rec.conn == req.conn {
						log.Printf("Connection for %s dropped", node)
						nReg[node].Active = false
						nReg[node].Time = now
					} else if rs > regLimit && !rec.Active && now.Sub(rec.Time).Minutes() > float64(unregTTL) {
						log.Printf("REG prune %s:%+v", node, rec)
						delete(nReg, node)
					}
				}
				continue
			}
			replyTo := req.replyTo
			log.Printf("IN: %v", buf)
			switch dist.MessageId(buf[0]) {
			case dist.ALIVE2_REQ:
				nConn := req.conn
				nPort := binary.BigEndian.Uint16(buf[1:3])
				nType := buf[3]
				nProto := buf[4]
				highVsn := binary.BigEndian.Uint16(buf[5:7])
				lowVsn := binary.BigEndian.Uint16(buf[7:9])
				nLen := binary.BigEndian.Uint16(buf[9:11])
				offset := (11 + nLen)
				nName := string(buf[11:offset])
				//nELen := binary.BigEndian.Uint16(buf[offset:(offset+2)])
				nExtra := buf[(offset + 2):]
				log.Printf("Alive: N:%s, P:%d, T:%d", nName, nPort, nType)

				reply := make([]byte, 4)
				reply[0] = byte(dist.ALIVE2_RESP)
				reply[1] = 0 // OK

				var data uint16 = 0
				if rec, ok := nReg[nName]; ok {
					log.Printf("Node %s found", nName)
					if rec.Active {
						log.Printf("Node %s is running", nName)
						reply[1] = 1 // ERROR
						data = 99    // CANNOT REGISTER
					} else {
						log.Printf("Node %s is not running", nName)
						rec.conn = nConn
						rec.Port = nPort
						rec.Type = nType
						rec.Protocol = nProto
						rec.HighVsn = highVsn
						rec.LowVsn = lowVsn
						rec.Extra = nExtra
						rec.Creation = (rec.Creation % 3) + 1
						rec.Active = true
						data = rec.Creation
					}
				} else {
					log.Printf("New node %s", nName)
					rec := &nodeRec{
						NodeInfo: dist.NodeInfo{
							Name:     nName,
							Port:     nPort,
							Type:     nType,
							Protocol: nProto,
							HighVsn:  highVsn,
							LowVsn:   lowVsn,
							Extra:    nExtra,
							Creation: 1,
						},
						conn:  nConn,
						Time:  time.Now(),
						Active: true,
					}
					nReg[nName] = rec
					data = rec.Creation
				}

				binary.BigEndian.PutUint16(reply[2:4], data)
				replyTo <- regAns{reply: reply, isClose: false}
			case dist.PORT_PLEASE2_REQ:
				nName := buf[1:]
				var reply []byte
				if rec, ok := nReg[string(nName)]; ok && rec.Active {
					reply = make([]byte, 14+len(nName)+len(rec.Extra))
					reply[0] = byte(dist.PORT2_RESP)
					reply[1] = 0 // OK
					binary.BigEndian.PutUint16(reply[2:4], rec.Port)
					reply[4] = rec.Type
					reply[5] = rec.Protocol
					binary.BigEndian.PutUint16(reply[6:8], rec.HighVsn)
					binary.BigEndian.PutUint16(reply[8:10], rec.LowVsn)
					nLen := len(rec.Name)
					binary.BigEndian.PutUint16(reply[10:12], uint16(nLen))
					offset := (12 + nLen)
					copy(reply[12:offset], rec.Name)
					nELen := len(rec.Extra)
					binary.BigEndian.PutUint16(reply[offset:offset+2], uint16(nELen))
					copy(reply[offset+2:offset+2+nELen], rec.Extra)
				} else {
					reply = make([]byte, 2)
					reply[0] = byte(dist.PORT2_RESP)
					reply[1] = 1 // ERROR
				}
				replyTo <- regAns{reply: reply, isClose: true}
			case dist.NAMES_REQ, dist.DUMP_REQ:
				log.Printf("NAMES_REQ")
				lp, err := strconv.Atoi(listenPort)
				if err != nil {
					log.Printf("Cannot convert %s to integer", listenPort)
					replyTo <- regAns{reply: nil, isClose: true}
				} else {
					log.Printf("Make a reply")

					var replyB bytes.Buffer
					reply := make([]byte, 4)
					binary.BigEndian.PutUint32(reply, uint32(lp))
					replyB.Write(reply)

					for node, rec := range nReg {
						if dist.MessageId(buf[0]) == dist.NAMES_REQ {
							if rec.Active {
								replyB.Write([]byte(fmt.Sprintf("name %s at port %d\n", node, rec.Port)))
							} else {
								if rec.Active {
									replyB.Write([]byte(fmt.Sprintf("active name     <%s> at port %d\n", node, rec.Port)))
								} else {
									replyB.Write([]byte(fmt.Sprintf("old/unused name <%s>, port = %d\n", node, rec.Port)))
								}
							}
						}
					}
					replyTo <- regAns{reply: replyB.Bytes(), isClose: true}
				}
			case dist.KILL_REQ:
				replyTo <- regAns{reply: []byte("OK"), isClose: true}
			default:
				replyTo <- regAns{reply: nil, isClose: true}
			}
		}
	}
}

func mLoop(c net.Conn, epm chan regReq) {
	buf := make([]byte, 1024)
	for {
		n, err := c.Read(buf)
		if err != nil {
			c.Close()
			log.Printf("Stop loop: %v", err)
			epm <- regReq{buf: []byte{}, conn: c}
			return
		}
		length := binary.BigEndian.Uint16(buf[0:2])
		if length != uint16(n-2) {
			log.Printf("Incomplete packet: %d from %d", n, length)
		}
		log.Printf("Read %d, %d: %v", n, length, buf[2:n])
		if isClose := handleMsg(c, buf[2:n], epm); isClose {
			break
		}
	}
	c.Close()
}

func handleMsg(c net.Conn, buf []byte, epm chan regReq) bool {
	myChan := make(chan regAns)
	epm <- regReq{buf: buf, replyTo: myChan, conn: c}
	select {
	case ans := <-myChan:
		log.Printf("Got reply: %+v", ans)
		if ans.reply != nil {
			c.Write(ans.reply)
		}
		return ans.isClose
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright 2015 Luke Shumaker

package web

import (
	he "httpentity"
)

type postHack struct{}

func (p postHack) Before(req *he.Request) {
	hash, ok := req.Entity.(map[string]interface{})
	if !ok {
		return
	}
	method, ok := hash["_method"].(string)
	if !ok {
		return
	}
	req.Method = method
}

func (p postHack) After(req he.Request, res *he.Response) {}
<commit_msg>middleware_posthack: drop the _method item from the body<commit_after>// Copyright 2015 Luke Shumaker

package web

import (
	he "httpentity"
)

type postHack struct{}

func (p postHack) Before(req *he.Request) {
	hash, ok := req.Entity.(map[string]interface{})
	if !ok {
		return
	}
	method, ok := hash["_method"].(string)
	delete(hash, "_method")
	if !ok {
		return
	}
	req.Method = method
}

func (p postHack) After(req he.Request, res *he.Response) {}
<|endoftext|>