<commit_before>// Copyright 2016 Mender Software AS
//
//    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 images

import (
	"net/http"
	"strconv"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/asaskevich/govalidator"
	"github.com/mendersoftware/artifacts/mvc"
	"github.com/pkg/errors"
)

// API input validation constants
const (
	DefaultDownloadLinkExpire = 60
	DefaultUploadLinkExpire   = 60

	// AWS limitation is 1 week
	MaxLinkExpire = 60 * 7 * 24
)

var (
	ErrIDNotUUIDv4        = errors.New("ID is not UUIDv4")
	ErrInvalidExpireParam = errors.New("Invalid expire parameter")
)

type ImagesModeler interface {
	ListImages(filters map[string]string) ([]*SoftwareImage, error)
	UploadLink(imageID string, expire time.Duration) (*Link, error)
	DownloadLink(imageID string, expire time.Duration) (*Link, error)
	GetImage(id string) (*SoftwareImage, error)
	DeleteImage(imageID string) error
	CreateImage(constructorData *SoftwareImageConstructor) (string, error)
	EditImage(id string, constructorData *SoftwareImageConstructor) (bool, error)
}

type SoftwareImagesController struct {
	views mvc.RESTViewDefaults
	model ImagesModeler
}

func NewSoftwareImagesController(model ImagesModeler, views mvc.RESTViewDefaults) *SoftwareImagesController {
	return &SoftwareImagesController{
		model: model,
		views: views,
	}
}

func (s *SoftwareImagesController) GetImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	image, err := s.model.GetImage(id)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if image == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, image)
}

func (s *SoftwareImagesController) ListImages(w rest.ResponseWriter, r *rest.Request) {

	list, err := s.model.ListImages(r.PathParams)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessGet(w, list)
}

func (s *SoftwareImagesController) UploadLink(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	expire := DefaultDownloadLinkExpire
	expireStr := r.URL.Query().Get("expire")

	// Validate input
	if !govalidator.IsNull(expireStr) {
		if !s.validExpire(expireStr) {
			s.views.RenderError(w, ErrInvalidExpireParam, http.StatusBadRequest)
			return
		}

		var err error
		expire, err = strconv.Atoi(expireStr)
		if err != nil {
			s.views.RenderError(w, err, http.StatusInternalServerError)
			return
		}
	}

	link, err := s.model.UploadLink(id, time.Duration(expire)*time.Minute)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if link == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, link)
}

func (s *SoftwareImagesController) DownloadLink(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	expire := DefaultUploadLinkExpire
	expireStr := r.URL.Query().Get("expire")

	// Validate input
	if !govalidator.IsNull(expireStr) {
		if !s.validExpire(expireStr) {
			s.views.RenderError(w, ErrInvalidExpireParam, http.StatusBadRequest)
			return
		}

		var err error
		expire, err = strconv.Atoi(expireStr)
		if err != nil {
			s.views.RenderError(w, err, http.StatusInternalServerError)
			return
		}
	}

	link, err := s.model.DownloadLink(id, time.Duration(expire)*time.Minute)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if link == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, link)
}

func (s *SoftwareImagesController) validExpire(expire string) bool {

	if govalidator.IsNull(expire) {
		return false
	}

	if !govalidator.IsInt(expire) {
		return false
	}

	number, err := strconv.ParseFloat(expire, 64)
	if err != nil {
		return false
	}

	if !govalidator.InRange(number, 0, MaxLinkExpire) {
		return false
	}

	return true
}

func (s *SoftwareImagesController) DeleteImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	if err := s.model.DeleteImage(id); err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessDelete(w)
}

func (s *SoftwareImagesController) EditImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	var constructor *SoftwareImageConstructor

	if err := r.DecodeJsonPayload(&constructor); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	if err := constructor.Validate(); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	found, err := s.model.EditImage(id, constructor)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if !found {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessPut(w)
}

func (s *SoftwareImagesController) NewImage(w rest.ResponseWriter, r *rest.Request) {

	var constructor *SoftwareImageConstructor

	if err := r.DecodeJsonPayload(&constructor); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	if err := constructor.Validate(); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	id, err := s.model.CreateImage(constructor)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessPost(w, r, id)
}
<commit_msg>Tidy-up expire time parameter in images.SoftwareImagesController<commit_after>// Copyright 2016 Mender Software AS
//
//    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 images

import (
	"net/http"
	"strconv"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	"github.com/asaskevich/govalidator"
	"github.com/mendersoftware/artifacts/mvc"
	"github.com/pkg/errors"
)

// API input validation constants
const (
	DefaultDownloadLinkExpire = 60
	DefaultUploadLinkExpire   = 60

	// AWS limitation is 1 week
	MaxLinkExpire = 60 * 7 * 24
)

var (
	ErrIDNotUUIDv4        = errors.New("ID is not UUIDv4")
	ErrInvalidExpireParam = errors.New("Invalid expire parameter")
)

type ImagesModeler interface {
	ListImages(filters map[string]string) ([]*SoftwareImage, error)
	UploadLink(imageID string, expire time.Duration) (*Link, error)
	DownloadLink(imageID string, expire time.Duration) (*Link, error)
	GetImage(id string) (*SoftwareImage, error)
	DeleteImage(imageID string) error
	CreateImage(constructorData *SoftwareImageConstructor) (string, error)
	EditImage(id string, constructorData *SoftwareImageConstructor) (bool, error)
}

type SoftwareImagesController struct {
	views mvc.RESTViewDefaults
	model ImagesModeler
}

func NewSoftwareImagesController(model ImagesModeler, views mvc.RESTViewDefaults) *SoftwareImagesController {
	return &SoftwareImagesController{
		model: model,
		views: views,
	}
}

func (s *SoftwareImagesController) GetImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	image, err := s.model.GetImage(id)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if image == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, image)
}

func (s *SoftwareImagesController) ListImages(w rest.ResponseWriter, r *rest.Request) {

	list, err := s.model.ListImages(r.PathParams)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessGet(w, list)
}

func (s *SoftwareImagesController) UploadLink(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	expire, err := s.getLinkExpireParam(r, DefaultDownloadLinkExpire)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	link, err := s.model.UploadLink(id, expire)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if link == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, link)
}

func (s *SoftwareImagesController) DownloadLink(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	expire, err := s.getLinkExpireParam(r, DefaultUploadLinkExpire)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	link, err := s.model.DownloadLink(id, expire)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if link == nil {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessGet(w, link)
}

func (s *SoftwareImagesController) getLinkExpireParam(r *rest.Request, defaultValue uint64) (time.Duration, error) {

	expire := defaultValue
	expireStr := r.URL.Query().Get("expire")

	// Validate input
	if !govalidator.IsNull(expireStr) {
		if !s.validExpire(expireStr) {
			return 0, ErrInvalidExpireParam
		}

		var err error
		expire, err = strconv.ParseUint(expireStr, 10, 64)
		if err != nil {
			return 0, err
		}
	}

	return time.Duration(int64(expire)) * time.Minute, nil
}

func (s *SoftwareImagesController) validExpire(expire string) bool {

	if govalidator.IsNull(expire) {
		return false
	}

	number, err := strconv.ParseUint(expire, 10, 64)
	if err != nil {
		return false
	}

	if number > MaxLinkExpire {
		return false
	}

	return true
}

func (s *SoftwareImagesController) DeleteImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	if err := s.model.DeleteImage(id); err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessDelete(w)
}

func (s *SoftwareImagesController) EditImage(w rest.ResponseWriter, r *rest.Request) {

	id := r.PathParam("id")

	if !govalidator.IsUUIDv4(id) {
		s.views.RenderError(w, ErrIDNotUUIDv4, http.StatusBadRequest)
		return
	}

	var constructor *SoftwareImageConstructor

	if err := r.DecodeJsonPayload(&constructor); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	if err := constructor.Validate(); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	found, err := s.model.EditImage(id, constructor)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	if !found {
		s.views.RenderErrorNotFound(w)
		return
	}

	s.views.RenderSuccessPut(w)
}

func (s *SoftwareImagesController) NewImage(w rest.ResponseWriter, r *rest.Request) {

	var constructor *SoftwareImageConstructor

	if err := r.DecodeJsonPayload(&constructor); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	if err := constructor.Validate(); err != nil {
		s.views.RenderError(w, err, http.StatusBadRequest)
		return
	}

	id, err := s.model.CreateImage(constructor)
	if err != nil {
		s.views.RenderError(w, err, http.StatusInternalServerError)
		return
	}

	s.views.RenderSuccessPost(w, r, id)
}
<|endoftext|>


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

package net

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"sort"
	"strings"
	"syscall"
	"testing"
	"time"
)

func toErrno(err error) (syscall.Errno, bool) {
	operr, ok := err.(*OpError)
	if !ok {
		return 0, false
	}
	syserr, ok := operr.Err.(*os.SyscallError)
	if !ok {
		return 0, false
	}
	errno, ok := syserr.Err.(syscall.Errno)
	if !ok {
		return 0, false
	}
	return errno, true
}

