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

package http2amqp

import (
	"errors"
	"log"
	"strconv"
	"time"

	"encoding/json"

	"github.com/aleasoluciones/goaleasoluciones/safemap"
	"github.com/aleasoluciones/simpleamqp"
)

const (
	responsesQueue = "queries_responses"
	responseTopic  = "queries.response"
)

// NewService return the http2amqp service. This service publish a amqp message for each http request
// and process the corresponding amqp responses to answer to the original http request
func NewService(brokerURI, exchange string, timeout time.Duration) *Service {

	consumer := simpleamqp.NewAmqpConsumer(brokerURI)

	service := Service{
		amqpConsumer:   consumer,
		amqpPublisher:  simpleamqp.NewAmqpPublisher(brokerURI, exchange),
		idsGenerator:   NewUUIDIdsGenerator(),
		exchange:       exchange,
		queryTimeout:   timeout,
		queryResponses: safemap.NewSafeMap(),
		amqpResponses:  consumer.ReceiveWithoutTimeout(exchange, []string{responseTopic}, responsesQueue, simpleamqp.QueueOptions{Durable: false, Delete: true, Exclusive: true}),
	}

	go service.receiveResponses()

	return &service
}

// Service http2amqp service
type Service struct {
	amqpConsumer   simpleamqp.AMQPConsumer
	amqpPublisher  simpleamqp.AMQPPublisher
	idsGenerator   IdsGenerator
	exchange       string
	queryTimeout   time.Duration
	queryResponses safemap.SafeMap
	amqpResponses  chan simpleamqp.AmqpMessage
}

func (service *Service) receiveResponses() {
	var deserialized AmqpResponseMessage
	var value safemap.Value
	var responses chan Response
	var found bool

	for message := range service.amqpResponses {
		log.Println("Response received")
		err := json.Unmarshal([]byte(message.Body), &deserialized)

		if err != nil {
			log.Println("Error unmarshaling json response:", err)
			continue
		}

		log.Println("Response received ID:", deserialized.ID)
		value, found = service.queryResponses.Find(deserialized.ID)
		if found {
			log.Println("Pending request found for", deserialized.ID)
			responses = value.(chan Response)
			responses <- deserialized.Response
		}
	}
	log.Println("This trace never should be printed")
}

func (service *Service) publishQuery(id string, topic string, request Request, ttl time.Duration) {
	serialized, _ := json.Marshal(AmqpRequestMessage{
		ID:            id,
		Request:       request,
		ResponseTopic: responseTopic,
	})
	log.Println("[queries_service] Query id:", id, "topic:", topic, "request:", request, "ttl:", ttl)
	service.amqpPublisher.PublishWithTTL(topic, serialized, durationToMilliseconds(ttl))
}

func durationToMilliseconds(value time.Duration) int {
	return int(value.Nanoseconds() / 1000000)
}

// DispatchHTTPRequest process a request. Send the request to the broker using the
// given topic and wait for the response (or the timeout)
func (service *Service) DispatchHTTPRequest(topic string, request Request) (Response, error) {
	id := service.idsGenerator.Next()
	responses := make(chan Response)
	service.queryResponses.Insert(id, responses)
	defer service.queryResponses.Delete(id)

	timeout := service.queryTimeout
	for k, v := range request.URL.Query() {
		if k == "timeout" {
			milliseconds, _ := strconv.Atoi(v[0])
			timeout = time.Duration(milliseconds) * time.Millisecond
		}
	}

	service.publishQuery(id, topic, request, timeout)
	log.Println("Request published", id)

	timeoutTicker := time.NewTicker(timeout)
	defer timeoutTicker.Stop()
	afterTimeout := timeoutTicker.C

	select {
	case response := <-responses:
		return response, nil
	case <-afterTimeout:
		log.Println("[response channel] :", service.amqpResponses)
		log.Println("[queries_service] Timeout for query id:", id)
		return Response{}, errors.New("Timeout")
	}
}
<commit_msg>More traces to debug<commit_after>// Copyright 2015 The http2amqp Authors. All rights reserved.  Use of this
// source code is governed by a MIT-style license that can be found in the
// LICENSE file.

package http2amqp

import (
	"errors"
	"log"
	"strconv"
	"time"

	"encoding/json"

	"github.com/aleasoluciones/goaleasoluciones/safemap"
	"github.com/aleasoluciones/simpleamqp"
)

const (
	responsesQueue = "queries_responses"
	responseTopic  = "queries.response"
)

// NewService return the http2amqp service. This service publish a amqp message for each http request
// and process the corresponding amqp responses to answer to the original http request
func NewService(brokerURI, exchange string, timeout time.Duration) *Service {

	consumer := simpleamqp.NewAmqpConsumer(brokerURI)

	service := Service{
		amqpConsumer:   consumer,
		amqpPublisher:  simpleamqp.NewAmqpPublisher(brokerURI, exchange),
		idsGenerator:   NewUUIDIdsGenerator(),
		exchange:       exchange,
		queryTimeout:   timeout,
		queryResponses: safemap.NewSafeMap(),
		amqpResponses:  consumer.ReceiveWithoutTimeout(exchange, []string{responseTopic}, responsesQueue, simpleamqp.QueueOptions{Durable: false, Delete: true, Exclusive: true}),
	}

	go service.receiveResponses()

	return &service
}

// Service http2amqp service
type Service struct {
	amqpConsumer   simpleamqp.AMQPConsumer
	amqpPublisher  simpleamqp.AMQPPublisher
	idsGenerator   IdsGenerator
	exchange       string
	queryTimeout   time.Duration
	queryResponses safemap.SafeMap
	amqpResponses  chan simpleamqp.AmqpMessage
}

func (service *Service) receiveResponses() {
	var deserialized AmqpResponseMessage
	var value safemap.Value
	var responses chan Response
	var found bool

	for message := range service.amqpResponses {
		log.Println("Response received")
		err := json.Unmarshal([]byte(message.Body), &deserialized)

		if err != nil {
			log.Println("Error unmarshaling json response:", err)
			continue
		}

		log.Println("Response received ID:", deserialized.ID)
		value, found = service.queryResponses.Find(deserialized.ID)
		if found {
			log.Println("Pending request found for", deserialized.ID)
			responses = value.(chan Response)
			responses <- deserialized.Response
		}
	}
	log.Println("This trace never should be printed")
}

func (service *Service) publishQuery(id string, topic string, request Request, ttl time.Duration) {
	serialized, _ := json.Marshal(AmqpRequestMessage{
		ID:            id,
		Request:       request,
		ResponseTopic: responseTopic,
	})
	log.Println("[queries_service] Query id:", id, "topic:", topic, "request:", request, "ttl:", ttl)
	service.amqpPublisher.PublishWithTTL(topic, serialized, durationToMilliseconds(ttl))
}

func durationToMilliseconds(value time.Duration) int {
	return int(value.Nanoseconds() / 1000000)
}

// DispatchHTTPRequest process a request. Send the request to the broker using the
// given topic and wait for the response (or the timeout)
func (service *Service) DispatchHTTPRequest(topic string, request Request) (Response, error) {
	id := service.idsGenerator.Next()
	responses := make(chan Response)

	log.Println("[DispatchHTTPRequest] reponsesChannel created:", responses)

	service.queryResponses.Insert(id, responses)
	defer service.queryResponses.Delete(id)

	timeout := service.queryTimeout
	for k, v := range request.URL.Query() {
		if k == "timeout" {
			milliseconds, _ := strconv.Atoi(v[0])
			timeout = time.Duration(milliseconds) * time.Millisecond
		}
	}

	service.publishQuery(id, topic, request, timeout)
	log.Println("Request published", id)

	timeoutTicker := time.NewTicker(timeout)
	defer timeoutTicker.Stop()
	afterTimeout := timeoutTicker.C

	select {
	case response := <-responses:
		return response, nil
	case <-afterTimeout:
		log.Println("[response channel] :", service.amqpResponses)
		log.Println("[queries_service] Timeout for query id:", id)
		return Response{}, errors.New("Timeout")
	}
}
<|endoftext|>


<commit_before>package grouper_test

import (
	"errors"
	"os"
	"syscall"
	"time"

	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/fake_runner"
	"github.com/tedsuo/ifrit/grouper"

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

var _ = Describe("Parallel Group", func() {
	var (
		started chan struct{}

		groupRunner  ifrit.Runner
		groupProcess ifrit.Process
		members      grouper.Members

		childRunner1 *fake_runner.TestRunner
		childRunner2 *fake_runner.TestRunner
		childRunner3 *fake_runner.TestRunner

		Δ time.Duration = 10 * time.Millisecond
	)

	BeforeEach(func() {
		childRunner1 = fake_runner.NewTestRunner()
		childRunner2 = fake_runner.NewTestRunner()
		childRunner3 = fake_runner.NewTestRunner()

		members = grouper.Members{
			{"child1", childRunner1},
			{"child2", childRunner2},
			{"child3", childRunner3},
		}

		groupRunner = grouper.NewParallel(os.Interrupt, members)
	})

	AfterEach(func() {
		childRunner1.EnsureExit()
		childRunner2.EnsureExit()
		childRunner3.EnsureExit()

		Eventually(started).Should(BeClosed())
		groupProcess.Signal(os.Kill)
		Eventually(groupProcess.Wait()).Should(Receive())
	})

	Describe("Start", func() {
		BeforeEach(func() {
			started = make(chan struct{})
			go func() {
				groupProcess = ifrit.Envoke(groupRunner)
				close(started)
			}()
		})

		It("runs all runners at the same time", func() {
			Eventually(childRunner1.RunCallCount).Should(Equal(1))
			Eventually(childRunner2.RunCallCount).Should(Equal(1))
			Eventually(childRunner3.RunCallCount).Should(Equal(1))

			childRunner1.TriggerReady()
			childRunner2.TriggerReady()
			childRunner3.TriggerReady()

			Eventually(started).Should(BeClosed())
		})

		Describe("when all the runners are ready", func() {
			var (
				signal1 <-chan os.Signal
				signal2 <-chan os.Signal
				signal3 <-chan os.Signal
			)

			BeforeEach(func() {
				signal1 = childRunner1.WaitForCall()
				childRunner1.TriggerReady()
				signal2 = childRunner2.WaitForCall()
				childRunner2.TriggerReady()
				signal3 = childRunner3.WaitForCall()
				childRunner3.TriggerReady()

				Eventually(started).Should(BeClosed())
			})

			Describe("when it receives a signal", func() {
				BeforeEach(func() {
					groupProcess.Signal(syscall.SIGUSR2)
				})

				It("sends the signal to all child runners", func() {
					Eventually(signal1).Should(Receive(Equal(syscall.SIGUSR2)))
					Eventually(signal2).Should(Receive(Equal(syscall.SIGUSR2)))
					Eventually(signal3).Should(Receive(Equal(syscall.SIGUSR2)))
				})

				It("doesn't send any more signals to remaining child processes", func() {
					Eventually(signal3).Should(Receive(Equal(syscall.SIGUSR2)))
					childRunner2.TriggerExit(nil)
					Consistently(signal3).ShouldNot(Receive())
				})
			})

			Describe("when a process exits cleanly", func() {
				BeforeEach(func() {
					childRunner1.TriggerExit(nil)
				})

				It("sends an interrupt signal to the other processes", func() {
					Eventually(signal2).Should(Receive(Equal(os.Interrupt)))
					Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
				})

				It("does not exit", func() {
					Consistently(groupProcess.Wait(), Δ).ShouldNot(Receive())
				})

				Describe("when another process exits", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(nil)
					})

					It("doesn't send any more signals to remaining child processes", func() {
						Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
						Consistently(signal3).ShouldNot(Receive())
					})
				})

				Describe("when all of the processes have exited cleanly", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(nil)
						childRunner3.TriggerExit(nil)
					})

					It("exits cleanly", func() {
						Eventually(groupProcess.Wait()).Should(Receive(BeNil()))
					})
				})

				Describe("when one of the processes exits with an error", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(errors.New("Fail"))
						childRunner3.TriggerExit(nil)
					})

					It("returns an error indicating which child processes failed", func() {
						var err error
						Eventually(groupProcess.Wait()).Should(Receive(&err))
						Ω(err).Should(Equal(grouper.ErrorTrace{
							{grouper.Member{"child1", childRunner1}, nil},
							{grouper.Member{"child2", childRunner2}, errors.New("Fail")},
							{grouper.Member{"child3", childRunner3}, nil},
						}))
					})
				})
			})
		})

		Describe("Failed start", func() {
			BeforeEach(func() {
				signal1 := childRunner1.WaitForCall()
				childRunner1.TriggerReady()

				childRunner2.TriggerExit(errors.New("Fail"))

				Eventually(signal1).Should(Receive(Equal(os.Interrupt)))
				childRunner1.TriggerExit(nil)

				signal3 := childRunner1.WaitForCall()
				childRunner3.TriggerReady()
				Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
				childRunner3.TriggerExit(nil)

				Eventually(started).Should(BeClosed())
			})

			PIt("exits after starting all processes", func() {
				var err error

				Eventually(groupProcess.Wait()).Should(Receive(&err))
				Ω(err).Should(Equal(grouper.ErrorTrace{
					{grouper.Member{"child2", childRunner2}, errors.New("Fail")},
					{grouper.Member{"child1", childRunner1}, nil},
					{grouper.Member{"child3", childRunner1}, nil},
				}))
			})
		})
	})
})
<commit_msg>fixed parallel group test<commit_after>package grouper_test

