<commit_before>package main

import (
	"time"

	"github.com/jaracil/nxcli/nxcore"

	"github.com/gopherjs/gopherjs/js"
	"github.com/jaracil/ei"
)

func ret(r interface{}, e error, cb []*js.Object) {
	switch len(cb) {
	case 1:
		cb[0].Invoke(r, WrapError(e))

	case 2:
		if e == nil {
			cb[0].Invoke(r)
		} else {
			cb[1].Invoke(WrapError(e))
		}
	}
}

func WrapError(e error) *js.Object {
	if e == nil {
		return nil
	}
	jserr := js.Global.Get("Object").New()
	if err, ok := e.(*nxcore.JsonRpcErr); ok {
		jserr.Set("code", err.Cod)
		jserr.Set("message", err.Mess)
		jserr.Set("data", err.Dat)
	} else {
		jserr.Set("code", 0)
		jserr.Set("message", e.Error())
		jserr.Set("data", nil)
	}
	return jserr
}

func WrapTask(task *nxcore.Task) *js.Object {
	if task == nil {
		return nil
	}
	jstask := js.Global.Get("Object").New()
	jstask.Set("sendResult", func(res interface{}, cb ...*js.Object) {
		go func() {
			r, e := task.SendResult(res)
			ret(r, e, cb)
		}()
	})
	jstask.Set("sendError", func(code int, msg string, data interface{}, cb ...*js.Object) {
		go func() {
			r, e := task.SendError(code, msg, data)
			ret(r, e, cb)
		}()
	})
	jstask.Set("path", task.Path)
	jstask.Set("method", task.Method)
	jstask.Set("params", task.Params)
	jstask.Set("tags", task.Tags)
	return jstask
}

func WrapPipe(pipe *nxcore.Pipe) *js.Object {
	if pipe == nil {
		return nil
	}
	jspipe := js.Global.Get("Object").New()
	jspipe.Set("close", func(cb ...*js.Object) {
		go func() {
			r, e := pipe.Close()
			ret(r, e, cb)
		}()
	})
	jspipe.Set("read", func(max int, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := pipe.Read(max, time.Duration(timeout*float64(time.Second)))
			if e != nil {
				ret(nil, e, cb)
				return
			}
			msgs := make([]ei.M, 0)
			for _, msg := range r.Msgs {
				msgs = append(msgs, ei.M{"count": msg.Count, "msg": msg.Msg})
			}
			result := ei.M{"msgs": msgs, "waiting": r.Waiting, "drops": r.Drops}
			ret(result, e, cb)
		}()
	})
	jspipe.Set("write", func(msg interface{}, cb ...*js.Object) {
		go func() {
			r, e := pipe.Write(msg)
			ret(r, e, cb)
		}()
	})
	jspipe.Set("id", pipe.Id())
	return jspipe
}