// TestAcceptIgnoreSomeErrors tests that windows TCPListener.AcceptTCP
// handles broken connections. It verifies that broken connections do
// not affect future connections.
func TestAcceptIgnoreSomeErrors(t *testing.T) {
	recv := func(ln Listener, ignoreSomeReadErrors bool) (string, error) {
		c, err := ln.Accept()
		if err != nil {
			// Display windows errno in error message.
			errno, ok := toErrno(err)
			if !ok {
				return "", err
			}
			return "", fmt.Errorf("%v (windows errno=%d)", err, errno)
		}
		defer c.Close()

		b := make([]byte, 100)
		n, err := c.Read(b)
		if err == nil || err == io.EOF {
			return string(b[:n]), nil
		}
		errno, ok := toErrno(err)
		if ok && ignoreSomeReadErrors && (errno == syscall.ERROR_NETNAME_DELETED || errno == syscall.WSAECONNRESET) {
			return "", nil
		}
		return "", err
	}

	send := func(addr string, data string) error {
		c, err := Dial("tcp", addr)
		if err != nil {
			return err
		}
		defer c.Close()

		b := []byte(data)
		n, err := c.Write(b)
		if err != nil {
			return err
		}
		if n != len(b) {
			return fmt.Errorf(`Only %d chars of string "%s" sent`, n, data)
		}
		return nil
	}

	if envaddr := os.Getenv("GOTEST_DIAL_ADDR"); envaddr != "" {
		// In child process.
		c, err := Dial("tcp", envaddr)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("sleeping\n")
		time.Sleep(time.Minute) // process will be killed here
		c.Close()
	}

	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()

	// Start child process that connects to our listener.
	cmd := exec.Command(os.Args[0], "-test.run=TestAcceptIgnoreSomeErrors")
	cmd.Env = append(os.Environ(), "GOTEST_DIAL_ADDR="+ln.Addr().String())
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		t.Fatalf("cmd.StdoutPipe failed: %v", err)
	}
	err = cmd.Start()
	if err != nil {
		t.Fatalf("cmd.Start failed: %v\n", err)
	}
	outReader := bufio.NewReader(stdout)
	for {
		s, err := outReader.ReadString('\n')
		if err != nil {
			t.Fatalf("reading stdout failed: %v", err)
		}
		if s == "sleeping\n" {
			break
		}
	}
	defer cmd.Wait() // ignore error - we know it is getting killed

	const alittle = 100 * time.Millisecond
	time.Sleep(alittle)
	cmd.Process.Kill() // the only way to trigger the errors
	time.Sleep(alittle)

	// Send second connection data (with delay in a separate goroutine).
	result := make(chan error)
	go func() {
		time.Sleep(alittle)
		err := send(ln.Addr().String(), "abc")
		if err != nil {
			result <- err
		}
		result <- nil
	}()
	defer func() {
		err := <-result
		if err != nil {
			t.Fatalf("send failed: %v", err)
		}
	}()

	// Receive first or second connection.
	s, err := recv(ln, true)
	if err != nil {
		t.Fatalf("recv failed: %v", err)
	}
	switch s {
	case "":
		// First connection data is received, let's get second connection data.
	case "abc":
		// First connection is lost forever, but that is ok.
		return
	default:
		t.Fatalf(`"%s" received from recv, but "" or "abc" expected`, s)
	}

	// Get second connection data.
	s, err = recv(ln, false)
	if err != nil {
		t.Fatalf("recv failed: %v", err)
	}
	if s != "abc" {
		t.Fatalf(`"%s" received from recv, but "abc" expected`, s)
	}
}

func isWindowsXP(t *testing.T) bool {
	v, err := syscall.GetVersion()
	if err != nil {
		t.Fatalf("GetVersion failed: %v", err)
	}
	major := byte(v)
	return major < 6
}

func listInterfacesWithNetsh() ([]string, error) {
	removeUTF8BOM := func(b []byte) []byte {
		if len(b) >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF {
			return b[3:]
		}
		return b
	}
	f, err := ioutil.TempFile("", "netsh")
	if err != nil {
		return nil, err
	}
	f.Close()
	defer os.Remove(f.Name())
	cmd := fmt.Sprintf(`netsh interface ip show config | Out-File "%s" -encoding UTF8`, f.Name())
	out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
	if err != nil {
		if len(out) != 0 {
			return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
		}
		var err2 error
		out, err2 = ioutil.ReadFile(f.Name())
		if err2 != nil {
			return nil, err2
		}
		if len(out) != 0 {
			return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
		}
		return nil, fmt.Errorf("netsh failed: %v", err)
	}
	out, err = ioutil.ReadFile(f.Name())
	if err != nil {
		return nil, err
	}
	out = removeUTF8BOM(out)
	lines := bytes.Split(out, []byte{'\r', '\n'})
	names := make([]string, 0)
	for _, line := range lines {
		f := bytes.Split(line, []byte{'"'})
		if len(f) == 3 {
			names = append(names, string(f[1]))
		}
	}
	return names, nil
}

func TestInterfaceList(t *testing.T) {
	if isWindowsXP(t) {
		t.Skip("Windows XP netsh command does not provide required functionality")
	}
	ift, err := Interfaces()
	if err != nil {
		t.Fatal(err)
	}
	have := make([]string, 0)
	for _, ifi := range ift {
		have = append(have, ifi.Name)
	}
	sort.Strings(have)

	want, err := listInterfacesWithNetsh()
	if err != nil {
		t.Fatal(err)
	}
	sort.Strings(want)

	if strings.Join(want, "/") != strings.Join(have, "/") {
		t.Fatalf("unexpected interface list %q, want %q", have, want)
	}
}
<commit_msg>net: add TestInterfaceAddrsWithNetsh<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"sort"
	"strings"
	"syscall"
	"testing"
	"time"
)

func toErrno(err error) (syscall.Errno, bool) {
	operr, ok := err.(*OpError)
	if !ok {
		return 0, false
	}
	syserr, ok := operr.Err.(*os.SyscallError)
	if !ok {
		return 0, false
	}
	errno, ok := syserr.Err.(syscall.Errno)
	if !ok {
		return 0, false
	}
	return errno, true
}

// TestAcceptIgnoreSomeErrors tests that windows TCPListener.AcceptTCP
// handles broken connections. It verifies that broken connections do
// not affect future connections.
func TestAcceptIgnoreSomeErrors(t *testing.T) {
	recv := func(ln Listener, ignoreSomeReadErrors bool) (string, error) {
		c, err := ln.Accept()
		if err != nil {
			// Display windows errno in error message.
			errno, ok := toErrno(err)
			if !ok {
				return "", err
			}
			return "", fmt.Errorf("%v (windows errno=%d)", err, errno)
		}
		defer c.Close()

		b := make([]byte, 100)
		n, err := c.Read(b)
		if err == nil || err == io.EOF {
			return string(b[:n]), nil
		}
		errno, ok := toErrno(err)
		if ok && ignoreSomeReadErrors && (errno == syscall.ERROR_NETNAME_DELETED || errno == syscall.WSAECONNRESET) {
			return "", nil
		}
		return "", err
	}

	send := func(addr string, data string) error {
		c, err := Dial("tcp", addr)
		if err != nil {
			return err
		}
		defer c.Close()

		b := []byte(data)
		n, err := c.Write(b)
		if err != nil {
			return err
		}
		if n != len(b) {
			return fmt.Errorf(`Only %d chars of string "%s" sent`, n, data)
		}
		return nil
	}

	if envaddr := os.Getenv("GOTEST_DIAL_ADDR"); envaddr != "" {
		// In child process.
		c, err := Dial("tcp", envaddr)
		if err != nil {
			t.Fatal(err)
		}
		fmt.Printf("sleeping\n")
		time.Sleep(time.Minute) // process will be killed here
		c.Close()
	}

	ln, err := Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()

	// Start child process that connects to our listener.
	cmd := exec.Command(os.Args[0], "-test.run=TestAcceptIgnoreSomeErrors")
	cmd.Env = append(os.Environ(), "GOTEST_DIAL_ADDR="+ln.Addr().String())
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		t.Fatalf("cmd.StdoutPipe failed: %v", err)
	}
	err = cmd.Start()
	if err != nil {
		t.Fatalf("cmd.Start failed: %v\n", err)
	}
	outReader := bufio.NewReader(stdout)
	for {
		s, err := outReader.ReadString('\n')
		if err != nil {
			t.Fatalf("reading stdout failed: %v", err)
		}
		if s == "sleeping\n" {
			break
		}
	}
	defer cmd.Wait() // ignore error - we know it is getting killed

	const alittle = 100 * time.Millisecond
	time.Sleep(alittle)
	cmd.Process.Kill() // the only way to trigger the errors
	time.Sleep(alittle)

	// Send second connection data (with delay in a separate goroutine).
	result := make(chan error)
	go func() {
		time.Sleep(alittle)
		err := send(ln.Addr().String(), "abc")
		if err != nil {
			result <- err
		}
		result <- nil
	}()
	defer func() {
		err := <-result
		if err != nil {
			t.Fatalf("send failed: %v", err)
		}
	}()

	// Receive first or second connection.
	s, err := recv(ln, true)
	if err != nil {
		t.Fatalf("recv failed: %v", err)
	}
	switch s {
	case "":
		// First connection data is received, let's get second connection data.
	case "abc":
		// First connection is lost forever, but that is ok.
		return
	default:
		t.Fatalf(`"%s" received from recv, but "" or "abc" expected`, s)
	}

	// Get second connection data.
	s, err = recv(ln, false)
	if err != nil {
		t.Fatalf("recv failed: %v", err)
	}
	if s != "abc" {
		t.Fatalf(`"%s" received from recv, but "abc" expected`, s)
	}
}

func isWindowsXP(t *testing.T) bool {
	v, err := syscall.GetVersion()
	if err != nil {
		t.Fatalf("GetVersion failed: %v", err)
	}
	major := byte(v)
	return major < 6
}

func runNetsh(args ...string) ([]byte, error) {
	removeUTF8BOM := func(b []byte) []byte {
		if len(b) >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF {
			return b[3:]
		}
		return b
	}
	f, err := ioutil.TempFile("", "netsh")
	if err != nil {
		return nil, err
	}
	f.Close()
	defer os.Remove(f.Name())
	cmd := fmt.Sprintf(`%s | Out-File "%s" -encoding UTF8`, strings.Join(args, " "), f.Name())
	out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
	if err != nil {
		if len(out) != 0 {
			return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
		}
		var err2 error
		out, err2 = ioutil.ReadFile(f.Name())
		if err2 != nil {
			return nil, err2
		}
		if len(out) != 0 {
			return nil, fmt.Errorf("netsh failed: %v: %q", err, string(removeUTF8BOM(out)))
		}
		return nil, fmt.Errorf("netsh failed: %v", err)
	}
	out, err = ioutil.ReadFile(f.Name())
	if err != nil {
		return nil, err
	}
	return removeUTF8BOM(out), nil
}

func netshInterfaceIPShowConfig() ([]string, error) {
	out, err := runNetsh("netsh", "interface", "ip", "show", "config")
	if err != nil {
		return nil, err
	}
	lines := bytes.Split(out, []byte{'\r', '\n'})
	names := make([]string, 0)
	for _, line := range lines {
		f := bytes.Split(line, []byte{'"'})
		if len(f) == 3 {
			names = append(names, string(f[1]))
		}
	}
	return names, nil
}

func TestInterfacesWithNetsh(t *testing.T) {
	if isWindowsXP(t) {
		t.Skip("Windows XP netsh command does not provide required functionality")
	}
	ift, err := Interfaces()
	if err != nil {
		t.Fatal(err)
	}
	have := make([]string, 0)
	for _, ifi := range ift {
		have = append(have, ifi.Name)
	}
	sort.Strings(have)

	want, err := netshInterfaceIPShowConfig()
	if err != nil {
		t.Fatal(err)
	}
	sort.Strings(want)

	if strings.Join(want, "/") != strings.Join(have, "/") {
		t.Fatalf("unexpected interface list %q, want %q", have, want)
	}
}