import (
	"errors"
	"os"
	"syscall"
	"time"

	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/fake_runner"
	"github.com/tedsuo/ifrit/grouper"

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

var _ = Describe("Parallel Group", func() {
	var (
		started chan struct{}

		groupRunner  ifrit.Runner
		groupProcess ifrit.Process
		members      grouper.Members

		childRunner1 *fake_runner.TestRunner
		childRunner2 *fake_runner.TestRunner
		childRunner3 *fake_runner.TestRunner

		Δ time.Duration = 10 * time.Millisecond
	)

	BeforeEach(func() {
		childRunner1 = fake_runner.NewTestRunner()
		childRunner2 = fake_runner.NewTestRunner()
		childRunner3 = fake_runner.NewTestRunner()

		members = grouper.Members{
			{"child1", childRunner1},
			{"child2", childRunner2},
			{"child3", childRunner3},
		}

		groupRunner = grouper.NewParallel(os.Interrupt, members)
	})

	AfterEach(func() {
		childRunner1.EnsureExit()
		childRunner2.EnsureExit()
		childRunner3.EnsureExit()

		Eventually(started).Should(BeClosed())
		groupProcess.Signal(os.Kill)
		Eventually(groupProcess.Wait()).Should(Receive())
	})

	Describe("Start", func() {
		BeforeEach(func() {
			started = make(chan struct{})
			go func() {
				groupProcess = ifrit.Envoke(groupRunner)
				close(started)
			}()
		})

		It("runs all runners at the same time", func() {
			Eventually(childRunner1.RunCallCount).Should(Equal(1))
			Eventually(childRunner2.RunCallCount).Should(Equal(1))
			Eventually(childRunner3.RunCallCount).Should(Equal(1))

			childRunner1.TriggerReady()
			childRunner2.TriggerReady()
			childRunner3.TriggerReady()

			Eventually(started).Should(BeClosed())
		})

		Describe("when all the runners are ready", func() {
			var (
				signal1 <-chan os.Signal
				signal2 <-chan os.Signal
				signal3 <-chan os.Signal
			)

			BeforeEach(func() {
				signal1 = childRunner1.WaitForCall()
				childRunner1.TriggerReady()
				signal2 = childRunner2.WaitForCall()
				childRunner2.TriggerReady()
				signal3 = childRunner3.WaitForCall()
				childRunner3.TriggerReady()

				Eventually(started).Should(BeClosed())
			})

			Describe("when it receives a signal", func() {
				BeforeEach(func() {
					groupProcess.Signal(syscall.SIGUSR2)
				})

				It("sends the signal to all child runners", func() {
					Eventually(signal1).Should(Receive(Equal(syscall.SIGUSR2)))
					Eventually(signal2).Should(Receive(Equal(syscall.SIGUSR2)))
					Eventually(signal3).Should(Receive(Equal(syscall.SIGUSR2)))
				})

				It("doesn't send any more signals to remaining child processes", func() {
					Eventually(signal3).Should(Receive(Equal(syscall.SIGUSR2)))
					childRunner2.TriggerExit(nil)
					Consistently(signal3).ShouldNot(Receive())
				})
			})

			Describe("when a process exits cleanly", func() {
				BeforeEach(func() {
					childRunner1.TriggerExit(nil)
				})

				It("sends an interrupt signal to the other processes", func() {
					Eventually(signal2).Should(Receive(Equal(os.Interrupt)))
					Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
				})

				It("does not exit", func() {
					Consistently(groupProcess.Wait(), Δ).ShouldNot(Receive())
				})

				Describe("when another process exits", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(nil)
					})

					It("doesn't send any more signals to remaining child processes", func() {
						Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
						Consistently(signal3).ShouldNot(Receive())
					})
				})

				Describe("when all of the processes have exited cleanly", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(nil)
						childRunner3.TriggerExit(nil)
					})

					It("exits cleanly", func() {
						Eventually(groupProcess.Wait()).Should(Receive(BeNil()))
					})
				})

				Describe("when one of the processes exits with an error", func() {
					BeforeEach(func() {
						childRunner2.TriggerExit(errors.New("Fail"))
						childRunner3.TriggerExit(nil)
					})

					It("returns an error indicating which child processes failed", func() {
						var err error
						Eventually(groupProcess.Wait()).Should(Receive(&err))
						Ω(err).Should(Equal(grouper.ErrorTrace{
							{grouper.Member{"child1", childRunner1}, nil},
							{grouper.Member{"child2", childRunner2}, errors.New("Fail")},
							{grouper.Member{"child3", childRunner3}, nil},
						}))
					})
				})
			})
		})

		Describe("Failed start", func() {
			BeforeEach(func() {
				childRunner2.TriggerExit(errors.New("Fail"))

				signal1 := childRunner1.WaitForCall()
				Eventually(signal1).Should(Receive(Equal(os.Interrupt)))
				childRunner1.TriggerExit(nil)

				signal3 := childRunner3.WaitForCall()
				Eventually(signal3).Should(Receive(Equal(os.Interrupt)))
				childRunner3.TriggerExit(nil)

				Eventually(started).Should(BeClosed())
			})

			It("exits after starting all processes", func() {
				var err error

				Eventually(groupProcess.Wait()).Should(Receive(&err))
				Ω(err).Should(Equal(grouper.ErrorTrace{
					{grouper.Member{"child2", childRunner2}, errors.New("Fail")},
					{grouper.Member{"child1", childRunner1}, nil},
					{grouper.Member{"child3", childRunner3}, nil},
				}))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "flag"
  "net/http"
  "html/template"
  "encoding/json"
  "runtime"
  "time"
  "io/ioutil"
)

type Link map[string]string
type Links struct {
  Urls []Link
}

var (
  httpuri   = flag.String("uri", "127.0.0.1", "what PORT to run the DumpLink daemon")
  httpport  = flag.String("port", "8100", "what PORT to run the DumpLink daemon")
  linkfile  = flag.String("json", "./public/static/links.json", "path to json file to save links, need {'url':[]}")
)

func not_in_list(new_link string, list []Link) bool{
  for _, item := range list {
    for link, _ := range item {
      if link == new_link { return false }
    }
  }
  return true
}

func read_json() string{
  contents, err := ioutil.ReadFile(*linkfile)
  if err != nil {
    fmt.Println("Error:", err)
    return "Error: JSON gave error while reading."
  }
  return string(contents)
}

func save_json(new_url string, title string) bool{
  contents,_ := ioutil.ReadFile(*linkfile)
  var dump Links
  err := json.Unmarshal([]byte(contents), &dump)
  if err != nil {
    fmt.Println("Error:", err)
    return false
  }
  var _link Link
  _link = make(Link)
  _link[new_url] = title

  if not_in_list(new_url, dump.Urls) {
    dump.Urls = append(dump.Urls, _link)
  } else {
    return true
  }
  b, _ := json.Marshal(&dump)
  ioutil.WriteFile(*linkfile, b, 0x644)
  return true
}

func DumpLink(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")

  t, _ := template.ParseFiles("public/bookmarklet.html")
  t.Execute(w, map[string]string {"HTTPURI": *httpuri, "HTTPPort": *httpport})
}

func Dump(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")
  req.ParseForm()
  fmt.Println(req.FormValue("url"))
  fmt.Println(req.FormValue("title"))
  save_json(req.FormValue("url"), req.FormValue("title"))

  t, _ := template.ParseFiles("public/dump200.html")
  t.Execute(w, nil)
}

func GetLinks(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")

  t, _ := template.ParseFiles("public/status.html")
  t.Execute(w, map[string]string {"BODY": read_json()})
}

func main(){
  runtime.GOMAXPROCS(runtime.NumCPU())
  flag.Parse()

  http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public/static/"))))
  http.HandleFunc("/", DumpLink)
  http.HandleFunc("/dumplink", DumpLink)

  http.HandleFunc("/dump", Dump)
  http.HandleFunc("/links", GetLinks)

  srv := &http.Server{
    Addr:        fmt.Sprintf("%s:%s", *httpuri, *httpport),
    Handler:     http.DefaultServeMux,
    ReadTimeout: time.Duration(5) * time.Second,
  }

  fmt.Printf("access your goshare at http://%s:%s\n", *httpuri, *httpport)
  err := srv.ListenAndServe()
  fmt.Println("Game Over:", err)
}
<commit_msg>dumplinks updated WIP links page with dumped links yet<commit_after>package main

import (
  "fmt"
  "flag"
  "net/http"
  "html/template"
  "encoding/json"
  "runtime"
  "time"
  "io/ioutil"
)

type Link map[string]string
type Links struct {
  Urls []Link
}

var (
  httpuri   = flag.String("uri", "127.0.0.1", "what PORT to run the DumpLink daemon")
  httpport  = flag.String("port", "8100", "what PORT to run the DumpLink daemon")
  linkfile  = flag.String("json", "./public/static/links.json", "path to json file to save links, need {'url':[]}")
)

func not_in_list(new_link string, list []Link) bool{
  for _, item := range list {
    for link, _ := range item {
      if link == new_link { return false }
    }
  }
  return true
}

func save_json(new_url string, title string) bool{
  contents,_ := ioutil.ReadFile(*linkfile)
  var dump Links
  err := json.Unmarshal([]byte(contents), &dump)
  if err != nil {
    fmt.Println("Error:", err)
    return false
  }
  var _link Link
  _link = make(Link)
  _link[new_url] = title

  if not_in_list(new_url, dump.Urls) {
    dump.Urls = append(dump.Urls, _link)
  } else {
    return true
  }
  b, _ := json.Marshal(&dump)
  ioutil.WriteFile(*linkfile, b, 0x644)
  return true
}

func DumpLink(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")

  t, _ := template.ParseFiles("public/bookmarklet.html")
  t.Execute(w, map[string]string {"HTTPURI": *httpuri, "HTTPPort": *httpport})
}

func Dump(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")
  req.ParseForm()
  fmt.Println(req.FormValue("url"))
  fmt.Println(req.FormValue("title"))
  save_json(req.FormValue("url"), req.FormValue("title"))

  t, _ := template.ParseFiles("public/dump200.html")
  t.Execute(w, nil)
}

func GetLinks(w http.ResponseWriter, req *http.Request) {
  w.Header().Set("Content-Type", "text/html")

  contents, err := ioutil.ReadFile(*linkfile)
  if err != nil {
    fmt.Println("Error:", err)
    contents = []byte("Error: JSON gave error while reading.")
  }

  t, err := template.ParseFiles("public/status.html")
  if err != nil {
    fmt.Println("Error: Link template failed.")
  }
  var content_html string
  var content_json Links
  json.Unmarshal(contents, &content_json)
  for _, linkmap  := range content_json.Urls {
    for link, linkname := range linkmap {
        content_html += fmt.Sprintf("%s
", link, linkname)
    }
  }
  t.Execute(w, map[string]string {"LINK_JSON": content_html})
}

func main(){
  runtime.GOMAXPROCS(runtime.NumCPU())
  flag.Parse()

  http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public/static/"))))
  http.HandleFunc("/", DumpLink)
  http.HandleFunc("/dumplink", DumpLink)

  http.HandleFunc("/dump", Dump)
  http.HandleFunc("/links", GetLinks)

  srv := &http.Server{
    Addr:        fmt.Sprintf("%s:%s", *httpuri, *httpport),
    Handler:     http.DefaultServeMux,
    ReadTimeout: time.Duration(5) * time.Second,
  }

  fmt.Printf("access your goshare at http://%s:%s\n", *httpuri, *httpport)
  err := srv.ListenAndServe()
  fmt.Println("Game Over:", err)
}
<|endoftext|>


<commit_before>// +build windows

package ansicolor

import (
	"bytes"
	"io"
	"strings"
	"syscall"
	"unsafe"
)

type csiState int

const (
	TEXT csiState = iota
	ESC1
	ESC2
)

type ansiColorWriter struct {
	w        io.Writer
	state    csiState
	paramBuf bytes.Buffer
	textBuf  bytes.Buffer
}

const (
	CSI1  byte = '\x1b'
	CSI2  byte = '['
	SEP   byte = ';'
	COLOR byte = 'm'
)

const (
	foregroundBlue      = uint16(0x0001)
	foregroundGreen     = uint16(0x0002)
	foregroundRed       = uint16(0x0004)
	foregroundIntensity = uint16(0x0008)
	backgroundBlue      = uint16(0x0010)
	backgroundGreen     = uint16(0x0020)
	backgroundRed       = uint16(0x0040)
	backgroundIntensity = uint16(0x0080)

	foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
	backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
)

const (
	ansiReset        = "0"
	ansiIntensityOn  = "1"
	ansiIntensityOff = "22"

	ansiForegroundBlack   = "30"
	ansiForegroundRed     = "31"
	ansiForegroundGreen   = "32"
	ansiForegroundYellow  = "33"
	ansiForegroundBlue    = "34"
	ansiForegroundMagenta = "35"
	ansiForegroundCyan    = "36"
	ansiForegroundWhite   = "37"
	ansiForegroundDefault = "39"

	ansiBackgroundBlack   = "40"
	ansiBackgroundRed     = "41"
	ansiBackgroundGreen   = "42"
	ansiBackgroundYellow  = "43"
	ansiBackgroundBlue    = "44"
	ansiBackgroundMagenta = "45"
	ansiBackgroundCyan    = "46"
	ansiBackgroundWhite   = "47"
	ansiBackgroundDefault = "49"
)

type drawType int

const (
	foreground drawType = iota
	background
)

type winColor struct {
	code     uint16
	drawType drawType
}

var colorMap = map[string]winColor{
	ansiForegroundBlack:   {0, foreground},
	ansiForegroundRed:     {foregroundRed, foreground},
	ansiForegroundGreen:   {foregroundGreen, foreground},
	ansiForegroundYellow:  {foregroundRed | foregroundGreen, foreground},
	ansiForegroundBlue:    {foregroundBlue, foreground},
	ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
	ansiForegroundCyan:    {foregroundGreen | foregroundBlue, foreground},
	ansiForegroundWhite:   {foregroundRed | foregroundGreen | foregroundBlue, foreground},
	ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiBackgroundBlack:   {0, background},
	ansiBackgroundRed:     {backgroundRed, background},
	ansiBackgroundGreen:   {backgroundGreen, background},
	ansiBackgroundYellow:  {backgroundRed | backgroundGreen, background},
	ansiBackgroundBlue:    {backgroundBlue, background},
	ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
	ansiBackgroundCyan:    {backgroundGreen | backgroundBlue, background},
	ansiBackgroundWhite:   {backgroundRed | backgroundGreen | backgroundBlue, background},
	ansiBackgroundDefault: {0, background},
}

var (
	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
)

type coord struct {
	X, Y int16
}

type smallRect struct {
	Left, Top, Right, Bottom int16
}

type consoleScreenBufferInfo struct {
	DwSize              coord
	DwCursorPosition    coord
	WAttributes         uint16
	SrWindow            smallRect
	DwMaximumWindowSize coord
}

func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
	var csbi consoleScreenBufferInfo
	ret, _, _ := procGetConsoleScreenBufferInfo.Call(
		hConsoleOutput,
		uintptr(unsafe.Pointer(&csbi)))
	if ret == 0 {
		return nil
	}
	return &csbi
}

func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
	ret, _, _ := procSetConsoleTextAttribute.Call(
		hConsoleOutput,
		uintptr(wAttributes))
	return ret != 0
}

func changeColor(param []byte) {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		return
	}

	wAttributes := screenInfo.WAttributes
	winForeColor := wAttributes & (foregroundRed | foregroundGreen | foregroundBlue)
	winBackColor := wAttributes & (backgroundRed | backgroundGreen | backgroundBlue)
	winIntensity := (wAttributes & foregroundIntensity) != 0
	paramLine := strings.Split(string(param), string(SEP))
	for _, p := range paramLine {
		c, ok := colorMap[p]
		switch {
		case !ok:
			switch p {
			case ansiReset:
				winForeColor = foregroundRed | foregroundGreen | foregroundBlue
				winBackColor = 0
				winIntensity = false
			case ansiIntensityOn:
				winIntensity = true
			case ansiIntensityOff:
				winIntensity = false
			default:
				// unknown code
			}
		case c.drawType == foreground:
			winForeColor = c.code
		case c.drawType == background:
			winBackColor = c.code
		}
	}
	if winIntensity {
		winForeColor |= foregroundIntensity
	}
	setConsoleTextAttribute(uintptr(syscall.Stdout), winForeColor|winBackColor)
}

func parseEscapeSequence(command byte, param []byte) {
	switch command {
	case COLOR:
		changeColor(param)
	}
}

func isParam(b byte) bool {
	return ('0' <= b && b <= '9') || b == SEP
}

func (cw *ansiColorWriter) pushBuffer(ch byte) {
	cw.textBuf.WriteByte(ch)
}

func (cw *ansiColorWriter) flushBuffer() (int, error) {
	text := cw.textBuf.Bytes()
	cw.textBuf.Reset()
	return cw.w.Write(text)
}

func (cw *ansiColorWriter) Write(p []byte) (int, error) {
	r := 0
	for _, ch := range p {
		switch cw.state {
		case TEXT:
			if ch == CSI1 {
				cw.state = ESC1
			} else {
				cw.pushBuffer(ch)
			}
		case ESC1:
			switch ch {
			case CSI1:
				cw.pushBuffer(ch)
			case CSI2:
				cw.state = ESC2
			default:
				cw.pushBuffer(CSI1)
				cw.pushBuffer(ch)
				cw.state = TEXT
			}
		case ESC2:
			if isParam(ch) {
				cw.paramBuf.WriteByte(ch)
			} else {
				nw, err := cw.flushBuffer()
				r += nw
				if err != nil {
					return r, err
				}
				param := cw.paramBuf.Bytes()
				cw.paramBuf.Reset()
				parseEscapeSequence(ch, param)
				cw.state = TEXT
			}
		default:
			cw.pushBuffer(ch)
			cw.state = TEXT
		}
	}

	nw, err := cw.flushBuffer()
	return r + nw, err
}
<commit_msg>Improved variable name<commit_after>// +build windows

package ansicolor

import (
	"bytes"
	"io"
	"strings"
	"syscall"
	"unsafe"
)

type csiState int

const (
	outsideCsiCode csiState = iota
	firstCsiCode
	secondeCsiCode
)

type ansiColorWriter struct {
	w        io.Writer
	state    csiState
	paramBuf bytes.Buffer
	textBuf  bytes.Buffer
}

const (
	firstCsiChar   byte = '\x1b'
	secondeCsiChar byte = '['
	separatorChar  byte = ';'
	sgrCode        byte = 'm'
)

const (
	foregroundBlue      = uint16(0x0001)
	foregroundGreen     = uint16(0x0002)
	foregroundRed       = uint16(0x0004)
	foregroundIntensity = uint16(0x0008)
	backgroundBlue      = uint16(0x0010)
	backgroundGreen     = uint16(0x0020)
	backgroundRed       = uint16(0x0040)
	backgroundIntensity = uint16(0x0080)

	foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity
	backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity
)

const (
	ansiReset        = "0"
	ansiIntensityOn  = "1"
	ansiIntensityOff = "22"

	ansiForegroundBlack   = "30"
	ansiForegroundRed     = "31"
	ansiForegroundGreen   = "32"
	ansiForegroundYellow  = "33"
	ansiForegroundBlue    = "34"
	ansiForegroundMagenta = "35"
	ansiForegroundCyan    = "36"
	ansiForegroundWhite   = "37"
	ansiForegroundDefault = "39"

	ansiBackgroundBlack   = "40"
	ansiBackgroundRed     = "41"
	ansiBackgroundGreen   = "42"
	ansiBackgroundYellow  = "43"
	ansiBackgroundBlue    = "44"
	ansiBackgroundMagenta = "45"
	ansiBackgroundCyan    = "46"
	ansiBackgroundWhite   = "47"
	ansiBackgroundDefault = "49"
)

type drawType int

const (
	foreground drawType = iota
	background
)

type winColor struct {
	code     uint16
	drawType drawType
}

var colorMap = map[string]winColor{
	ansiForegroundBlack:   {0, foreground},
	ansiForegroundRed:     {foregroundRed, foreground},
	ansiForegroundGreen:   {foregroundGreen, foreground},
	ansiForegroundYellow:  {foregroundRed | foregroundGreen, foreground},
	ansiForegroundBlue:    {foregroundBlue, foreground},
	ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground},
	ansiForegroundCyan:    {foregroundGreen | foregroundBlue, foreground},
	ansiForegroundWhite:   {foregroundRed | foregroundGreen | foregroundBlue, foreground},
	ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground},

	ansiBackgroundBlack:   {0, background},
	ansiBackgroundRed:     {backgroundRed, background},
	ansiBackgroundGreen:   {backgroundGreen, background},
	ansiBackgroundYellow:  {backgroundRed | backgroundGreen, background},
	ansiBackgroundBlue:    {backgroundBlue, background},
	ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background},
	ansiBackgroundCyan:    {backgroundGreen | backgroundBlue, background},
	ansiBackgroundWhite:   {backgroundRed | backgroundGreen | backgroundBlue, background},
	ansiBackgroundDefault: {0, background},
}