func WrapNexusConn(nc *nxcore.NexusConn) *js.Object {
	if nc == nil {
		return nil
	}
	jsnc := js.Global.Get("Object").New()
	jsnc.Set("login", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.Login(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("taskPush", func(method string, params interface{}, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := nc.TaskPush(method, params, time.Duration(timeout*float64(time.Second)))
			ret(r, e, cb)
		}()
	})
	jsnc.Set("taskPull", func(prefix string, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := nc.TaskPull(prefix, time.Duration(timeout*float64(time.Second)))
			ret(WrapTask(r), e, cb)
		}()
	})
	jsnc.Set("userCreate", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserCreate(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userDelete", func(user string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserDelete(user)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userDelTags", func(user string, prefix string, tags []string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserDelTags(user, prefix, tags)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userSetPass", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserSetPass(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userSetTags", func(user string, prefix string, tags map[string]interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.UserSetTags(user, prefix, tags)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("pipeCreate", func(jopts ei.M, cb ...*js.Object) {
		go func() {
			opts := &nxcore.PipeOpts{
				Length: ei.N(jopts).M("length").IntZ(),
			}
			r, e := nc.PipeCreate(opts)
			ret(WrapPipe(r), e, cb)
		}()
	})
	jsnc.Set("pipeOpen", func(id string, cb ...*js.Object) {
		go func() {
			r, e := nc.PipeOpen(id)
			ret(WrapPipe(r), e, cb)
		}()
	})
	jsnc.Set("topicPublish", func(topic string, msg interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.TopicPublish(topic, msg)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("topicSubscribe", func(jspipe *js.Object, topic string, cb ...*js.Object) { // !!!Warning, Don't work!!!
		go func() {
			par := ei.M{
				"pipeid": jspipe.Get("id").String(),
				"topic":   topic,
			}
			r, e := nc.Exec("topic.sub", par)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("topicUnsubscribe", func(jspipe *js.Object, topic string, cb ...*js.Object) {
		go func() {
			par := ei.M{
				"pipeid": jspipe.Get("id").String(),
				"topic":   topic,
			}
			r, e := nc.Exec("topic.unsub", par)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("exec", func(method string, params interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.Exec(method, params)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("close", func(cb ...*js.Object) {
		go func() {
			nc.Close()
			ret(nil, nil, cb)
		}()
	})
	jsnc.Set("closed", nc.Closed)
	jsnc.Set("ping", func(timeout float64, cb ...*js.Object) {
		go func() {
			e := nc.Ping(time.Duration(timeout * float64(time.Second)))
			ret(nil, e, cb)
		}()
	})
	return jsnc
}
<commit_msg>Bump javascript client to match 0.1.0 tag<commit_after>package main

import (
	"time"

	"github.com/jaracil/nxcli/nxcore"

	"github.com/gopherjs/gopherjs/js"
	"github.com/jaracil/ei"
)

func ret(r interface{}, e error, cb []*js.Object) {
	switch len(cb) {
	case 1:
		cb[0].Invoke(r, WrapError(e))

	case 2:
		if e == nil {
			cb[0].Invoke(r)
		} else {
			cb[1].Invoke(WrapError(e))
		}
	}
}

func WrapError(e error) *js.Object {
	if e == nil {
		return nil
	}
	jserr := js.Global.Get("Object").New()
	if err, ok := e.(*nxcore.JsonRpcErr); ok {
		jserr.Set("code", err.Cod)
		jserr.Set("message", err.Mess)
		jserr.Set("data", err.Dat)
	} else {
		jserr.Set("code", 0)
		jserr.Set("message", e.Error())
		jserr.Set("data", nil)
	}
	return jserr
}

func WrapTask(task *nxcore.Task) *js.Object {
	if task == nil {
		return nil
	}
	jstask := js.Global.Get("Object").New()
	jstask.Set("sendResult", func(res interface{}, cb ...*js.Object) {
		go func() {
			r, e := task.SendResult(res)
			ret(r, e, cb)
		}()
	})
	jstask.Set("sendError", func(code int, msg string, data interface{}, cb ...*js.Object) {
		go func() {
			r, e := task.SendError(code, msg, data)
			ret(r, e, cb)
		}()
	})
	jstask.Set("path", task.Path)
	jstask.Set("method", task.Method)
	jstask.Set("params", task.Params)
	jstask.Set("tags", task.Tags)
	return jstask
}

func WrapPipe(pipe *nxcore.Pipe) *js.Object {
	if pipe == nil {
		return nil
	}
	jspipe := js.Global.Get("Object").New()
	jspipe.Set("close", func(cb ...*js.Object) {
		go func() {
			r, e := pipe.Close()
			ret(r, e, cb)
		}()
	})
	jspipe.Set("read", func(max int, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := pipe.Read(max, time.Duration(timeout*float64(time.Second)))
			if e != nil {
				ret(nil, e, cb)
				return
			}
			msgs := make([]ei.M, 0)
			for _, msg := range r.Msgs {
				msgs = append(msgs, ei.M{"count": msg.Count, "msg": msg.Msg})
			}
			result := ei.M{"msgs": msgs, "waiting": r.Waiting, "drops": r.Drops}
			ret(result, e, cb)
		}()
	})
	jspipe.Set("write", func(msg interface{}, cb ...*js.Object) {
		go func() {
			r, e := pipe.Write(msg)
			ret(r, e, cb)
		}()
	})
	jspipe.Set("id", pipe.Id())
	return jspipe
}

func WrapNexusConn(nc *nxcore.NexusConn) *js.Object {
	if nc == nil {
		return nil
	}
	jsnc := js.Global.Get("Object").New()
	jsnc.Set("login", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.Login(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("taskPush", func(method string, params interface{}, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := nc.TaskPush(method, params, time.Duration(timeout*float64(time.Second)))
			ret(r, e, cb)
		}()
	})
	jsnc.Set("taskPull", func(prefix string, timeout float64, cb ...*js.Object) {
		go func() {
			r, e := nc.TaskPull(prefix, time.Duration(timeout*float64(time.Second)))
			ret(WrapTask(r), e, cb)
		}()
	})
	jsnc.Set("userCreate", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserCreate(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userDelete", func(user string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserDelete(user)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userSetTags", func(user string, prefix string, tags map[string]interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.UserSetTags(user, prefix, tags)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userDelTags", func(user string, prefix string, tags []string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserDelTags(user, prefix, tags)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userSetPass", func(user string, pass string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserSetPass(user, pass)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userList", func(prefix string, limit int, skip int, cb ...*js.Object) {
		go func() {
			r, e := nc.UserList(prefix, limit, skip)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userAddTemplate", func(user string, template string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserAddTemplate(user, template)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userDelTemplate", func(user string, template string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserDelTemplate(user, template)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("userListTemplate", func(user string, cb ...*js.Object) {
		go func() {
			r, e := nc.UserListTemplate(user)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("sessionList", func(prefix string, limit int, skip int, cb ...*js.Object) {
		go func() {
			r, e := nc.SessionList(prefix, limit, skip)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("sessionKick", func(connId string, cb ...*js.Object) {
		go func() {
			r, e := nc.SessionKick(connId)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("sessionReload", func(connId string, cb ...*js.Object) {
		go func() {
			r, e := nc.SessionReload(connId)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("nodeList", func(limit int, skip int, cb ...*js.Object) {
		go func() {
			r, e := nc.NodeList(limit, skip)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("pipeCreate", func(jopts ei.M, cb ...*js.Object) {
		go func() {
			opts := &nxcore.PipeOpts{
				Length: ei.N(jopts).M("length").IntZ(),
			}
			r, e := nc.PipeCreate(opts)
			ret(WrapPipe(r), e, cb)
		}()
	})
	jsnc.Set("pipeOpen", func(id string, cb ...*js.Object) {
		go func() {
			r, e := nc.PipeOpen(id)
			ret(WrapPipe(r), e, cb)
		}()
	})
	jsnc.Set("topicPublish", func(topic string, msg interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.TopicPublish(topic, msg)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("topicSubscribe", func(jspipe *js.Object, topic string, cb ...*js.Object) { // !!!Warning, Don't work!!!
		go func() {
			par := ei.M{
				"pipeid": jspipe.Get("id").String(),
				"topic":  topic,
			}
			r, e := nc.Exec("topic.sub", par)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("topicUnsubscribe", func(jspipe *js.Object, topic string, cb ...*js.Object) {
		go func() {
			par := ei.M{
				"pipeid": jspipe.Get("id").String(),
				"topic":  topic,
			}
			r, e := nc.Exec("topic.unsub", par)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("exec", func(method string, params interface{}, cb ...*js.Object) {
		go func() {
			r, e := nc.Exec(method, params)
			ret(r, e, cb)
		}()
	})
	jsnc.Set("close", func(cb ...*js.Object) {
		go func() {
			nc.Close()
			ret(nil, nil, cb)
		}()
	})
	jsnc.Set("closed", nc.Closed)
	jsnc.Set("ping", func(timeout float64, cb ...*js.Object) {
		go func() {
			e := nc.Ping(time.Duration(timeout * float64(time.Second)))
			ret(nil, e, cb)
		}()
	})
	return jsnc
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"log"
	"strconv"
	"time"

	"github.com/brotherlogic/goserver"
	"google.golang.org/grpc"

	pbd "github.com/brotherlogic/discovery/proto"
	pb "github.com/brotherlogic/gobuildmaster/proto"
	pbs "github.com/brotherlogic/gobuildslave/proto"
)

const (
	intentWait = 1000
)

// Server the main server type
type Server struct {
	*goserver.GoServer
	config  *pb.Config
	serving bool
}

type mainChecker struct{}

func getIP(servertype, servername string) (string, int) {
	conn, _ := grpc.Dial("192.168.86.34:50055", grpc.WithInsecure())
	defer conn.Close()

	registry := pbd.NewDiscoveryServiceClient(conn)
	r, err := registry.ListAllServices(context.Background(), &pbd.Empty{})
	if err != nil {
		return "", -1
	}
	for _, s := range r.Services {
		log.Printf("Does %v = %v and %v = %v?", s.Name, servertype, s.Identifier, servername)
		if s.Name == servertype && s.Identifier == servername {
			return s.Ip, int(s.Port)
		}
	}

	return "", -1
}

func (t *mainChecker) assess(server string) *pbs.JobList {
	list := &pbs.JobList{}

	ip, port := getIP("gobuildslave", server)
	conn, _ := grpc.Dial(ip+":"+strconv.Itoa(port), grpc.WithInsecure())
	defer conn.Close()

	slave := pbs.NewGoBuildSlaveClient(conn)
	r, err := slave.List(context.Background(), &pbs.Empty{})
	if err == nil {
		return r
	}

	return list
}

func runJob(job *pbs.JobSpec) {
	log.Printf("RUNNING: %v", job)
	ip, port := getIP("gobuildslave", job.Server)
	conn, _ := grpc.Dial(ip+":"+strconv.Itoa(port), grpc.WithInsecure())
	defer conn.Close()

	slave := pbs.NewGoBuildSlaveClient(conn)
	slave.Run(context.Background(), job)
}

func (t *mainChecker) discover() *pbd.ServiceList {
	ret := &pbd.ServiceList{}

	conn, _ := grpc.Dial("192.168.86.34:50055", grpc.WithInsecure())
	defer conn.Close()

	registry := pbd.NewDiscoveryServiceClient(conn)
	r, err := registry.ListAllServices(context.Background(), &pbd.Empty{})
	if err == nil {
		for _, s := range r.Services {
			ret.Services = append(ret.Services, s)
		}
	}

	return ret
}

// DoRegister Registers this server
func (s Server) DoRegister(server *grpc.Server) {
	// Do nothing
}

// ReportHealth determines if the server is healthy
func (s Server) ReportHealth() bool {
	return true
}

func getConfig(c checker) *pb.Config {
	list := getFleetStatus(c)
	config := &pb.Config{}

	for _, jlist := range list {
		for _, job := range jlist.Details {
			found := false
			for _, ij := range config.Intents {
				if job.Spec.Name == ij.Spec.Name {
					ij.Masters++
					found = true
				}
			}

			if !found {
				config.Intents = append(config.Intents, &pb.Intent{Spec: &pbs.JobSpec{Name: job.Spec.Name}, Masters: 1})
			}
		}
	}

	return config
}

// MatchIntent tries to match the intent with the state of production
func (s Server) MatchIntent() {
	//for s.serving {
	time.Sleep(intentWait)

	state := getConfig(&mainChecker{})
	diff := configDiff(s.config, state)
	joblist := runJobs(diff)
	log.Printf("FOUND %v from %v and %v", joblist, state, diff)
	for _, job := range joblist {
		runJob(job)
	}
	//}
}

func main() {
	config, err := loadConfig("config.pb")
	if err != nil {
		log.Fatalf("Fatal loading of config: %v", err)
	}

	var sync = flag.Bool("once", true, "One pass intent match")
	s := Server{&goserver.GoServer{}, config, true}
	if *sync {
		s.MatchIntent()
	} else {
		s.Register = s
		s.PrepServer()
		s.RegisterServer("gobuildmaster", false)
		s.Serve()
	}
}
<commit_msg>Added some logging<commit_after>package main

import (
	"context"
	"flag"
	"log"
	"strconv"
	"time"

	"github.com/brotherlogic/goserver"
	"google.golang.org/grpc"

	pbd "github.com/brotherlogic/discovery/proto"
	pb "github.com/brotherlogic/gobuildmaster/proto"
	pbs "github.com/brotherlogic/gobuildslave/proto"
)

const (
	intentWait = 1000
)

// Server the main server type
type Server struct {
	*goserver.GoServer
	config  *pb.Config
	serving bool
}

type mainChecker struct{}

func getIP(servertype, servername string) (string, int) {
	conn, _ := grpc.Dial("192.168.86.34:50055", grpc.WithInsecure())
	defer conn.Close()

	registry := pbd.NewDiscoveryServiceClient(conn)
	r, err := registry.ListAllServices(context.Background(), &pbd.Empty{})
	if err != nil {
		return "", -1
	}
	for _, s := range r.Services {
		log.Printf("Does %v = %v and %v = %v?", s.Name, servertype, s.Identifier, servername)
		if s.Name == servertype && s.Identifier == servername {
			return s.Ip, int(s.Port)
		}
	}

	return "", -1
}

func (t *mainChecker) assess(server string) *pbs.JobList {
	list := &pbs.JobList{}

	ip, port := getIP("gobuildslave", server)
	conn, _ := grpc.Dial(ip+":"+strconv.Itoa(port), grpc.WithInsecure())
	defer conn.Close()

	slave := pbs.NewGoBuildSlaveClient(conn)
	r, err := slave.List(context.Background(), &pbs.Empty{})
	if err == nil {
		return r
	}

	return list
}

func runJob(job *pbs.JobSpec) {
	log.Printf("RUNNING: %v", job)
	ip, port := getIP("gobuildslave", job.Server)
	conn, _ := grpc.Dial(ip+":"+strconv.Itoa(port), grpc.WithInsecure())
	defer conn.Close()

	slave := pbs.NewGoBuildSlaveClient(conn)
	slave.Run(context.Background(), job)
}

func (t *mainChecker) discover() *pbd.ServiceList {
	ret := &pbd.ServiceList{}

	conn, _ := grpc.Dial("192.168.86.34:50055", grpc.WithInsecure())
	defer conn.Close()

	registry := pbd.NewDiscoveryServiceClient(conn)
	r, err := registry.ListAllServices(context.Background(), &pbd.Empty{})
	if err == nil {
		for _, s := range r.Services {
			ret.Services = append(ret.Services, s)
		}
	}

	return ret
}

// DoRegister Registers this server
func (s Server) DoRegister(server *grpc.Server) {
	// Do nothing
}

// ReportHealth determines if the server is healthy
func (s Server) ReportHealth() bool {
	return true
}

func getConfig(c checker) *pb.Config {
	list := getFleetStatus(c)
	config := &pb.Config{}

	for _, jlist := range list {
		for _, job := range jlist.Details {
			found := false
			for _, ij := range config.Intents {
				if job.Spec.Name == ij.Spec.Name {
					ij.Masters++
					found = true
				}
			}

			if !found {
				config.Intents = append(config.Intents, &pb.Intent{Spec: &pbs.JobSpec{Name: job.Spec.Name}, Masters: 1})
			}
		}
	}

	return config
}

// MatchIntent tries to match the intent with the state of production
func (s Server) MatchIntent() {
	//for s.serving {
	time.Sleep(intentWait)

	state := getConfig(&mainChecker{})
	diff := configDiff(s.config, state)
	joblist := runJobs(diff)
	log.Printf("FOUND %v from %v and %v", joblist, state, s.config)
	for _, job := range joblist {
		runJob(job)
	}
	//}
}

func main() {
	config, err := loadConfig("config.pb")
	if err != nil {
		log.Fatalf("Fatal loading of config: %v", err)
	}

	var sync = flag.Bool("once", true, "One pass intent match")
	s := Server{&goserver.GoServer{}, config, true}
	if *sync {
		s.MatchIntent()
	} else {
		s.Register = s
		s.PrepServer()
		s.RegisterServer("gobuildmaster", false)
		s.Serve()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/jonnenauha/obj-simplify/objectfile"
)

var (
	ObjectsParsed int
	GroupsParsed  int
)

type Parser struct {
	Filepath string
}

func (p *Parser) ParseFile(path string) (*objectfile.OBJ, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return p.Parse(b)
}

func (p *Parser) Parse(b []byte) (*objectfile.OBJ, error) {
	dest := objectfile.NewOBJ()
	geom := dest.Geometry

	scanner := bufio.NewScanner(bytes.NewBuffer(b))
	linenum := 0

	var (
		currentObject           *objectfile.Object
		currentObjectName       string
		currentObjectChildIndex int
		currentMaterial         string
		currentSmoothGroup      string
	)

	fakeObject := func(material string) *objectfile.Object {
		ot := objectfile.ChildObject
		if currentObject != nil {
			ot = currentObject.Type
		}
		currentObjectChildIndex++
		name := fmt.Sprintf("%s_%d", currentObjectName, currentObjectChildIndex)
		return dest.CreateObject(ot, name, material)
	}

	for scanner.Scan() {
		linenum++

		line := strings.TrimSpace(scanner.Text())
		if len(line) == 0 {
			continue
		}
		t, value := parseLineType(line)

		switch t {

		// comments
		case objectfile.Comment:
			if currentObject == nil && len(dest.MaterialLibraries) == 0 {
				dest.Comments = append(dest.Comments, value)
			} else if currentObject != nil {
				// skip comments that might refecence vertex, normal, uv, polygon etc.
				// counts as they wont be most likely true after this tool is done.
				if len(value) > 0 && !strContainsAny(value, []string{"vertices", "normals", "uvs", "texture coords", "polygons", "triangles"}, caseInsensitive) {
					currentObject.Comments = append(currentObject.Comments, value)
				}
			}

		// mtl file ref
		case objectfile.MtlLib:
			dest.MaterialLibraries = append(dest.MaterialLibraries, value)

		// geometry
		case objectfile.Vertex, objectfile.Normal, objectfile.UV, objectfile.Param:
			if _, err := geom.ReadValue(t, value); err != nil {
				return nil, wrapErrorLine(err, linenum)
			}

		// object, group
		case objectfile.ChildObject, objectfile.ChildGroup:
			currentObjectName = value
			currentObjectChildIndex = 0
			// inherit currently declared material
			currentObject = dest.CreateObject(t, currentObjectName, currentMaterial)
			if t == objectfile.ChildObject {
				ObjectsParsed++
			} else if t == objectfile.ChildGroup {
				GroupsParsed++
			}

		// object: material
		case objectfile.MtlUse:

			// obj files can define multiple materials inside a single object/group.
			// usually these are small face groups that kill performance on 3D engines
			// as they have to render hundreds or thousands of meshes with the same material,
			// each mesh containing a few faces.
			//
			// this app will convert all these "multi material" objects into
			// separate object, later merging all meshes with the same material into
			// a single draw call geometry.
			//
			// this might be undesirable for certain users, renderers and authoring software,
			// in this case don't use this simplified on your obj files. simple as that.

			// only fake if an object has been declared
			if currentObject != nil {
				// only fake if the current object has declared vertex data (faces etc.)
				// and the material name actually changed (ecountering the same usemtl
				// multiple times in a row would be rare, but check for completeness)
				if len(currentObject.VertexData) > 0 && currentObject.Material != value {
					currentObject = fakeObject(value)
				}
			}

			// store material value for inheriting
			currentMaterial = value

			// set material to current object
			if currentObject != nil {
				currentObject.Material = currentMaterial
			}

		// object: faces
		case objectfile.Face, objectfile.Line, objectfile.Point:
			// most tools support the file not defining a o/g prior to face declarations.
			// I'm not sure if the spec allows not declaring any o/g.
			// Our data structures and parsing however requires objects to put the faces into,
			// create a default object that is named after the input file (without suffix).
			if currentObject == nil {
				currentObject = dest.CreateObject(objectfile.ChildObject, fileBasename(StartParams.Input), currentMaterial)
			}
			vd, vdErr := currentObject.ReadVertexData(t, value)
			if vdErr != nil {
				return nil, wrapErrorLine(vdErr, linenum)
			}
			// attach current smooth group and reset it
			if len(currentSmoothGroup) > 0 {
				vd.SetMeta(objectfile.SmoothingGroup, currentSmoothGroup)
				currentSmoothGroup = ""
			}

		case objectfile.SmoothingGroup:
			// smooth group can change mid vertex data declaration
			// so it is attched to the vertex data instead of current object directly
			currentSmoothGroup = value

		// unknown
		case objectfile.Unkown:
			return nil, wrapErrorLine(fmt.Errorf("Unsupported line %q\n\nPlease submit a bug report. If you can, provide this file as an attachement.\n> %s\n", line, ApplicationURL+"/issues"), linenum)
		default:
			return nil, wrapErrorLine(fmt.Errorf("Unsupported line %q\n\nPlease submit a bug report. If you can, provide this file as an attachement.\n> %s\n", line, ApplicationURL+"/issues"), linenum)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return dest, nil
}

func wrapErrorLine(err error, linenum int) error {
	return fmt.Errorf("line:%d %s", linenum, err.Error())
}

func parseLineType(str string) (objectfile.Type, string) {
	value := ""
	if i := strings.Index(str, " "); i != -1 {
		value = strings.TrimSpace(str[i+1:])
		str = str[0:i]
	}
	return objectfile.TypeFromString(str), value
}
<commit_msg>Stream file contents to the parser instead of reading the full file into memory, doh.<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/jonnenauha/obj-simplify/objectfile"
)

var (
	ObjectsParsed int
	GroupsParsed  int
)

type Parser struct {
	Filepath string
}

func (p *Parser) ParseFile(path string) (*objectfile.OBJ, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return p.Parse(f)
}

func (p *Parser) ParseBytes(b []byte) (*objectfile.OBJ, error) {
	return p.Parse(bytes.NewBuffer(b))
}

func (p *Parser) Parse(src io.Reader) (*objectfile.OBJ, error) {
	dest := objectfile.NewOBJ()
	geom := dest.Geometry

	scanner := bufio.NewScanner(src)
	linenum := 0

	var (
		currentObject           *objectfile.Object
		currentObjectName       string
		currentObjectChildIndex int
		currentMaterial         string
		currentSmoothGroup      string
	)

	fakeObject := func(material string) *objectfile.Object {
		ot := objectfile.ChildObject
		if currentObject != nil {
			ot = currentObject.Type
		}
		currentObjectChildIndex++
		name := fmt.Sprintf("%s_%d", currentObjectName, currentObjectChildIndex)
		return dest.CreateObject(ot, name, material)
	}

	for scanner.Scan() {
		linenum++

		line := strings.TrimSpace(scanner.Text())
		if len(line) == 0 {
			continue
		}
		t, value := parseLineType(line)

		switch t {

		// comments
		case objectfile.Comment:
			if currentObject == nil && len(dest.MaterialLibraries) == 0 {
				dest.Comments = append(dest.Comments, value)
			} else if currentObject != nil {
				// skip comments that might refecence vertex, normal, uv, polygon etc.
				// counts as they wont be most likely true after this tool is done.
				if len(value) > 0 && !strContainsAny(value, []string{"vertices", "normals", "uvs", "texture coords", "polygons", "triangles"}, caseInsensitive) {
					currentObject.Comments = append(currentObject.Comments, value)
				}
			}

		// mtl file ref
		case objectfile.MtlLib:
			dest.MaterialLibraries = append(dest.MaterialLibraries, value)

		// geometry
		case objectfile.Vertex, objectfile.Normal, objectfile.UV, objectfile.Param:
			if _, err := geom.ReadValue(t, value); err != nil {
				return nil, wrapErrorLine(err, linenum)
			}

		// object, group
		case objectfile.ChildObject, objectfile.ChildGroup:
			currentObjectName = value
			currentObjectChildIndex = 0
			// inherit currently declared material
			currentObject = dest.CreateObject(t, currentObjectName, currentMaterial)
			if t == objectfile.ChildObject {
				ObjectsParsed++
			} else if t == objectfile.ChildGroup {
				GroupsParsed++
			}

		// object: material
		case objectfile.MtlUse:

			// obj files can define multiple materials inside a single object/group.
			// usually these are small face groups that kill performance on 3D engines
			// as they have to render hundreds or thousands of meshes with the same material,
			// each mesh containing a few faces.
			//
			// this app will convert all these "multi material" objects into
			// separate object, later merging all meshes with the same material into
			// a single draw call geometry.
			//
			// this might be undesirable for certain users, renderers and authoring software,
			// in this case don't use this simplified on your obj files. simple as that.

			// only fake if an object has been declared
			if currentObject != nil {
				// only fake if the current object has declared vertex data (faces etc.)
				// and the material name actually changed (ecountering the same usemtl
				// multiple times in a row would be rare, but check for completeness)
				if len(currentObject.VertexData) > 0 && currentObject.Material != value {
					currentObject = fakeObject(value)
				}
			}

			// store material value for inheriting
			currentMaterial = value

			// set material to current object
			if currentObject != nil {
				currentObject.Material = currentMaterial
			}

		// object: faces
		case objectfile.Face, objectfile.Line, objectfile.Point:
			// most tools support the file not defining a o/g prior to face declarations.
			// I'm not sure if the spec allows not declaring any o/g.
			// Our data structures and parsing however requires objects to put the faces into,
			// create a default object that is named after the input file (without suffix).
			if currentObject == nil {
				currentObject = dest.CreateObject(objectfile.ChildObject, fileBasename(StartParams.Input), currentMaterial)
			}
			vd, vdErr := currentObject.ReadVertexData(t, value)
			if vdErr != nil {
				return nil, wrapErrorLine(vdErr, linenum)
			}
			// attach current smooth group and reset it
			if len(currentSmoothGroup) > 0 {
				vd.SetMeta(objectfile.SmoothingGroup, currentSmoothGroup)
				currentSmoothGroup = ""
			}

		case objectfile.SmoothingGroup:
			// smooth group can change mid vertex data declaration
			// so it is attched to the vertex data instead of current object directly
			currentSmoothGroup = value

		// unknown
		case objectfile.Unkown:
			return nil, wrapErrorLine(fmt.Errorf("Unsupported line %q\n\nPlease submit a bug report. If you can, provide this file as an attachement.\n> %s\n", line, ApplicationURL+"/issues"), linenum)
		default:
			return nil, wrapErrorLine(fmt.Errorf("Unsupported line %q\n\nPlease submit a bug report. If you can, provide this file as an attachement.\n> %s\n", line, ApplicationURL+"/issues"), linenum)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return dest, nil
}

func wrapErrorLine(err error, linenum int) error {
	return fmt.Errorf("line:%d %s", linenum, err.Error())
}

func parseLineType(str string) (objectfile.Type, string) {
	value := ""
	if i := strings.Index(str, " "); i != -1 {
		value = strings.TrimSpace(str[i+1:])
		str = str[0:i]
	}
	return objectfile.TypeFromString(str), value
}
<|endoftext|>


<commit_before>package nulls

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"strconv"
)

// Int adds an implementation for int
// that supports proper JSON encoding/decoding.
type Int struct {
	Int   int
	Valid bool // Valid is true if Int is not NULL
}

func (ns Int) Interface() interface{} {
	if !ns.Valid {
		return nil
	}
	return ns.Int
}

// NewInt returns a new, properly instantiated
// Int object.
func NewInt(i int) Int {
	return Int{Int: i, Valid: true}
}

// Scan implements the Scanner interface.
func (ns *Int) Scan(value interface{}) error {
	n := sql.NullInt64{Int64: int64(ns.Int)}
	err := n.Scan(value)
	ns.Int, ns.Valid = int(n.Int64), n.Valid
	return err
}

// Value implements the driver Valuer interface.
func (ns Int) Value() (driver.Value, error) {
	if !ns.Valid {
		return nil, nil
	}
	return int64(ns.Int), nil
}

// MarshalJSON marshals the underlying value to a
// proper JSON representation.
func (ns Int) MarshalJSON() ([]byte, error) {
	if ns.Valid {
		return json.Marshal(ns.Int)
	}
	return json.Marshal(nil)
}

// UnmarshalJSON will unmarshal a JSON value into
// the propert representation of that value.
func (ns *Int) UnmarshalJSON(text []byte) error {
	txt := string(text)
	ns.Valid = true
	if txt == "null" {
		ns.Valid = false
		return nil
	}
	i, err := strconv.ParseInt(txt, 10, strconv.IntSize)
	if err != nil {
		ns.Valid = false
		return err
	}
	j := int(i)
	ns.Int = j
	return nil
}

func (ns *Int) UnmarshalText(text []byte) error {
	return ns.UnmarshalJSON(text)
}
<commit_msg>cleaner implementation of nulls.Int.UnmarshalJSON<commit_after>package nulls

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"strconv"
)

// Int adds an implementation for int
// that supports proper JSON encoding/decoding.
type Int struct {
	Int   int
	Valid bool // Valid is true if Int is not NULL
}

func (ns Int) Interface() interface{} {
	if !ns.Valid {
		return nil
	}
	return ns.Int
}

// NewInt returns a new, properly instantiated
// Int object.
func NewInt(i int) Int {
	return Int{Int: i, Valid: true}
}

// Scan implements the Scanner interface.
func (ns *Int) Scan(value interface{}) error {
	n := sql.NullInt64{Int64: int64(ns.Int)}
	err := n.Scan(value)
	ns.Int, ns.Valid = int(n.Int64), n.Valid
	return err
}

// Value implements the driver Valuer interface.
func (ns Int) Value() (driver.Value, error) {
	if !ns.Valid {
		return nil, nil
	}
	return int64(ns.Int), nil
}

// MarshalJSON marshals the underlying value to a
// proper JSON representation.
func (ns Int) MarshalJSON() ([]byte, error) {
	if ns.Valid {
		return json.Marshal(ns.Int)
	}
	return json.Marshal(nil)
}

// UnmarshalJSON will unmarshal a JSON value into
// the propert representation of that value.
func (ns *Int) UnmarshalJSON(text []byte) error {
	if i, err := strconv.ParseInt(string(text), 10, strconv.IntSize); err == nil {
		ns.Valid = true
		ns.Int = int(i)
	}
	return nil
}

func (ns *Int) UnmarshalText(text []byte) error {
	return ns.UnmarshalJSON(text)
}
<|endoftext|>


<commit_before>package corgis

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
)

type StatusCtn struct {
	Status string
}

func HttpServe() {
	r := mux.NewRouter()
	r.HandleFunc("/", StatusHandler).Methods("POST")
	http.Handle("/", r)

	n := negroni.Classic()
	n.UseHandler(r)

	log.Fatal(http.ListenAndServe(":44005", r))
}

func StatusHandler(rw http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)
	var status StatusCtn
	err := decoder.Decode(&status)
	if err != nil {
		log.Printf("Status Handler Error: %v\n", err)
	}
	fmt.Fprintf(rw, "POSTed %v\n", status)
}
<commit_msg>change status handle path<commit_after>package corgis

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
)

type StatusCtn struct {
	Status string
}

func HttpServe() {
	r := mux.NewRouter()
	r.HandleFunc("/status", StatusHandler).Methods("POST")
	http.Handle("/", r)

	n := negroni.Classic()
	n.UseHandler(r)

	log.Fatal(http.ListenAndServe(":44005", r))
}

func StatusHandler(rw http.ResponseWriter, req *http.Request) {
	decoder := json.NewDecoder(req.Body)
	var status StatusCtn
	err := decoder.Decode(&status)
	if err != nil {
		log.Printf("Status Handler Error: %v\n", err)
	}
	fmt.Fprintf(rw, "POSTed %v\n", status)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/mitchellh/multistep"
	"github.com/hashicorp/packer/packer"
	"fmt"
	"github.com/jetbrains-infra/packer-builder-vsphere/driver"
)

type CloneConfig struct {
	Template     string `mapstructure:"template"`
	VMName       string `mapstructure:"vm_name"`
	Folder       string `mapstructure:"folder"`
	Host         string `mapstructure:"host"`
	ResourcePool string `mapstructure:"resource_pool"`
	Datastore    string `mapstructure:"datastore"`
	LinkedClone  bool   `mapstructure:"linked_clone"`
}

func (c *CloneConfig) Prepare() []error {
	var errs []error

	if c.Template == "" {
		errs = append(errs, fmt.Errorf("Template name is required"))
	}
	if c.VMName == "" {
		errs = append(errs, fmt.Errorf("Target VM name is required"))
	}
	if c.Host == "" {
		errs = append(errs, fmt.Errorf("vSphere host is required"))
	}

	return errs
}

type StepCloneVM struct {
	config *CloneConfig
}

func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	d := state.Get("driver").(*driver.Driver)

	ui.Say("Cloning VM...")

	template, err := d.FindVM(s.config.Template)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	vm, err := template.Clone(&driver.CloneConfig{
		Name:         s.config.VMName,
		Folder:       s.config.Folder,
		Host:         s.config.Host,
		ResourcePool: s.config.ResourcePool,
		Datastore:    s.config.Datastore,
		LinkedClone:  s.config.LinkedClone,
	})
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	state.Put("vm", vm)
	return multistep.ActionContinue
}

func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)
	if !cancelled && !halted {
		return
	}

	ui := state.Get("ui").(packer.Ui)
	vm := state.Get("vm").(*driver.VirtualMachine)

	ui.Say("Destroying VM...")

	err := vm.Destroy()
	if err != nil {
		ui.Error(err.Error())
	}
}
<commit_msg>handle VM clone errors<commit_after>package main

import (
	"github.com/mitchellh/multistep"
	"github.com/hashicorp/packer/packer"
	"fmt"
	"github.com/jetbrains-infra/packer-builder-vsphere/driver"
)

type CloneConfig struct {
	Template     string `mapstructure:"template"`
	VMName       string `mapstructure:"vm_name"`
	Folder       string `mapstructure:"folder"`
	Host         string `mapstructure:"host"`
	ResourcePool string `mapstructure:"resource_pool"`
	Datastore    string `mapstructure:"datastore"`
	LinkedClone  bool   `mapstructure:"linked_clone"`
}

func (c *CloneConfig) Prepare() []error {
	var errs []error

	if c.Template == "" {
		errs = append(errs, fmt.Errorf("Template name is required"))
	}
	if c.VMName == "" {
		errs = append(errs, fmt.Errorf("Target VM name is required"))
	}
	if c.Host == "" {
		errs = append(errs, fmt.Errorf("vSphere host is required"))
	}

	return errs
}

type StepCloneVM struct {
	config *CloneConfig
}

func (s *StepCloneVM) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	d := state.Get("driver").(*driver.Driver)

	ui.Say("Cloning VM...")

	template, err := d.FindVM(s.config.Template)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	vm, err := template.Clone(&driver.CloneConfig{
		Name:         s.config.VMName,
		Folder:       s.config.Folder,
		Host:         s.config.Host,
		ResourcePool: s.config.ResourcePool,
		Datastore:    s.config.Datastore,
		LinkedClone:  s.config.LinkedClone,
	})
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	state.Put("vm", vm)
	return multistep.ActionContinue
}

func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)
	if !cancelled && !halted {
		return
	}

	ui := state.Get("ui").(packer.Ui)

	st := state.Get("vm")
	if st == nil {
		return
	}
	vm := st.(*driver.VirtualMachine)

	ui.Say("Destroying VM...")

	err := vm.Destroy()
	if err != nil {
		ui.Error(err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Jigsaw Operations LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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 shadowsocks

import (
	"errors"
	"fmt"
	"net"
	"runtime/debug"
	"time"

	"github.com/Jigsaw-Code/outline-ss-server/metrics"
	onet "github.com/Jigsaw-Code/outline-ss-server/net"

	"sync"

	"github.com/shadowsocks/go-shadowsocks2/shadowaead"
	"github.com/shadowsocks/go-shadowsocks2/socks"
)

const udpBufSize = 64 * 1024

// upack decripts src into dst. It tries each cipher until it finds one that authenticates
// correctly. dst and src must not overlap.
func unpack(dst, src []byte, ciphers map[string]shadowaead.Cipher) ([]byte, string, shadowaead.Cipher, error) {
	for id, cipher := range ciphers {
		logger.Debugf("Trying UDP cipher %v", id)
		buf, err := shadowaead.Unpack(dst, src, cipher)
		if err != nil {
			logger.Debugf("Failed UDP cipher %v: %v", id, err)
			continue
		}
		logger.Debugf("Selected UDP cipher %v", id)
		return buf, id, cipher, nil
	}
	return nil, "", nil, errors.New("could not find valid cipher")
}

type udpService struct {
	clientConn net.PacketConn
	natTimeout time.Duration
	ciphers    *map[string]shadowaead.Cipher
	m          metrics.ShadowsocksMetrics
	isRunning  bool
}

func NewUDPService(clientConn net.PacketConn, natTimeout time.Duration, ciphers *map[string]shadowaead.Cipher, m metrics.ShadowsocksMetrics) UDPService {
	return &udpService{clientConn: clientConn, natTimeout: natTimeout, ciphers: ciphers, m: m}
}

type UDPService interface {
	Start()
	Stop() error
}

// Listen on addr for encrypted packets and basically do UDP NAT.
// We take the ciphers as a pointer because it gets replaced on config updates.
func (s *udpService) Start() {
	defer s.clientConn.Close()

	nm := newNATmap(s.natTimeout, s.m)
	cipherBuf := make([]byte, udpBufSize)
	textBuf := make([]byte, udpBufSize)

	s.isRunning = true
	for s.isRunning {
		func() (connError *onet.ConnectionError) {
			defer func() {
				if r := recover(); r != nil {
					logger.Errorf("Panic in UDP loop: %v", r)
					debug.PrintStack()
				}
			}()
			clientLocation := ""
			keyID := ""
			var clientProxyBytes, proxyTargetBytes int
			defer func() {
				status := "OK"
				if connError != nil {
					logger.Debugf("UDP Error: %v: %v", connError.Message, connError.Cause)
					status = connError.Status
				}
				s.m.AddUDPPacketFromClient(clientLocation, keyID, status, clientProxyBytes, proxyTargetBytes)
			}()
			clientProxyBytes, clientAddr, err := s.clientConn.ReadFrom(cipherBuf)
			if err != nil {
				if !s.isRunning {
					return nil
				}
				return onet.NewConnectionError("ERR_READ", "Failed to read from client", err)
			}
			clientLocation, locErr := s.m.GetLocation(clientAddr)
			if locErr != nil {
				logger.Warningf("Failed location lookup: %v", locErr)
			}
			logger.Debugf("Got location \"%v\" for IP %v", clientLocation, clientAddr.String())
			defer logger.Debugf("UDP done with %v", clientAddr.String())
			logger.Debugf("UDP Request from %v with %v bytes", clientAddr, clientProxyBytes)
			buf, keyID, cipher, err := unpack(textBuf, cipherBuf[:clientProxyBytes], *s.ciphers)
			if err != nil {
				return onet.NewConnectionError("ERR_CIPHER", "Failed to upack data from client", err)
			}

			tgtAddr := socks.SplitAddr(buf)
			if tgtAddr == nil {
				return onet.NewConnectionError("ERR_READ_ADDRESS", "Failed to get target address", nil)
			}

			tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
			if err != nil {
				return onet.NewConnectionError("ERR_RESOLVE_ADDRESS", fmt.Sprintf("Failed to resolve target address %v", tgtAddr.String()), err)
			}
			if !tgtUDPAddr.IP.IsGlobalUnicast() {
				return onet.NewConnectionError("ERR_ADDRESS_INVALID", fmt.Sprintf("Target address is not global unicast: %v", tgtAddr.String()), err)
			}

			payload := buf[len(tgtAddr):]

			targetConn := nm.Get(clientAddr.String())
			if targetConn == nil {
				targetConn, err = net.ListenPacket("udp", "")
				if err != nil {
					return onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
				}
				nm.Add(clientAddr, s.clientConn, cipher, targetConn, clientLocation, keyID)
			}
			logger.Debugf("UDP Nat: client %v <-> proxy exit %v", clientAddr, targetConn.LocalAddr())

			proxyTargetBytes, err = targetConn.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
			if err != nil {
				return onet.NewConnectionError("ERR_WRITE", "Failed to write to target", err)
			}
			return nil
		}()
	}
}

func (s *udpService) Stop() error {
	s.isRunning = false
	return s.clientConn.Close()
}

// Packet NAT table
type natmap struct {
	sync.RWMutex
	keyConn map[string]net.PacketConn
	timeout time.Duration
	metrics metrics.ShadowsocksMetrics
}

func newNATmap(timeout time.Duration, sm metrics.ShadowsocksMetrics) *natmap {
	m := &natmap{metrics: sm}
	m.keyConn = make(map[string]net.PacketConn)
	m.timeout = timeout
	return m
}

func (m *natmap) Get(key string) net.PacketConn {
	m.RLock()
	defer m.RUnlock()
	return m.keyConn[key]
}

func (m *natmap) set(key string, pc net.PacketConn) {
	m.Lock()
	defer m.Unlock()

	m.keyConn[key] = pc
}

func (m *natmap) del(key string) net.PacketConn {
	m.Lock()
	defer m.Unlock()

	pc, ok := m.keyConn[key]
	if ok {
		delete(m.keyConn, key)
		return pc
	}
	return nil
}

func (m *natmap) Add(clientAddr net.Addr, clientConn net.PacketConn, cipher shadowaead.Cipher, targetConn net.PacketConn, clientLocation, keyID string) {
	m.set(clientAddr.String(), targetConn)

	m.metrics.AddUdpNatEntry()
	go func() {
		timedCopy(clientAddr, clientConn, cipher, targetConn, m.timeout, clientLocation, keyID, m.metrics)
		m.metrics.RemoveUdpNatEntry()
		if pc := m.del(clientAddr.String()); pc != nil {
			pc.Close()
		}
	}()
}

// copy from src to dst at target with read timeout
func timedCopy(clientAddr net.Addr, clientConn net.PacketConn, cipher shadowaead.Cipher, targetConn net.PacketConn,
	timeout time.Duration, clientLocation, keyID string, sm metrics.ShadowsocksMetrics) {
	textBuf := make([]byte, udpBufSize)
	cipherBuf := make([]byte, udpBufSize)

	expired := false
	for !expired {
		var targetProxyBytes, proxyClientBytes int
		connError := func() (connError *onet.ConnectionError) {
			var (
				raddr net.Addr
				err   error
			)
			targetConn.SetReadDeadline(time.Now().Add(timeout))
			targetProxyBytes, raddr, err = targetConn.ReadFrom(textBuf)
			if err != nil {
				if netErr, ok := err.(net.Error); ok {
					if netErr.Timeout() {
						expired = true
						return nil
					}
				}
				return onet.NewConnectionError("ERR_READ", "Failed to read from target", err)
			}

			srcAddr := socks.ParseAddr(raddr.String())
			logger.Debugf("UDP response from %v to %v", srcAddr, clientAddr)
			// Shift data buffer to prepend with srcAddr.
			copy(textBuf[len(srcAddr):], textBuf[:targetProxyBytes])
			copy(textBuf, srcAddr)

			buf, err := shadowaead.Pack(cipherBuf, textBuf[:len(srcAddr)+targetProxyBytes], cipher)
			if err != nil {
				return onet.NewConnectionError("ERR_PACK", "Failed to pack data to client", err)
			}
			proxyClientBytes, err = clientConn.WriteTo(buf, clientAddr)
			if err != nil {
				return onet.NewConnectionError("ERR_WRITE", "Failed to write to client", err)
			}
			return nil
		}()
		status := "OK"
		if connError != nil {
			logger.Debugf("UDP Error: %v: %v", connError.Message, connError.Cause)
			status = connError.Status
		}
		sm.AddUDPPacketFromTarget(clientLocation, keyID, status, targetProxyBytes, proxyClientBytes)
	}
}
<commit_msg>spelling: decrypts<commit_after>// Copyright 2018 Jigsaw Operations LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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 shadowsocks

import (
	"errors"
	"fmt"
	"net"
	"runtime/debug"
	"time"

	"github.com/Jigsaw-Code/outline-ss-server/metrics"
	onet "github.com/Jigsaw-Code/outline-ss-server/net"

	"sync"

	"github.com/shadowsocks/go-shadowsocks2/shadowaead"
	"github.com/shadowsocks/go-shadowsocks2/socks"
)

const udpBufSize = 64 * 1024

// upack decrypts src into dst. It tries each cipher until it finds one that authenticates
// correctly. dst and src must not overlap.
func unpack(dst, src []byte, ciphers map[string]shadowaead.Cipher) ([]byte, string, shadowaead.Cipher, error) {
	for id, cipher := range ciphers {
		logger.Debugf("Trying UDP cipher %v", id)
		buf, err := shadowaead.Unpack(dst, src, cipher)
		if err != nil {
			logger.Debugf("Failed UDP cipher %v: %v", id, err)
			continue
		}
		logger.Debugf("Selected UDP cipher %v", id)
		return buf, id, cipher, nil
	}
	return nil, "", nil, errors.New("could not find valid cipher")
}

type udpService struct {
	clientConn net.PacketConn
	natTimeout time.Duration
	ciphers    *map[string]shadowaead.Cipher
	m          metrics.ShadowsocksMetrics
	isRunning  bool
}

func NewUDPService(clientConn net.PacketConn, natTimeout time.Duration, ciphers *map[string]shadowaead.Cipher, m metrics.ShadowsocksMetrics) UDPService {
	return &udpService{clientConn: clientConn, natTimeout: natTimeout, ciphers: ciphers, m: m}
}

type UDPService interface {
	Start()
	Stop() error
}

// Listen on addr for encrypted packets and basically do UDP NAT.
// We take the ciphers as a pointer because it gets replaced on config updates.
func (s *udpService) Start() {
	defer s.clientConn.Close()

	nm := newNATmap(s.natTimeout, s.m)
	cipherBuf := make([]byte, udpBufSize)
	textBuf := make([]byte, udpBufSize)

	s.isRunning = true
	for s.isRunning {
		func() (connError *onet.ConnectionError) {
			defer func() {
				if r := recover(); r != nil {
					logger.Errorf("Panic in UDP loop: %v", r)
					debug.PrintStack()
				}
			}()
			clientLocation := ""
			keyID := ""
			var clientProxyBytes, proxyTargetBytes int
			defer func() {
				status := "OK"
				if connError != nil {
					logger.Debugf("UDP Error: %v: %v", connError.Message, connError.Cause)
					status = connError.Status
				}
				s.m.AddUDPPacketFromClient(clientLocation, keyID, status, clientProxyBytes, proxyTargetBytes)
			}()
			clientProxyBytes, clientAddr, err := s.clientConn.ReadFrom(cipherBuf)
			if err != nil {
				if !s.isRunning {
					return nil
				}
				return onet.NewConnectionError("ERR_READ", "Failed to read from client", err)
			}
			clientLocation, locErr := s.m.GetLocation(clientAddr)
			if locErr != nil {
				logger.Warningf("Failed location lookup: %v", locErr)
			}
			logger.Debugf("Got location \"%v\" for IP %v", clientLocation, clientAddr.String())
			defer logger.Debugf("UDP done with %v", clientAddr.String())
			logger.Debugf("UDP Request from %v with %v bytes", clientAddr, clientProxyBytes)
			buf, keyID, cipher, err := unpack(textBuf, cipherBuf[:clientProxyBytes], *s.ciphers)
			if err != nil {
				return onet.NewConnectionError("ERR_CIPHER", "Failed to upack data from client", err)
			}

			tgtAddr := socks.SplitAddr(buf)
			if tgtAddr == nil {
				return onet.NewConnectionError("ERR_READ_ADDRESS", "Failed to get target address", nil)
			}

			tgtUDPAddr, err := net.ResolveUDPAddr("udp", tgtAddr.String())
			if err != nil {
				return onet.NewConnectionError("ERR_RESOLVE_ADDRESS", fmt.Sprintf("Failed to resolve target address %v", tgtAddr.String()), err)
			}
			if !tgtUDPAddr.IP.IsGlobalUnicast() {
				return onet.NewConnectionError("ERR_ADDRESS_INVALID", fmt.Sprintf("Target address is not global unicast: %v", tgtAddr.String()), err)
			}

			payload := buf[len(tgtAddr):]

			targetConn := nm.Get(clientAddr.String())
			if targetConn == nil {
				targetConn, err = net.ListenPacket("udp", "")
				if err != nil {
					return onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
				}
				nm.Add(clientAddr, s.clientConn, cipher, targetConn, clientLocation, keyID)
			}
			logger.Debugf("UDP Nat: client %v <-> proxy exit %v", clientAddr, targetConn.LocalAddr())

			proxyTargetBytes, err = targetConn.WriteTo(payload, tgtUDPAddr) // accept only UDPAddr despite the signature
			if err != nil {
				return onet.NewConnectionError("ERR_WRITE", "Failed to write to target", err)
			}
			return nil
		}()
	}
}

func (s *udpService) Stop() error {
	s.isRunning = false
	return s.clientConn.Close()
}

// Packet NAT table
type natmap struct {
	sync.RWMutex
	keyConn map[string]net.PacketConn
	timeout time.Duration
	metrics metrics.ShadowsocksMetrics
}

func newNATmap(timeout time.Duration, sm metrics.ShadowsocksMetrics) *natmap {
	m := &natmap{metrics: sm}
	m.keyConn = make(map[string]net.PacketConn)
	m.timeout = timeout
	return m
}

func (m *natmap) Get(key string) net.PacketConn {
	m.RLock()
	defer m.RUnlock()
	return m.keyConn[key]
}

func (m *natmap) set(key string, pc net.PacketConn) {
	m.Lock()
	defer m.Unlock()

	m.keyConn[key] = pc
}

func (m *natmap) del(key string) net.PacketConn {
	m.Lock()
	defer m.Unlock()

	pc, ok := m.keyConn[key]
	if ok {
		delete(m.keyConn, key)
		return pc
	}
	return nil
}

func (m *natmap) Add(clientAddr net.Addr, clientConn net.PacketConn, cipher shadowaead.Cipher, targetConn net.PacketConn, clientLocation, keyID string) {
	m.set(clientAddr.String(), targetConn)

	m.metrics.AddUdpNatEntry()
	go func() {
		timedCopy(clientAddr, clientConn, cipher, targetConn, m.timeout, clientLocation, keyID, m.metrics)
		m.metrics.RemoveUdpNatEntry()
		if pc := m.del(clientAddr.String()); pc != nil {
			pc.Close()
		}
	}()
}

// copy from src to dst at target with read timeout
func timedCopy(clientAddr net.Addr, clientConn net.PacketConn, cipher shadowaead.Cipher, targetConn net.PacketConn,
	timeout time.Duration, clientLocation, keyID string, sm metrics.ShadowsocksMetrics) {
	textBuf := make([]byte, udpBufSize)
	cipherBuf := make([]byte, udpBufSize)

	expired := false
	for !expired {
		var targetProxyBytes, proxyClientBytes int
		connError := func() (connError *onet.ConnectionError) {
			var (
				raddr net.Addr
				err   error
			)
			targetConn.SetReadDeadline(time.Now().Add(timeout))
			targetProxyBytes, raddr, err = targetConn.ReadFrom(textBuf)
			if err != nil {
				if netErr, ok := err.(net.Error); ok {
					if netErr.Timeout() {
						expired = true
						return nil
					}
				}
				return onet.NewConnectionError("ERR_READ", "Failed to read from target", err)
			}

			srcAddr := socks.ParseAddr(raddr.String())
			logger.Debugf("UDP response from %v to %v", srcAddr, clientAddr)
			// Shift data buffer to prepend with srcAddr.
			copy(textBuf[len(srcAddr):], textBuf[:targetProxyBytes])
			copy(textBuf, srcAddr)

			buf, err := shadowaead.Pack(cipherBuf, textBuf[:len(srcAddr)+targetProxyBytes], cipher)
			if err != nil {
				return onet.NewConnectionError("ERR_PACK", "Failed to pack data to client", err)
			}
			proxyClientBytes, err = clientConn.WriteTo(buf, clientAddr)
			if err != nil {
				return onet.NewConnectionError("ERR_WRITE", "Failed to write to client", err)
			}
			return nil
		}()
		status := "OK"
		if connError != nil {
			logger.Debugf("UDP Error: %v: %v", connError.Message, connError.Cause)
			status = connError.Status
		}
		sm.AddUDPPacketFromTarget(clientLocation, keyID, status, targetProxyBytes, proxyClientBytes)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command subscriptions is a tool to manage Google Cloud Pub/Sub subscriptions by using the Pub/Sub API.
// See more about Google Cloud Pub/Sub at https://cloud.google.com/pubsub/docs/overview.
package main

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"

	// [START imports]
	"golang.org/x/net/context"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/pubsub"
	"google.golang.org/api/iterator"
	// [END imports]
)

func main() {
	ctx := context.Background()
	// [START auth]
	proj := os.Getenv("GOOGLE_CLOUD_PROJECT")
	if proj == "" {
		fmt.Fprintf(os.Stderr, "GOOGLE_CLOUD_PROJECT environment variable must be set.\n")
		os.Exit(1)
	}
	client, err := pubsub.NewClient(ctx, proj)
	if err != nil {
		log.Fatalf("Could not create pubsub Client: %v", err)
	}
	// [END auth]

	// Print all the subscriptions in the project.
	fmt.Println("Listing all subscriptions from the project:")
	subs, err := list(client)
	if err != nil {
		log.Fatal(err)
	}
	for _, sub := range subs {
		fmt.Println(sub)
	}

	t := createTopicIfNotExists(client)

	const sub = "example-subscription"
	// Create a new subscription.
	if err := create(client, sub, t); err != nil {
		log.Fatal(err)
	}

	// Pull messages via the subscription.
	if err := pullMsgs(client, sub, t); err != nil {
		log.Fatal(err)
	}

	// Delete the subscription.
	if err := delete(client, sub); err != nil {
		log.Fatal(err)
	}
}

func list(client *pubsub.Client) ([]*pubsub.Subscription, error) {
	ctx := context.Background()
	// [START get_all_subscriptions]
	var subs []*pubsub.Subscription
	it := client.Subscriptions(ctx)
	for {
		s, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		subs = append(subs, s)
	}
	// [END get_all_subscriptions]
	return subs, nil
}

func pullMsgs(client *pubsub.Client, name string, topic *pubsub.Topic) error {
	ctx := context.Background()

	// Publish 10 messages on the topic.
	var results []*pubsub.PublishResult
	for i := 0; i < 10; i++ {
		res := topic.Publish(ctx, &pubsub.Message{
			Data: []byte(fmt.Sprintf("hello world #%d", i)),
		})
		results = append(results, res)
	}

	// Check that all messages were published.
	for _, r := range results {
		_, err := r.Get(ctx)
		if err != nil {
			return err
		}
	}

	// [START pull_messages]
	// Consume 10 messages.
	var mu sync.Mutex
	received := 0
	sub := client.Subscription(name)
	cctx, cancel := context.WithCancel(ctx)
	err := sub.Receive(cctx, func(ctx context.Context, msg *pubsub.Message) {
		mu.Lock()
		defer mu.Unlock()
		received++
		if received >= 10 {
			cancel()
			msg.Nack()
			return
		}
		fmt.Printf("Got message: %q\n", string(msg.Data))
		msg.Ack()
	})
	if err != nil {
		return err
	}
	// [END pull_messages]
	return nil
}

func pullMsgsError(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START pull_messages_error]
	// If the service returns a non-retryable error, Receive returns that error after
	// all of the outstanding calls to the handler have returned.
	err := client.Subscription(name).Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		fmt.Printf("Got message: %q\n", string(msg.Data))
		msg.Ack()
	})
	if err != nil {
		return err
	}
	// [END pull_messages_error]
	return nil
}

func pullMsgsSettings(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START pull_messages_settings]
	sub := client.Subscription(name)
	sub.ReceiveSettings.MaxOutstandingMessages = 10
	err := sub.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		fmt.Printf("Got message: %q\n", string(msg.Data))
		msg.Ack()
	})
	if err != nil {
		return err
	}
	// [END pull_messages_settings]
	return nil
}

func create(client *pubsub.Client, name string, topic *pubsub.Topic) error {
	ctx := context.Background()
	// [START create_subscription]
	sub, err := client.CreateSubscription(ctx, name, pubsub.SubscriptionConfig{
		Topic:       topic,
		AckDeadline: 20 * time.Second,
	})
	if err != nil {
		return err
	}
	fmt.Printf("Created subscription: %v\n", sub)
	// [END create_subscription]
	return nil
}

func createWithEndpoint(client *pubsub.Client, name string, topic *pubsub.Topic, endpoint string) error {
	ctx := context.Background()
	// [START create_push_subscription]

	// For example, endpoint is "https://my-test-project.appspot.com/push".
	sub, err := client.CreateSubscription(ctx, name, pubsub.SubscriptionConfig{
		Topic:       topic,
		AckDeadline: 10 * time.Second,
		PushConfig:  pubsub.PushConfig{Endpoint: endpoint},
	})
	if err != nil {
		return err
	}
	fmt.Printf("Created subscription: %v\n", sub)
	// [END create_push_subscription]
	return nil
}

func updateEndpoint(client *pubsub.Client, name string, endpoint string) error {
	ctx := context.Background()
	// [START update_push_subscription]

	// For example, endpoint is "https://my-test-project.appspot.com/push".
	subConfig, err := client.Subscription(name).Update(ctx, pubsub.SubscriptionConfigToUpdate{
		PushConfig: &pubsub.PushConfig{Endpoint: endpoint},
	})
	if err != nil {
		return err
	}
	fmt.Printf("Updated subscription config: %#v", subConfig)
	// [END update_push_subscription]
	return nil
}

func delete(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START delete_subscription]
	sub := client.Subscription(name)
	if err := sub.Delete(ctx); err != nil {
		return err
	}
	fmt.Println("Subscription deleted.")
	// [END delete_subscription]
	return nil
}

func createTopicIfNotExists(c *pubsub.Client) *pubsub.Topic {
	ctx := context.Background()

	const topic = "example-topic"
	// Create a topic to subscribe to.
	t := c.Topic(topic)
	ok, err := t.Exists(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if ok {
		return t
	}

	t, err = c.CreateTopic(ctx, topic)
	if err != nil {
		log.Fatalf("Failed to create the topic: %v", err)
	}
	return t
}

func getPolicy(c *pubsub.Client, subName string) (*iam.Policy, error) {
	ctx := context.Background()

	// [START pubsub_get_subscription_policy]
	policy, err := c.Subscription(subName).IAM().Policy(ctx)
	if err != nil {
		return nil, err
	}
	for _, role := range policy.Roles() {
		log.Printf("%q: %q", role, policy.Members(role))
	}
	// [END pubsub_get_subscription_policy]
	return policy, nil
}

func addUsers(c *pubsub.Client, subName string) error {
	ctx := context.Background()

	// [START pubsub_set_subscription_policy]
	sub := c.Subscription(subName)
	policy, err := sub.IAM().Policy(ctx)
	if err != nil {
		return err
	}
	// Other valid prefixes are "serviceAccount:", "user:"
	// See the documentation for more values.
	policy.Add(iam.AllUsers, iam.Viewer)
	policy.Add("group:cloud-logs@google.com", iam.Editor)
	if err := sub.IAM().SetPolicy(ctx, policy); err != nil {
		return err
	}
	// NOTE: It may be necessary to retry this operation if IAM policies are
	// being modified concurrently. SetPolicy will return an error if the policy
	// was modified since it was retrieved.
	// [END pubsub_set_subscription_policy]
	return nil
}

func testPermissions(c *pubsub.Client, subName string) ([]string, error) {
	ctx := context.Background()

	// [START pubsub_test_subscription_permissions]
	sub := c.Subscription(subName)
	perms, err := sub.IAM().TestPermissions(ctx, []string{
		"pubsub.subscriptions.consume",
		"pubsub.subscriptions.update",
	})
	if err != nil {
		return nil, err
	}
	for _, perm := range perms {
		log.Printf("Allowed: %v", perm)
	}
	// [END pubsub_test_subscription_permissions]
	return perms, nil
}
<commit_msg>pubsub/subscriptions: Ack all 10 messages (#455)<commit_after>// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// Command subscriptions is a tool to manage Google Cloud Pub/Sub subscriptions by using the Pub/Sub API.
// See more about Google Cloud Pub/Sub at https://cloud.google.com/pubsub/docs/overview.
package main

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"

	// [START imports]
	"golang.org/x/net/context"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/pubsub"
	"google.golang.org/api/iterator"
	// [END imports]
)

func main() {
	ctx := context.Background()
	// [START auth]
	proj := os.Getenv("GOOGLE_CLOUD_PROJECT")
	if proj == "" {
		fmt.Fprintf(os.Stderr, "GOOGLE_CLOUD_PROJECT environment variable must be set.\n")
		os.Exit(1)
	}
	client, err := pubsub.NewClient(ctx, proj)
	if err != nil {
		log.Fatalf("Could not create pubsub Client: %v", err)
	}
	// [END auth]

	// Print all the subscriptions in the project.
	fmt.Println("Listing all subscriptions from the project:")
	subs, err := list(client)
	if err != nil {
		log.Fatal(err)
	}
	for _, sub := range subs {
		fmt.Println(sub)
	}

	t := createTopicIfNotExists(client)

	const sub = "example-subscription"
	// Create a new subscription.
	if err := create(client, sub, t); err != nil {
		log.Fatal(err)
	}

	// Pull messages via the subscription.
	if err := pullMsgs(client, sub, t); err != nil {
		log.Fatal(err)
	}

	// Delete the subscription.
	if err := delete(client, sub); err != nil {
		log.Fatal(err)
	}
}

func list(client *pubsub.Client) ([]*pubsub.Subscription, error) {
	ctx := context.Background()
	// [START get_all_subscriptions]
	var subs []*pubsub.Subscription
	it := client.Subscriptions(ctx)
	for {
		s, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		subs = append(subs, s)
	}
	// [END get_all_subscriptions]
	return subs, nil
}

func pullMsgs(client *pubsub.Client, name string, topic *pubsub.Topic) error {
	ctx := context.Background()

	// Publish 10 messages on the topic.
	var results []*pubsub.PublishResult
	for i := 0; i < 10; i++ {
		res := topic.Publish(ctx, &pubsub.Message{
			Data: []byte(fmt.Sprintf("hello world #%d", i)),
		})
		results = append(results, res)
	}

	// Check that all messages were published.
	for _, r := range results {
		_, err := r.Get(ctx)
		if err != nil {
			return err
		}
	}

	// [START pull_messages]
	// Consume 10 messages.
	var mu sync.Mutex
	received := 0
	sub := client.Subscription(name)
	cctx, cancel := context.WithCancel(ctx)
	err := sub.Receive(cctx, func(ctx context.Context, msg *pubsub.Message) {
		msg.Ack()
		fmt.Printf("Got message: %q\n", string(msg.Data))
		mu.Lock()
		defer mu.Unlock()
		received++
		if received == 10 {
			cancel()
		}
	})
	if err != nil {
		return err
	}
	// [END pull_messages]
	return nil
}

func pullMsgsError(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START pull_messages_error]
	// If the service returns a non-retryable error, Receive returns that error after
	// all of the outstanding calls to the handler have returned.
	err := client.Subscription(name).Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		fmt.Printf("Got message: %q\n", string(msg.Data))
		msg.Ack()
	})
	if err != nil {
		return err
	}
	// [END pull_messages_error]
	return nil
}

func pullMsgsSettings(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START pull_messages_settings]
	sub := client.Subscription(name)
	sub.ReceiveSettings.MaxOutstandingMessages = 10
	err := sub.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		fmt.Printf("Got message: %q\n", string(msg.Data))
		msg.Ack()
	})
	if err != nil {
		return err
	}
	// [END pull_messages_settings]
	return nil
}

func create(client *pubsub.Client, name string, topic *pubsub.Topic) error {
	ctx := context.Background()
	// [START create_subscription]
	sub, err := client.CreateSubscription(ctx, name, pubsub.SubscriptionConfig{
		Topic:       topic,
		AckDeadline: 20 * time.Second,
	})
	if err != nil {
		return err
	}
	fmt.Printf("Created subscription: %v\n", sub)
	// [END create_subscription]
	return nil
}

func createWithEndpoint(client *pubsub.Client, name string, topic *pubsub.Topic, endpoint string) error {
	ctx := context.Background()
	// [START create_push_subscription]

	// For example, endpoint is "https://my-test-project.appspot.com/push".
	sub, err := client.CreateSubscription(ctx, name, pubsub.SubscriptionConfig{
		Topic:       topic,
		AckDeadline: 10 * time.Second,
		PushConfig:  pubsub.PushConfig{Endpoint: endpoint},
	})
	if err != nil {
		return err
	}
	fmt.Printf("Created subscription: %v\n", sub)
	// [END create_push_subscription]
	return nil
}

func updateEndpoint(client *pubsub.Client, name string, endpoint string) error {
	ctx := context.Background()
	// [START update_push_subscription]

	// For example, endpoint is "https://my-test-project.appspot.com/push".
	subConfig, err := client.Subscription(name).Update(ctx, pubsub.SubscriptionConfigToUpdate{
		PushConfig: &pubsub.PushConfig{Endpoint: endpoint},
	})
	if err != nil {
		return err
	}
	fmt.Printf("Updated subscription config: %#v", subConfig)
	// [END update_push_subscription]
	return nil
}

func delete(client *pubsub.Client, name string) error {
	ctx := context.Background()
	// [START delete_subscription]
	sub := client.Subscription(name)
	if err := sub.Delete(ctx); err != nil {
		return err
	}
	fmt.Println("Subscription deleted.")
	// [END delete_subscription]
	return nil
}

func createTopicIfNotExists(c *pubsub.Client) *pubsub.Topic {
	ctx := context.Background()

	const topic = "example-topic"
	// Create a topic to subscribe to.
	t := c.Topic(topic)
	ok, err := t.Exists(ctx)
	if err != nil {
		log.Fatal(err)
	}
	if ok {
		return t
	}

	t, err = c.CreateTopic(ctx, topic)
	if err != nil {
		log.Fatalf("Failed to create the topic: %v", err)
	}
	return t
}

func getPolicy(c *pubsub.Client, subName string) (*iam.Policy, error) {
	ctx := context.Background()

	// [START pubsub_get_subscription_policy]
	policy, err := c.Subscription(subName).IAM().Policy(ctx)
	if err != nil {
		return nil, err
	}
	for _, role := range policy.Roles() {
		log.Printf("%q: %q", role, policy.Members(role))
	}
	// [END pubsub_get_subscription_policy]
	return policy, nil
}

func addUsers(c *pubsub.Client, subName string) error {
	ctx := context.Background()

	// [START pubsub_set_subscription_policy]
	sub := c.Subscription(subName)
	policy, err := sub.IAM().Policy(ctx)
	if err != nil {
		return err
	}
	// Other valid prefixes are "serviceAccount:", "user:"
	// See the documentation for more values.
	policy.Add(iam.AllUsers, iam.Viewer)
	policy.Add("group:cloud-logs@google.com", iam.Editor)
	if err := sub.IAM().SetPolicy(ctx, policy); err != nil {
		return err
	}
	// NOTE: It may be necessary to retry this operation if IAM policies are
	// being modified concurrently. SetPolicy will return an error if the policy
	// was modified since it was retrieved.
	// [END pubsub_set_subscription_policy]
	return nil
}

func testPermissions(c *pubsub.Client, subName string) ([]string, error) {
	ctx := context.Background()

	// [START pubsub_test_subscription_permissions]
	sub := c.Subscription(subName)
	perms, err := sub.IAM().TestPermissions(ctx, []string{
		"pubsub.subscriptions.consume",
		"pubsub.subscriptions.update",
	})
	if err != nil {
		return nil, err
	}
	for _, perm := range perms {
		log.Printf("Allowed: %v", perm)
	}
	// [END pubsub_test_subscription_permissions]
	return perms, nil
}
<|endoftext|>


<commit_before>package bufit

import (
	"bytes"
	"crypto/rand"
	"io"
	"io/ioutil"
	"os"
	"sync"
	"testing"
	"time"
)

func ExampleBytes() {
	buf := newWriter(make([]byte, 0, 10))
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, io.NewSectionReader(*&buf, 0, 100))

	io.WriteString(buf, "Hello ")
	r := io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 5)
	io.CopyN(os.Stdout, buf, 5)
	io.WriteString(buf, "World")
	r = io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 6)

	io.WriteString(buf, "abcdefg")
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, buf)

	io.WriteString(buf, "Hello World")
	r = io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 5)
	io.CopyN(os.Stdout, buf, 4)

	io.WriteString(buf, "abcdefg")
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, buf)
	//Output:
	// HelloHello World WorldabcdefgHelloHello Worldabcdefg
}

type badBuffer []byte

func (b *badBuffer) Write(p []byte) (int, error) {
	*b = append(*b, p...)
	return len(p), nil
}

func (b *badBuffer) Read(p []byte) (n int, err error) {
	n = copy(p, *b)
	*b = (*b)[n:]
	if len(*b) == 0 {
		err = io.EOF
	}
	return n, err
}

func BenchmarkBuffer(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(1)
	}
	b.ReportAllocs()
}

func BenchmarkBuffer100(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(100)
	}
	b.ReportAllocs()
}

func BenchmarkBuffer1000(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(1000)
	}
	b.ReportAllocs()
}

func benchBuffer(n int) {
	var grp sync.WaitGroup
	buf := New()
	go func() {
		io.CopyN(buf, rand.Reader, 32*1024*100)
		buf.Close()
	}()
	rs := []io.Reader{}
	for i := 0; i < n; i++ {
		rs = append(rs, buf.NextReader())
	}
	for _, rdr := range rs {
		grp.Add(1)
		go func(r io.Reader) {
			defer grp.Done()
			io.Copy(ioutil.Discard, r)
		}(rdr)
	}
	grp.Wait()
}

func BenchmarkStdBuffer(b *testing.B) {
	for i := 0; i < b.N; i++ {
		r, w := io.Pipe()
		go func() {
			io.CopyN(w, rand.Reader, 32*1024*100)
			w.Close()
		}()
		io.Copy(ioutil.Discard, r)
	}
	b.ReportAllocs()
}

func BenchmarkMyBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryBuffer(newWriter(nil))
	}
	b.ReportAllocs()
}

func BenchmarkStdBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryBuffer(bytes.NewBuffer(nil))
	}
	b.ReportAllocs()
}

func BenchmarkFwdMyBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryFwdBuffer(newWriter(nil))
	}
	b.ReportAllocs()
}

func BenchmarkStdFwdBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryFwdBuffer(bytes.NewBuffer(nil))
	}
	b.ReportAllocs()
}

const tries = 1000

func tryFwdBuffer(buf io.ReadWriter) {
	for i := 0; i < tries; i++ {
		io.CopyN(buf, rand.Reader, 60*1024)
		io.Copy(ioutil.Discard, buf)
	}
}

func tryBuffer(buf io.ReadWriter) {
	for i := 0; i < tries; i++ {
		io.CopyN(buf, rand.Reader, 60*1024)
		io.CopyN(ioutil.Discard, buf, 32*1024)
		io.CopyN(buf, rand.Reader, 60*1024)
	}
	io.Copy(ioutil.Discard, buf)
}

func TestConcurrent(t *testing.T) {
	var grp sync.WaitGroup
	buf := New()

	var rs []io.ReadCloser
	for i := 0; i < 1000; i++ {
		rs = append(rs, buf.NextReader())
	}

	testData := bytes.NewBuffer(nil)
	io.CopyN(testData, rand.Reader, 32*1024*10)

	for _, r := range rs {
		grp.Add(1)
		go func(r io.ReadCloser) {
			defer grp.Done()
			defer r.Close()
			data, err := ioutil.ReadAll(r)
			if err != nil {
				t.Error(err)
			}
			if !bytes.Equal(testData.Bytes(), data) {
				t.Error("unexpected result...", testData.Len(), len(data))
			}
		}(r)
	}

	r := bytes.NewReader(testData.Bytes())
	for r.Len() > 0 {
		io.CopyN(buf, r, 32*1024*2)
		<-time.After(100 * time.Millisecond)
	}
	buf.Close()
	grp.Wait()
}

func ExampleBuffer() {
	// Start a new buffer
	buf := New()

	// Create two readers
	r1, r2 := buf.NextReader(), buf.NextReader()

	// Broadcast a message
	io.WriteString(buf, "Hello World\n")

	// Wait
	var grp sync.WaitGroup
	grp.Add(4)

	// Read fast
	go func() {
		defer grp.Done()
		io.Copy(os.Stdout, r1) // "Hello World\n"
	}()

	// Read slow
	go func() {
		defer grp.Done()
		<-time.After(100 * time.Millisecond)
		io.CopyN(os.Stdout, r2, 5) // "Hello"
		<-time.After(time.Second)
		io.Copy(os.Stdout, r2) // "World\n"
	}()

	// Both readers will read the entire buffer! The slow reader
	// won't block the fast one from reading ahead either.

	// Late reader
	// Since this reader joins after all existing readers have Read "Hello"
	// "Hello" has already been cleared from the Buffer, this Reader will only see
	// "World\n" and beyond.
	go func() {
		defer grp.Done()
		<-time.After(500 * time.Millisecond)
		r3 := buf.NextReader()
		io.Copy(os.Stdout, r3) // "World\n"
	}()

	// Short Reader
	// **Important!** if your reader isn't going to read until the buffer is empty
	// you'll need to call Close() when you are done with it to tell the buffer
	// it's done reading data.
	go func() {
		defer grp.Done()
		<-time.After(100 * time.Millisecond)
		r4 := buf.NextReader()
		io.CopyN(os.Stdout, r4, 5) // "Hello"
		r4.Close()                 // tell the buffer you're done reading
	}()

	// **Important!** mark close so that readers can ret. io.EOF
	buf.Close()

	grp.Wait()
	// Output:
	// Hello World
	// HelloHelloHello World
	//  World
}
<commit_msg>adding test case for breaking fetch on Read<commit_after>package bufit

import (
	"bytes"
	"crypto/rand"
	"io"
	"io/ioutil"
	"os"
	"sync"
	"testing"
	"time"
)

func ExampleBytes() {
	buf := newWriter(make([]byte, 0, 10))
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, io.NewSectionReader(*&buf, 0, 100))

	io.WriteString(buf, "Hello ")
	r := io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 5)
	io.CopyN(os.Stdout, buf, 5)
	io.WriteString(buf, "World")
	r = io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 6)

	io.WriteString(buf, "abcdefg")
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, buf)

	io.WriteString(buf, "Hello World")
	r = io.NewSectionReader(*&buf, 0, int64(buf.Len()))
	io.CopyN(os.Stdout, r, 5)
	io.CopyN(os.Stdout, buf, 4)

	io.WriteString(buf, "abcdefg")
	io.Copy(os.Stdout, buf)
	io.Copy(os.Stdout, buf)
	//Output:
	// HelloHello World WorldabcdefgHelloHello Worldabcdefg
}

type badBuffer []byte

func (b *badBuffer) Write(p []byte) (int, error) {
	*b = append(*b, p...)
	return len(p), nil
}

func (b *badBuffer) Read(p []byte) (n int, err error) {
	n = copy(p, *b)
	*b = (*b)[n:]
	if len(*b) == 0 {
		err = io.EOF
	}
	return n, err
}

func BenchmarkBuffer(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(1)
	}
	b.ReportAllocs()
}

func BenchmarkBuffer100(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(100)
	}
	b.ReportAllocs()
}

func BenchmarkBuffer1000(b *testing.B) {
	for i := 0; i < b.N; i++ {
		benchBuffer(1000)
	}
	b.ReportAllocs()
}

func benchBuffer(n int) {
	var grp sync.WaitGroup
	buf := New()
	go func() {
		io.CopyN(buf, rand.Reader, 32*1024*100)
		buf.Close()
	}()
	rs := []io.Reader{}
	for i := 0; i < n; i++ {
		rs = append(rs, buf.NextReader())
	}
	for _, rdr := range rs {
		grp.Add(1)
		go func(r io.Reader) {
			defer grp.Done()
			io.Copy(ioutil.Discard, r)
		}(rdr)
	}
	grp.Wait()
}

func BenchmarkStdBuffer(b *testing.B) {
	for i := 0; i < b.N; i++ {
		r, w := io.Pipe()
		go func() {
			io.CopyN(w, rand.Reader, 32*1024*100)
			w.Close()
		}()
		io.Copy(ioutil.Discard, r)
	}
	b.ReportAllocs()
}

func BenchmarkMyBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryBuffer(newWriter(nil))
	}
	b.ReportAllocs()
}

func BenchmarkStdBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryBuffer(bytes.NewBuffer(nil))
	}
	b.ReportAllocs()
}

func BenchmarkFwdMyBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryFwdBuffer(newWriter(nil))
	}
	b.ReportAllocs()
}

func BenchmarkStdFwdBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		tryFwdBuffer(bytes.NewBuffer(nil))
	}
	b.ReportAllocs()
}

const tries = 1000

func tryFwdBuffer(buf io.ReadWriter) {
	for i := 0; i < tries; i++ {
		io.CopyN(buf, rand.Reader, 60*1024)
		io.Copy(ioutil.Discard, buf)
	}
}

func tryBuffer(buf io.ReadWriter) {
	for i := 0; i < tries; i++ {
		io.CopyN(buf, rand.Reader, 60*1024)
		io.CopyN(ioutil.Discard, buf, 32*1024)
		io.CopyN(buf, rand.Reader, 60*1024)
	}
	io.Copy(ioutil.Discard, buf)
}

func TestConcurrent(t *testing.T) {
	var grp sync.WaitGroup
	buf := New()

	var rs []io.ReadCloser
	for i := 0; i < 1000; i++ {
		rs = append(rs, buf.NextReader())
	}

	testData := bytes.NewBuffer(nil)
	io.CopyN(testData, rand.Reader, 32*1024*10)

	for _, r := range rs {
		grp.Add(1)
		go func(r io.ReadCloser) {
			defer grp.Done()
			defer r.Close()
			data, err := ioutil.ReadAll(r)
			if err != nil {
				t.Error(err)
			}
			if !bytes.Equal(testData.Bytes(), data) {
				t.Error("unexpected result...", testData.Len(), len(data))
			}
		}(r)
	}

	r := bytes.NewReader(testData.Bytes())
	for r.Len() > 0 {
		io.CopyN(buf, r, 32*1024*2)
		<-time.After(100 * time.Millisecond)
	}
	buf.Close()
	grp.Wait()
}