func netshInterfaceIPv4ShowAddress(name string) ([]string, error) {
	out, err := runNetsh("netsh", "interface", "ipv4", "show", "address", "name=\""+name+"\"")
	if err != nil {
		return nil, err
	}
	// adress information is listed like:
	//    IP Address:                           10.0.0.2
	//    Subnet Prefix:                        10.0.0.0/24 (mask 255.255.255.0)
	//    IP Address:                           10.0.0.3
	//    Subnet Prefix:                        10.0.0.0/24 (mask 255.255.255.0)
	addrs := make([]string, 0)
	var addr, subnetprefix string
	lines := bytes.Split(out, []byte{'\r', '\n'})
	for _, line := range lines {
		if bytes.Contains(line, []byte("Subnet Prefix:")) {
			f := bytes.Split(line, []byte{':'})
			if len(f) == 2 {
				f = bytes.Split(f[1], []byte{'('})
				if len(f) == 2 {
					f = bytes.Split(f[0], []byte{'/'})
					if len(f) == 2 {
						subnetprefix = string(bytes.TrimSpace(f[1]))
						if addr != "" && subnetprefix != "" {
							addrs = append(addrs, addr+"/"+subnetprefix)
						}
					}
				}
			}
		}
		addr = ""
		if bytes.Contains(line, []byte("IP Address:")) {
			f := bytes.Split(line, []byte{':'})
			if len(f) == 2 {
				addr = string(bytes.TrimSpace(f[1]))
			}
		}
	}
	return addrs, nil
}

func netshInterfaceIPv6ShowAddress(name string) ([]string, error) {
	// TODO: need to test ipv6 netmask too, but netsh does not outputs it
	out, err := runNetsh("netsh", "interface", "ipv6", "show", "address", "interface=\""+name+"\"")
	if err != nil {
		return nil, err
	}
	addrs := make([]string, 0)
	lines := bytes.Split(out, []byte{'\r', '\n'})
	for _, line := range lines {
		if !bytes.HasPrefix(line, []byte("Address")) {
			continue
		}
		if !bytes.HasSuffix(line, []byte("Parameters")) {
			continue
		}
		f := bytes.Split(line, []byte{' '})
		if len(f) != 3 {
			continue
		}
		// remove scope ID if present
		f = bytes.Split(f[1], []byte{'%'})
		addrs = append(addrs, string(bytes.TrimSpace(f[0])))
	}
	return addrs, nil
}

func TestInterfaceAddrsWithNetsh(t *testing.T) {
	t.Skip("skipping test; see https://golang.org/issue/12811")
	if isWindowsXP(t) {
		t.Skip("Windows XP netsh command does not provide required functionality")
	}
	ift, err := Interfaces()
	if err != nil {
		t.Fatal(err)
	}
	for _, ifi := range ift {
		have := make([]string, 0)
		addrs, err := ifi.Addrs()
		if err != nil {
			t.Fatal(err)
		}
		for _, addr := range addrs {
			switch addr := addr.(type) {
			case *IPNet:
				if addr.IP.To4() != nil {
					have = append(have, addr.String())
				}
				if addr.IP.To16() != nil && addr.IP.To4() == nil {
					// netsh does not output netmask for ipv6, so ignore ipv6 mask
					have = append(have, addr.IP.String())
				}
			case *IPAddr:
				if addr.IP.To4() != nil {
					have = append(have, addr.String())
				}
				if addr.IP.To16() != nil && addr.IP.To4() == nil {
					// netsh does not output netmask for ipv6, so ignore ipv6 mask
					have = append(have, addr.IP.String())
				}
			}
		}
		sort.Strings(have)

		want, err := netshInterfaceIPv4ShowAddress(ifi.Name)
		if err != nil {
			t.Fatal(err)
		}
		wantIPv6, err := netshInterfaceIPv6ShowAddress(ifi.Name)
		if err != nil {
			t.Fatal(err)
		}
		want = append(want, wantIPv6...)
		sort.Strings(want)

		if strings.Join(want, "/") != strings.Join(have, "/") {
			t.Errorf("%s: unexpected addresses list %q, want %q", ifi.Name, have, want)
		}
	}
}
<|endoftext|>


<commit_before>package daemon

import (
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/container"
	derr "github.com/docker/docker/errors"
)

// ContainerStop looks for the given container and terminates it,
// waiting the given number of seconds before forcefully killing the
// container. If a negative number of seconds is given, ContainerStop
// will wait for a graceful termination. An error is returned if the
// container is not found, is already stopped, or if there is a
// problem stopping the container.
func (daemon *Daemon) ContainerStop(name string, seconds int) error {
	container, err := daemon.GetContainer(name)
	if err != nil {
		return err
	}
	if !container.IsRunning() {
		return derr.ErrorCodeStopped
	}
	if err := daemon.containerStop(container, seconds); err != nil {
		return derr.ErrorCodeCantStop.WithArgs(name, err)
	}
	return nil
}

// containerStop halts a container by sending a stop signal, waiting for the given
// duration in seconds, and then calling SIGKILL and waiting for the
// process to exit. If a negative duration is given, Stop will wait
// for the initial signal forever. If the container is not running Stop returns
// immediately.
func (daemon *Daemon) containerStop(container *container.Container, seconds int) error {
	if !container.IsRunning() {
		return nil
	}

	// 1. Send a SIGTERM
	if err := daemon.killPossiblyDeadProcess(container, container.StopSignal()); err != nil {
		logrus.Infof("Failed to send SIGTERM to the process, force killing")
		if err := daemon.killPossiblyDeadProcess(container, 9); err != nil {
			return err
		}
	}

	// 2. Wait for the process to exit on its own
	if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
		logrus.Infof("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
		// 3. If it doesn't, then send SIGKILL
		if err := daemon.Kill(container); err != nil {
			container.WaitStop(-1 * time.Second)
			logrus.Warn(err) // Don't return error because we only care that container is stopped, not what function stopped it
		}
	}

	daemon.LogContainerEvent(container, "stop")
	return nil
}
<commit_msg>Correct the info message when stop container<commit_after>package daemon

import (
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/container"
	derr "github.com/docker/docker/errors"
)

// ContainerStop looks for the given container and terminates it,
// waiting the given number of seconds before forcefully killing the
// container. If a negative number of seconds is given, ContainerStop
// will wait for a graceful termination. An error is returned if the
// container is not found, is already stopped, or if there is a
// problem stopping the container.
func (daemon *Daemon) ContainerStop(name string, seconds int) error {
	container, err := daemon.GetContainer(name)
	if err != nil {
		return err
	}
	if !container.IsRunning() {
		return derr.ErrorCodeStopped
	}
	if err := daemon.containerStop(container, seconds); err != nil {
		return derr.ErrorCodeCantStop.WithArgs(name, err)
	}
	return nil
}

// containerStop halts a container by sending a stop signal, waiting for the given
// duration in seconds, and then calling SIGKILL and waiting for the
// process to exit. If a negative duration is given, Stop will wait
// for the initial signal forever. If the container is not running Stop returns
// immediately.
func (daemon *Daemon) containerStop(container *container.Container, seconds int) error {
	if !container.IsRunning() {
		return nil
	}

	stopSignal := container.StopSignal()
	// 1. Send a stop signal
	if err := daemon.killPossiblyDeadProcess(container, stopSignal); err != nil {
		logrus.Infof("Failed to send signal %d to the process, force killing", stopSignal)
		if err := daemon.killPossiblyDeadProcess(container, 9); err != nil {
			return err
		}
	}

	// 2. Wait for the process to exit on its own
	if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
		logrus.Infof("Container %v failed to exit within %d seconds of signal %d - using the force", container.ID, seconds, stopSignal)
		// 3. If it doesn't, then send SIGKILL
		if err := daemon.Kill(container); err != nil {
			container.WaitStop(-1 * time.Second)
			logrus.Warn(err) // Don't return error because we only care that container is stopped, not what function stopped it
		}
	}

	daemon.LogContainerEvent(container, "stop")
	return nil
}
<|endoftext|>


<commit_before>package builder

import (
	"github.com/appc/spec/schema/types"
	"github.com/blablacar/cnt/log"
	"github.com/blablacar/cnt/spec"
	"github.com/ghodss/yaml"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const EXEC_FILES = `
execute_files() {
  fdir=$1
  [ -d "$fdir" ] || return 0

  for file in $fdir/*; do
    [ -e "$file" ] && {
     [ -x "$file" ] || /cnt/bin/busybox chmod +x "$file"
    }
    echo -e "\e[1m\e[32mRunning script -> $file\e[0m"
    $file
  done
}`

const BUILD_SCRIPT = `#!/cnt/bin/busybox sh
set -x
set -e
export TARGET=$( dirname $0 )
export ROOTFS=%%ROOTFS%%
export TERM=xterm

` + EXEC_FILES + `

execute_files "$ROOTFS/cnt/runlevels/inherit-build-early"
execute_files "$TARGET/runlevels/build"
`

const BUILD_SCRIPT_LATE = `#!/cnt/bin/busybox sh
set -x
set -e
export TARGET=$( dirname $0 )
export ROOTFS=%%ROOTFS%%
export TERM=xterm

` + EXEC_FILES + `

execute_files "$TARGET/runlevels/build-late"
execute_files "$ROOTFS/cnt/runlevels/inherit-build-late"
`

const PRESTART = `#!/cnt/bin/busybox sh
set -x
set -e

BASEDIR=${0%/*}
CNT_PATH=/cnt

` + EXEC_FILES + `

execute_files ${CNT_PATH}/runlevels/prestart-early

${BASEDIR}/attributes-merger -i ${CNT_PATH}/attributes -e CONFD_OVERRIDE
export CONFD_DATA=$(cat attributes.json)
${BASEDIR}/confd -onetime -config-file=${CNT_PATH}/prestart/confd.toml

execute_files ${CNT_PATH}/runlevels/prestart-late
`

const PATH_MANIFEST = "/manifest"
const PATH_IMAGE_ACI = "/image.aci"
const PATH_ROOTFS = "/rootfs"
const PATH_TARGET = "/target"
const PATH_CNT = "/cnt"
const PATH_CNT_MANIFEST = "/cnt-manifest.yml"
const PATH_RUNLEVELS = "/runlevels"
const PATH_PRESTART_EARLY = "/prestart-early"
const PATH_PRESTART_LATE = "/prestart-late"
const PATH_INHERIT_BUILD_LATE = "/inherit-build-late"
const PATH_INHERIT_BUILD_EARLY = "/inherit-build-early"
const PATH_ATTRIBUTES = "/attributes"
const PATH_FILES = "/files"
const PATH_CONFD = "/confd"
const PATH_BUILD_LATE = "/build-late"
const PATH_BUILD_SETUP = "/build-setup"
const PATH_BUILD = "/build"
const PATH_CONFDOTD = "/conf.d"
const PATH_TEMPLATES = "/templates"

type Img struct {
	path     string
	target   string
	rootfs   string
	PodName  *spec.ACFullname
	manifest spec.AciManifest
	args     BuildArgs
}

func Version(nameAndVersion string) string {
	split := strings.Split(nameAndVersion, ":")
	if len(split) == 1 {
		return ""
	}
	return split[1]
}

func ShortNameId(name types.ACIdentifier) string {
	return strings.Split(string(name), "/")[1]
}

func ShortName(nameAndVersion string) string {
	return strings.Split(Name(nameAndVersion), "/")[1]
}

func Name(nameAndVersion string) string {
	return strings.Split(nameAndVersion, ":")[0]
}

////////////////////////////////////////////

func NewAciWithManifest(path string, args BuildArgs, manifest spec.AciManifest) (*Img, error) {
	log.Get().Debug("New aci", path, args, manifest)
	cnt, err := PrepAci(path, args)
	if err != nil {
		return nil, err
	}
	cnt.manifest = manifest
	return cnt, nil
}

func NewAci(path string, args BuildArgs) (*Img, error) {
	manifest, err := readManifest(path + PATH_CNT_MANIFEST)
	if err != nil {
		log.Get().Debug(path, PATH_CNT_MANIFEST+" does not exists")
		return nil, err
	}
	return NewAciWithManifest(path, args, *manifest)
}

func PrepAci(aciPath string, args BuildArgs) (*Img, error) {
	cnt := new(Img)
	cnt.args = args

	if fullPath, err := filepath.Abs(aciPath); err != nil {
		log.Get().Panic("Cannot get fullpath of project", err)
	} else {
		cnt.path = fullPath
		cnt.target = cnt.path + PATH_TARGET
		if args.TargetPath != "" {
			currentAbsDir, err := filepath.Abs(args.TargetPath + "/" + cnt.manifest.NameAndVersion.ShortName())
			if err != nil {
				log.Get().Panic("invalid target path")
			}
			cnt.target = currentAbsDir
		}
		cnt.rootfs = cnt.target + PATH_ROOTFS
	}
	return cnt, nil
}

//////////////////////////////////////////////////////////////////

func readManifest(manifestPath string) (*spec.AciManifest, error) {
	manifest := spec.AciManifest{Aci: spec.AciDefinition{}}

	source, err := ioutil.ReadFile(manifestPath)
	if err != nil {
		return nil, err
	}
	err = yaml.Unmarshal([]byte(source), &manifest)
	if err != nil {
		log.Get().Panic(err)
	}

	return &manifest, nil
}

func (i *Img) checkBuilt() {
	if _, err := os.Stat(i.target + PATH_IMAGE_ACI); os.IsNotExist(err) {
		if err := i.Build(); err != nil {
			log.Get().Panic("Cannot Install since build failed")
		}
	}
}
<commit_msg>fix 3, }<commit_after>package builder