var (
	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
)

type coord struct {
	X, Y int16
}

type smallRect struct {
	Left, Top, Right, Bottom int16
}

type consoleScreenBufferInfo struct {
	DwSize              coord
	DwCursorPosition    coord
	WAttributes         uint16
	SrWindow            smallRect
	DwMaximumWindowSize coord
}

func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo {
	var csbi consoleScreenBufferInfo
	ret, _, _ := procGetConsoleScreenBufferInfo.Call(
		hConsoleOutput,
		uintptr(unsafe.Pointer(&csbi)))
	if ret == 0 {
		return nil
	}
	return &csbi
}

func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool {
	ret, _, _ := procSetConsoleTextAttribute.Call(
		hConsoleOutput,
		uintptr(wAttributes))
	return ret != 0
}

func changeColor(param []byte) {
	screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout))
	if screenInfo == nil {
		return
	}

	wAttributes := screenInfo.WAttributes
	winForegroundColor := wAttributes & (foregroundRed | foregroundGreen | foregroundBlue)
	winBackgroundColor := wAttributes & (backgroundRed | backgroundGreen | backgroundBlue)
	isWinIntensity := (wAttributes & foregroundIntensity) != 0
	csiParam := strings.Split(string(param), string(separatorChar))
	for _, p := range csiParam {
		c, ok := colorMap[p]
		switch {
		case !ok:
			switch p {
			case ansiReset:
				winForegroundColor = foregroundRed | foregroundGreen | foregroundBlue
				winBackgroundColor = 0
				isWinIntensity = false
			case ansiIntensityOn:
				isWinIntensity = true
			case ansiIntensityOff:
				isWinIntensity = false
			default:
				// unknown code
			}
		case c.drawType == foreground:
			winForegroundColor = c.code
		case c.drawType == background:
			winBackgroundColor = c.code
		}
	}
	if isWinIntensity {
		winForegroundColor |= foregroundIntensity
	}
	setConsoleTextAttribute(uintptr(syscall.Stdout), winForegroundColor|winBackgroundColor)
}