func TestQuit(t *testing.T) {
	buf := New()
	r := buf.NextReader()

	wait := make(chan struct{})
	go func() {
		io.Copy(ioutil.Discard, r)
		close(wait)
	}()

	r.Close()
	select {
	case <-wait:
	case <-time.After(100 * time.Millisecond):
		t.Error("timed out waiting for Reader to Close")
	}
}

func ExampleBuffer() {
	// Start a new buffer
	buf := New()

	// Create two readers
	r1, r2 := buf.NextReader(), buf.NextReader()

	// Broadcast a message
	io.WriteString(buf, "Hello World\n")

	// Wait
	var grp sync.WaitGroup
	grp.Add(4)

	// Read fast
	go func() {
		defer grp.Done()
		io.Copy(os.Stdout, r1) // "Hello World\n"
	}()

	// Read slow
	go func() {
		defer grp.Done()
		<-time.After(100 * time.Millisecond)
		io.CopyN(os.Stdout, r2, 5) // "Hello"
		<-time.After(time.Second)
		io.Copy(os.Stdout, r2) // "World\n"
	}()

	// Both readers will read the entire buffer! The slow reader
	// won't block the fast one from reading ahead either.

	// Late reader
	// Since this reader joins after all existing readers have Read "Hello"
	// "Hello" has already been cleared from the Buffer, this Reader will only see
	// "World\n" and beyond.
	go func() {
		defer grp.Done()
		<-time.After(500 * time.Millisecond)
		r3 := buf.NextReader()
		io.Copy(os.Stdout, r3) // "World\n"
	}()

	// Short Reader
	// **Important!** if your reader isn't going to read until the buffer is empty
	// you'll need to call Close() when you are done with it to tell the buffer
	// it's done reading data.
	go func() {
		defer grp.Done()
		<-time.After(100 * time.Millisecond)
		r4 := buf.NextReader()
		io.CopyN(os.Stdout, r4, 5) // "Hello"
		r4.Close()                 // tell the buffer you're done reading
	}()

	// **Important!** mark close so that readers can ret. io.EOF
	buf.Close()

	grp.Wait()
	// Output:
	// Hello World
	// HelloHelloHello World
	//  World
}
<|endoftext|>