import (
	"github.com/appc/spec/schema/types"
	"github.com/blablacar/cnt/log"
	"github.com/blablacar/cnt/spec"
	"github.com/ghodss/yaml"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const EXEC_FILES = `
execute_files() {
  fdir=$1
  [ -d "$fdir" ] || return 0

  for file in $fdir/*; do
    [ -e "$file" ] && {
     	[ -x "$file" ] || /cnt/bin/busybox chmod +x "$file"
     	echo -e "\e[1m\e[32mRunning script -> $file\e[0m"
     	$file
    }
  done
}`

const BUILD_SCRIPT = `#!/cnt/bin/busybox sh
set -x
set -e
export TARGET=$( dirname $0 )
export ROOTFS=%%ROOTFS%%
export TERM=xterm

` + EXEC_FILES + `

execute_files "$ROOTFS/cnt/runlevels/inherit-build-early"
execute_files "$TARGET/runlevels/build"
`

const BUILD_SCRIPT_LATE = `#!/cnt/bin/busybox sh
set -x
set -e
export TARGET=$( dirname $0 )
export ROOTFS=%%ROOTFS%%
export TERM=xterm

` + EXEC_FILES + `

execute_files "$TARGET/runlevels/build-late"
execute_files "$ROOTFS/cnt/runlevels/inherit-build-late"
`

const PRESTART = `#!/cnt/bin/busybox sh
set -x
set -e

BASEDIR=${0%/*}
CNT_PATH=/cnt

` + EXEC_FILES + `

execute_files ${CNT_PATH}/runlevels/prestart-early

${BASEDIR}/attributes-merger -i ${CNT_PATH}/attributes -e CONFD_OVERRIDE
export CONFD_DATA=$(cat attributes.json)
${BASEDIR}/confd -onetime -config-file=${CNT_PATH}/prestart/confd.toml

execute_files ${CNT_PATH}/runlevels/prestart-late
`

const PATH_MANIFEST = "/manifest"
const PATH_IMAGE_ACI = "/image.aci"
const PATH_ROOTFS = "/rootfs"
const PATH_TARGET = "/target"
const PATH_CNT = "/cnt"
const PATH_CNT_MANIFEST = "/cnt-manifest.yml"
const PATH_RUNLEVELS = "/runlevels"
const PATH_PRESTART_EARLY = "/prestart-early"
const PATH_PRESTART_LATE = "/prestart-late"
const PATH_INHERIT_BUILD_LATE = "/inherit-build-late"
const PATH_INHERIT_BUILD_EARLY = "/inherit-build-early"
const PATH_ATTRIBUTES = "/attributes"
const PATH_FILES = "/files"
const PATH_CONFD = "/confd"
const PATH_BUILD_LATE = "/build-late"
const PATH_BUILD_SETUP = "/build-setup"
const PATH_BUILD = "/build"
const PATH_CONFDOTD = "/conf.d"
const PATH_TEMPLATES = "/templates"

type Img struct {
	path     string
	target   string
	rootfs   string
	PodName  *spec.ACFullname
	manifest spec.AciManifest
	args     BuildArgs
}

func Version(nameAndVersion string) string {
	split := strings.Split(nameAndVersion, ":")
	if len(split) == 1 {
		return ""
	}
	return split[1]
}

func ShortNameId(name types.ACIdentifier) string {
	return strings.Split(string(name), "/")[1]
}

func ShortName(nameAndVersion string) string {
	return strings.Split(Name(nameAndVersion), "/")[1]
}

func Name(nameAndVersion string) string {
	return strings.Split(nameAndVersion, ":")[0]
}

////////////////////////////////////////////

func NewAciWithManifest(path string, args BuildArgs, manifest spec.AciManifest) (*Img, error) {
	log.Get().Debug("New aci", path, args, manifest)
	cnt, err := PrepAci(path, args)
	if err != nil {
		return nil, err
	}
	cnt.manifest = manifest
	return cnt, nil
}

func NewAci(path string, args BuildArgs) (*Img, error) {
	manifest, err := readManifest(path + PATH_CNT_MANIFEST)
	if err != nil {
		log.Get().Debug(path, PATH_CNT_MANIFEST+" does not exists")
		return nil, err
	}
	return NewAciWithManifest(path, args, *manifest)
}

func PrepAci(aciPath string, args BuildArgs) (*Img, error) {
	cnt := new(Img)
	cnt.args = args

	if fullPath, err := filepath.Abs(aciPath); err != nil {
		log.Get().Panic("Cannot get fullpath of project", err)
	} else {
		cnt.path = fullPath
		cnt.target = cnt.path + PATH_TARGET
		if args.TargetPath != "" {
			currentAbsDir, err := filepath.Abs(args.TargetPath + "/" + cnt.manifest.NameAndVersion.ShortName())
			if err != nil {
				log.Get().Panic("invalid target path")
			}
			cnt.target = currentAbsDir
		}
		cnt.rootfs = cnt.target + PATH_ROOTFS
	}
	return cnt, nil
}

//////////////////////////////////////////////////////////////////

func readManifest(manifestPath string) (*spec.AciManifest, error) {
	manifest := spec.AciManifest{Aci: spec.AciDefinition{}}

	source, err := ioutil.ReadFile(manifestPath)
	if err != nil {
		return nil, err
	}
	err = yaml.Unmarshal([]byte(source), &manifest)
	if err != nil {
		log.Get().Panic(err)
	}

	return &manifest, nil
}

func (i *Img) checkBuilt() {
	if _, err := os.Stat(i.target + PATH_IMAGE_ACI); os.IsNotExist(err) {
		if err := i.Build(); err != nil {
			log.Get().Panic("Cannot Install since build failed")
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>v4.6.5<commit_after><|endoftext|>


<commit_before>package packet

import "errors"

// Length of the Fixed header of the CONNACK Packet.
const lenCONNACKFixedHeader = 2

// Length of the Variable header of the CONNACK Packet.
const lenCONNACKVariableHeader = 2

// First byte of the Fixed header of the CONNACK Packet.
const firstByteCONNACKFixedHeader = 0x20

// Error values
var (
	ErrInvalidCONNACKFixedHeaderLen       = errors.New("the length of the Fixed header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKVariableHeaderLen    = errors.New("the length of the Variable header of the CONNACK Packet is invalid")
	ErrInvalidfirstByteCONNACKFixedHeader = errors.New("the first byte of the Fixed header of the CONNACK Packet is invalid")
)

// CONNACK represents the CONNACK Packet.
type CONNACK struct {
	Base
	// SessionPresentFlag is the Session Present Flag of
	// the Connect Acknowledge Flags.
	SessionPresentFlag bool
	// ConnectReturnCode is the Connect Return Code.
	ConnectReturnCode byte
}

// NewCONNACKFromBytes creates the CONNACK Packet from the byte data and returns it.
func NewCONNACKFromBytes(fixedHeader, variableHeader []byte) (*CONNACK, error) {
	// Check the length of the Fixed header of the CONNACK Packet.
	if len(fixedHeader) != lenCONNACKFixedHeader {
		return nil, ErrInvalidCONNACKFixedHeaderLen
	}

	// Check the length of the Variable header of the CONNACK Packet.
	if len(variableHeader) != lenCONNACKVariableHeader {
		return nil, ErrInvalidCONNACKVariableHeaderLen
	}

	// Check the first byte of the Fixed header of the CONNACK Packet.
	if fixedHeader[0] != firstByteCONNACKFixedHeader {
		return nil, ErrInvalidCONNACKVariableHeaderLen
	}

	// Create a CONNACK Packet.
	p := &CONNACK{}

	// Set the Fixed header to the Packet.
	p.FixedHeader = fixedHeader

	// Set the Variable header to the Packet.
	p.VariableHeader = variableHeader

	// Set the Session Present Flag to the Packet.
	p.SessionPresentFlag = (variableHeader[0] & 1) == 1

	// Set the Connect Return Code to the Packet.
	p.ConnectReturnCode = variableHeader[1]

	return p, nil
}
<commit_msg>Update mqtt/packet/connack.go<commit_after>package packet

import "errors"

// Length of the Fixed header of the CONNACK Packet
const lenCONNACKFixedHeader = 2

// Length of the Variable header of the CONNACK Packet
const lenCONNACKVariableHeader = 2

// First byte of the Fixed header of the CONNACK Packet
const firstByteCONNACKFixedHeader = TypeCONNACK << 4

// Connect Return code values of the CONNACK Packet
const (
	CONNACKConnectionAccepted                           = 0x00
	CONNACKConnectionRefusedUnacceptableProtocolVersion = 0x01
	CONNACKConnectionRefusedIdentifierRejected          = 0x02
	CONNACKConnectionRefusedServerUnavailable           = 0x03
	CONNACKConnectionRefusedBadUserNameOrPassword       = 0x04
	CONNACKConnectionRefusedNotAuthorized               = 0x05
)

// Error values
var (
	ErrInvalidCONNACKFixedHeaderLen          = errors.New("the length of the Fixed header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKVariableHeaderLen       = errors.New("the length of the Variable header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKFixedHeaderFirstByte    = errors.New("the first byte of the Fixed header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKRemainingLength         = errors.New("the Remaining Length of the Fixed header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKConnectAcknowledgeFlags = errors.New("the Connect Acknowledge Flags of the Variable header of the CONNACK Packet is invalid")
	ErrInvalidCONNACKConnectReturnCode       = errors.New("the Connect Return code of the Variable header of the CONNACK Packet is invalid")
)

// Valid Connect Return code values
var validConnectReturnCodes = []byte{
	CONNACKConnectionAccepted,
	CONNACKConnectionRefusedUnacceptableProtocolVersion,
	CONNACKConnectionRefusedIdentifierRejected,
	CONNACKConnectionRefusedServerUnavailable,
	CONNACKConnectionRefusedBadUserNameOrPassword,
	CONNACKConnectionRefusedNotAuthorized,
}

// CONNACK represents the CONNACK Packet.
type CONNACK struct {
	Base
	// SessionPresentFlag is the Session Present Flag of
	// the Connect Acknowledge Flags.
	SessionPresentFlag bool
	// ConnectReturnCode is the Connect Return Code.
	ConnectReturnCode byte
}

// NewCONNACKFromBytes creates the CONNACK Packet from the byte data and returns it.
func NewCONNACKFromBytes(fixedHeader, variableHeader []byte) (*CONNACK, error) {
	// Check the length of the Fixed header.
	if len(fixedHeader) != lenCONNACKFixedHeader {
		return nil, ErrInvalidCONNACKFixedHeaderLen
	}

	// Check the length of the Variable header.
	if len(variableHeader) != lenCONNACKVariableHeader {
		return nil, ErrInvalidCONNACKVariableHeaderLen
	}

	// Check the first byte of the Fixed header.
	if fixedHeader[0] != firstByteCONNACKFixedHeader {
		return nil, ErrInvalidCONNACKFixedHeaderFirstByte
	}

	// Check the Remaining Length of the Fixed header.
	if fixedHeader[1] != lenCONNACKVariableHeader {
		return nil, ErrInvalidCONNACKRemainingLength
	}

	// Check the Connect Acknowledge Flags of the Variable header.
	if variableHeader[0]>>1 != 0x00 {
		return nil, ErrInvalidCONNACKConnectAcknowledgeFlags
	}

	// Check the Connect Return code of the Variable header.
	connectReturnCode := variableHeader[1]

	var validConnectReturnCode bool

	for _, c := range validConnectReturnCodes {
		if connectReturnCode == c {
			validConnectReturnCode = true
			break
		}
	}

	if !validConnectReturnCode {
		return nil, ErrInvalidCONNACKConnectReturnCode
	}

	// Create a CONNACK Packet.
	p := &CONNACK{}

	// Set the Fixed header to the Packet.
	p.FixedHeader = fixedHeader

	// Set the Variable header to the Packet.
	p.VariableHeader = variableHeader

	// Set the Session Present Flag to the Packet.
	p.SessionPresentFlag = (variableHeader[0]<<7 == 0x80)

	// Set the Connect Return Code to the Packet.
	p.ConnectReturnCode = connectReturnCode

	// Return the CONNACK Packet.
	return p, nil
}
<|endoftext|>


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

// guru: a tool for answering questions about Go source code.
//
//    http://golang.org/s/oracle-design
//    http://golang.org/s/oracle-user-manual

package commands

import (
	"encoding/json"
	"fmt"
	"go/build"
	"go/token"
	"strconv"
	"strings"
	"sync"
	"time"

	"nvim-go/config"
	"nvim-go/context"
	"nvim-go/guru"
	"nvim-go/nvim"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/buildutil"
)

func init() {
	plugin.HandleFunction("GoGuru", &plugin.FunctionOptions{Eval: "[expand('%:p:h'), expand('%:p')]"}, funcGuru)
}

type funcGuruEval struct {
	Cwd  string `msgpack:",array"`
	File string
}

func funcGuru(v *vim.Vim, args []string, eval *funcGuruEval) {
	go Guru(v, args, eval)
}

// Guru go source analysis and output result to the quickfix or locationlist.
func Guru(v *vim.Vim, args []string, eval *funcGuruEval) error {
	defer nvim.Profile(time.Now(), "Guru")

	defer context.WithGoBuildForPath(eval.Cwd)()

	var (
		b vim.Buffer
		w vim.Window
	)

	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	dir := strings.Split(eval.Cwd, "src/")
	scopeFlag := dir[len(dir)-1]

	mode := args[0]

	pos, err := nvim.ByteOffset(p)
	if err != nil {
		return nvim.Echomsg(v, err)
	}

	ctxt := &build.Default

	// TODO(zchee): Use p.BufferOption("modified", modified)?
	var modified string
	p.CommandOutput("silent set modified?", &modified)
	// https://github.com/golang/tools/blob/master/cmd/guru/main.go
	if modified == "modified" {
		overlay := make(map[string][]byte)

		var (
			buffer  [][]byte
			bytebuf []byte
			bname   string
		)

		p.BufferName(b, &bname)
		p.BufferLines(b, -1, 0, false, &buffer)
		for _, byt := range buffer {
			bytebuf = append(bytebuf, byt...)
		}

		overlay[bname] = bytebuf
		ctxt = buildutil.OverlayContext(ctxt, overlay)
	}

	var outputMu sync.Mutex
	var loclist []*nvim.ErrorlistData
	output := func(fset *token.FileSet, qr guru.QueryResult) {
		outputMu.Lock()
		defer outputMu.Unlock()
		if loclist, err = parseResult(mode, fset, qr.JSON(fset)); err != nil {
			nvim.Echoerr(v, "GoGuru: %v", err)
		}
	}

	query := guru.Query{
		Output:     output,
		Pos:        eval.File + ":#" + strconv.FormatInt(int64(pos), 10),
		Build:      ctxt,
		Scope:      []string{scopeFlag},
		Reflection: config.GuruReflection,
	}

	if err := guru.Run(mode, &query); err != nil {
		return nvim.Echomsg(v, "GoGuru:", err)
	}

	if err := nvim.SetLoclist(p, loclist); err != nil {
		return nvim.Echomsg(v, "GoGuru:", err)
	}

	// jumpfirst or definition mode
	if config.GuruJumpFirst || mode == "definition" {
		p.Command("silent! ll 1")
		p.FeedKeys("zz", "n", false)
	}

	// not definition mode
	if mode != "definition" {
		return nvim.OpenLoclist(p, w, loclist, config.GuruKeepCursor)
	}

	return nil
}

func parseResult(mode string, fset *token.FileSet, data []byte) ([]*nvim.ErrorlistData, error) {
	var (
		loclist []*nvim.ErrorlistData
		fname   string
		line    int
		col     int
		text    string
	)

	switch mode {

	case "callees":
		var value = serial.Callees{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.Callees {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = value.Desc + ": " + v.Name
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "callers":
		var value = []serial.Caller{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = v.Desc + ": " + v.Caller
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "callstack":
		var value = serial.CallStack{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.Callers {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = v.Desc + " " + value.Target
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "definition":
		var value = serial.Definition{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.ObjPos)
		text = value.Desc
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "describe":
		var value = serial.Describe{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.Value.ObjPos)
		text = value.Desc + " " + value.Value.Type
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "freevars":
		var value = serial.FreeVar{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.Pos)
		text = value.Kind + " " + value.Type + " " + value.Ref
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "implements":
		var value = serial.Implements{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.AssignableFrom {
			fname, line, col := nvim.SplitPos(v.Pos)
			text = v.Kind + " " + v.Name
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "peers":
		var value = serial.Peers{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col := nvim.SplitPos(value.Pos)
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     "Base: selected channel op (<-)",
		})
		for _, v := range value.Allocs {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Allocs: make(chan) ops",
			})
		}
		for _, v := range value.Sends {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Sends: ch<-x ops",
			})
		}
		for _, v := range value.Receives {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Receives: <-ch ops",
			})
		}
		for _, v := range value.Closes {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Closes: close(ch) ops",
			})
		}

	case "pointsto":
		var value = []serial.PointsTo{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value {
			fname, line, col := nvim.SplitPos(v.NamePos)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "type: " + v.Type,
			})
			if len(v.Labels) > -1 {
				for _, vl := range v.Labels {
					fname, line, col := nvim.SplitPos(vl.Pos)
					loclist = append(loclist, &nvim.ErrorlistData{
						FileName: fname,
						LNum:     line,
						Col:      col,
						Text:     vl.Desc,
					})
				}
			}
		}

	case "referrers":
		var packages = serial.ReferrersPackage{}
		if err := json.Unmarshal(data, &packages); err != nil {
			return loclist, err
		}
		for _, v := range packages.Refs {
			fname, line, col := nvim.SplitPos(v.Pos)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     v.Text,
			})
		}

	case "whicherrs":
		var value = serial.WhichErrs{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col := nvim.SplitPos(value.ErrPos)
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     "Errror Position",
		})
		for _, vg := range value.Globals {
			fname, line, col := nvim.SplitPos(vg)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Globals",
			})
		}
		for _, vc := range value.Constants {
			fname, line, col := nvim.SplitPos(vc)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Constants",
			})
		}
		for _, vt := range value.Types {
			fname, line, col := nvim.SplitPos(vt.Position)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Types: " + vt.Type,
			})
		}

	}

	if len(loclist) == 0 {
		return loclist, fmt.Errorf("%s not fount", mode)
	}
	return loclist, nil
}
<commit_msg>Add p.Wait() for modified check<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// guru: a tool for answering questions about Go source code.
//
//    http://golang.org/s/oracle-design
//    http://golang.org/s/oracle-user-manual