func parseEscapeSequence(command byte, param []byte) {
	switch command {
	case sgrCode:
		changeColor(param)
	}
}

func isParameterChar(b byte) bool {
	return ('0' <= b && b <= '9') || b == separatorChar
}

func (cw *ansiColorWriter) pushBuffer(ch byte) {
	cw.textBuf.WriteByte(ch)
}

func (cw *ansiColorWriter) flushBuffer() (int, error) {
	text := cw.textBuf.Bytes()
	cw.textBuf.Reset()
	return cw.w.Write(text)
}

func (cw *ansiColorWriter) Write(p []byte) (int, error) {
	r := 0
	for _, ch := range p {
		switch cw.state {
		case outsideCsiCode:
			if ch == firstCsiChar {
				cw.state = firstCsiCode
			} else {
				cw.pushBuffer(ch)
			}
		case firstCsiCode:
			switch ch {
			case firstCsiChar:
				cw.pushBuffer(ch)
			case secondeCsiChar:
				cw.state = secondeCsiCode
			default:
				cw.pushBuffer(firstCsiChar)
				cw.pushBuffer(ch)
				cw.state = outsideCsiCode
			}
		case secondeCsiCode:
			if isParameterChar(ch) {
				cw.paramBuf.WriteByte(ch)
			} else {
				nw, err := cw.flushBuffer()
				r += nw
				if err != nil {
					return r, err
				}
				param := cw.paramBuf.Bytes()
				cw.paramBuf.Reset()
				parseEscapeSequence(ch, param)
				cw.state = outsideCsiCode
			}
		default:
			cw.pushBuffer(ch)
			cw.state = outsideCsiCode
		}
	}

	nw, err := cw.flushBuffer()
	return r + nw, err
}
<|endoftext|>


<commit_before>package microcache

import (
	"sync"
	"time"
)

// MonitorFunc turns a function into a Monitor
func MonitorFunc(interval time.Duration, logFunc func(Stats)) Monitor {
	return &monitorFunc{
		interval: interval,
		logFunc:  logFunc,
	}
}

type monitorFunc struct {
	interval     time.Duration
	logFunc      func(Stats)
	hits         int
	hitMutex     sync.Mutex
	misses       int
	missMutex    sync.Mutex
	stales       int
	staleMutex   sync.Mutex
	backend      int
	backendMutex sync.Mutex
	errors       int
	errorMutex   sync.Mutex
	stop         chan bool
}

func (m *monitorFunc) GetInterval() time.Duration {
	return m.interval
}

func (m *monitorFunc) Log(stats Stats) {
	// hits
	m.hitMutex.Lock()
	stats.Hits = m.hits
	m.hits = 0
	m.hitMutex.Unlock()

	// misses
	m.missMutex.Lock()
	stats.Misses = m.misses
	m.misses = 0
	m.missMutex.Unlock()

	// stales
	m.staleMutex.Lock()
	stats.Stales = m.stales
	m.stales = 0
	m.staleMutex.Unlock()

	// backend
	m.backendMutex.Lock()
	stats.Backend = m.backend
	m.backend = 0
	m.backendMutex.Unlock()

	// errors
	m.errorMutex.Lock()
	stats.Errors = m.errors
	m.errors = 0
	m.errorMutex.Unlock()

	// log
	m.logFunc(stats)
}

func (m *monitorFunc) Hit() {
	m.hitMutex.Lock()
	m.hits += 1
	m.hitMutex.Unlock()
}

func (m *monitorFunc) Miss() {
	m.missMutex.Lock()
	m.misses += 1
	m.missMutex.Unlock()
}

func (m *monitorFunc) Stale() {
	m.staleMutex.Lock()
	m.stales += 1
	m.staleMutex.Unlock()
}

func (m *monitorFunc) Backend() {
	m.backendMutex.Lock()
	m.backend += 1
	m.backendMutex.Unlock()
}

func (m *monitorFunc) Error() {
	m.errorMutex.Lock()
	m.errors += 1
	m.errorMutex.Unlock()
}
<commit_msg>Use sync/atomic instead of mutexes for counters<commit_after>package microcache

import (
	"sync/atomic"
	"time"
)

// MonitorFunc turns a function into a Monitor
func MonitorFunc(interval time.Duration, logFunc func(Stats)) Monitor {
	return &monitorFunc{
		interval: interval,
		logFunc:  logFunc,
	}
}

type monitorFunc struct {
	interval time.Duration
	logFunc  func(Stats)
	hits     int64
	misses   int64
	stales   int64
	backend  int64
	errors   int64
	stop     chan bool
}

func (m *monitorFunc) GetInterval() time.Duration {
	return m.interval
}

func (m *monitorFunc) Log(stats Stats) {
	// hits
	stats.Hits = int(atomic.SwapInt64(&m.hits, 0))

	// misses
	stats.Misses = int(atomic.SwapInt64(&m.misses, 0))

	// stales
	stats.Stales = int(atomic.SwapInt64(&m.stales, 0))

	// backend
	stats.Backend = int(atomic.SwapInt64(&m.backend, 0))

	// errors
	stats.Errors = int(atomic.SwapInt64(&m.errors, 0))

	// log
	m.logFunc(stats)
}

func (m *monitorFunc) Hit() {
	atomic.AddInt64(&m.hits, 1)
}

func (m *monitorFunc) Miss() {
	atomic.AddInt64(&m.misses, 1)
}

func (m *monitorFunc) Stale() {
	atomic.AddInt64(&m.stales, 1)
}

func (m *monitorFunc) Backend() {
	atomic.AddInt64(&m.backend, 1)
}

func (m *monitorFunc) Error() {
	atomic.AddInt64(&m.errors, 1)
}
<|endoftext|>


<commit_before>package roger

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"io"
)

type session struct {
	readWriteClose     io.ReadWriteCloser
	readWriter         *bufio.ReadWriter
	authReq            bool
	authType           authType
	key                string
	connected          bool
	rServeIDSig        string
	rServeProtocol     string
	rServeCommProtocol string
}

func newSession(client RClient) (*session, error) {
	readWriteCloser, err := client.getReadWriteCloser()
	if err != nil {
		return nil, err
	}
	buffRead := bufio.NewReader(readWriteCloser)
	buffWrite := bufio.NewWriter(readWriteCloser)
	sess := &session{
		readWriteClose: readWriteCloser,
		readWriter:     bufio.NewReadWriter(buffRead, buffWrite),
	}
	sess.handshake()
	return sess, nil
}

func (s *session) close() {
	s.connected = false
	s.readWriter = nil
	s.readWriteClose.Close()
	s.readWriteClose = nil
}

func (s *session) readNBytes(bytes int) []byte {
	ret := make([]byte, bytes)
	for v := 0; v < bytes; v++ {
		ret[v], _ = s.readWriter.ReadByte()
	}
	return ret
}

func (s *session) toCharset(str string) []byte {
	return []byte(str)
}

func (s *session) handshake() {
	s.rServeIDSig = string(s.readNBytes(4))
	s.rServeProtocol = string(s.readNBytes(4))
	s.rServeCommProtocol = string(s.readNBytes(4))
	for i := 12; i < 32; i += 4 {
		attr := s.readNBytes(4)
		attrString := string(attr)
		if attrString == "ARpt" && s.authReq == false {
			s.authReq = true
			s.authType = atPlain
		}
		if attrString == "ARuc" {
			s.authReq = true
			s.authType = atCrypt
		}
		if attrString[0] == 'K' {
			s.key = attrString[1:3]
		}
	}
	s.connected = true
}

func (s *session) setHdr(valueType dataType, valueLength int, buf []byte) {
	buf[0] = byte(valueType)
	buf[1] = byte(valueLength & 255)
	buf[2] = byte((valueLength & 0xff00) >> 8)
	buf[3] = byte((valueLength & 0xff0000) >> 16)
}

func (s *session) prepareStringCommand(cmd string) []byte {
	rawCmdBytes := s.toCharset(cmd)
	requiredLength := len(rawCmdBytes) + 1
	//make sure length is divisible by 4
	if requiredLength&3 > 0 {
		requiredLength = (requiredLength & 0xfffffc) + 4
	}
	cmdBytes := make([]byte, requiredLength+5)
	for i := 0; i < len(rawCmdBytes); i++ {
		cmdBytes[4+i] = rawCmdBytes[i]
	}
	s.setHdr(dtString, requiredLength, cmdBytes)
	return cmdBytes
}

func (s *session) sendCommand(cmd string) *Packet {
	cmdBytes := s.prepareStringCommand(cmd)
	buf := new(bytes.Buffer)
	//command
	binary.Write(buf, binary.LittleEndian, int32(cmdEval))
	//length of message (bits 0-31)
	binary.Write(buf, binary.LittleEndian, int32(len(cmdBytes)))
	//offset of message part
	binary.Write(buf, binary.LittleEndian, int32(0))
	// length of message (bits 32-63)
	binary.Write(buf, binary.LittleEndian, int32(0))
	binary.Write(buf, binary.LittleEndian, cmdBytes)

	s.readWriter.Write(buf.Bytes())
	s.readWriter.Flush()

	rep := binary.LittleEndian.Uint32(s.readNBytes(4))
	r1 := binary.LittleEndian.Uint32(s.readNBytes(4))
	s.readNBytes(8)

	if r1 <= 0 {
		return newPacket(int(rep), nil)
	}

	results := s.readNBytes(int(r1))
	return newPacket(int(rep), results)
}
<commit_msg>Adding log message if unexpected version of Rserve<commit_after>package roger

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"io"
	"log"
)

type session struct {
	readWriteClose     io.ReadWriteCloser
	readWriter         *bufio.ReadWriter
	authReq            bool
	authType           authType
	key                string
	connected          bool
	rServeIDSig        string
	rServeProtocol     string
	rServeCommProtocol string
}

func newSession(client RClient) (*session, error) {
	readWriteCloser, err := client.getReadWriteCloser()
	if err != nil {
		return nil, err
	}
	buffRead := bufio.NewReader(readWriteCloser)
	buffWrite := bufio.NewWriter(readWriteCloser)
	sess := &session{
		readWriteClose: readWriteCloser,
		readWriter:     bufio.NewReadWriter(buffRead, buffWrite),
	}
	sess.handshake()
	return sess, nil
}

func (s *session) close() {
	s.connected = false
	s.readWriter = nil
	s.readWriteClose.Close()
	s.readWriteClose = nil
}

func (s *session) readNBytes(bytes int) []byte {
	ret := make([]byte, bytes)
	for v := 0; v < bytes; v++ {
		ret[v], _ = s.readWriter.ReadByte()
	}
	return ret
}

func (s *session) toCharset(str string) []byte {
	return []byte(str)
}

func (s *session) handshake() {
	s.rServeIDSig = string(s.readNBytes(4))
	s.rServeProtocol = string(s.readNBytes(4))
	s.rServeCommProtocol = string(s.readNBytes(4))
	for i := 12; i < 32; i += 4 {
		attr := s.readNBytes(4)
		attrString := string(attr)
		if attrString == "ARpt" && s.authReq == false {
			s.authReq = true
			s.authType = atPlain
		}
		if attrString == "ARuc" {
			s.authReq = true
			s.authType = atCrypt
		}
		if attrString[0] == 'K' {
			s.key = attrString[1:3]
		}
	}
	s.connected = true

	if s.rServeCommProtocol != "QAP1" ||
		s.rServeIDSig != "Rsrv" ||
		s.rServeProtocol != "0103" {
		log.Println("The version of RServe installed is not officially supported. Please consider upgrading to the latest version of RServe.")
	}
}

func (s *session) setHdr(valueType dataType, valueLength int, buf []byte) {
	buf[0] = byte(valueType)
	buf[1] = byte(valueLength & 255)
	buf[2] = byte((valueLength & 0xff00) >> 8)
	buf[3] = byte((valueLength & 0xff0000) >> 16)
}