<commit_before>package simulator

import "testing"

// Error test case 1
func TestErrorCase1(t *testing.T) {
	defer func() {
		if r := recover(); r == nil {
			t.Error("Expected error. But not found any.")
		}
	}()

	circle := new(CircleOfDeath)
	circle.Init(3, 5)
}

// Error test case 2
func TestErrorCase2(t *testing.T) {
	defer func() {
		if r := recover(); r == nil {
			t.Error("Expected error. But not found any.")
		}
	}()

	circle := new(CircleOfDeath)
	circle.Init(0, 5)
}

func TestSimulator(t *testing.T) {
	circle := new(CircleOfDeath)
	circle.Init(7, 1)

	output := circle.Execute()

	if output.LastAlive != 6 {
		t.Error("Expected 7. Got:", output)
	}
}
<commit_msg>- Fixing test error message<commit_after>package simulator

import "testing"

// Error test case 1
func TestErrorCase1(t *testing.T) {
	defer func() {
		if r := recover(); r == nil {
			t.Error("Expected error. But not found any.")
		}
	}()

	circle := new(CircleOfDeath)
	circle.Init(3, 5)
}

// Error test case 2
func TestErrorCase2(t *testing.T) {
	defer func() {
		if r := recover(); r == nil {
			t.Error("Expected error. But not found any.")
		}
	}()

	circle := new(CircleOfDeath)
	circle.Init(0, 5)
}