package commands

import (
	"encoding/json"
	"fmt"
	"go/build"
	"go/token"
	"strconv"
	"strings"
	"sync"
	"time"

	"nvim-go/config"
	"nvim-go/context"
	"nvim-go/guru"
	"nvim-go/nvim"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/buildutil"
)

func init() {
	plugin.HandleFunction("GoGuru", &plugin.FunctionOptions{Eval: "[expand('%:p:h'), expand('%:p')]"}, funcGuru)
}

type funcGuruEval struct {
	Cwd  string `msgpack:",array"`
	File string
}

func funcGuru(v *vim.Vim, args []string, eval *funcGuruEval) {
	go Guru(v, args, eval)
}

// Guru go source analysis and output result to the quickfix or locationlist.
func Guru(v *vim.Vim, args []string, eval *funcGuruEval) error {
	defer nvim.Profile(time.Now(), "Guru")
	defer context.WithGoBuildForPath(eval.Cwd)()

	var (
		b vim.Buffer
		w vim.Window
	)

	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	dir := strings.Split(eval.Cwd, "src/")
	scopeFlag := dir[len(dir)-1]

	mode := args[0]

	pos, err := nvim.ByteOffset(p)
	if err != nil {
		return nvim.Echomsg(v, err)
	}

	ctxt := &build.Default

	// TODO(zchee): Use p.BufferOption("modified", modified)?
	var modified string
	p.CommandOutput("silent set modified?", &modified)
	if err := p.Wait(); err != nil {
		return err
	}
	// https://github.com/golang/tools/blob/master/cmd/guru/main.go
	if modified == "modified" {
		overlay := make(map[string][]byte)

		var (
			buffer  [][]byte
			bytebuf []byte
			bname   string
		)

		p.BufferName(b, &bname)
		p.BufferLines(b, -1, 0, false, &buffer)
		for _, byt := range buffer {
			bytebuf = append(bytebuf, byt...)
		}

		overlay[bname] = bytebuf
		ctxt = buildutil.OverlayContext(ctxt, overlay)
	}

	var outputMu sync.Mutex
	var loclist []*nvim.ErrorlistData
	output := func(fset *token.FileSet, qr guru.QueryResult) {
		outputMu.Lock()
		defer outputMu.Unlock()
		if loclist, err = parseResult(mode, fset, qr.JSON(fset)); err != nil {
			nvim.Echoerr(v, "GoGuru: %v", err)
		}
	}

	query := guru.Query{
		Output:     output,
		Pos:        eval.File + ":#" + strconv.FormatInt(int64(pos), 10),
		Build:      ctxt,
		Scope:      []string{scopeFlag},
		Reflection: config.GuruReflection,
	}

	if err := guru.Run(mode, &query); err != nil {
		return nvim.Echomsg(v, "GoGuru:", err)
	}

	if err := nvim.SetLoclist(p, loclist); err != nil {
		return nvim.Echomsg(v, "GoGuru:", err)
	}

	// jumpfirst or definition mode
	if config.GuruJumpFirst || mode == "definition" {
		p.Command("silent! ll 1")
		p.FeedKeys("zz", "n", false)
	}

	// not definition mode
	if mode != "definition" {
		return nvim.OpenLoclist(p, w, loclist, config.GuruKeepCursor)
	}

	return nil
}