func (s *session) prepareStringCommand(cmd string) []byte {
	rawCmdBytes := s.toCharset(cmd)
	requiredLength := len(rawCmdBytes) + 1
	//make sure length is divisible by 4
	if requiredLength&3 > 0 {
		requiredLength = (requiredLength & 0xfffffc) + 4
	}
	cmdBytes := make([]byte, requiredLength+5)
	for i := 0; i < len(rawCmdBytes); i++ {
		cmdBytes[4+i] = rawCmdBytes[i]
	}
	s.setHdr(dtString, requiredLength, cmdBytes)
	return cmdBytes
}

func (s *session) sendCommand(cmd string) *Packet {
	cmdBytes := s.prepareStringCommand(cmd)
	buf := new(bytes.Buffer)
	//command
	binary.Write(buf, binary.LittleEndian, int32(cmdEval))
	//length of message (bits 0-31)
	binary.Write(buf, binary.LittleEndian, int32(len(cmdBytes)))
	//offset of message part
	binary.Write(buf, binary.LittleEndian, int32(0))
	// length of message (bits 32-63)
	binary.Write(buf, binary.LittleEndian, int32(0))
	binary.Write(buf, binary.LittleEndian, cmdBytes)

	s.readWriter.Write(buf.Bytes())
	s.readWriter.Flush()

	rep := binary.LittleEndian.Uint32(s.readNBytes(4))
	r1 := binary.LittleEndian.Uint32(s.readNBytes(4))
	s.readNBytes(8)

	if r1 <= 0 {
		return newPacket(int(rep), nil)
	}

	results := s.readNBytes(int(r1))
	return newPacket(int(rep), results)
}
<|endoftext|>


<commit_before>package goparse

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"

	"github.com/parnurzeal/gorequest"
)

const (
	headerAppID        = "X-Parse-Application-Id" // Parse Application ID
	headerMasterKey    = "X-Parse-Master-Key"     // Parse Master Key
	headerAPIKey       = "X-Parse-REST-API-Key"   // Parse REST API Key
	headerSessionToken = "X-Parse-Session-Token"  // Parse Session Token

	pathMe = "/users/me"
)

// ParseSession is the client which has SessionToken as user authentication.
type ParseSession struct {
	client       *ParseClient
	SessionToken string
}

const (
	// Error code referrense at parse.com
	// http://www.parse.com/docs/dotnet/api/html/T_Parse_ParseException_ErrorCode.htm

	// errCodeObjectNotFound is object not found
	errCodeObjectNotFound = 101
)

var (
	// ErrObjectNotFound Error code indicating the specified object doesn't exist.
	ErrObjectNotFound = errors.New("object not found")
)

// Create a request which is set headers for Parse API
func (s *ParseSession) initRequest(req *gorequest.SuperAgent, useMaster bool) {
	if useMaster {
		req.
			Set(headerAppID, s.client.ApplicationID).
			Set(headerMasterKey, s.client.MasterKey).
			Timeout(s.client.TimeOut)
	} else {
		req.
			Set(headerAppID, s.client.ApplicationID).
			Set(headerAPIKey, s.client.RESTAPIKey).
			Timeout(s.client.TimeOut)
	}

	if s.SessionToken != "" {
		req.Set(headerSessionToken, s.SessionToken)
	}
}