func TestSimulator(t *testing.T) {
	circle := new(CircleOfDeath)
	circle.Init(7, 1)

	output := circle.Execute()

	if output.LastAlive != 6 {
		t.Error("Expected 6. Got:", output)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"syscall"
)

var (
	envOpener = os.Getenv("OPENER")
	envEditor = os.Getenv("EDITOR")
	envPager  = os.Getenv("PAGER")
	envShell  = os.Getenv("SHELL")
	envTcellTruecolor = os.Getenv("TCELL_TRUECOLOR")
)

var envPathExt = os.Getenv("PATHEXT")

var (
	gDefaultShell      = "cmd"
	gDefaultSocketProt = "tcp"
	gDefaultSocketPath = ":12345"
)

var (
	gUser        *user.User
	gConfigPaths []string
	gMarksPath   string
	gHistoryPath string
)

func init() {
	if envOpener == "" {
		envOpener = `start ""`
	}

	if envEditor == "" {
		envEditor = "notepad"
	}

	if envPager == "" {
		envPager = "more"
	}

	if envShell == "" {
		envShell = "cmd"
	}

	if envTcellTruecolor == "" {
		envTcellTruecolor = "disable"
	}

	u, err := user.Current()
	if err != nil {
		log.Printf("user: %s", err)
	}
	gUser = u

	// remove domain prefix
	gUser.Username = strings.Split(gUser.Username, `\`)[1]

	data := os.Getenv("LOCALAPPDATA")

	gConfigPaths = []string{
		filepath.Join(os.Getenv("ProgramData"), "lf", "lfrc"),
		filepath.Join(data, "lf", "lfrc"),
	}

	gMarksPath = filepath.Join(data, "lf", "marks")
	gHistoryPath = filepath.Join(data, "lf", "history")
}

func detachedCommand(name string, arg ...string) *exec.Cmd {
	cmd := exec.Command(name, arg...)
	cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 8}
	return cmd
}

func pauseCommand() *exec.Cmd {
	return exec.Command("cmd", "/c", "pause")
}

func shellCommand(s string, args []string) *exec.Cmd {
	args = append([]string{"/c", s}, args...)

	args = append(gOpts.shellopts, args...)

	return exec.Command(gOpts.shell, args...)
}

func setDefaults() {
	gOpts.cmds["open"] = &execExpr{"&", "%OPENER% %f%"}
	gOpts.keys["e"] = &execExpr{"$", "%EDITOR% %f%"}
	gOpts.keys["i"] = &execExpr{"!", "%PAGER% %f%"}
	gOpts.keys["w"] = &execExpr{"$", "%SHELL%"}

	gOpts.cmds["doc"] = &execExpr{"!", "lf -doc | %PAGER%"}
	gOpts.keys["<f-1>"] = &callExpr{"doc", nil, 1}
}

func isExecutable(f os.FileInfo) bool {
	exts := strings.Split(envPathExt, string(filepath.ListSeparator))
	for _, e := range exts {
		if strings.HasSuffix(strings.ToLower(f.Name()), strings.ToLower(e)) {
			log.Print(f.Name(), e)
			return true
		}
	}
	return false
}

func isHidden(f os.FileInfo, path string) bool {
	ptr, err := syscall.UTF16PtrFromString(filepath.Join(path, f.Name()))
	if err != nil {
		return false
	}
	attrs, err := syscall.GetFileAttributes(ptr)
	if err != nil {
		return false
	}
	return attrs&syscall.FILE_ATTRIBUTE_HIDDEN != 0
}

func errCrossDevice(err error) bool {
	return err.(*os.LinkError).Err.(syscall.Errno) == 17
}

func exportFiles(f string, fs []string) {
	envFile := fmt.Sprintf(`"%s"`, f)

	var quotedFiles []string
	for _, f := range fs {
		quotedFiles = append(quotedFiles, fmt.Sprintf(`"%s"`, f))
	}
	envFiles := strings.Join(quotedFiles, gOpts.filesep)

	os.Setenv("f", envFile)
	os.Setenv("fs", envFiles)

	if len(fs) == 0 {
		os.Setenv("fx", envFile)
	} else {
		os.Setenv("fx", envFiles)
	}
}
<commit_msg>only listen 127.0.0.1 in the server<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
	"syscall"
)

var (
	envOpener = os.Getenv("OPENER")
	envEditor = os.Getenv("EDITOR")
	envPager  = os.Getenv("PAGER")
	envShell  = os.Getenv("SHELL")
	envTcellTruecolor = os.Getenv("TCELL_TRUECOLOR")
)

var envPathExt = os.Getenv("PATHEXT")

var (
	gDefaultShell      = "cmd"
	gDefaultSocketProt = "tcp"
	gDefaultSocketPath = "127.0.0.1:12345"
)

var (
	gUser        *user.User
	gConfigPaths []string
	gMarksPath   string
	gHistoryPath string
)

func init() {
	if envOpener == "" {
		envOpener = `start ""`
	}

	if envEditor == "" {
		envEditor = "notepad"
	}

	if envPager == "" {
		envPager = "more"
	}

	if envShell == "" {
		envShell = "cmd"
	}

	if envTcellTruecolor == "" {
		envTcellTruecolor = "disable"
	}

	u, err := user.Current()
	if err != nil {
		log.Printf("user: %s", err)
	}
	gUser = u

	// remove domain prefix
	gUser.Username = strings.Split(gUser.Username, `\`)[1]

	data := os.Getenv("LOCALAPPDATA")

	gConfigPaths = []string{
		filepath.Join(os.Getenv("ProgramData"), "lf", "lfrc"),
		filepath.Join(data, "lf", "lfrc"),
	}

	gMarksPath = filepath.Join(data, "lf", "marks")
	gHistoryPath = filepath.Join(data, "lf", "history")
}

func detachedCommand(name string, arg ...string) *exec.Cmd {
	cmd := exec.Command(name, arg...)
	cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: 8}
	return cmd
}

func pauseCommand() *exec.Cmd {
	return exec.Command("cmd", "/c", "pause")
}

func shellCommand(s string, args []string) *exec.Cmd {
	args = append([]string{"/c", s}, args...)

	args = append(gOpts.shellopts, args...)

	return exec.Command(gOpts.shell, args...)
}

func setDefaults() {
	gOpts.cmds["open"] = &execExpr{"&", "%OPENER% %f%"}
	gOpts.keys["e"] = &execExpr{"$", "%EDITOR% %f%"}
	gOpts.keys["i"] = &execExpr{"!", "%PAGER% %f%"}
	gOpts.keys["w"] = &execExpr{"$", "%SHELL%"}

	gOpts.cmds["doc"] = &execExpr{"!", "lf -doc | %PAGER%"}
	gOpts.keys["<f-1>"] = &callExpr{"doc", nil, 1}
}

func isExecutable(f os.FileInfo) bool {
	exts := strings.Split(envPathExt, string(filepath.ListSeparator))
	for _, e := range exts {
		if strings.HasSuffix(strings.ToLower(f.Name()), strings.ToLower(e)) {
			log.Print(f.Name(), e)
			return true
		}
	}
	return false
}

func isHidden(f os.FileInfo, path string) bool {
	ptr, err := syscall.UTF16PtrFromString(filepath.Join(path, f.Name()))
	if err != nil {
		return false
	}
	attrs, err := syscall.GetFileAttributes(ptr)
	if err != nil {
		return false
	}
	return attrs&syscall.FILE_ATTRIBUTE_HIDDEN != 0
}

func errCrossDevice(err error) bool {
	return err.(*os.LinkError).Err.(syscall.Errno) == 17
}

func exportFiles(f string, fs []string) {
	envFile := fmt.Sprintf(`"%s"`, f)

	var quotedFiles []string
	for _, f := range fs {
		quotedFiles = append(quotedFiles, fmt.Sprintf(`"%s"`, f))
	}
	envFiles := strings.Join(quotedFiles, gOpts.filesep)

	os.Setenv("f", envFile)
	os.Setenv("fs", envFiles)

	if len(fs) == 0 {
		os.Setenv("fx", envFile)
	} else {
		os.Setenv("fx", envFiles)
	}
}
<|endoftext|>