func parseResult(mode string, fset *token.FileSet, data []byte) ([]*nvim.ErrorlistData, error) {
	var (
		loclist []*nvim.ErrorlistData
		fname   string
		line    int
		col     int
		text    string
	)

	switch mode {

	case "callees":
		var value = serial.Callees{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.Callees {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = value.Desc + ": " + v.Name
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "callers":
		var value = []serial.Caller{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = v.Desc + ": " + v.Caller
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "callstack":
		var value = serial.CallStack{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.Callers {
			fname, line, col = nvim.SplitPos(v.Pos)
			text = v.Desc + " " + value.Target
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "definition":
		var value = serial.Definition{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.ObjPos)
		text = value.Desc
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "describe":
		var value = serial.Describe{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.Value.ObjPos)
		text = value.Desc + " " + value.Value.Type
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "freevars":
		var value = serial.FreeVar{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col = nvim.SplitPos(value.Pos)
		text = value.Kind + " " + value.Type + " " + value.Ref
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     text,
		})

	case "implements":
		var value = serial.Implements{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value.AssignableFrom {
			fname, line, col := nvim.SplitPos(v.Pos)
			text = v.Kind + " " + v.Name
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     text,
			})
		}

	case "peers":
		var value = serial.Peers{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col := nvim.SplitPos(value.Pos)
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     "Base: selected channel op (<-)",
		})
		for _, v := range value.Allocs {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Allocs: make(chan) ops",
			})
		}
		for _, v := range value.Sends {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Sends: ch<-x ops",
			})
		}
		for _, v := range value.Receives {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Receives: <-ch ops",
			})
		}
		for _, v := range value.Closes {
			fname, line, col := nvim.SplitPos(v)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Closes: close(ch) ops",
			})
		}

	case "pointsto":
		var value = []serial.PointsTo{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		for _, v := range value {
			fname, line, col := nvim.SplitPos(v.NamePos)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "type: " + v.Type,
			})
			if len(v.Labels) > -1 {
				for _, vl := range v.Labels {
					fname, line, col := nvim.SplitPos(vl.Pos)
					loclist = append(loclist, &nvim.ErrorlistData{
						FileName: fname,
						LNum:     line,
						Col:      col,
						Text:     vl.Desc,
					})
				}
			}
		}

	case "referrers":
		var packages = serial.ReferrersPackage{}
		if err := json.Unmarshal(data, &packages); err != nil {
			return loclist, err
		}
		for _, v := range packages.Refs {
			fname, line, col := nvim.SplitPos(v.Pos)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     v.Text,
			})
		}

	case "whicherrs":
		var value = serial.WhichErrs{}
		err := json.Unmarshal(data, &value)
		if err != nil {
			return loclist, err
		}
		fname, line, col := nvim.SplitPos(value.ErrPos)
		loclist = append(loclist, &nvim.ErrorlistData{
			FileName: fname,
			LNum:     line,
			Col:      col,
			Text:     "Errror Position",
		})
		for _, vg := range value.Globals {
			fname, line, col := nvim.SplitPos(vg)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Globals",
			})
		}
		for _, vc := range value.Constants {
			fname, line, col := nvim.SplitPos(vc)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Constants",
			})
		}
		for _, vt := range value.Types {
			fname, line, col := nvim.SplitPos(vt.Position)
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: fname,
				LNum:     line,
				Col:      col,
				Text:     "Types: " + vt.Type,
			})
		}

	}

	if len(loclist) == 0 {
		return loclist, fmt.Errorf("%s not fount", mode)
	}
	return loclist, nil
}
<|endoftext|>


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

package commands

import (
	"bytes"
	"fmt"
	"go/build"
	"runtime"
	"strconv"
	"time"

	"nvim-go/gb"
	"nvim-go/nvim"

	log "github.com/Sirupsen/logrus"
	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/rogpeppe/godef/go/ast"
	"github.com/rogpeppe/godef/go/parser"
	"github.com/rogpeppe/godef/go/printer"
	"github.com/rogpeppe/godef/go/token"
	"github.com/rogpeppe/godef/go/types"
)

var (
	b vim.Buffer
)

func init() {
	plugin.HandleCommand("Godef", &plugin.CommandOptions{NArgs: "?", Eval: "expand('%:p:h')"}, Def)
	// plugin.HandleAutocmd("CursorMoved", &plugin.AutocmdOptions{Pattern: "*.go"}, onCursorMoved)
}

func onCursorMoved(v *vim.Vim) error {
	time.AfterFunc(4*time.Second, func() {
		v.Command("Godef info")
	})
	return nil
}

func Def(v *vim.Vim, args []string, file string) error {
	defer gb.WithGoBuildForPath(file)()

	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	if err := p.Wait(); err != nil {
		return err
	}

	buf, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}
	src := bytes.Join(buf, []byte{'\n'})

	filename, err := v.BufferName(b)
	if err != nil {
		return v.WriteErr("cannot get current buffer name")
	}

	searchpos, err := nvim.ByteOffset(v)
	if err != nil {
		return v.WriteErr("cannot get current buffer byte offset")
	}

	pkgScope := ast.NewScope(parser.Universe)
	f, err := parser.ParseFile(types.FileSet, filename, src, 0, pkgScope)
	if f == nil {
		nvim.Echomsg(v, "Godef: cannot parse %s: %v", filename, err)
	}

	o := findIdentifier(v, f, searchpos)

	switch e := o.(type) {
	case *ast.ImportSpec:
		path := importPath(v, e)
		pkg, err := build.Default.Import(path, "", build.FindOnly)
		if err != nil {
			nvim.Echomsg(v, "Godef: error finding import path for %s: %s", path, err)
		}
		fmt.Println(pkg.Dir)
	case ast.Expr:
		obj, _ := types.ExprType(e, types.DefaultImporter)
		if obj != nil {
			out := types.FileSet.Position(types.DeclPos(obj))
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.String():", out.String())
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.Filename:", out.Filename)
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.Line:", out.Line)
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.Column:", out.Column)
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.Offset:", out.Offset)
			log.WithFields(log.Fields{"cmd": "Godef"}).Debugln("out.IsValid():", out.IsValid())

			v.Command("silent lexpr '" + fmt.Sprintf("%v", out) + "'")
			// v.Command("silent lgetexpr '" + fmt.Sprintf("%v", out) + "'")
			// v.Command("sil ll 1")
			w, err := v.CurrentWindow()
			if err != nil {
				log.Debugln(err)
			}
			v.SetWindowCursor(w, [2]int{out.Line, out.Column - 1})
			v.Feedkeys("zz", "normal", false)
		} else {
			nvim.Echomsg(v, "Godef: not found of obj")
		}
	default:
		nvim.Echomsg(v, "Godef: no declaration found for %v", pretty{e})
	}
	return nil
}

func typeStrMap(obj *ast.Object, typ types.Type) map[string]string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		dict := map[string]string{
			"Object.Kind":   obj.Kind.String(),
			"Object.Name":   obj.Name,
			"Type.Kind":     typ.Kind.String(),
			"Type.Pkg":      typ.Pkg,
			"Type.String()": typ.String(),
			// "Object.Decl": obj.Decl,
			// "Object.Data":   obj.Data,
			// "Object.Type":   obj.Type,
			// "Object.Pos()":  obj.Pos(),
			// "Type.Node":     typ.Node,
		}
		return dict
		// 	return fmt.Sprintf("%s %v", typ.obj.Name, prettyType{typ})
		// case ast.Pkg:
		// 	return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
		// case ast.Con:
		// 	if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
		// 		return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		// 	}
		// 	return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
		// case ast.Lbl:
		// 	return fmt.Sprintf("label %s", obj.Name)
		// case ast.Typ:
		// 	typ = typ.Underlying(false, types.DefaultImporter)
		// 	return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
		// }
		// return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
	}
	return map[string]string{}
}