func (s *ParseSession) get(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Get(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) post(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Post(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) put(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Put(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) del(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Delete(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

// Signup new user
func (s *ParseSession) Signup(data interface{}) (user User, err error) {
	return user, do(s.post("/users", false).Send(data), &user)
}

// Login with data
func (s *ParseSession) Login(username string, password string) (user User, err error) {

	// Query values
	vals := url.Values{
		"username": []string{username},
		"password": []string{password},
	}

	// Create a user
	err = do(s.get("/login", false).Query(vals.Encode()), &user)

	if user.SessionToken != "" {
		s.SessionToken = user.SessionToken
	}

	return user, err
}

// GetUser gets user information
func (s *ParseSession) GetUser(userObjectID string) (user User, err error) {
	return user, s.getUser(userObjectID, &user, false)
}

// GetUserByMaster gets user information by use master key
func (s *ParseSession) GetUserByMaster(userObjectID string) (user User, err error) {
	return user, s.getUser(userObjectID, &user, true)
}

// GetUserInto gets user information into provided object
func (s *ParseSession) GetUserInto(userObjectID string, user interface{}) (err error) {
	return s.getUser(userObjectID, user, false)
}

// GetUserIntoByMaster gets user information into provided object by use master key
func (s *ParseSession) GetUserIntoByMaster(userObjectID string, user interface{}) (err error) {
	return s.getUser(userObjectID, user, true)
}

// GetUserByMaster gets user information by private
func (s *ParseSession) getUser(userObjectID string, user interface{}, useMaster bool) (err error) {
	if userObjectID == "" {
		return errors.New("userObjectID must not be empty")
	}
	if useMaster && s.client.MasterKey == "" {
		return errors.New("request is requires PARSE_REST_API_KEY")
	}
	return do(s.get("/users/"+userObjectID, useMaster), &user)
}

// UpdateUser update user information
func (s *ParseSession) UpdateUser(userObjectID string, data interface{}) (*ObjectResponse, error) {
	return s.updateUser(userObjectID, data, false)
}

// UpdateUserByMaster update user information by use master key
func (s *ParseSession) UpdateUserByMaster(userObjectID string, data interface{}) (*ObjectResponse, error) {
	return s.updateUser(userObjectID, data, true)
}

// UpdateUser update user information by private
func (s *ParseSession) updateUser(userObjectID string, data interface{}, useMaster bool) (*ObjectResponse, error) {
	if userObjectID == "" {
		return nil, errors.New("userObjectID must not be empty")
	}
	if useMaster && s.client.MasterKey == "" {
		return nil, errors.New("request is requires PARSE_REST_API_KEY")
	}
	var resp ObjectResponse
	return &resp, do(s.put("/users/"+userObjectID, useMaster).Send(data), &resp)
}

// GetMe gets self user information
func (s *ParseSession) GetMe() (user User, err error) {
	err = s.GetMeInto(&user)
	return user, err
}

// GetMeInto gets self user information into provided object
func (s *ParseSession) GetMeInto(user interface{}) error {
	if user == nil {
		return errors.New("user must not be nil")
	}
	return do(s.get("/users/me", false), user)
}

// DeleteUser deletes user by ID
func (s *ParseSession) DeleteUser(userID string) error {
	return do(s.del("/users/"+userID, false), nil)
}

// UploadInstallation stores the subscription data for installations
func (s *ParseSession) UploadInstallation(data Installation, result interface{}) error {
	return do(s.post("/installations", false).Send(data), result)
}

// PushNotification sends push-notifiaction each device via parse
func (s *ParseSession) PushNotification(body PushNotificationQuery) error {
	return do(s.post("/push", false).Send(body), nil)
}

// Execute a parse request
func do(req *gorequest.SuperAgent, data interface{}) error {

	res, body, errs := req.End()
	if errs != nil {
		return fmt.Errorf("%v", errs)
	}
	if res.StatusCode < 200 || res.StatusCode >= 300 {
		// parse as error model
		reserr := new(Error)
		err := json.NewDecoder(strings.NewReader(body)).Decode(reserr)
		if err != nil {
			return err
		}
		return reserr
	}
	if data == nil {
		return nil
	}
	return json.NewDecoder(strings.NewReader(body)).Decode(data)
}

// NewClass creates a new class from the session
func (s *ParseSession) NewClass(className string) *ParseClass {
	return &ParseClass{
		Session:   s,
		Name:      className,
		ClassURL:  "/classes/" + className,
		UseMaster: false,
	}
}

// IsObjectNotFound check the error "not found" or not
func IsObjectNotFound(err error) bool {
	v, ok := err.(*Error)
	return ok && v.Code == errCodeObjectNotFound
}
<commit_msg>add master push notif<commit_after>package goparse

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"

	"github.com/parnurzeal/gorequest"
)

const (
	headerAppID        = "X-Parse-Application-Id" // Parse Application ID
	headerMasterKey    = "X-Parse-Master-Key"     // Parse Master Key
	headerAPIKey       = "X-Parse-REST-API-Key"   // Parse REST API Key
	headerSessionToken = "X-Parse-Session-Token"  // Parse Session Token

	pathMe = "/users/me"
)

// ParseSession is the client which has SessionToken as user authentication.
type ParseSession struct {
	client       *ParseClient
	SessionToken string
}

const (
	// Error code referrense at parse.com
	// http://www.parse.com/docs/dotnet/api/html/T_Parse_ParseException_ErrorCode.htm

	// errCodeObjectNotFound is object not found
	errCodeObjectNotFound = 101
)

var (
	// ErrObjectNotFound Error code indicating the specified object doesn't exist.
	ErrObjectNotFound = errors.New("object not found")
)

// Create a request which is set headers for Parse API
func (s *ParseSession) initRequest(req *gorequest.SuperAgent, useMaster bool) {
	if useMaster {
		req.
			Set(headerAppID, s.client.ApplicationID).
			Set(headerMasterKey, s.client.MasterKey).
			Timeout(s.client.TimeOut)
	} else {
		req.
			Set(headerAppID, s.client.ApplicationID).
			Set(headerAPIKey, s.client.RESTAPIKey).
			Timeout(s.client.TimeOut)
	}

	if s.SessionToken != "" {
		req.Set(headerSessionToken, s.SessionToken)
	}
}

func (s *ParseSession) get(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Get(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) post(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Post(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) put(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Put(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

func (s *ParseSession) del(path string, useMaster bool) *gorequest.SuperAgent {
	req := gorequest.New().Delete(s.client.URL + path)
	s.initRequest(req, useMaster)
	return req
}

// Signup new user
func (s *ParseSession) Signup(data interface{}) (user User, err error) {
	return user, do(s.post("/users", false).Send(data), &user)
}

// Login with data
func (s *ParseSession) Login(username string, password string) (user User, err error) {

	// Query values
	vals := url.Values{
		"username": []string{username},
		"password": []string{password},
	}

	// Create a user
	err = do(s.get("/login", false).Query(vals.Encode()), &user)

	if user.SessionToken != "" {
		s.SessionToken = user.SessionToken
	}

	return user, err
}

// GetUser gets user information
func (s *ParseSession) GetUser(userObjectID string) (user User, err error) {
	return user, s.getUser(userObjectID, &user, false)
}

// GetUserByMaster gets user information by use master key
func (s *ParseSession) GetUserByMaster(userObjectID string) (user User, err error) {
	return user, s.getUser(userObjectID, &user, true)
}

// GetUserInto gets user information into provided object
func (s *ParseSession) GetUserInto(userObjectID string, user interface{}) (err error) {
	return s.getUser(userObjectID, user, false)
}

// GetUserIntoByMaster gets user information into provided object by use master key
func (s *ParseSession) GetUserIntoByMaster(userObjectID string, user interface{}) (err error) {
	return s.getUser(userObjectID, user, true)
}

// GetUserByMaster gets user information by private
func (s *ParseSession) getUser(userObjectID string, user interface{}, useMaster bool) (err error) {
	if userObjectID == "" {
		return errors.New("userObjectID must not be empty")
	}
	if useMaster && s.client.MasterKey == "" {
		return errors.New("request is requires PARSE_REST_API_KEY")
	}
	return do(s.get("/users/"+userObjectID, useMaster), &user)
}

// UpdateUser update user information
func (s *ParseSession) UpdateUser(userObjectID string, data interface{}) (*ObjectResponse, error) {
	return s.updateUser(userObjectID, data, false)
}

// UpdateUserByMaster update user information by use master key
func (s *ParseSession) UpdateUserByMaster(userObjectID string, data interface{}) (*ObjectResponse, error) {
	return s.updateUser(userObjectID, data, true)
}

// UpdateUser update user information by private
func (s *ParseSession) updateUser(userObjectID string, data interface{}, useMaster bool) (*ObjectResponse, error) {
	if userObjectID == "" {
		return nil, errors.New("userObjectID must not be empty")
	}
	if useMaster && s.client.MasterKey == "" {
		return nil, errors.New("request is requires PARSE_REST_API_KEY")
	}
	var resp ObjectResponse
	return &resp, do(s.put("/users/"+userObjectID, useMaster).Send(data), &resp)
}

// GetMe gets self user information
func (s *ParseSession) GetMe() (user User, err error) {
	err = s.GetMeInto(&user)
	return user, err
}

// GetMeInto gets self user information into provided object
func (s *ParseSession) GetMeInto(user interface{}) error {
	if user == nil {
		return errors.New("user must not be nil")
	}
	return do(s.get("/users/me", false), user)
}

// DeleteUser deletes user by ID
func (s *ParseSession) DeleteUser(userID string) error {
	return do(s.del("/users/"+userID, false), nil)
}

// UploadInstallation stores the subscription data for installations
func (s *ParseSession) UploadInstallation(data Installation, result interface{}) error {
	return do(s.post("/installations", false).Send(data), result)
}

// PushNotification sends push-notifiaction each device via parse
func (s *ParseSession) PushNotification(body PushNotificationQuery) error {
	return do(s.post("/push", false).Send(body), nil)
}

// MasterPushNotification sends push-notifiaction as master (master key) each device via parse
func (s *ParseSession) MasterPushNotification(body PushNotificationQuery) error {
	return do(s.post("/push", true).Send(body), nil)
}

// Execute a parse request
func do(req *gorequest.SuperAgent, data interface{}) error {

	res, body, errs := req.End()
	if errs != nil {
		return fmt.Errorf("%v", errs)
	}
	if res.StatusCode < 200 || res.StatusCode >= 300 {
		// parse as error model
		reserr := new(Error)
		err := json.NewDecoder(strings.NewReader(body)).Decode(reserr)
		if err != nil {
			return err
		}
		return reserr
	}
	if data == nil {
		return nil
	}
	return json.NewDecoder(strings.NewReader(body)).Decode(data)
}

// NewClass creates a new class from the session
func (s *ParseSession) NewClass(className string) *ParseClass {
	return &ParseClass{
		Session:   s,
		Name:      className,
		ClassURL:  "/classes/" + className,
		UseMaster: false,
	}
}

// IsObjectNotFound check the error "not found" or not
func IsObjectNotFound(err error) bool {
	v, ok := err.(*Error)
	return ok && v.Code == errCodeObjectNotFound
}
<|endoftext|>


<commit_before>// session.go - mixnet client session
// Copyright (C) 2018  David Stainton.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package client provides the Katzenpost midclient
package client

import (
	"errors"
	"fmt"
	"time"

	"github.com/katzenpost/client/internal/authority"
	"github.com/katzenpost/client/internal/pkiclient"
	coreconstants "github.com/katzenpost/core/constants"
	"github.com/katzenpost/core/crypto/ecdh"
	"github.com/katzenpost/core/crypto/rand"
	"github.com/katzenpost/core/log"
	"github.com/katzenpost/core/pki"
	"github.com/katzenpost/core/sphinx/constants"
	"github.com/katzenpost/core/worker"
	"github.com/katzenpost/minclient"
	"github.com/katzenpost/minclient/block"
	"gopkg.in/op/go-logging.v1"
)

// Session holds the client session
type Session struct {
	worker.Worker

	minclient       *minclient.Client
	authority       *authority.Authority
	log             *logging.Logger
	logBackend      *log.Backend
	connected       chan bool
	identityPrivKey *ecdh.PrivateKey
}

// NewSession stablishes a session with provider using key.
// This method will block until session is connected to the Provider.
func (c *Client) NewSession() (*Session, error) {
	var err error
	session := new(Session)
	proxyCfg := c.cfg.UpstreamProxyConfig()
	pkiClient, err := c.cfg.NonvotingAuthority.New(c.logBackend, proxyCfg)
	if err != nil {
		return nil, err
	}
	pkiCacheClient := pkiclient.New(pkiClient)

	// Configure and bring up the minclient instance.
	clientCfg := &minclient.ClientConfig{
		User:                c.cfg.Account.User,
		Provider:            c.cfg.Account.Provider,
		ProviderKeyPin:      c.cfg.Account.ProviderKeyPin,
		LinkKey:             c.cfg.Account.LinkKey,
		LogBackend:          c.logBackend,
		PKIClient:           pkiCacheClient,
		OnConnFn:            session.onConnection,
		OnMessageFn:         session.onMessage,
		OnACKFn:             session.onACK,
		OnDocumentFn:        session.onDocument,
		DialContextFn:       proxyCfg.ToDialContext("nonvoting:" + c.cfg.NonvotingAuthority.PublicKey.String()),
		MessagePollInterval: time.Duration(c.cfg.Debug.PollingInterval) * time.Second,
		EnableTimeSync:      false, // Be explicit about it.
	}

	c.authority = authority.NewStore(c.logBackend, proxyCfg)
	session.connected = make(chan bool, 0)
	session.log = c.logBackend.GetLogger(fmt.Sprintf("%s@%s_session", c.cfg.Account.User, c.cfg.Account.Provider))
	session.minclient, err = minclient.New(clientCfg)
	if err != nil {
		return nil, err
	}
	err = session.waitForConnection()
	if err != nil {
		return nil, err
	}
	return session, nil
}

// Shutdown the session
func (s *Session) Shutdown() {
	s.minclient.Shutdown()
}

// waitForConnection blocks until the client is
// connected to the Provider
func (s *Session) waitForConnection() error {
	isConnected := <-s.connected
	if !isConnected {
		return errors.New("status is not connected even with status change")
	}
	return nil
}

// Send reliably delivers the message to the recipient's queue
// on the destination provider or returns an error
func (s *Session) Send(recipient, provider string, message []byte) (*[block.MessageIDLength]byte, error) {
	s.log.Debugf("Send")
	return nil, errors.New("failure: Send is not yet implemented")
}

// SendUnreliable unreliably sends a message to the recipient's queue
// on the destination provider or returns an error
func (s *Session) SendUnreliable(recipient, provider string, message []byte) error {
	s.log.Debugf("SendUnreliable")
	messageID := [block.MessageIDLength]byte{}
	_, err := rand.Reader.Read(messageID[:])
	if err != nil {
		return err
	}
	if len(message) > coreconstants.UserForwardPayloadLength {
		return errors.New("failure: SendUnreliable message payload exceeds maximum.")
	}
	return s.minclient.SendUnreliableCiphertext(recipient, provider, message)
}

// OnConnection will be called by the minclient api
// upon connecting to the Provider
func (s *Session) onConnection(err error) {
	s.log.Debugf("OnConnection")
	if err == nil {
		s.connected <- true
	}
}

// OnMessage will be called by the minclient api
// upon receiving a message
func (s *Session) onMessage(ciphertextBlock []byte) error {
	s.log.Debugf("OnMessage")
	return nil
}

// OnACK is called by the minclient api whe
// we receive an ACK message
func (s *Session) onACK(surbid *[constants.SURBIDLength]byte, message []byte) error {
	s.log.Debugf("OnACK")
	return nil
}

func (s *Session) onDocument(doc *pki.Document) {
	s.log.Debugf("onDocument(): Epoch %v", doc.Epoch)
}
<commit_msg>Add GetService for finding provider side services<commit_after>// session.go - mixnet client session
// Copyright (C) 2018  David Stainton.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package client provides the Katzenpost midclient
package client

import (
	"context"
	"errors"
	"fmt"
	"math/rand"
	"time"

	"github.com/katzenpost/client/internal/authority"
	"github.com/katzenpost/client/internal/pkiclient"
	coreconstants "github.com/katzenpost/core/constants"
	"github.com/katzenpost/core/crypto/ecdh"
	"github.com/katzenpost/core/epochtime"
	"github.com/katzenpost/core/log"
	"github.com/katzenpost/core/pki"
	"github.com/katzenpost/core/sphinx/constants"
	"github.com/katzenpost/core/worker"
	"github.com/katzenpost/minclient"
	"github.com/katzenpost/minclient/block"
	"gopkg.in/op/go-logging.v1"
)

// Session holds the client session
type Session struct {
	worker.Worker

	pkiClient       pki.Client
	minclient       *minclient.Client
	authority       *authority.Authority
	log             *logging.Logger
	logBackend      *log.Backend
	connected       chan bool
	identityPrivKey *ecdh.PrivateKey
}

// NewSession stablishes a session with provider using key.
// This method will block until session is connected to the Provider.
func (c *Client) NewSession() (*Session, error) {
	var err error
	session := new(Session)

	// create a pkiclient for our own client lookups
	proxyCfg := c.cfg.UpstreamProxyConfig()
	session.pkiClient, err = c.cfg.NonvotingAuthority.New(c.logBackend, proxyCfg)
	if err != nil {
		return nil, err
	}

	// create a pkiclient for minclient's use
	pkiClient, err := c.cfg.NonvotingAuthority.New(c.logBackend, proxyCfg)
	if err != nil {
		return nil, err
	}
	pkiCacheClient := pkiclient.New(pkiClient)

	// Configure and bring up the minclient instance.
	clientCfg := &minclient.ClientConfig{
		User:                c.cfg.Account.User,
		Provider:            c.cfg.Account.Provider,
		ProviderKeyPin:      c.cfg.Account.ProviderKeyPin,
		LinkKey:             c.cfg.Account.LinkKey,
		LogBackend:          c.logBackend,
		PKIClient:           pkiCacheClient,
		OnConnFn:            session.onConnection,
		OnMessageFn:         session.onMessage,
		OnACKFn:             session.onACK,
		OnDocumentFn:        session.onDocument,
		DialContextFn:       proxyCfg.ToDialContext("nonvoting:" + c.cfg.NonvotingAuthority.PublicKey.String()),
		MessagePollInterval: time.Duration(c.cfg.Debug.PollingInterval) * time.Second,
		EnableTimeSync:      false, // Be explicit about it.
	}

	c.authority = authority.NewStore(c.logBackend, proxyCfg)
	session.connected = make(chan bool, 0)
	session.log = c.logBackend.GetLogger(fmt.Sprintf("%s@%s_session", c.cfg.Account.User, c.cfg.Account.Provider))
	session.minclient, err = minclient.New(clientCfg)
	if err != nil {
		return nil, err
	}
	err = session.waitForConnection()
	if err != nil {
		return nil, err
	}
	return session, nil
}

// Shutdown the session
func (s *Session) Shutdown() {
	s.minclient.Shutdown()
}

// waitForConnection blocks until the client is
// connected to the Provider
func (s *Session) waitForConnection() error {
	isConnected := <-s.connected
	if !isConnected {
		return errors.New("status is not connected even with status change")
	}
	return nil
}

// Send reliably delivers the message to the recipient's queue
// on the destination provider or returns an error
func (s *Session) Send(recipient, provider string, message []byte) (*[block.MessageIDLength]byte, error) {
	s.log.Debugf("Send")
	return nil, errors.New("failure: Send is not yet implemented")
}

// SendUnreliable unreliably sends a message to the recipient's queue
// on the destination provider or returns an error
func (s *Session) SendUnreliable(recipient, provider string, message []byte) error {
	s.log.Debugf("SendUnreliable")
	if len(message) > coreconstants.UserForwardPayloadLength {
		return errors.New("failure: SendUnreliable message payload exceeds maximum.")
	}
	return s.minclient.SendUnreliableCiphertext(recipient, provider, message)
}

// GetService returns a randomly selected service
// matching the specified service name
func (s *Session) GetService(serviceName string) (*ServiceDescriptor, error) {
	epoch, _, _ := epochtime.Now()
	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) // XXX
	doc, _, err := s.pkiClient.Get(ctx, epoch)
	if err != nil {
		return nil, err
	}
	serviceDescriptors := FindServices(serviceName, doc)
	return &serviceDescriptors[rand.Intn(len(serviceDescriptors))], nil
}

// OnConnection will be called by the minclient api
// upon connecting to the Provider
func (s *Session) onConnection(err error) {
	s.log.Debugf("OnConnection")
	if err == nil {
		s.connected <- true
	}
}

// OnMessage will be called by the minclient api
// upon receiving a message
func (s *Session) onMessage(ciphertextBlock []byte) error {
	s.log.Debugf("OnMessage")
	return nil
}

// OnACK is called by the minclient api whe
// we receive an ACK message
func (s *Session) onACK(surbid *[constants.SURBIDLength]byte, message []byte) error {
	s.log.Debugf("OnACK")
	return nil
}

func (s *Session) onDocument(doc *pki.Document) {
	s.log.Debugf("onDocument(): Epoch %v", doc.Epoch)
}
<|endoftext|>


<commit_before>// Copyright 2015 Afshin Darian. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package wares

import (
	"code.google.com/p/go-uuid/uuid"
	"fmt"
	"github.com/ursiform/bear"
	"github.com/ursiform/forest"
	"net/http"
)

func SessionDel(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionDel := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		sessionID, ok := ctx.Get(forest.SessionID).(string)
		if !ok {
			err := fmt.Errorf("SessionDel %s: %v",
				forest.SessionID, ctx.Get(forest.SessionID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		userID, ok := ctx.Get(forest.SessionUserID).(string)
		if !ok {
			err := fmt.Errorf("SessionDel %s: %v",
				forest.SessionUserID, ctx.Get(forest.SessionUserID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		if err := manager.Delete(sessionID, userID); err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionDel)
}

func SessionGet(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionGet := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		cookieName := forest.SessionID
		createEmptySession := func(sessionID string) {
			path := app.CookiePath
			if path == "" {
				path = "/"
			}
			cookieValue := sessionID
			duration := app.Duration("Cookie")
			// Reset the cookie.
			app.SetCookie(ctx, path, cookieName, cookieValue, duration)
			manager.CreateEmpty(sessionID, ctx)
			ctx.Next()
		}
		cookie, err := ctx.Request.Cookie(cookieName)
		if err != nil || cookie.Value == "" {
			createEmptySession(uuid.New())
			return
		}
		sessionID := cookie.Value
		userID, userJSON, err := manager.Read(sessionID)
		if err != nil || userID == "" || userJSON == "" {
			createEmptySession(sessionID)
			return
		}
		if err := manager.Create(sessionID, userID, userJSON, ctx); err != nil {
			println(fmt.Sprintf("error creating session: %s", err))
			defer func(sessionID string, userID string) {
				if err := manager.Delete(sessionID, userID); err != nil {
					println(fmt.Sprintf("error deleting session: %s", err))
				}
			}(sessionID, userID)
			createEmptySession(sessionID)
			return
		}
		// If SessionRefresh is set to false, the session will not refresh;
		// if it's not set or if it's set to true, the session is refreshed.
		refresh, ok := ctx.Get(forest.SessionRefresh).(bool)
		if !ok || refresh {
			path := app.CookiePath
			if path == "" {
				path = "/"
			}
			cookieName := forest.SessionID
			cookieValue := sessionID
			duration := app.Duration("Cookie")
			// Refresh the cookie.
			app.SetCookie(ctx, path, cookieName, cookieValue, duration)
			defer func(sessionID string, userJSON string) {
				err := manager.Update(sessionID, userID, userJSON,
					app.Duration("Session"))
				if err != nil {
					println(fmt.Sprintf("error updating session: %s", err))
				}
			}(sessionID, userJSON)
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionGet)
}

func SessionSet(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionSet := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		userJSON, err := manager.Marshal(ctx)
		if err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		sessionID, ok := ctx.Get(forest.SessionID).(string)
		if !ok {
			err := fmt.Errorf("%s: %v",
				forest.SessionID, ctx.Get(forest.SessionID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		userID, ok := ctx.Get(forest.SessionUserID).(string)
		if !ok {
			err := fmt.Errorf("%s: %v",
				forest.SessionUserID, ctx.Get(forest.SessionUserID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		if err := manager.Update(sessionID, userID,
			string(userJSON), app.Duration("Session")); err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionSet)
}
<commit_msg>session updating should not be deferred because that causes incorrect states if a session manager deletes the current session<commit_after>// Copyright 2015 Afshin Darian. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package wares

import (
	"code.google.com/p/go-uuid/uuid"
	"fmt"
	"github.com/ursiform/bear"
	"github.com/ursiform/forest"
	"net/http"
)

func SessionDel(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionDel := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		sessionID, ok := ctx.Get(forest.SessionID).(string)
		if !ok {
			err := fmt.Errorf("SessionDel %s: %v",
				forest.SessionID, ctx.Get(forest.SessionID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		userID, ok := ctx.Get(forest.SessionUserID).(string)
		if !ok {
			err := fmt.Errorf("SessionDel %s: %v",
				forest.SessionUserID, ctx.Get(forest.SessionUserID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		if err := manager.Delete(sessionID, userID); err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionDel)
}

func SessionGet(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionGet := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		cookieName := forest.SessionID
		createEmptySession := func(sessionID string) {
			path := app.CookiePath
			if path == "" {
				path = "/"
			}
			cookieValue := sessionID
			duration := app.Duration("Cookie")
			// Reset the cookie.
			app.SetCookie(ctx, path, cookieName, cookieValue, duration)
			manager.CreateEmpty(sessionID, ctx)
			ctx.Next()
		}
		cookie, err := ctx.Request.Cookie(cookieName)
		if err != nil || cookie.Value == "" {
			createEmptySession(uuid.New())
			return
		}
		sessionID := cookie.Value
		userID, userJSON, err := manager.Read(sessionID)
		if err != nil || userID == "" || userJSON == "" {
			createEmptySession(uuid.New())
			return
		}
		if err := manager.Create(sessionID, userID, userJSON, ctx); err != nil {
			println(fmt.Sprintf("error creating session: %s", err))
			defer func(sessionID string, userID string) {
				if err := manager.Delete(sessionID, userID); err != nil {
					println(fmt.Sprintf("error deleting session: %s", err))
				}
			}(sessionID, userID)
			createEmptySession(uuid.New())
			return
		}
		// If SessionRefresh is set to false, the session will not refresh;
		// if it's not set or if it's set to true, the session is refreshed.
		refresh, ok := ctx.Get(forest.SessionRefresh).(bool)
		if !ok || refresh {
			path := app.CookiePath
			if path == "" {
				path = "/"
			}
			cookieName := forest.SessionID
			cookieValue := sessionID
			duration := app.Duration("Cookie")
			// Refresh the cookie.
			app.SetCookie(ctx, path, cookieName, cookieValue, duration)
			err := manager.Update(sessionID, userID,
				userJSON, app.Duration("Session"))
			if err != nil {
				println(fmt.Sprintf("error updating session: %s", err))
			}
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionGet)
}

func SessionSet(app *forest.App, manager SessionManager) bear.HandlerFunc {
	sessionSet := func(
		_ http.ResponseWriter, _ *http.Request, ctx *bear.Context) {
		userJSON, err := manager.Marshal(ctx)
		if err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		sessionID, ok := ctx.Get(forest.SessionID).(string)
		if !ok {
			err := fmt.Errorf("%s: %v",
				forest.SessionID, ctx.Get(forest.SessionID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		userID, ok := ctx.Get(forest.SessionUserID).(string)
		if !ok {
			err := fmt.Errorf("%s: %v",
				forest.SessionUserID, ctx.Get(forest.SessionUserID))
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		if err := manager.Update(sessionID, userID,
			string(userJSON), app.Duration("Session")); err != nil {
			ctx.Set(forest.Error, err)
			message := safeErrorMessage(app, ctx, app.Error("Generic"))
			app.Response(ctx, http.StatusInternalServerError,
				forest.Failure, message).Write(nil)
			return
		}
		ctx.Next()
	}
	return bear.HandlerFunc(sessionSet)
}
<|endoftext|>


<commit_before>package maillist

import (
	"errors"
	"fmt"
	"html/template"
	"io"
	"os"
	"time"

	"github.com/sendgrid/sendgrid-go"
)

type getAttendeeFunc func(eventID int64) []*Subscriber

// Session is an opaque type holding database connections and other
// implementation details
type Session struct {
	database
	config    Config
	wake      chan bool
	templates map[int64]*template.Template
	sgClient  *sendgrid.SGClient
}

// Config stores application defined options
type Config struct {
	DatabaseAddress      string
	JustPrint            bool
	Logger               io.Writer
	GetAttendeesCallback getAttendeeFunc
	UnsubscribeURL       string

	SendGridAPIKey   string
	SendGridUsername string
	SendGridPassword string
}

// OpenSession initialises a connection with the mailing list system. A call to
// Session.Close() should follow to ensure a clean exit.
func OpenSession(config *Config) (*Session, error) {
	var s Session
	var err error

	s.database, err = openDatabase(config.DatabaseAddress)
	if err != nil {
		return nil, err
	}

	s.config = *config

	if !config.JustPrint {
		if config.SendGridAPIKey == "" {
			return nil, errors.New("maillist: SendGridAPIKey must be set")
		}
		if config.SendGridUsername == "" {
			return nil, errors.New("maillist: SendGridUsername must be set")
		}
		if config.SendGridPassword == "" {
			return nil, errors.New("maillist: SendGridPassword must be set")
		}
	}

	if s.config.Logger == nil {
		s.config.Logger = os.Stderr
	}

	s.addTable(Account{}, "account")
	s.addTable(List{}, "list")
	s.addTable(Campaign{}, "campaign")
	s.addTable(Subscriber{}, "subscriber")
	s.addTable(Message{}, "message")
	s.addTable(ListSubscriber{}, "list_subscriber")

	// err = s.dbmap.CreateTablesIfNotExists()

	s.templates = make(map[int64]*template.Template)
	s.sgClient = sendgrid.NewSendGridClientWithApiKey(s.config.SendGridAPIKey)

	s.wake = make(chan bool)
	go service(&s)
	s.wake <- true

	return &s, err
}

// Close closes the session. It blocks until the session is cleanly exited
func (s *Session) Close() error {
	close(s.wake)
	return s.db.Close()
}

// listens for commands from the API. This is intended to be run asynchronously
// and mainly exists to prevent the API from blocking.
func service(s *Session) {
	ticker := time.NewTicker(time.Minute)

next:
	select {
	case _, ok := <-s.wake:
		if !ok {
			ticker.Stop()
			return
		}
	case <-ticker.C:
	}

	for {
		c, err := getDueCampaign(s)
		if err == ErrNotFound {
			break

		} else if err != nil {
			s.logf("couldn't retrieve due campaign: %v\n", err)
			break
		}

		if err = s.sendCampaign(c.ID); err != nil {
			s.logf("couldn't send campaign: %v\n", err)
			break
		}
	}

	for {
		m, err := pendingMessage(s)
		if err == ErrNotFound {
			break

		} else if err != nil {
			s.logf("couldn't retrieve pending message: %v\n", err)
			break
		}

		if err = s.sendMessage(m); err != nil {
			s.logf("couldn't send message: %v\n", err)
			break
		}
		time.Sleep(time.Second)
	}
	goto next
}

func (s *Session) logf(format string, args ...interface{}) {
	fmt.Fprintf(s.config.Logger, format, args)
}
<commit_msg>added better error for missing Config.GetAttendeesCallback<commit_after>package maillist

import (
	"errors"
	"fmt"
	"html/template"
	"io"
	"os"
	"time"

	"github.com/sendgrid/sendgrid-go"
)

type getAttendeeFunc func(eventID int64) []*Subscriber

// Session is an opaque type holding database connections and other
// implementation details
type Session struct {
	database
	config    Config
	wake      chan bool
	templates map[int64]*template.Template
	sgClient  *sendgrid.SGClient
}

// Config stores application defined options
type Config struct {
	DatabaseAddress      string
	JustPrint            bool
	Logger               io.Writer
	GetAttendeesCallback getAttendeeFunc
	UnsubscribeURL       string

	SendGridAPIKey   string
	SendGridUsername string
	SendGridPassword string
}

// OpenSession initialises a connection with the mailing list system. A call to
// Session.Close() should follow to ensure a clean exit.
func OpenSession(config *Config) (*Session, error) {
	var s Session
	var err error

	s.database, err = openDatabase(config.DatabaseAddress)
	if err != nil {
		return nil, err
	}

	s.config = *config

	if !config.JustPrint {
		if config.SendGridAPIKey == "" {
			return nil, errors.New("maillist: SendGridAPIKey must be set")
		}
		if config.SendGridUsername == "" {
			return nil, errors.New("maillist: SendGridUsername must be set")
		}
		if config.SendGridPassword == "" {
			return nil, errors.New("maillist: SendGridPassword must be set")
		}
	}

	if s.config.Logger == nil {
		s.config.Logger = os.Stderr
	}

	if s.config.GetAttendeesCallback == nil {
		fmt.Fprintln(s.config.Logger, "maillist: GetAttendeesCallback not set -- sending to events disabled")
		s.config.GetAttendeesCallback = func(eventID int64) []*Subscriber {
			fmt.Fprintln(s.config.Logger, "maillist: GetAttendeesCallback not set -- sending to events disabled")
			return nil
		}
	}

	s.addTable(Account{}, "account")
	s.addTable(List{}, "list")
	s.addTable(Campaign{}, "campaign")
	s.addTable(Subscriber{}, "subscriber")
	s.addTable(Message{}, "message")
	s.addTable(ListSubscriber{}, "list_subscriber")

	// err = s.dbmap.CreateTablesIfNotExists()

	s.templates = make(map[int64]*template.Template)
	s.sgClient = sendgrid.NewSendGridClientWithApiKey(s.config.SendGridAPIKey)

	s.wake = make(chan bool)
	go service(&s)
	s.wake <- true

	return &s, err
}

// Close closes the session. It blocks until the session is cleanly exited
func (s *Session) Close() error {
	close(s.wake)
	return s.db.Close()
}

// listens for commands from the API. This is intended to be run asynchronously
// and mainly exists to prevent the API from blocking.
func service(s *Session) {
	ticker := time.NewTicker(time.Minute)

next:
	select {
	case _, ok := <-s.wake:
		if !ok {
			ticker.Stop()
			return
		}
	case <-ticker.C:
	}

	for {
		c, err := getDueCampaign(s)
		if err == ErrNotFound {
			break

		} else if err != nil {
			s.logf("couldn't retrieve due campaign: %v\n", err)
			break
		}

		if err = s.sendCampaign(c.ID); err != nil {
			s.logf("couldn't send campaign: %v\n", err)
			break
		}
	}

	for {
		m, err := pendingMessage(s)
		if err == ErrNotFound {
			break

		} else if err != nil {
			s.logf("couldn't retrieve pending message: %v\n", err)
			break
		}

		if err = s.sendMessage(m); err != nil {
			s.logf("couldn't send message: %v\n", err)
			break
		}
		time.Sleep(time.Second)
	}
	goto next
}

func (s *Session) logf(format string, args ...interface{}) {
	fmt.Fprintf(s.config.Logger, format, args)
}
<|endoftext|>


<commit_before>package main

import "github.com/spf13/cobra"
import "fmt"
import "os"
import "net"
import "strconv"

// import "bufio"

func sendToTV(sharpCommand string, sharpParameter string) {

	debug := true
	cmdString := fmt.Sprintf("%4s%-4s\r", sharpCommand, sharpParameter)
	conn, err := net.Dial("tcp", "192.168.4.11:10002")

	if err != nil {
		fmt.Println("Error connecting to TV.")
		return
	}

	if debug {
		fmt.Printf("Sending command %v\n", cmdString)
	}

	fmt.Fprintf(conn, cmdString)
	if err != nil {
		fmt.Println("An error occured.")
		fmt.Println(err.Error())
	} else {
		if debug {
			fmt.Printf(">>>> Sent %v\n", cmdString)
		}
	}

	tmp := make([]byte, 256)
	result, err := conn.Read(tmp)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		if debug {
			fmt.Printf(">>>> Received: %s %s\n", tmp, string(result))
		}

	}

}

func main() {

	var sharptvCmd = &cobra.Command{
		Use:   "sharptv",
		Short: "sharptv is your command line interface to your television set",
		Long: `sharptv is the main command, used to control your TV

GoSharpTV is a hobbist project by an owner of a Sharp brand TV for other owners
of Sharp brand TVs.  It is implemented in the the Go programming lanugage.

`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("SharpTV command line remote control.")
		},
	}

	var cmdVolume = &cobra.Command{
		Use:   "volume {0..60|up|down}",
		Short: "Set the volume level of the TV.",
		Long: `Adjust the sound volume for the television.

You may find that a lower volume is more pleasant at night.
    `,
		Run: func(cmd *cobra.Command, args []string) {

			if len(args) != 1 {
				cmd.Usage()
				os.Exit(1)
			}

			numerical_argument, err := strconv.Atoi(args[0])
			if err == nil {
				if (numerical_argument > -1 && numerical_argument < 61) {
					fmt.Printf("Setting volume to %v\n", args[0])
					sendToTV("VOLM", args[0])
				} else {
					fmt.Printf("Volume specificed is out of range 0 to 60")
					return
				}
				return
			}

			switch args[0] {

			case "down":
				fmt.Println("Reducing the volume")
				sendToTV("RCKY", "32")

			case "up":
				fmt.Println("Increasing the volume")
				sendToTV("RCKY", "33")

			default:
				cmd.Usage();
			}

		},
	}

	var cmdMute = &cobra.Command{
		Use:   "mute {on|off}",
		Short: "Turn the volume of the TV off or on",
		Long: `Mutes or unmutes the television.  If not subcommand of either "off" or "on" are
    specfified, then the mute will be toggled from it's current state.`,
		Run: func(cmd *cobra.Command, args []string) {
			switch {
			case len(args) > 1:
				cmd.Usage()
			case len(args) == 0:
				fmt.Println("Toggling mute.")
				sendToTV("MUTE", "0000")

			case args[0] == "on":
				fmt.Println("Turning on mute.  This will silence the TV.")
				sendToTV("MUTE", "0001")

			case args[0] == "off":
				fmt.Println("Turning off mute.  This will return TV to the previous volume.")
				sendToTV("MUTE", "0002")

			case args[0] == "status":
				sendToTV("MUTE", "?")

			}
		},
	}

	var cmdPower = &cobra.Command{
		Use:   "power {on|off}",
		Short: "Turn the TV off or on",
		Long: `Powers the TV off or on.  If neither subcommand of either "off" nor "on" are
    specfified, then the power will be toggled from it's current state.`,
		Run: func(cmd *cobra.Command, args []string) {
			switch {
			case len(args) == 0:
				fmt.Println("Toggling Power is not yet implemented.")
			case len(args) > 1:
				cmd.Usage()
			case args[0] == "on":
				fmt.Println("Turning on the TV.")
				sendToTV("POWR", "1")
			case args[0] == "off":
				fmt.Println("Turning off the TV.")
				sendToTV("POWR", "0")
			case args[0] == "status":
				sendToTV("POWR", "?")
			default:
				cmd.Usage()
			}
		},
	}

	var cmdInput = &cobra.Command{
		Use:   "input [TV source input number]",
		Short: "Set the input source",
		Long: `Adjust the input source to be displayed on the TV

    `,
		Run: func(cmd *cobra.Command, args []string) {
			switch {

			case len(args) == 1:
				fmt.Printf("Setting input source to %v\n", args[0])
				sendToTV("IAVD", args[0])

			case len(args) != 1:
				cmd.Usage()
			}
		},
	}
	sharptvCmd.AddCommand(cmdPower)
	sharptvCmd.AddCommand(cmdMute)
	sharptvCmd.AddCommand(cmdInput)
	sharptvCmd.AddCommand(cmdVolume)
		sharptvCmd.Execute()
}
<commit_msg>Added examples to volume usage.<commit_after>package main

import "github.com/spf13/cobra"
import "fmt"
import "os"
import "net"
import "strconv"

// import "bufio"

func sendToTV(sharpCommand string, sharpParameter string) {

	debug := true
	cmdString := fmt.Sprintf("%4s%-4s\r", sharpCommand, sharpParameter)
	conn, err := net.Dial("tcp", "192.168.4.11:10002")

	if err != nil {
		fmt.Println("Error connecting to TV.")
		return
	}

	if debug {
		fmt.Printf("Sending command %v\n", cmdString)
	}

	fmt.Fprintf(conn, cmdString)
	if err != nil {
		fmt.Println("An error occured.")
		fmt.Println(err.Error())
	} else {
		if debug {
			fmt.Printf(">>>> Sent %v\n", cmdString)
		}
	}

	tmp := make([]byte, 256)
	result, err := conn.Read(tmp)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		if debug {
			fmt.Printf(">>>> Received: %s %s\n", tmp, string(result))
		}

	}

}

func main() {

	var sharptvCmd = &cobra.Command{
		Use:   "sharptv",
		Short: "sharptv is your command line interface to your television set",
		Long: `sharptv is the main command, used to control your TV

GoSharpTV is a hobbist project by an owner of a Sharp brand TV for other owners
of Sharp brand TVs.  It is implemented in the the Go programming lanugage.

`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("SharpTV command line remote control.")
		},
	}

	var cmdVolume = &cobra.Command{
		Use:   "volume {0..60|up|down}",
		Short: "Set the volume level of the TV.",
		Long: `Adjust the sound volume for the television.

You may find that a lower volume is more pleasant at night.

Examples:

	sharptv volume 0    # Effectively mutes without showing the mute icon
	sharptv volume 25   # Set TV to a little less than half volume.
	sharptv volume 60   # Blast the volume as loud as it will go!
	sharptv volume down # Reduce the volume by owe
    `,
		Run: func(cmd *cobra.Command, args []string) {

			if len(args) != 1 {
				cmd.Usage()
				os.Exit(1)
			}

			numerical_argument, err := strconv.Atoi(args[0])
			if err == nil {
				if (numerical_argument > -1 && numerical_argument < 61) {
					fmt.Printf("Setting volume to %v\n", args[0])
					sendToTV("VOLM", args[0])
				} else {
					fmt.Printf("Volume specificed is out of range 0 to 60")
					return
				}
				return
			}

			switch args[0] {

			case "down":
				fmt.Println("Reducing the volume")
				sendToTV("RCKY", "32")

			case "up":
				fmt.Println("Increasing the volume")
				sendToTV("RCKY", "33")

			default:
				cmd.Usage();
			}

		},
	}

	var cmdMute = &cobra.Command{
		Use:   "mute {on|off}",
		Short: "Turn the volume of the TV off or on",
		Long: `Mutes or unmutes the television.  If not subcommand of either "off" or "on" are
    specfified, then the mute will be toggled from it's current state.`,
		Run: func(cmd *cobra.Command, args []string) {
			switch {
			case len(args) > 1:
				cmd.Usage()
			case len(args) == 0:
				fmt.Println("Toggling mute.")
				sendToTV("MUTE", "0000")

			case args[0] == "on":
				fmt.Println("Turning on mute.  This will silence the TV.")
				sendToTV("MUTE", "0001")

			case args[0] == "off":
				fmt.Println("Turning off mute.  This will return TV to the previous volume.")
				sendToTV("MUTE", "0002")

			case args[0] == "status":
				sendToTV("MUTE", "?")

			}
		},
	}

	var cmdPower = &cobra.Command{
		Use:   "power {on|off}",
		Short: "Turn the TV off or on",
		Long: `Powers the TV off or on.  If neither subcommand of either "off" nor "on" are
    specfified, then the power will be toggled from it's current state.`,
		Run: func(cmd *cobra.Command, args []string) {
			switch {
			case len(args) == 0:
				fmt.Println("Toggling Power is not yet implemented.")
			case len(args) > 1:
				cmd.Usage()
			case args[0] == "on":
				fmt.Println("Turning on the TV.")
				sendToTV("POWR", "1")
			case args[0] == "off":
				fmt.Println("Turning off the TV.")
				sendToTV("POWR", "0")
			case args[0] == "status":
				sendToTV("POWR", "?")
			default:
				cmd.Usage()
			}
		},
	}

	var cmdInput = &cobra.Command{
		Use:   "input [TV source input number]",
		Short: "Set the input source",
		Long: `Adjust the input source to be displayed on the TV

    `,
		Run: func(cmd *cobra.Command, args []string) {
			switch {

			case len(args) == 1:
				fmt.Printf("Setting input source to %v\n", args[0])
				sendToTV("IAVD", args[0])

			case len(args) != 1:
				cmd.Usage()
			}
		},
	}
	sharptvCmd.AddCommand(cmdPower)
	sharptvCmd.AddCommand(cmdMute)
	sharptvCmd.AddCommand(cmdInput)
	sharptvCmd.AddCommand(cmdVolume)
		sharptvCmd.Execute()
}
<|endoftext|>