func typeStr(obj *ast.Object, typ types.Type) string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		return fmt.Sprintf("%s %v", obj.Name, prettyType{typ})
	case ast.Pkg:
		return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
	case ast.Con:
		if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
			return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		}
		return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
	case ast.Lbl:
		return fmt.Sprintf("label %s", obj.Name)
	case ast.Typ:
		typ = typ.Underlying(false, types.DefaultImporter)
		return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
	}
	return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
}

type orderedObjects []*ast.Object

func (o orderedObjects) Less(i, j int) bool { return o[i].Name < o[j].Name }
func (o orderedObjects) Len() int           { return len(o) }
func (o orderedObjects) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }

func importPath(v *vim.Vim, n *ast.ImportSpec) string {
	p, err := strconv.Unquote(n.Path.Value)
	if err != nil {
		nvim.Echomsg(v, "Godef: invalid string literal %q in ast.ImportSpec", n.Path.Value)
	}
	return p
}

// findIdentifier looks for an identifier at byte-offset searchpos
// inside the parsed source represented by node.
// If it is part of a selector expression, it returns
// that expression rather than the identifier itself.
//
// As a special case, if it finds an import spec, it returns ImportSpec.
func findIdentifier(v *vim.Vim, f *ast.File, searchpos int) ast.Node {
	ec := make(chan ast.Node)
	found := func(startPos, endPos token.Pos) bool {
		start := types.FileSet.Position(startPos).Offset
		end := start + int(endPos-startPos)
		return start <= searchpos && searchpos <= end
	}
	go func() {
		var visit func(ast.Node) bool
		visit = func(n ast.Node) bool {
			var startPos token.Pos
			switch n := n.(type) {
			default:
				return true
			case *ast.Ident:
				startPos = n.NamePos
			case *ast.SelectorExpr:
				startPos = n.Sel.NamePos
			case *ast.ImportSpec:
				startPos = n.Pos()
			case *ast.StructType:
				// If we find an anonymous bare field in a
				// struct type, its definition points to itself,
				// but we actually want to go elsewhere,
				// so assume (dubiously) that the expression
				// works globally and return a new node for it.
				for _, field := range n.Fields.List {
					if field.Names != nil {
						continue
					}
					t := field.Type
					if pt, ok := field.Type.(*ast.StarExpr); ok {
						t = pt.X
					}
					if id, ok := t.(*ast.Ident); ok {
						if found(id.NamePos, id.End()) {
							ec <- parseExpr(v, f.Scope, id.Name)
							runtime.Goexit()
						}
					}
				}
				return true
			}
			if found(startPos, n.End()) {
				ec <- n
				runtime.Goexit()
			}
			return true
		}
		ast.Walk(FVisitor(visit), f)
		ec <- nil
	}()
	ev := <-ec
	if ev == nil {
		nvim.Echomsg(v, "Godef: no identifier found")
	}
	return ev
}

func parseExpr(v *vim.Vim, s *ast.Scope, expr string) ast.Expr {
	n, err := parser.ParseExpr(types.FileSet, "<arg>", expr, s)
	if err != nil {
		nvim.Echomsg(v, "Godef: cannot parse expression: %v", err)
	}
	switch n := n.(type) {
	case *ast.Ident, *ast.SelectorExpr:
		return n
	}
	nvim.Echomsg(v, "Godef: no identifier found in expression")
	return nil
}

type FVisitor func(n ast.Node) bool

func (f FVisitor) Visit(n ast.Node) ast.Visitor {
	if f(n) {
		return f
	}
	return nil
}

// pkgName returns the package name implemented by the go source filename
func pkgName(filename string) string {
	prog, _ := parser.ParseFile(types.FileSet, filename, nil, parser.PackageClauseOnly, nil)
	if prog != nil {
		return prog.Name.Name
	}
	return ""
}

func hasSuffix(s, suff string) bool {
	return len(s) >= len(suff) && s[len(s)-len(suff):] == suff
}

type pretty struct {
	n interface{}
}

func (p pretty) String() string {
	var b bytes.Buffer
	printer.Fprint(&b, types.FileSet, p.n)
	return b.String()
}

type prettyType struct {
	n types.Type
}

func (p prettyType) String() string {
	// TODO print path package when appropriate.
	// Current issues with using p.n.Pkg:
	//	- we should actually print the local package identifier
	//	rather than the package path when possible.
	//	- p.n.Pkg is non-empty even when
	//	the type is not relative to the package.
	return pretty{p.n.Node}.String()
}
<commit_msg>Remove Debug log<commit_after>// Copyright 2016 Koichi Shiraishi. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"bytes"
	"fmt"
	"go/build"
	"runtime"
	"strconv"
	"time"

	"nvim-go/gb"
	"nvim-go/nvim"

	log "github.com/Sirupsen/logrus"
	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"github.com/rogpeppe/godef/go/ast"
	"github.com/rogpeppe/godef/go/parser"
	"github.com/rogpeppe/godef/go/printer"
	"github.com/rogpeppe/godef/go/token"
	"github.com/rogpeppe/godef/go/types"
)

var (
	b vim.Buffer
)

func init() {
	plugin.HandleCommand("Godef", &plugin.CommandOptions{NArgs: "?", Eval: "expand('%:p:h')"}, Def)
	// plugin.HandleAutocmd("CursorMoved", &plugin.AutocmdOptions{Pattern: "*.go"}, onCursorMoved)
}

func onCursorMoved(v *vim.Vim) error {
	time.AfterFunc(4*time.Second, func() {
		v.Command("Godef info")
	})
	return nil
}

func Def(v *vim.Vim, args []string, file string) error {
	defer gb.WithGoBuildForPath(file)()

	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	if err := p.Wait(); err != nil {
		return err
	}

	buf, err := v.BufferLineSlice(b, 0, -1, true, true)
	if err != nil {
		return err
	}
	src := bytes.Join(buf, []byte{'\n'})

	filename, err := v.BufferName(b)
	if err != nil {
		return v.WriteErr("cannot get current buffer name")
	}

	searchpos, err := nvim.ByteOffset(v)
	if err != nil {
		return v.WriteErr("cannot get current buffer byte offset")
	}

	pkgScope := ast.NewScope(parser.Universe)
	f, err := parser.ParseFile(types.FileSet, filename, src, 0, pkgScope)
	if f == nil {
		nvim.Echomsg(v, "Godef: cannot parse %s: %v", filename, err)
	}

	o := findIdentifier(v, f, searchpos)

	switch e := o.(type) {
	case *ast.ImportSpec:
		path := importPath(v, e)
		pkg, err := build.Default.Import(path, "", build.FindOnly)
		if err != nil {
			nvim.Echomsg(v, "Godef: error finding import path for %s: %s", path, err)
		}
		fmt.Println(pkg.Dir)
	case ast.Expr:
		obj, _ := types.ExprType(e, types.DefaultImporter)
		if obj != nil {
			out := types.FileSet.Position(types.DeclPos(obj))

			v.Command("silent lexpr '" + fmt.Sprintf("%v", out) + "'")
			// v.Command("silent lgetexpr '" + fmt.Sprintf("%v", out) + "'")
			// v.Command("sil ll 1")
			w, err := v.CurrentWindow()
			if err != nil {
				log.Debugln(err)
			}
			v.SetWindowCursor(w, [2]int{out.Line, out.Column - 1})
			v.Feedkeys("zz", "normal", false)
		} else {
			nvim.Echomsg(v, "Godef: not found of obj")
		}
	default:
		nvim.Echomsg(v, "Godef: no declaration found for %v", pretty{e})
	}
	return nil
}

func typeStrMap(obj *ast.Object, typ types.Type) map[string]string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		dict := map[string]string{
			"Object.Kind":   obj.Kind.String(),
			"Object.Name":   obj.Name,
			"Type.Kind":     typ.Kind.String(),
			"Type.Pkg":      typ.Pkg,
			"Type.String()": typ.String(),
			// "Object.Decl": obj.Decl,
			// "Object.Data":   obj.Data,
			// "Object.Type":   obj.Type,
			// "Object.Pos()":  obj.Pos(),
			// "Type.Node":     typ.Node,
		}
		return dict
		// 	return fmt.Sprintf("%s %v", typ.obj.Name, prettyType{typ})
		// case ast.Pkg:
		// 	return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
		// case ast.Con:
		// 	if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
		// 		return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		// 	}
		// 	return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
		// case ast.Lbl:
		// 	return fmt.Sprintf("label %s", obj.Name)
		// case ast.Typ:
		// 	typ = typ.Underlying(false, types.DefaultImporter)
		// 	return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
		// }
		// return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
	}
	return map[string]string{}
}

func typeStr(obj *ast.Object, typ types.Type) string {
	switch obj.Kind {
	case ast.Fun, ast.Var:
		return fmt.Sprintf("%s %v", obj.Name, prettyType{typ})
	case ast.Pkg:
		return fmt.Sprintf("import (%s %s)", obj.Name, typ.Node.(*ast.ImportSpec).Path.Value)
	case ast.Con:
		if decl, ok := obj.Decl.(*ast.ValueSpec); ok {
			return fmt.Sprintf("const %s %v = %s", obj.Name, prettyType{typ}, pretty{decl.Values[0]})
		}
		return fmt.Sprintf("const %s %v", obj.Name, prettyType{typ})
	case ast.Lbl:
		return fmt.Sprintf("label %s", obj.Name)
	case ast.Typ:
		typ = typ.Underlying(false, types.DefaultImporter)
		return fmt.Sprintf("type %s %v", obj.Name, prettyType{typ})
	}
	return fmt.Sprintf("unknown %s %v", obj.Name, typ.Kind)
}

type orderedObjects []*ast.Object

func (o orderedObjects) Less(i, j int) bool { return o[i].Name < o[j].Name }
func (o orderedObjects) Len() int           { return len(o) }
func (o orderedObjects) Swap(i, j int)      { o[i], o[j] = o[j], o[i] }

func importPath(v *vim.Vim, n *ast.ImportSpec) string {
	p, err := strconv.Unquote(n.Path.Value)
	if err != nil {
		nvim.Echomsg(v, "Godef: invalid string literal %q in ast.ImportSpec", n.Path.Value)
	}
	return p
}

// findIdentifier looks for an identifier at byte-offset searchpos
// inside the parsed source represented by node.
// If it is part of a selector expression, it returns
// that expression rather than the identifier itself.
//
// As a special case, if it finds an import spec, it returns ImportSpec.
func findIdentifier(v *vim.Vim, f *ast.File, searchpos int) ast.Node {
	ec := make(chan ast.Node)
	found := func(startPos, endPos token.Pos) bool {
		start := types.FileSet.Position(startPos).Offset
		end := start + int(endPos-startPos)
		return start <= searchpos && searchpos <= end
	}
	go func() {
		var visit func(ast.Node) bool
		visit = func(n ast.Node) bool {
			var startPos token.Pos
			switch n := n.(type) {
			default:
				return true
			case *ast.Ident:
				startPos = n.NamePos
			case *ast.SelectorExpr:
				startPos = n.Sel.NamePos
			case *ast.ImportSpec:
				startPos = n.Pos()
			case *ast.StructType:
				// If we find an anonymous bare field in a
				// struct type, its definition points to itself,
				// but we actually want to go elsewhere,
				// so assume (dubiously) that the expression
				// works globally and return a new node for it.
				for _, field := range n.Fields.List {
					if field.Names != nil {
						continue
					}
					t := field.Type
					if pt, ok := field.Type.(*ast.StarExpr); ok {
						t = pt.X
					}
					if id, ok := t.(*ast.Ident); ok {
						if found(id.NamePos, id.End()) {
							ec <- parseExpr(v, f.Scope, id.Name)
							runtime.Goexit()
						}
					}
				}
				return true
			}
			if found(startPos, n.End()) {
				ec <- n
				runtime.Goexit()
			}
			return true
		}
		ast.Walk(FVisitor(visit), f)
		ec <- nil
	}()
	ev := <-ec
	if ev == nil {
		nvim.Echomsg(v, "Godef: no identifier found")
	}
	return ev
}

func parseExpr(v *vim.Vim, s *ast.Scope, expr string) ast.Expr {
	n, err := parser.ParseExpr(types.FileSet, "<arg>", expr, s)
	if err != nil {
		nvim.Echomsg(v, "Godef: cannot parse expression: %v", err)
	}
	switch n := n.(type) {
	case *ast.Ident, *ast.SelectorExpr:
		return n
	}
	nvim.Echomsg(v, "Godef: no identifier found in expression")
	return nil
}

type FVisitor func(n ast.Node) bool

func (f FVisitor) Visit(n ast.Node) ast.Visitor {
	if f(n) {
		return f
	}
	return nil
}

// pkgName returns the package name implemented by the go source filename
func pkgName(filename string) string {
	prog, _ := parser.ParseFile(types.FileSet, filename, nil, parser.PackageClauseOnly, nil)
	if prog != nil {
		return prog.Name.Name
	}
	return ""
}

func hasSuffix(s, suff string) bool {
	return len(s) >= len(suff) && s[len(s)-len(suff):] == suff
}

type pretty struct {
	n interface{}
}

func (p pretty) String() string {
	var b bytes.Buffer
	printer.Fprint(&b, types.FileSet, p.n)
	return b.String()
}

type prettyType struct {
	n types.Type
}

func (p prettyType) String() string {
	// TODO print path package when appropriate.
	// Current issues with using p.n.Pkg:
	//	- we should actually print the local package identifier
	//	rather than the package path when possible.
	//	- p.n.Pkg is non-empty even when
	//	the type is not relative to the package.
	return pretty{p.n.Node}.String()
}
<|endoftext|>


<commit_before><commit_msg>tagMap,pubsub add ability to create empty tags and keys<commit_after><|endoftext|>


<commit_before><commit_msg>Fix lint error<commit_after><|endoftext|>


<commit_before>package consensus

import (
	"container/heap"
	"container/vector"
	"doozer/store"
	"goprotobuf.googlecode.com/hg/proto"
)

type packet struct {
	Addr string
	M
}

func (p packet) Less(y interface{}) bool {
	return *p.Seqn < *y.(packet).Seqn
}

type Packet struct {
	Addr string
	Data []byte
}

type Stats struct {
	Runs        int
	WaitPackets int
}

type Manager <-chan Stats

func NewManager(in <-chan Packet, out chan<- packet, runs <-chan *run, ops chan<- store.Op) Manager {
	stats := make(chan Stats)
	running := make(map[int64]*run)
	packets := new(vector.Vector)

	var nextRun int64

	go func() {
		for {
			select {
			case run := <-runs:
				running[run.seqn] = run
				nextRun = run.seqn + 1
				run.ops = ops
			case p := <-in:
				recvPacket(packets, p)
			case stats <- Stats{len(running), packets.Len()}:
			}

			for packets.Len() > 0 {
				p := packets.At(0).(packet)

				seqn := *p.Seqn

				if seqn >= nextRun {
					break
				}

				heap.Pop(packets)

				running[seqn].deliver(p)
			}
		}
	}()

	return stats
}

func recvPacket(q heap.Interface, P Packet) {
	var p packet

	err := proto.Unmarshal(P.Data, &p.M)
	if err != nil {
		return
	}

	if p.M.Seqn == nil {
		return
	}

	heap.Push(q, p)
}
<commit_msg>refactor<commit_after>package consensus

import (
	"container/heap"
	"container/vector"
	"doozer/store"
	"goprotobuf.googlecode.com/hg/proto"
)

type packet struct {
	Addr string
	M
}

func (p packet) Less(y interface{}) bool {
	return *p.Seqn < *y.(packet).Seqn
}

type Packet struct {
	Addr string
	Data []byte
}

type Stats struct {
	Runs        int
	WaitPackets int
}

type Manager <-chan Stats

func NewManager(in <-chan Packet, out chan<- packet, runs <-chan *run, ops chan<- store.Op) Manager {
	statCh := make(chan Stats)
	running := make(map[int64]*run)
	packets := new(vector.Vector)

	var nextRun int64

	go func() {
		var stats Stats
		for {
			stats.Runs = len(running)
			stats.WaitPackets = packets.Len()

			select {
			case run := <-runs:
				running[run.seqn] = run
				nextRun = run.seqn + 1
				run.ops = ops
			case p := <-in:
				recvPacket(packets, p)
			case statCh <- stats:
			}

			for packets.Len() > 0 {
				p := packets.At(0).(packet)

				seqn := *p.Seqn

				if seqn >= nextRun {
					break
				}

				heap.Pop(packets)

				running[seqn].deliver(p)
			}
		}
	}()

	return statCh
}

func recvPacket(q heap.Interface, P Packet) {
	var p packet

	err := proto.Unmarshal(P.Data, &p.M)
	if err != nil {
		return
	}

	if p.M.Seqn == nil {
		return
	}

	heap.Push(q, p)
}
<|endoftext|>


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

package av

import (
	"image"
)

// Native Client image format:
// a single linear array of 32-bit ARGB as packed uint32s.

// An Image represents a Native Client frame buffer.
// The pixels in the image can be accessed as a single
// linear slice or as a two-dimensional slice of slices.
// Image implements image.Image.
type Image struct {
	Linear []Color
	Pixel  [][]Color
}

var _ image.Image = (*Image)(nil)

func (m *Image) ColorModel() image.ColorModel { return ColorModel }

func (m *Image) Bounds() image.Rectangle {
	if len(m.Pixel) == 0 {
		return image.ZR
	}
	return image.Rectangle{image.ZP, image.Point{len(m.Pixel[0]), len(m.Pixel)}}
}

func (m *Image) At(x, y int) image.Color { return m.Pixel[y][x] }

func (m *Image) Set(x, y int, color image.Color) {
	if c, ok := color.(Color); ok {
		m.Pixel[y][x] = c
	}
	m.Pixel[y][x] = makeColor(color.RGBA())
}

func newImage(dx, dy int, linear []Color) *Image {
	if linear == nil {
		linear = make([]Color, dx*dy)
	}
	pix := make([][]Color, dy)
	for i := range pix {
		pix[i] = linear[dx*i : dx*(i+1)]
	}
	return &Image{linear, pix}
}

// A Color represents a Native Client color value,
// a 32-bit R, G, B, A value packed as 0xAARRGGBB.
type Color uint32

func (p Color) RGBA() (r, g, b, a uint32) {
	x := uint32(p)
	a = x >> 24
	a |= a << 8
	r = (x >> 16) & 0xFF
	r |= r << 8
	g = (x >> 8) & 0xFF
	g |= g << 8
	b = x & 0xFF
	b |= b << 8
	return
}

func makeColor(r, g, b, a uint32) Color {
	return Color(a>>24<<24 | r>>24<<16 | g>>24<<8 | b>>24)
}

func toColor(color image.Color) image.Color {
	if c, ok := color.(Color); ok {
		return c
	}
	return makeColor(color.RGBA())
}

// ColorModel is the color model corresponding to the Native Client Color.
var ColorModel = image.ColorModelFunc(toColor)
<commit_msg>exp/nacl/av: update color to max out at 1<<16-1 instead of 1<<32-1. Fix missing return in Set(x, y, color).<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package av

import (
	"image"
)

// Native Client image format:
// a single linear array of 32-bit ARGB as packed uint32s.

// An Image represents a Native Client frame buffer.
// The pixels in the image can be accessed as a single
// linear slice or as a two-dimensional slice of slices.
// Image implements image.Image.
type Image struct {
	Linear []Color
	Pixel  [][]Color
}

var _ image.Image = (*Image)(nil)

func (m *Image) ColorModel() image.ColorModel { return ColorModel }

func (m *Image) Bounds() image.Rectangle {
	if len(m.Pixel) == 0 {
		return image.ZR
	}
	return image.Rectangle{image.ZP, image.Point{len(m.Pixel[0]), len(m.Pixel)}}
}

func (m *Image) At(x, y int) image.Color { return m.Pixel[y][x] }

func (m *Image) Set(x, y int, color image.Color) {
	if c, ok := color.(Color); ok {
		m.Pixel[y][x] = c
		return
	}
	m.Pixel[y][x] = makeColor(color.RGBA())
}

func newImage(dx, dy int, linear []Color) *Image {
	if linear == nil {
		linear = make([]Color, dx*dy)
	}
	pix := make([][]Color, dy)
	for i := range pix {
		pix[i] = linear[dx*i : dx*(i+1)]
	}
	return &Image{linear, pix}
}

// A Color represents a Native Client color value,
// a 32-bit R, G, B, A value packed as 0xAARRGGBB.
type Color uint32

func (p Color) RGBA() (r, g, b, a uint32) {
	x := uint32(p)
	a = x >> 24
	a |= a << 8
	r = (x >> 16) & 0xFF
	r |= r << 8
	g = (x >> 8) & 0xFF
	g |= g << 8
	b = x & 0xFF
	b |= b << 8
	return
}

func makeColor(r, g, b, a uint32) Color {
	return Color(a>>8<<24 | r>>8<<16 | g>>8<<8 | b>>8)
}

func toColor(color image.Color) image.Color {
	if c, ok := color.(Color); ok {
		return c
	}
	return makeColor(color.RGBA())
}

// ColorModel is the color model corresponding to the Native Client Color.
var ColorModel = image.ColorModelFunc(toColor)
<|endoftext|>