<commit_before>package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"net/http"
	"os"
	"time"

	"github.com/ethereum/go-ethereum/log"
	"gopkg.in/urfave/cli.v1"
)

func main() {
	app := cli.NewApp()
	app.Name = "livepeer-cli"
	app.Usage = "interact with local Livepeer node"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "http",
			Usage: "local http port",
			Value: "8935",
		},
		cli.StringFlag{
			Name:  "rtmp",
			Usage: "local rtmp port",
			Value: "1935",
		},
		cli.IntFlag{
			Name:  "loglevel",
			Value: 4,
			Usage: "log level to emit to the screen",
		},
	}
	app.Action = func(c *cli.Context) error {
		// Set up the logger to print everything and the random generator
		log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
		rand.Seed(time.Now().UnixNano())

		// Start the wizard and relinquish control
		w := &wizard{
			endpoint: fmt.Sprintf("http://localhost:%v/status", c.String("http")),
			rtmpPort: c.String("rtmp"),
			httpPort: c.String("http"),
			in:       bufio.NewReader(os.Stdin),
		}
		w.run()

		return nil
	}
	app.Run(os.Args)
}

type wizard struct {
	// conf     config        // Configurations from previous runs
	endpoint string // Local livepeer node
	rtmpPort string
	httpPort string
	in       *bufio.Reader // Wrapper around stdin to allow reading user input
}

func (w *wizard) run() {
	fmt.Println("+-----------------------------------------------------------+")
	fmt.Println("| Welcome to livepeer-cli, your Livepeer command line tool  |")
	fmt.Println("|                                                           |")
	fmt.Println("| This tool lets you interact with a local Livepeer node    |")
	fmt.Println("| and participate in the Livepeer protocol without the	    |")
	fmt.Println("| hassle that it would normally entail.                     |")
	fmt.Println("|                                                           |")
	fmt.Println("+-----------------------------------------------------------+")
	fmt.Println()

	// Make sure there is a local node running
	_, err := http.Get(w.endpoint)
	if err != nil {
		log.Error("Cannot find local node")
		return
	}

	w.stats(false)
	// Basics done, loop ad infinitum about what to do
	for {
		fmt.Println()
		fmt.Println("What would you like to do? (default = stats)")
		fmt.Println(" 1. Get node status")
		fmt.Println(" 2. Depoist token (TODO)")
		fmt.Println(" 3. Broadcast video")
		fmt.Println(" 4. Stream video")
		fmt.Println(" 5. Set transcoder config (TODO)")
		fmt.Println(" 6. Bond (TODO)")
		fmt.Println(" 7. Unbond (TODO)")
		fmt.Println(" 8. Become a transcoder (TODO)")
		fmt.Println(" 9. Get test Livepeer Token (TODO)")

		choice := w.read()
		switch {
		case choice == "" || choice == "1":
			w.stats(false)
		case choice == "2":
			//Deposit token
		case choice == "3":
			w.broadcast()
		case choice == "4":
			w.stream()
		case choice == "5":
			//Print transcoder config
			//Set transcoder config
		case choice == "6":
			//Check balance
			//Bond
		case choice == "7":
			//Check Bond Amount
			//Unbond
		case choice == "8":
			//Activate Transcoder
		case choice == "9":
			//Get test Livepeer Token

		default:
			log.Error("That's not something I can do")
		}
	}
}
<commit_msg>cleanup<commit_after>package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"net/http"
	"os"
	"time"

	"github.com/ethereum/go-ethereum/log"
	"gopkg.in/urfave/cli.v1"
)

func main() {
	app := cli.NewApp()
	app.Name = "livepeer-cli"
	app.Usage = "interact with local Livepeer node"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "http",
			Usage: "local http port",
			Value: "8935",
		},
		cli.StringFlag{
			Name:  "rtmp",
			Usage: "local rtmp port",
			Value: "1935",
		},
		cli.IntFlag{
			Name:  "loglevel",
			Value: 4,
			Usage: "log level to emit to the screen",
		},
	}
	app.Action = func(c *cli.Context) error {
		// Set up the logger to print everything and the random generator
		log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
		rand.Seed(time.Now().UnixNano())

		// Start the wizard and relinquish control
		w := &wizard{
			endpoint: fmt.Sprintf("http://localhost:%v/status", c.String("http")),
			rtmpPort: c.String("rtmp"),
			httpPort: c.String("http"),
			in:       bufio.NewReader(os.Stdin),
		}
		w.run()

		return nil
	}
	app.Run(os.Args)
}

type wizard struct {
	// conf     config        // Configurations from previous runs
	endpoint string // Local livepeer node
	rtmpPort string
	httpPort string
	in       *bufio.Reader // Wrapper around stdin to allow reading user input
}

func (w *wizard) run() {
	// Make sure there is a local node running
	_, err := http.Get(w.endpoint)
	if err != nil {
		log.Error(fmt.Sprintf("Cannot find local node. Is your node running on http:%v and rtmp:%v?", w.httpPort, w.rtmpPort))
		return
	}

	fmt.Println("+-----------------------------------------------------------+")
	fmt.Println("| Welcome to livepeer-cli, your Livepeer command line tool  |")
	fmt.Println("|                                                           |")
	fmt.Println("| This tool lets you interact with a local Livepeer node    |")
	fmt.Println("| and participate in the Livepeer protocol without the	    |")
	fmt.Println("| hassle that it would normally entail.                     |")
	fmt.Println("|                                                           |")
	fmt.Println("+-----------------------------------------------------------+")
	fmt.Println()

	w.stats(false)
	// Basics done, loop ad infinitum about what to do
	for {
		fmt.Println()
		fmt.Println("What would you like to do? (default = stats)")
		fmt.Println(" 1. Get node status")
		fmt.Println(" 2. Depoist token (TODO)")
		fmt.Println(" 3. Broadcast video")
		fmt.Println(" 4. Stream video")
		fmt.Println(" 5. Set transcoder config (TODO)")
		fmt.Println(" 6. Bond (TODO)")
		fmt.Println(" 7. Unbond (TODO)")
		fmt.Println(" 8. Become a transcoder (TODO)")
		fmt.Println(" 9. Get test Livepeer Token (TODO)")

		choice := w.read()
		switch {
		case choice == "" || choice == "1":
			w.stats(false)
		case choice == "2":
			//Deposit token
		case choice == "3":
			w.broadcast()
		case choice == "4":
			w.stream()
		case choice == "5":
			//Print transcoder config
			//Set transcoder config
		case choice == "6":
			//Check balance
			//Bond
		case choice == "7":
			//Check Bond Amount
			//Unbond
		case choice == "8":
			//Activate Transcoder
		case choice == "9":
			//Get test Livepeer Token

		default:
			log.Error("That's not something I can do")
		}
	}
}
<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package cmd

import (
	"fmt"
	"time"

	"github.com/TheThingsNetwork/ttn/utils/security"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// networkserverAuthorizeCmd represents the secure command
var networkserverAuthorizeCmd = &cobra.Command{
	Use:   "authorize [id]",
	Short: "Generate a token that Brokers should use to connect",
	Long:  `ttn networkserver authorize generates a token that Brokers should use to connect`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			cmd.UsageFunc()(cmd)
		}

		_, priv, _, err := security.LoadKeys(viper.GetString("key-dir"))
		if err != nil {
			ctx.WithError(err).Fatal("Could not load security keys")
		}
		ttl, err := cmd.Flags().GetInt("valid")
		if err != nil {
			ctx.WithError(err).Fatal("Could not read TTL")
		}
		token, err := security.BuildJWT(args[0], time.Duration(ttl)*time.Hour*24, priv)
		if err != nil {
			ctx.WithError(err).Fatal("Could not generate a JWT")
		}

		ctx.WithField("ID", args[0]).Info("Generated NS token")
		fmt.Println()
		fmt.Println(token)
		fmt.Println()
	},
}

func init() {
	networkserverCmd.AddCommand(networkserverAuthorizeCmd)
	networkserverAuthorizeCmd.Flags().Int("valid", 0, "The number of days the token is valid")
}
<commit_msg>Fix networkserver authorize cmd<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package cmd

import (
	"fmt"
	"time"

	"github.com/TheThingsNetwork/ttn/utils/security"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// networkserverAuthorizeCmd represents the secure command
var networkserverAuthorizeCmd = &cobra.Command{
	Use:   "authorize [id]",
	Short: "Generate a token that Brokers should use to connect",
	Long:  `ttn networkserver authorize generates a token that Brokers should use to connect`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			cmd.UsageFunc()(cmd)
		}

		_, privateKey, _, err := security.LoadKeys(viper.GetString("key-dir"))
		if err != nil {
			ctx.WithError(err).Fatal("Could not load security keys")
		}
		ttl, err := cmd.Flags().GetInt("valid")
		if err != nil {
			ctx.WithError(err).Fatal("Could not read TTL")
		}
		claims := jwt.StandardClaims{
			Subject:   args[0],
			Issuer:    viper.GetString("id"),
			IssuedAt:  time.Now().Unix(),
			NotBefore: time.Now().Unix(),
		}
		if ttl > 0 {
			claims.ExpiresAt = time.Now().Add(time.Duration(ttl) * time.Hour * 24).Unix()
		}
		tokenBuilder := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
		key, err := jwt.ParseECPrivateKeyFromPEM(privateKey)
		if err != nil {
			ctx.WithError(err).Fatal("Could not parse private kay")
		}
		token, err := tokenBuilder.SignedString(key)
		if err != nil {
			ctx.WithError(err).Fatal("Could not sign JWT")
		}

		ctx.WithField("ID", args[0]).Info("Generated NS token")
		fmt.Println()
		fmt.Println(token)
		fmt.Println()
	},
}

func init() {
	networkserverCmd.AddCommand(networkserverAuthorizeCmd)
	networkserverAuthorizeCmd.Flags().Int("valid", 0, "The number of days the token is valid")
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The xridge kubestone contributors.

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

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

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

package e2e

import (
	"bytes"
	"log"
	"os/exec"

	"github.com/firepear/qsplit"
)

func run(command string) (stdout, stderr string, err error) {
	commandArray := qsplit.ToStrings([]byte(command))
	cmd := exec.Command(commandArray[0], commandArray[1:]...)
	var stdOut bytes.Buffer
	var stdErr bytes.Buffer
	cmd.Stdout, cmd.Stderr = &stdOut, &stdErr
	err = cmd.Run()
	if err != nil {
		log.Printf("Error during execution of `%v`\nerr: %v\nstdout: %v\nstderr: %v\n",
			command, err, stdOut.String(), stdErr.String())
		return "", "", err
	}

	return stdOut.String(), stdErr.String(), nil
}
<commit_msg>MAINT: Brevity in run()<commit_after>/*
Copyright 2019 The xridge kubestone contributors.

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

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

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

package e2e

import (
	"bytes"
	"log"
	"os/exec"

	"github.com/firepear/qsplit"
)

func run(command string) (stdout, stderr string, err error) {
	commandArray := qsplit.ToStrings([]byte(command))
	cmd := exec.Command(commandArray[0], commandArray[1:]...)
	var stdOut, stdErr bytes.Buffer
	cmd.Stdout, cmd.Stderr = &stdOut, &stdErr
	if err = cmd.Run(); err != nil {
		log.Printf("Error during execution of `%v`\nerr: %v\nstdout: %v\nstderr: %v\n",
			command, err, stdOut.String(), stdErr.String())
		return "", "", err
	}

	return stdOut.String(), stdErr.String(), nil
}
<|endoftext|>


<commit_before>package main_test

import (
	"encoding/json"
	"time"

	"github.com/apcera/nats"
	"github.com/cloudfoundry-incubator/route-emitter/routing_table"
	. "github.com/cloudfoundry-incubator/route-emitter/routing_table/matchers"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/lager/lagertest"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

const emitterInterruptTimeout = 5 * time.Second

var _ = Describe("Route Emitter", func() {
	listenForRoutes := func(subject string) <-chan routing_table.RegistryMessage {
		routes := make(chan routing_table.RegistryMessage)

		natsClient.Subscribe(subject, func(msg *nats.Msg) {
			defer GinkgoRecover()

			var message routing_table.RegistryMessage
			err := json.Unmarshal(msg.Data, &message)
			Ω(err).ShouldNot(HaveOccurred())

			routes <- message
		})

		return routes
	}

	var (
		registeredRoutes   <-chan routing_table.RegistryMessage
		unregisteredRoutes <-chan routing_table.RegistryMessage

		processGuid string
		domain      string
		desiredLRP  models.DesiredLRP

		lrpKey       models.ActualLRPKey
		containerKey models.ActualLRPContainerKey
		netInfo      models.ActualLRPNetInfo
	)

	BeforeEach(func() {
		processGuid = "guid1"
		domain = "tests"

		desiredLRP = models.DesiredLRP{
			Domain:      domain,
			ProcessGuid: processGuid,
			Routes:      []string{"route-1", "route-2"},
			Instances:   5,
			Stack:       "some-stack",
			MemoryMB:    1024,
			DiskMB:      512,
			LogGuid:     "some-log-guid",
			Action: &models.RunAction{
				Path: "ls",
			},
		}

		lrpKey = models.NewActualLRPKey(processGuid, 0, domain)
		containerKey = models.NewActualLRPContainerKey("iguid1", "cell-id")
		netInfo = models.NewActualLRPNetInfo("1.2.3.4", []models.PortMapping{
			{ContainerPort: 8080, HostPort: 65100},
		})

		registeredRoutes = listenForRoutes("router.register")
		unregisteredRoutes = listenForRoutes("router.unregister")

		natsClient.Subscribe("router.greet", func(msg *nats.Msg) {
			defer GinkgoRecover()

			greeting := routing_table.RouterGreetingMessage{
				MinimumRegisterInterval: 2,
			}

			response, err := json.Marshal(greeting)
			Ω(err).ShouldNot(HaveOccurred())

			err = natsClient.Publish(msg.Reply, response)
			Ω(err).ShouldNot(HaveOccurred())
		})
	})

	Context("when the emitter is running", func() {
		var emitter ifrit.Process

		BeforeEach(func() {
			emitter = ginkgomon.Invoke(createEmitterRunner())
		})

		AfterEach(func() {
			ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
		})

		Context("and an lrp with routes is desired", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(desiredLRP)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and an instance starts", func() {
				BeforeEach(func() {
					_, err := bbs.StartActualLRP(lrpKey, containerKey, netInfo)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              desiredLRP.Routes,
						Host:              netInfo.Host,
						Port:              uint16(netInfo.Ports[0].HostPort),
						App:               desiredLRP.LogGuid,
						PrivateInstanceId: containerKey.InstanceGuid,
					})))
				})
			})

			Context("and an instance is claimed", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(desiredLRP)
					Ω(err).ShouldNot(HaveOccurred())

					_, err = bbs.CreateActualLRP(desiredLRP, 0, lagertest.NewTestLogger("test"))
					Ω(err).ShouldNot(HaveOccurred())

					_, err = bbs.ClaimActualLRP(lrpKey, containerKey)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("does not emit routes", func() {
					Consistently(registeredRoutes).ShouldNot(Receive())
				})
			})
		})

		Context("an actual lrp starts without a routed desried lrp", func() {
			BeforeEach(func() {
				_, err := bbs.StartActualLRP(lrpKey, containerKey, netInfo)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and a route is desired", func() {
				BeforeEach(func() {
					time.Sleep(100 * time.Millisecond)
					err := bbs.DesireLRP(desiredLRP)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              desiredLRP.Routes,
						Host:              netInfo.Host,
						Port:              uint16(netInfo.Ports[0].HostPort),
						App:               desiredLRP.LogGuid,
						PrivateInstanceId: containerKey.InstanceGuid,
					})))
				})

				It("repeats the route message at the interval given by the router", func() {
					var msg1 routing_table.RegistryMessage
					Eventually(registeredRoutes).Should(Receive(&msg1))
					t1 := time.Now()

					var msg2 routing_table.RegistryMessage
					Eventually(registeredRoutes, 5).Should(Receive(&msg2))
					t2 := time.Now()

					Ω(msg2).Should(MatchRegistryMessage(msg1))
					Ω(t2.Sub(t1)).Should(BeNumerically("~", 2*time.Second, 500*time.Millisecond))
				})

				Context("when etcd goes away", func() {
					var msg1 routing_table.RegistryMessage
					var msg2 routing_table.RegistryMessage

					BeforeEach(func() {
						// ensure it's seen the route at least once
						Eventually(registeredRoutes).Should(Receive(&msg1))

						etcdRunner.Stop()
					})

					It("continues to broadcast routes", func() {
						Eventually(registeredRoutes, 5).Should(Receive(&msg2))
						Ω(msg2).Should(MatchRegistryMessage(msg1))
					})
				})
			})
		})

		Context("and another emitter starts", func() {
			var (
				secondRunner  *ginkgomon.Runner
				secondEmitter ifrit.Process
			)

			BeforeEach(func() {
				secondRunner = createEmitterRunner()
				secondRunner.StartCheck = ""

				secondEmitter = ginkgomon.Invoke(secondRunner)
			})

			AfterEach(func() {
				Ω(secondEmitter.Wait()).ShouldNot(Receive(), "Runner should not have exploded!")
				ginkgomon.Interrupt(secondEmitter, emitterInterruptTimeout)
			})

			Describe("the second emitter", func() {
				It("does not become active", func() {
					Consistently(secondRunner.Buffer, 5*time.Second).ShouldNot(gbytes.Say("route-emitter.started"))
				})
			})

			Context("and the first emitter goes away", func() {
				BeforeEach(func() {
					ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
				})

				Describe("the second emitter", func() {
					It("becomes active", func() {
						Eventually(secondRunner.Buffer, 5*time.Second).Should(gbytes.Say("route-emitter.started"))
					})
				})
			})
		})

		Context("and etcd goes away", func() {
			BeforeEach(func() {
				etcdRunner.Stop()
			})

			It("does not explode", func() {
				Consistently(emitter.Wait(), 5).ShouldNot(Receive())
			})
		})
	})

	Context("when the bbs has routes to emit in /desired and /actual", func() {
		var emitter ifrit.Process

		BeforeEach(func() {
			err := bbs.DesireLRP(desiredLRP)
			Ω(err).ShouldNot(HaveOccurred())

			_, err = bbs.StartActualLRP(lrpKey, containerKey, netInfo)
			Ω(err).ShouldNot(HaveOccurred())
		})

		Context("and the emitter is started", func() {
			BeforeEach(func() {
				emitter = ginkgomon.Invoke(createEmitterRunner())
			})

			AfterEach(func() {
				ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
			})

			It("immediately emits all routes", func() {
				Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
					URIs:              []string{"route-1", "route-2"},
					Host:              "1.2.3.4",
					Port:              65100,
					App:               "some-log-guid",
					PrivateInstanceId: "iguid1",
				})))
			})

			Context("and a route is added", func() {
				var changedDesiredLRP models.DesiredLRP

				BeforeEach(func() {
					changedDesiredLRP = desiredLRP
					changedDesiredLRP.Routes = []string{"route-1", "route-2", "route-3"}
					err := bbs.ChangeDesiredLRP(models.DesiredLRPChange{
						Before: &desiredLRP,
						After:  &changedDesiredLRP,
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.register", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              []string{"route-1", "route-2", "route-3"},
						Host:              "1.2.3.4",
						Port:              65100,
						App:               "some-log-guid",
						PrivateInstanceId: "iguid1",
					})))
				})
			})

			Context("and a route is removed", func() {
				var changedDesiredLRP models.DesiredLRP

				BeforeEach(func() {
					changedDesiredLRP = desiredLRP
					changedDesiredLRP.Routes = []string{"route-2"}
					err := bbs.ChangeDesiredLRP(models.DesiredLRPChange{
						Before: &desiredLRP,
						After:  &changedDesiredLRP,
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.unregister", func() {
					Eventually(unregisteredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              []string{"route-1"},
						Host:              "1.2.3.4",
						Port:              65100,
						App:               "some-log-guid",
						PrivateInstanceId: "iguid1",
					})))
				})
			})
		})
	})
})
<commit_msg>LRP lifecycle methods return only an error<commit_after>package main_test

import (
	"encoding/json"
	"time"

	"github.com/apcera/nats"
	"github.com/cloudfoundry-incubator/route-emitter/routing_table"
	. "github.com/cloudfoundry-incubator/route-emitter/routing_table/matchers"
	"github.com/cloudfoundry-incubator/runtime-schema/models"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/pivotal-golang/lager/lagertest"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

const emitterInterruptTimeout = 5 * time.Second

var _ = Describe("Route Emitter", func() {
	listenForRoutes := func(subject string) <-chan routing_table.RegistryMessage {
		routes := make(chan routing_table.RegistryMessage)

		natsClient.Subscribe(subject, func(msg *nats.Msg) {
			defer GinkgoRecover()

			var message routing_table.RegistryMessage
			err := json.Unmarshal(msg.Data, &message)
			Ω(err).ShouldNot(HaveOccurred())

			routes <- message
		})

		return routes
	}

	var (
		registeredRoutes   <-chan routing_table.RegistryMessage
		unregisteredRoutes <-chan routing_table.RegistryMessage

		processGuid string
		domain      string
		desiredLRP  models.DesiredLRP

		lrpKey       models.ActualLRPKey
		containerKey models.ActualLRPContainerKey
		netInfo      models.ActualLRPNetInfo
	)

	BeforeEach(func() {
		processGuid = "guid1"
		domain = "tests"

		desiredLRP = models.DesiredLRP{
			Domain:      domain,
			ProcessGuid: processGuid,
			Routes:      []string{"route-1", "route-2"},
			Instances:   5,
			Stack:       "some-stack",
			MemoryMB:    1024,
			DiskMB:      512,
			LogGuid:     "some-log-guid",
			Action: &models.RunAction{
				Path: "ls",
			},
		}

		lrpKey = models.NewActualLRPKey(processGuid, 0, domain)
		containerKey = models.NewActualLRPContainerKey("iguid1", "cell-id")
		netInfo = models.NewActualLRPNetInfo("1.2.3.4", []models.PortMapping{
			{ContainerPort: 8080, HostPort: 65100},
		})

		registeredRoutes = listenForRoutes("router.register")
		unregisteredRoutes = listenForRoutes("router.unregister")

		natsClient.Subscribe("router.greet", func(msg *nats.Msg) {
			defer GinkgoRecover()

			greeting := routing_table.RouterGreetingMessage{
				MinimumRegisterInterval: 2,
			}

			response, err := json.Marshal(greeting)
			Ω(err).ShouldNot(HaveOccurred())

			err = natsClient.Publish(msg.Reply, response)
			Ω(err).ShouldNot(HaveOccurred())
		})
	})

	Context("when the emitter is running", func() {
		var emitter ifrit.Process

		BeforeEach(func() {
			emitter = ginkgomon.Invoke(createEmitterRunner())
		})

		AfterEach(func() {
			ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
		})

		Context("and an lrp with routes is desired", func() {
			BeforeEach(func() {
				err := bbs.DesireLRP(desiredLRP)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and an instance starts", func() {
				BeforeEach(func() {
					err := bbs.StartActualLRP(lrpKey, containerKey, netInfo)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              desiredLRP.Routes,
						Host:              netInfo.Host,
						Port:              uint16(netInfo.Ports[0].HostPort),
						App:               desiredLRP.LogGuid,
						PrivateInstanceId: containerKey.InstanceGuid,
					})))
				})
			})

			Context("and an instance is claimed", func() {
				BeforeEach(func() {
					err := bbs.DesireLRP(desiredLRP)
					Ω(err).ShouldNot(HaveOccurred())

					err = bbs.CreateActualLRP(desiredLRP, 0, lagertest.NewTestLogger("test"))
					Ω(err).ShouldNot(HaveOccurred())

					err = bbs.ClaimActualLRP(lrpKey, containerKey)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("does not emit routes", func() {
					Consistently(registeredRoutes).ShouldNot(Receive())
				})
			})
		})

		Context("an actual lrp starts without a routed desried lrp", func() {
			BeforeEach(func() {
				err := bbs.StartActualLRP(lrpKey, containerKey, netInfo)
				Ω(err).ShouldNot(HaveOccurred())
			})

			Context("and a route is desired", func() {
				BeforeEach(func() {
					time.Sleep(100 * time.Millisecond)
					err := bbs.DesireLRP(desiredLRP)
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("emits its routes immediately", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              desiredLRP.Routes,
						Host:              netInfo.Host,
						Port:              uint16(netInfo.Ports[0].HostPort),
						App:               desiredLRP.LogGuid,
						PrivateInstanceId: containerKey.InstanceGuid,
					})))
				})

				It("repeats the route message at the interval given by the router", func() {
					var msg1 routing_table.RegistryMessage
					Eventually(registeredRoutes).Should(Receive(&msg1))
					t1 := time.Now()

					var msg2 routing_table.RegistryMessage
					Eventually(registeredRoutes, 5).Should(Receive(&msg2))
					t2 := time.Now()

					Ω(msg2).Should(MatchRegistryMessage(msg1))
					Ω(t2.Sub(t1)).Should(BeNumerically("~", 2*time.Second, 500*time.Millisecond))
				})

				Context("when etcd goes away", func() {
					var msg1 routing_table.RegistryMessage
					var msg2 routing_table.RegistryMessage

					BeforeEach(func() {
						// ensure it's seen the route at least once
						Eventually(registeredRoutes).Should(Receive(&msg1))

						etcdRunner.Stop()
					})

					It("continues to broadcast routes", func() {
						Eventually(registeredRoutes, 5).Should(Receive(&msg2))
						Ω(msg2).Should(MatchRegistryMessage(msg1))
					})
				})
			})
		})

		Context("and another emitter starts", func() {
			var (
				secondRunner  *ginkgomon.Runner
				secondEmitter ifrit.Process
			)

			BeforeEach(func() {
				secondRunner = createEmitterRunner()
				secondRunner.StartCheck = ""

				secondEmitter = ginkgomon.Invoke(secondRunner)
			})

			AfterEach(func() {
				Ω(secondEmitter.Wait()).ShouldNot(Receive(), "Runner should not have exploded!")
				ginkgomon.Interrupt(secondEmitter, emitterInterruptTimeout)
			})

			Describe("the second emitter", func() {
				It("does not become active", func() {
					Consistently(secondRunner.Buffer, 5*time.Second).ShouldNot(gbytes.Say("route-emitter.started"))
				})
			})

			Context("and the first emitter goes away", func() {
				BeforeEach(func() {
					ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
				})

				Describe("the second emitter", func() {
					It("becomes active", func() {
						Eventually(secondRunner.Buffer, 5*time.Second).Should(gbytes.Say("route-emitter.started"))
					})
				})
			})
		})

		Context("and etcd goes away", func() {
			BeforeEach(func() {
				etcdRunner.Stop()
			})

			It("does not explode", func() {
				Consistently(emitter.Wait(), 5).ShouldNot(Receive())
			})
		})
	})

	Context("when the bbs has routes to emit in /desired and /actual", func() {
		var emitter ifrit.Process

		BeforeEach(func() {
			err := bbs.DesireLRP(desiredLRP)
			Ω(err).ShouldNot(HaveOccurred())

			err = bbs.StartActualLRP(lrpKey, containerKey, netInfo)
			Ω(err).ShouldNot(HaveOccurred())
		})

		Context("and the emitter is started", func() {
			BeforeEach(func() {
				emitter = ginkgomon.Invoke(createEmitterRunner())
			})

			AfterEach(func() {
				ginkgomon.Interrupt(emitter, emitterInterruptTimeout)
			})

			It("immediately emits all routes", func() {
				Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
					URIs:              []string{"route-1", "route-2"},
					Host:              "1.2.3.4",
					Port:              65100,
					App:               "some-log-guid",
					PrivateInstanceId: "iguid1",
				})))
			})

			Context("and a route is added", func() {
				var changedDesiredLRP models.DesiredLRP

				BeforeEach(func() {
					changedDesiredLRP = desiredLRP
					changedDesiredLRP.Routes = []string{"route-1", "route-2", "route-3"}
					err := bbs.ChangeDesiredLRP(models.DesiredLRPChange{
						Before: &desiredLRP,
						After:  &changedDesiredLRP,
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.register", func() {
					Eventually(registeredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              []string{"route-1", "route-2", "route-3"},
						Host:              "1.2.3.4",
						Port:              65100,
						App:               "some-log-guid",
						PrivateInstanceId: "iguid1",
					})))
				})
			})

			Context("and a route is removed", func() {
				var changedDesiredLRP models.DesiredLRP

				BeforeEach(func() {
					changedDesiredLRP = desiredLRP
					changedDesiredLRP.Routes = []string{"route-2"}
					err := bbs.ChangeDesiredLRP(models.DesiredLRPChange{
						Before: &desiredLRP,
						After:  &changedDesiredLRP,
					})
					Ω(err).ShouldNot(HaveOccurred())
				})

				It("immediately emits router.unregister", func() {
					Eventually(unregisteredRoutes).Should(Receive(MatchRegistryMessage(routing_table.RegistryMessage{
						URIs:              []string{"route-1"},
						Host:              "1.2.3.4",
						Port:              65100,
						App:               "some-log-guid",
						PrivateInstanceId: "iguid1",
					})))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/livepeer/lpms/ffmpeg"
)

func validRenditions() []string {
	valids := make([]string, len(ffmpeg.VideoProfileLookup))
	for p, _ := range ffmpeg.VideoProfileLookup {
		valids = append(valids, p)
	}
	return valids
}

func main() {
	var err error
	if len(os.Args) <= 3 {
		panic("Usage: <input file> <output renditions, comma separated> <sw/nv> <from> <to>")
	}
	str2accel := func(inp string) (ffmpeg.Acceleration, string) {
		if inp == "nv" {
			return ffmpeg.Nvidia, "nv"
		}
		return ffmpeg.Software, "sw"
	}
	str2profs := func(inp string) []ffmpeg.VideoProfile {
		profs := []ffmpeg.VideoProfile{}
		strs := strings.Split(inp, ",")
		for _, k := range strs {
			p, ok := ffmpeg.VideoProfileLookup[k]
			if !ok {
				panic(fmt.Sprintf("Invalid rendition %s. Valid renditions are:\n%s", k, validRenditions()))
			}
			profs = append(profs, p)
		}
		return profs
	}
	fname := os.Args[1]
	profiles := str2profs(os.Args[2])
	accel, lbl := str2accel(os.Args[3])
	var from, to time.Duration
	if len(os.Args) > 4 {
		from, err = time.ParseDuration(os.Args[4])
		if err != nil {
			panic(err)
		}
	}
	if len(os.Args) > 5 {
		to, err = time.ParseDuration(os.Args[5])
		if err != nil {
			panic(err)
		}
	}

	profs2opts := func(profs []ffmpeg.VideoProfile) []ffmpeg.TranscodeOptions {
		opts := []ffmpeg.TranscodeOptions{}
		for i := range profs {
			o := ffmpeg.TranscodeOptions{
				Oname:   fmt.Sprintf("out_%s_%d_out.mp4", lbl, i),
				Profile: profs[i],
				// Uncomment the following to test scene classifier
				// Detector: &ffmpeg.DSceneAdultSoccer,
				Accel: accel,
			}
			o.From = from
			o.To = to
			opts = append(opts, o)
		}
		return opts
	}
	options := profs2opts(profiles)

	var dev string
	if accel == ffmpeg.Nvidia {
		if len(os.Args) <= 4 {
			panic("Expected device number")
		}
		dev = os.Args[4]
	}

	ffmpeg.InitFFmpeg()

	t := time.Now()
	fmt.Printf("Setting fname %s encoding %d renditions with %v\n", fname, len(options), lbl)
	res, err := ffmpeg.Transcode3(&ffmpeg.TranscodeOptionsIn{
		Fname:  fname,
		Accel:  accel,
		Device: dev,
	}, options)
	if err != nil {
		panic(err)
	}
	end := time.Now()
	fmt.Printf("profile=input frames=%v pixels=%v\n", res.Decoded.Frames, res.Decoded.Pixels)
	for i, r := range res.Encoded {
		if r.DetectData != nil {
			fmt.Printf("profile=%v frames=%v pixels=%v detectdata=%v\n", profiles[i].Name, r.Frames, r.Pixels, r.DetectData)
		} else {
			fmt.Printf("profile=%v frames=%v pixels=%v\n", profiles[i].Name, r.Frames, r.Pixels)
		}
	}
	fmt.Printf("Transcoding time %0.4v\n", end.Sub(t).Seconds())
}
<commit_msg>cmd/transcoding: specify 'from' and 'to' args as flag options (-from, -to)<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/livepeer/lpms/ffmpeg"
)

func validRenditions() []string {
	valids := make([]string, len(ffmpeg.VideoProfileLookup))
	for p := range ffmpeg.VideoProfileLookup {
		valids = append(valids, p)
	}
	return valids
}

func main() {
	from := flag.Duration("from", 0, "Skip all frames before that timestamp, from start of the file")
	to := flag.Duration("to", 0, "Skip all frames after that timestamp, from start of the file")
	flag.Parse()
	var err error
	args := append([]string{os.Args[0]}, flag.Args()...)
	if len(args) <= 3 {
		panic("Usage: [-from dur] [-to dur] <input file> <output renditions, comma separated> <sw/nv>")
	}
	str2accel := func(inp string) (ffmpeg.Acceleration, string) {
		if inp == "nv" {
			return ffmpeg.Nvidia, "nv"
		}
		return ffmpeg.Software, "sw"
	}
	str2profs := func(inp string) []ffmpeg.VideoProfile {
		profs := []ffmpeg.VideoProfile{}
		strs := strings.Split(inp, ",")
		for _, k := range strs {
			p, ok := ffmpeg.VideoProfileLookup[k]
			if !ok {
				panic(fmt.Sprintf("Invalid rendition %s. Valid renditions are:\n%s", k, validRenditions()))
			}
			profs = append(profs, p)
		}
		return profs
	}
	fname := args[1]
	profiles := str2profs(args[2])
	accel, lbl := str2accel(args[3])

	profs2opts := func(profs []ffmpeg.VideoProfile) []ffmpeg.TranscodeOptions {
		opts := []ffmpeg.TranscodeOptions{}
		for i := range profs {
			o := ffmpeg.TranscodeOptions{
				Oname:   fmt.Sprintf("out_%s_%d_out.mp4", lbl, i),
				Profile: profs[i],
				// Uncomment the following to test scene classifier
				// Detector: &ffmpeg.DSceneAdultSoccer,
				Accel: accel,
			}
			o.From = *from
			o.To = *to
			opts = append(opts, o)
		}
		return opts
	}
	options := profs2opts(profiles)

	var dev string
	if accel == ffmpeg.Nvidia {
		if len(args) <= 4 {
			panic("Expected device number")
		}
		dev = args[4]
	}

	ffmpeg.InitFFmpeg()

	t := time.Now()
	fmt.Printf("Setting fname %s encoding %d renditions with %v from %s to %s\n", fname, len(options), lbl, *from, *to)
	res, err := ffmpeg.Transcode3(&ffmpeg.TranscodeOptionsIn{
		Fname:  fname,
		Accel:  accel,
		Device: dev,
	}, options)
	if err != nil {
		panic(err)
	}
	end := time.Now()
	fmt.Printf("profile=input frames=%v pixels=%v\n", res.Decoded.Frames, res.Decoded.Pixels)
	for i, r := range res.Encoded {
		if r.DetectData != nil {
			fmt.Printf("profile=%v frames=%v pixels=%v detectdata=%v\n", profiles[i].Name, r.Frames, r.Pixels, r.DetectData)
		} else {
			fmt.Printf("profile=%v frames=%v pixels=%v\n", profiles[i].Name, r.Frames, r.Pixels)
		}
	}
	fmt.Printf("Transcoding time %0.4v\n", end.Sub(t).Seconds())
}
<|endoftext|>


<commit_before>// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.

package layers

import (
	"encoding/binary"
	"fmt"
	"github.com/google/gopacket"
)

// EAPOL defines an EAP over LAN (802.1x) layer.
type EAPOL struct {
	BaseLayer
	Version uint8
	Type    EAPOLType
	Length  uint16
}

// LayerType returns LayerTypeEAPOL.
func (e *EAPOL) LayerType() gopacket.LayerType { return LayerTypeEAPOL }

// DecodeFromBytes decodes the given bytes into this layer.
func (e *EAPOL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	e.Version = data[0]
	e.Type = EAPOLType(data[1])
	e.Length = binary.BigEndian.Uint16(data[2:4])
	e.BaseLayer = BaseLayer{data[:4], data[4:]}
	return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer
func (e *EAPOL) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	bytes, _ := b.PrependBytes(4)
	bytes[0] = e.Version
	bytes[1] = byte(e.Type)
	binary.BigEndian.PutUint16(bytes[2:], e.Length)
	return nil
}

// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (e *EAPOL) CanDecode() gopacket.LayerClass {
	return LayerTypeEAPOL
}

// NextLayerType returns the layer type contained by this DecodingLayer.
func (e *EAPOL) NextLayerType() gopacket.LayerType {
	return e.Type.LayerType()
}

func decodeEAPOL(data []byte, p gopacket.PacketBuilder) error {
	e := &EAPOL{}
	return decodingLayerDecoder(e, data, p)
}

// EAPOLKeyDescriptorType is an enumeration of key descriptor types
// as specified by 802.1x in the EAPOL-Key frame
type EAPOLKeyDescriptorType uint8

// Enumeration of EAPOLKeyDescriptorType
const (
	EAPOLKeyDescriptorTypeRC4   EAPOLKeyDescriptorType = 1
	EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2
	EAPOLKeyDescriptorTypeWPA   EAPOLKeyDescriptorType = 254
)

func (kdt EAPOLKeyDescriptorType) String() string {
	switch kdt {
	case EAPOLKeyDescriptorTypeRC4:
		return "RC4"
	case EAPOLKeyDescriptorTypeDot11:
		return "802.11"
	case EAPOLKeyDescriptorTypeWPA:
		return "WPA"
	default:
		return fmt.Sprintf("unknown descriptor type %d", kdt)
	}
}

// EAPOLKeyDescriptorVersion is an enumeration of versions specifying the
// encryption algorithm for the key data and the authentication for the
// message integrity code (MIC)
type EAPOLKeyDescriptorVersion uint8

// Enumeration of EAPOLKeyDescriptorVersion
const (
	EAPOLKeyDescriptorVersionOther       EAPOLKeyDescriptorVersion = 0
	EAPOLKeyDescriptorVersionRC4HMACMD5  EAPOLKeyDescriptorVersion = 1
	EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2
	EAPOLKeyDescriptorVersionAES128CMAC  EAPOLKeyDescriptorVersion = 3
)

func (v EAPOLKeyDescriptorVersion) String() string {
	switch v {
	case EAPOLKeyDescriptorVersionOther:
		return "Other"
	case EAPOLKeyDescriptorVersionRC4HMACMD5:
		return "RC4-HMAC-MD5"
	case EAPOLKeyDescriptorVersionAESHMACSHA1:
		return "AES-HMAC-SHA1-128"
	case EAPOLKeyDescriptorVersionAES128CMAC:
		return "AES-128-CMAC"
	default:
		return fmt.Sprintf("unknown version %d", v)
	}
}

// EAPOLKeyType is an enumeration of key derivation types describing
// the purpose of the keys being derived.
type EAPOLKeyType uint8

// Enumeration of EAPOLKeyType
const (
	EAPOLKeyTypeGroupSMK EAPOLKeyType = 0
	EAPOLKeyTypePairwise EAPOLKeyType = 1
)

func (kt EAPOLKeyType) String() string {
	switch kt {
	case EAPOLKeyTypeGroupSMK:
		return "Group/SMK"
	case EAPOLKeyTypePairwise:
		return "Pairwise"
	default:
		return fmt.Sprintf("unknown key type %d", kt)
	}
}

// EAPOLKey defines an EAPOL-Key frame for 802.1x authentication
type EAPOLKey struct {
	BaseLayer
	KeyDescriptorType    EAPOLKeyDescriptorType
	KeyDescriptorVersion EAPOLKeyDescriptorVersion
	KeyType              EAPOLKeyType
	KeyIndex             uint8
	Install              bool
	KeyACK               bool
	KeyMIC               bool
	Secure               bool
	MICError             bool
	Request              bool
	HasEncryptedKeyData  bool
	SMKMessage           bool
	KeyLength            uint16
	ReplayCounter        uint64
	Nonce                []byte
	IV                   []byte
	RSC                  uint64
	ID                   uint64
	MIC                  []byte
	KeyDataLength        uint16
	EncryptedKeyData     []byte
}

// LayerType returns LayerTypeEAPOLKey.
func (ek *EAPOLKey) LayerType() gopacket.LayerType {
	return LayerTypeEAPOLKey
}

func (ek *EAPOLKey) CanDecode() gopacket.LayerType {
	return LayerTypeEAPOLKey
}

// NextLayerType returns layers.LayerTypeDot11InformationElement if the key
// data exists and is unencrypted, otherwise it does not expect a next layer.
func (ek *EAPOLKey) NextLayerType() gopacket.LayerType {
	if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 {
		return LayerTypeDot11InformationElement
	}
	return gopacket.LayerTypePayload
}

const eapolKeyFrameLen = 95

// DecodeFromBytes decodes the given bytes into this layer.
func (ek *EAPOLKey) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	if len(data) < eapolKeyFrameLen {
		df.SetTruncated()
		return fmt.Errorf("EAPOLKey length %v too short, %v required",
			len(data), eapolKeyFrameLen)
	}

	ek.KeyDescriptorType = EAPOLKeyDescriptorType(data[0])

	info := binary.BigEndian.Uint16(data[1:3])
	ek.KeyDescriptorVersion = EAPOLKeyDescriptorVersion(info & 0x0007)
	ek.KeyType = EAPOLKeyType((info & 0x0008) >> 3)
	ek.KeyIndex = uint8((info & 0x0030) >> 4)
	ek.Install = (info & 0x0040) != 0
	ek.KeyACK = (info & 0x0080) != 0
	ek.KeyMIC = (info & 0x0100) != 0
	ek.Secure = (info & 0x0200) != 0
	ek.MICError = (info & 0x0400) != 0
	ek.Request = (info & 0x0800) != 0
	ek.HasEncryptedKeyData = (info & 0x1000) != 0
	ek.SMKMessage = (info & 0x2000) != 0

	ek.KeyLength = binary.BigEndian.Uint16(data[3:5])
	ek.ReplayCounter = binary.BigEndian.Uint64(data[5:13])

	ek.Nonce = data[13:45]
	ek.IV = data[45:61]
	ek.RSC = binary.BigEndian.Uint64(data[61:69])
	ek.ID = binary.BigEndian.Uint64(data[69:77])
	ek.MIC = data[77:93]

	ek.KeyDataLength = binary.BigEndian.Uint16(data[93:95])

	totalLength := eapolKeyFrameLen + int(ek.KeyDataLength)
	if len(data) < totalLength {
		df.SetTruncated()
		return fmt.Errorf("EAPOLKey data length %d too short, %d required",
			len(data)-eapolKeyFrameLen, ek.KeyDataLength)
	}

	if ek.HasEncryptedKeyData {
		ek.EncryptedKeyData = data[eapolKeyFrameLen:totalLength]
		ek.BaseLayer = BaseLayer{
			Contents: data[:totalLength],
			Payload:  data[totalLength:],
		}
	} else {
		ek.BaseLayer = BaseLayer{
			Contents: data[:eapolKeyFrameLen],
			Payload:  data[eapolKeyFrameLen:],
		}
	}

	return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (ek *EAPOLKey) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	buf, err := b.PrependBytes(eapolKeyFrameLen + len(ek.EncryptedKeyData))
	if err != nil {
		return err
	}

	buf[0] = byte(ek.KeyDescriptorType)

	var info uint16
	info |= uint16(ek.KeyDescriptorVersion)
	info |= uint16(ek.KeyType) << 3
	info |= uint16(ek.KeyIndex) << 4
	if ek.Install {
		info |= 0x0040
	}
	if ek.KeyACK {
		info |= 0x0080
	}
	if ek.KeyMIC {
		info |= 0x0100
	}
	if ek.Secure {
		info |= 0x0200
	}
	if ek.MICError {
		info |= 0x0400
	}
	if ek.Request {
		info |= 0x0800
	}
	if ek.HasEncryptedKeyData {
		info |= 0x1000
	}
	if ek.SMKMessage {
		info |= 0x2000
	}
	binary.BigEndian.PutUint16(buf[1:3], info)

	binary.BigEndian.PutUint16(buf[3:5], ek.KeyLength)
	binary.BigEndian.PutUint64(buf[5:13], ek.ReplayCounter)

	copy(buf[13:45], ek.Nonce)
	copy(buf[45:61], ek.IV)
	binary.BigEndian.PutUint64(buf[61:69], ek.RSC)
	binary.BigEndian.PutUint64(buf[69:77], ek.ID)
	copy(buf[77:93], ek.MIC)

	binary.BigEndian.PutUint16(buf[93:95], ek.KeyDataLength)
	if len(ek.EncryptedKeyData) > 0 {
		copy(buf[95:95+len(ek.EncryptedKeyData)], ek.EncryptedKeyData)
	}

	return nil
}

func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error {
	ek := &EAPOLKey{}
	return decodingLayerDecoder(ek, data, p)
}
<commit_msg>Updated to match comment formatting<commit_after>// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.

package layers

import (
	"encoding/binary"
	"fmt"
	"github.com/google/gopacket"
)

// EAPOL defines an EAP over LAN (802.1x) layer.
type EAPOL struct {
	BaseLayer
	Version uint8
	Type    EAPOLType
	Length  uint16
}

// LayerType returns LayerTypeEAPOL.
func (e *EAPOL) LayerType() gopacket.LayerType { return LayerTypeEAPOL }

// DecodeFromBytes decodes the given bytes into this layer.
func (e *EAPOL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	e.Version = data[0]
	e.Type = EAPOLType(data[1])
	e.Length = binary.BigEndian.Uint16(data[2:4])
	e.BaseLayer = BaseLayer{data[:4], data[4:]}
	return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer
func (e *EAPOL) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	bytes, _ := b.PrependBytes(4)
	bytes[0] = e.Version
	bytes[1] = byte(e.Type)
	binary.BigEndian.PutUint16(bytes[2:], e.Length)
	return nil
}

// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (e *EAPOL) CanDecode() gopacket.LayerClass {
	return LayerTypeEAPOL
}

// NextLayerType returns the layer type contained by this DecodingLayer.
func (e *EAPOL) NextLayerType() gopacket.LayerType {
	return e.Type.LayerType()
}

func decodeEAPOL(data []byte, p gopacket.PacketBuilder) error {
	e := &EAPOL{}
	return decodingLayerDecoder(e, data, p)
}

// EAPOLKeyDescriptorType is an enumeration of key descriptor types
// as specified by 802.1x in the EAPOL-Key frame
type EAPOLKeyDescriptorType uint8

// Enumeration of EAPOLKeyDescriptorType
const (
	EAPOLKeyDescriptorTypeRC4   EAPOLKeyDescriptorType = 1
	EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2
	EAPOLKeyDescriptorTypeWPA   EAPOLKeyDescriptorType = 254
)

func (kdt EAPOLKeyDescriptorType) String() string {
	switch kdt {
	case EAPOLKeyDescriptorTypeRC4:
		return "RC4"
	case EAPOLKeyDescriptorTypeDot11:
		return "802.11"
	case EAPOLKeyDescriptorTypeWPA:
		return "WPA"
	default:
		return fmt.Sprintf("unknown descriptor type %d", kdt)
	}
}

// EAPOLKeyDescriptorVersion is an enumeration of versions specifying the
// encryption algorithm for the key data and the authentication for the
// message integrity code (MIC)
type EAPOLKeyDescriptorVersion uint8

// Enumeration of EAPOLKeyDescriptorVersion
const (
	EAPOLKeyDescriptorVersionOther       EAPOLKeyDescriptorVersion = 0
	EAPOLKeyDescriptorVersionRC4HMACMD5  EAPOLKeyDescriptorVersion = 1
	EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2
	EAPOLKeyDescriptorVersionAES128CMAC  EAPOLKeyDescriptorVersion = 3
)

func (v EAPOLKeyDescriptorVersion) String() string {
	switch v {
	case EAPOLKeyDescriptorVersionOther:
		return "Other"
	case EAPOLKeyDescriptorVersionRC4HMACMD5:
		return "RC4-HMAC-MD5"
	case EAPOLKeyDescriptorVersionAESHMACSHA1:
		return "AES-HMAC-SHA1-128"
	case EAPOLKeyDescriptorVersionAES128CMAC:
		return "AES-128-CMAC"
	default:
		return fmt.Sprintf("unknown version %d", v)
	}
}

// EAPOLKeyType is an enumeration of key derivation types describing
// the purpose of the keys being derived.
type EAPOLKeyType uint8

// Enumeration of EAPOLKeyType
const (
	EAPOLKeyTypeGroupSMK EAPOLKeyType = 0
	EAPOLKeyTypePairwise EAPOLKeyType = 1
)

func (kt EAPOLKeyType) String() string {
	switch kt {
	case EAPOLKeyTypeGroupSMK:
		return "Group/SMK"
	case EAPOLKeyTypePairwise:
		return "Pairwise"
	default:
		return fmt.Sprintf("unknown key type %d", kt)
	}
}

// EAPOLKey defines an EAPOL-Key frame for 802.1x authentication
type EAPOLKey struct {
	BaseLayer
	KeyDescriptorType    EAPOLKeyDescriptorType
	KeyDescriptorVersion EAPOLKeyDescriptorVersion
	KeyType              EAPOLKeyType
	KeyIndex             uint8
	Install              bool
	KeyACK               bool
	KeyMIC               bool
	Secure               bool
	MICError             bool
	Request              bool
	HasEncryptedKeyData  bool
	SMKMessage           bool
	KeyLength            uint16
	ReplayCounter        uint64
	Nonce                []byte
	IV                   []byte
	RSC                  uint64
	ID                   uint64
	MIC                  []byte
	KeyDataLength        uint16
	EncryptedKeyData     []byte
}

// LayerType returns LayerTypeEAPOLKey.
func (ek *EAPOLKey) LayerType() gopacket.LayerType {
	return LayerTypeEAPOLKey
}

// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (ek *EAPOLKey) CanDecode() gopacket.LayerType {
	return LayerTypeEAPOLKey
}

// NextLayerType returns layers.LayerTypeDot11InformationElement if the key
// data exists and is unencrypted, otherwise it does not expect a next layer.
func (ek *EAPOLKey) NextLayerType() gopacket.LayerType {
	if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 {
		return LayerTypeDot11InformationElement
	}
	return gopacket.LayerTypePayload
}

const eapolKeyFrameLen = 95

// DecodeFromBytes decodes the given bytes into this layer.
func (ek *EAPOLKey) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
	if len(data) < eapolKeyFrameLen {
		df.SetTruncated()
		return fmt.Errorf("EAPOLKey length %v too short, %v required",
			len(data), eapolKeyFrameLen)
	}

	ek.KeyDescriptorType = EAPOLKeyDescriptorType(data[0])

	info := binary.BigEndian.Uint16(data[1:3])
	ek.KeyDescriptorVersion = EAPOLKeyDescriptorVersion(info & 0x0007)
	ek.KeyType = EAPOLKeyType((info & 0x0008) >> 3)
	ek.KeyIndex = uint8((info & 0x0030) >> 4)
	ek.Install = (info & 0x0040) != 0
	ek.KeyACK = (info & 0x0080) != 0
	ek.KeyMIC = (info & 0x0100) != 0
	ek.Secure = (info & 0x0200) != 0
	ek.MICError = (info & 0x0400) != 0
	ek.Request = (info & 0x0800) != 0
	ek.HasEncryptedKeyData = (info & 0x1000) != 0
	ek.SMKMessage = (info & 0x2000) != 0

	ek.KeyLength = binary.BigEndian.Uint16(data[3:5])
	ek.ReplayCounter = binary.BigEndian.Uint64(data[5:13])

	ek.Nonce = data[13:45]
	ek.IV = data[45:61]
	ek.RSC = binary.BigEndian.Uint64(data[61:69])
	ek.ID = binary.BigEndian.Uint64(data[69:77])
	ek.MIC = data[77:93]

	ek.KeyDataLength = binary.BigEndian.Uint16(data[93:95])

	totalLength := eapolKeyFrameLen + int(ek.KeyDataLength)
	if len(data) < totalLength {
		df.SetTruncated()
		return fmt.Errorf("EAPOLKey data length %d too short, %d required",
			len(data)-eapolKeyFrameLen, ek.KeyDataLength)
	}

	if ek.HasEncryptedKeyData {
		ek.EncryptedKeyData = data[eapolKeyFrameLen:totalLength]
		ek.BaseLayer = BaseLayer{
			Contents: data[:totalLength],
			Payload:  data[totalLength:],
		}
	} else {
		ek.BaseLayer = BaseLayer{
			Contents: data[:eapolKeyFrameLen],
			Payload:  data[eapolKeyFrameLen:],
		}
	}

	return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (ek *EAPOLKey) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	buf, err := b.PrependBytes(eapolKeyFrameLen + len(ek.EncryptedKeyData))
	if err != nil {
		return err
	}

	buf[0] = byte(ek.KeyDescriptorType)

	var info uint16
	info |= uint16(ek.KeyDescriptorVersion)
	info |= uint16(ek.KeyType) << 3
	info |= uint16(ek.KeyIndex) << 4
	if ek.Install {
		info |= 0x0040
	}
	if ek.KeyACK {
		info |= 0x0080
	}
	if ek.KeyMIC {
		info |= 0x0100
	}
	if ek.Secure {
		info |= 0x0200
	}
	if ek.MICError {
		info |= 0x0400
	}
	if ek.Request {
		info |= 0x0800
	}
	if ek.HasEncryptedKeyData {
		info |= 0x1000
	}
	if ek.SMKMessage {
		info |= 0x2000
	}
	binary.BigEndian.PutUint16(buf[1:3], info)

	binary.BigEndian.PutUint16(buf[3:5], ek.KeyLength)
	binary.BigEndian.PutUint64(buf[5:13], ek.ReplayCounter)

	copy(buf[13:45], ek.Nonce)
	copy(buf[45:61], ek.IV)
	binary.BigEndian.PutUint64(buf[61:69], ek.RSC)
	binary.BigEndian.PutUint64(buf[69:77], ek.ID)
	copy(buf[77:93], ek.MIC)

	binary.BigEndian.PutUint16(buf[93:95], ek.KeyDataLength)
	if len(ek.EncryptedKeyData) > 0 {
		copy(buf[95:95+len(ek.EncryptedKeyData)], ek.EncryptedKeyData)
	}

	return nil
}

func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error {
	ek := &EAPOLKey{}
	return decodingLayerDecoder(ek, data, p)
}
<|endoftext|>


<commit_before>package arn

import (
	"encoding/json"
	"strconv"

	"github.com/animenotifier/shoboi"
	"github.com/fatih/color"
)

// Anime ...
type Anime struct {
	ID            string           `json:"id"`
	Type          string           `json:"type"`
	Title         *AnimeTitle      `json:"title"`
	Image         *AnimeImageTypes `json:"image"`
	StartDate     string           `json:"startDate"`
	EndDate       string           `json:"endDate"`
	EpisodeCount  int              `json:"episodeCount"`
	EpisodeLength int              `json:"episodeLength"`
	Status        string           `json:"status"`
	NSFW          int              `json:"nsfw"`
	Rating        AnimeRating      `json:"rating"`
	Summary       string           `json:"summary"`
	Trailers      []*ExternalMedia `json:"trailers"`
	Mappings      []*Mapping       `json:"mappings"`
	Episodes      []*AnimeEpisode  `json:"episodes"`

	// Adult         bool            `json:"adult"`

	// Hashtag       string          `json:"hashtag"`
	// Source        string          `json:"source"`

	// PageGenerated string          `json:"pageGenerated"`
	// AnilistEdited uint64          `json:"anilistEdited"`
	// Genres        []string        `json:"genres"`
	// Tracks        *AnimeTrackList `json:"tracks"`
	// Links         []AnimeLink     `json:"links"`
	// Studios       []AnimeStudio   `json:"studios"`
	// Relations     []AnimeRelation `json:"relations"`
	// Created       string          `json:"created"`
	// CreatedBy     string          `json:"createdBy"`
}

// AnimeRating ...
type AnimeRating struct {
	Overall    float64 `json:"overall" editable:"true"`
	Story      float64 `json:"story" editable:"true"`
	Visuals    float64 `json:"visuals" editable:"true"`
	Soundtrack float64 `json:"soundtrack" editable:"true"`
}

// AnimeImageTypes ...
type AnimeImageTypes struct {
	Tiny     string `json:"tiny"`
	Small    string `json:"small"`
	Large    string `json:"large"`
	Original string `json:"original"`
}

// AnimeTitle ...
type AnimeTitle struct {
	Romaji    string   `json:"romaji"`
	English   string   `json:"english"`
	Japanese  string   `json:"japanese"`
	Hiragana  string   `json:"hiragana"`
	Canonical string   `json:"canonical"`
	Synonyms  []string `json:"synonyms"`
}

// GetAnime ...
func GetAnime(id string) (*Anime, error) {
	obj, err := DB.Get("Anime", id)
	return obj.(*Anime), err
}

// Link returns the URI to the anime page.
func (anime *Anime) Link() string {
	return "/anime/" + anime.ID
}

// Save saves the anime in the database.
func (anime *Anime) Save() error {
	return DB.Set("Anime", anime.ID, anime)
}

// PrettyJSON ...
func (anime *Anime) PrettyJSON() (string, error) {
	data, err := json.MarshalIndent(anime, "", "    ")
	return string(data), err
}

// Watching ...
func (anime *Anime) Watching() int {
	return 0
}

// AddMapping adds the ID of an external site to the anime.
func (anime *Anime) AddMapping(name string, id string, userID string) {
	for _, external := range anime.Mappings {
		// If it already exists we don't need to add it
		if external.Service == name && external.ServiceID == id {
			return
		}
	}

	anime.Mappings = append(anime.Mappings, &Mapping{
		Service:   name,
		ServiceID: id,
		Created:   DateTimeUTC(),
		CreatedBy: userID,
	})

	go anime.RefreshMapping(name, id)
}

// RefreshMapping will refresh all the data we can get from the external site for that anime.
func (anime *Anime) RefreshMapping(serviceName string, serviceID string) {
	switch serviceName {
	case "shoboi/anime":
		shoboiAnime, err := shoboi.GetAnime(serviceID)

		if err != nil {
			color.Red(err.Error())
			return
		}

		anime.Episodes = []*AnimeEpisode{}

		shoboiEpisodes := shoboiAnime.Episodes()
		for _, shoboiEpisode := range shoboiEpisodes {
			airingDate := shoboiEpisode.AiringDate()

			episode := &AnimeEpisode{
				Number: shoboiEpisode.Number,
				Title: &EpisodeTitle{
					Japanese: shoboiEpisode.TitleJapanese,
				},
				AiringDate: &AnimeAiringDate{
					Start: airingDate.Start,
					End:   airingDate.End,
				},
			}

			anime.Episodes = append(anime.Episodes, episode)
		}

		anime.Save()
	}
}

// GetMapping returns the external ID for the given service.
func (anime *Anime) GetMapping(name string) string {
	for _, external := range anime.Mappings {
		if external.Service == name {
			return external.ServiceID
		}
	}

	return ""
}

// RemoveMapping removes all mappings with the given service name and ID.
func (anime *Anime) RemoveMapping(name string, id string) bool {
	for index, external := range anime.Mappings {
		if external.Service == name && external.ServiceID == id {
			anime.Mappings = append(anime.Mappings[:index], anime.Mappings[index+1:]...)
			return true
		}
	}

	return false
}

// EpisodeCountString ...
func (anime *Anime) EpisodeCountString() string {
	if anime.EpisodeCount == 0 {
		return "?"
	}

	return strconv.Itoa(anime.EpisodeCount)
}

// StreamAnime returns a stream of all anime.
func StreamAnime() (chan *Anime, error) {
	objects, err := DB.All("Anime")
	return objects.(chan *Anime), err
}

// AllAnime returns a slice of all anime.
func AllAnime() ([]*Anime, error) {
	var all []*Anime

	stream, err := StreamAnime()

	if err != nil {
		return nil, err
	}

	for obj := range stream {
		all = append(all, obj)
	}

	return all, nil
}

// FilterAnime filters all anime by a custom function.
func FilterAnime(filter func(*Anime) bool) ([]*Anime, error) {
	var filtered []*Anime

	channel := make(chan *Anime)
	err := DB.Scan("Anime", channel)

	if err != nil {
		return filtered, err
	}

	for obj := range channel {
		if filter(obj) {
			filtered = append(filtered, obj)
		}
	}

	return filtered, nil
}

// GetAiringAnime ...
func GetAiringAnime() ([]*Anime, error) {
	return FilterAnime(func(anime *Anime) bool {
		return anime.Status == "current" && anime.Type == "tv" && anime.NSFW == 0 && anime.Rating.Overall > 50
	})
}
<commit_msg>Added first channel<commit_after>package arn

import (
	"encoding/json"
	"strconv"

	"github.com/animenotifier/shoboi"
	"github.com/fatih/color"
)

// Anime ...
type Anime struct {
	ID            string           `json:"id"`
	Type          string           `json:"type"`
	Title         *AnimeTitle      `json:"title"`
	Image         *AnimeImageTypes `json:"image"`
	FirstChannel  string           `json:"firstChannel"`
	StartDate     string           `json:"startDate"`
	EndDate       string           `json:"endDate"`
	EpisodeCount  int              `json:"episodeCount"`
	EpisodeLength int              `json:"episodeLength"`
	Status        string           `json:"status"`
	NSFW          int              `json:"nsfw"`
	Rating        AnimeRating      `json:"rating"`
	Summary       string           `json:"summary"`
	Trailers      []*ExternalMedia `json:"trailers"`
	Mappings      []*Mapping       `json:"mappings"`
	Episodes      []*AnimeEpisode  `json:"episodes"`

	// Adult         bool            `json:"adult"`

	// Hashtag       string          `json:"hashtag"`
	// Source        string          `json:"source"`

	// PageGenerated string          `json:"pageGenerated"`
	// AnilistEdited uint64          `json:"anilistEdited"`
	// Genres        []string        `json:"genres"`
	// Tracks        *AnimeTrackList `json:"tracks"`
	// Links         []AnimeLink     `json:"links"`
	// Studios       []AnimeStudio   `json:"studios"`
	// Relations     []AnimeRelation `json:"relations"`
	// Created       string          `json:"created"`
	// CreatedBy     string          `json:"createdBy"`
}

// AnimeRating ...
type AnimeRating struct {
	Overall    float64 `json:"overall" editable:"true"`
	Story      float64 `json:"story" editable:"true"`
	Visuals    float64 `json:"visuals" editable:"true"`
	Soundtrack float64 `json:"soundtrack" editable:"true"`
}

// AnimeImageTypes ...
type AnimeImageTypes struct {
	Tiny     string `json:"tiny"`
	Small    string `json:"small"`
	Large    string `json:"large"`
	Original string `json:"original"`
}

// AnimeTitle ...
type AnimeTitle struct {
	Romaji    string   `json:"romaji"`
	English   string   `json:"english"`
	Japanese  string   `json:"japanese"`
	Hiragana  string   `json:"hiragana"`
	Canonical string   `json:"canonical"`
	Synonyms  []string `json:"synonyms"`
}

// GetAnime ...
func GetAnime(id string) (*Anime, error) {
	obj, err := DB.Get("Anime", id)
	return obj.(*Anime), err
}

// Link returns the URI to the anime page.
func (anime *Anime) Link() string {
	return "/anime/" + anime.ID
}

// Save saves the anime in the database.
func (anime *Anime) Save() error {
	return DB.Set("Anime", anime.ID, anime)
}

// PrettyJSON ...
func (anime *Anime) PrettyJSON() (string, error) {
	data, err := json.MarshalIndent(anime, "", "    ")
	return string(data), err
}

// Watching ...
func (anime *Anime) Watching() int {
	return 0
}

// AddMapping adds the ID of an external site to the anime.
func (anime *Anime) AddMapping(name string, id string, userID string) {
	for _, external := range anime.Mappings {
		// If it already exists we don't need to add it
		if external.Service == name && external.ServiceID == id {
			return
		}
	}

	anime.Mappings = append(anime.Mappings, &Mapping{
		Service:   name,
		ServiceID: id,
		Created:   DateTimeUTC(),
		CreatedBy: userID,
	})

	go anime.RefreshMapping(name, id)
}

// RefreshMapping will refresh all the data we can get from the external site for that anime.
func (anime *Anime) RefreshMapping(serviceName string, serviceID string) {
	switch serviceName {
	case "shoboi/anime":
		shoboiAnime, err := shoboi.GetAnime(serviceID)

		if err != nil {
			color.Red(err.Error())
			return
		}

		anime.Episodes = []*AnimeEpisode{}

		shoboiEpisodes := shoboiAnime.Episodes()
		for _, shoboiEpisode := range shoboiEpisodes {
			airingDate := shoboiEpisode.AiringDate()

			episode := &AnimeEpisode{
				Number: shoboiEpisode.Number,
				Title: &EpisodeTitle{
					Japanese: shoboiEpisode.TitleJapanese,
				},
				AiringDate: &AnimeAiringDate{
					Start: airingDate.Start,
					End:   airingDate.End,
				},
			}

			anime.Episodes = append(anime.Episodes, episode)
		}

		anime.Save()
	}
}

// GetMapping returns the external ID for the given service.
func (anime *Anime) GetMapping(name string) string {
	for _, external := range anime.Mappings {
		if external.Service == name {
			return external.ServiceID
		}
	}

	return ""
}

// RemoveMapping removes all mappings with the given service name and ID.
func (anime *Anime) RemoveMapping(name string, id string) bool {
	for index, external := range anime.Mappings {
		if external.Service == name && external.ServiceID == id {
			anime.Mappings = append(anime.Mappings[:index], anime.Mappings[index+1:]...)
			return true
		}
	}

	return false
}

// EpisodeCountString ...
func (anime *Anime) EpisodeCountString() string {
	if anime.EpisodeCount == 0 {
		return "?"
	}

	return strconv.Itoa(anime.EpisodeCount)
}

// StreamAnime returns a stream of all anime.
func StreamAnime() (chan *Anime, error) {
	objects, err := DB.All("Anime")
	return objects.(chan *Anime), err
}

// AllAnime returns a slice of all anime.
func AllAnime() ([]*Anime, error) {
	var all []*Anime

	stream, err := StreamAnime()

	if err != nil {
		return nil, err
	}

	for obj := range stream {
		all = append(all, obj)
	}

	return all, nil
}

// FilterAnime filters all anime by a custom function.
func FilterAnime(filter func(*Anime) bool) ([]*Anime, error) {
	var filtered []*Anime

	channel := make(chan *Anime)
	err := DB.Scan("Anime", channel)

	if err != nil {
		return filtered, err
	}

	for obj := range channel {
		if filter(obj) {
			filtered = append(filtered, obj)
		}
	}

	return filtered, nil
}

// GetAiringAnime ...
func GetAiringAnime() ([]*Anime, error) {
	return FilterAnime(func(anime *Anime) bool {
		return anime.Status == "current" && anime.Type == "tv" && anime.NSFW == 0 && anime.Rating.Overall > 50
	})
}
<|endoftext|>


<commit_before>package main

import "encoding/json"
import "github.com/jmhodges/levigo"
import "github.com/gokyle/kludge/common"
import "log"

var reqQ chan *common.Request

func startPool() {
	reqQ = make(chan *common.Request, reqBuf)
	for i := 0; i < poolSize; i++ {
		go requestHandler(i)
	}
}

func requestHandler(id int) {
	for {
		req, ok := <-reqQ
		if !ok {
			log.Printf("worker %d returns", id)
			return
		}
		req.Op.WID = id

		log.Printf("worker %d handling %s request", id,
			req.OpName())
		switch req.Op.OpCode {
		case common.OpGet:
			req.Resp <- store_get(req.Op)
		case common.OpSet:
			req.Resp <- store_set(req.Op)
		case common.OpDel:
			req.Resp <- store_del(req.Op)
		case common.OpLst:
			req.Resp <- store_lst(req.Op)
		default:
			log.Printf("worker %d received invalid operation %d",
				id, req.Op.OpCode)
			resp := new(common.Response)
			resp.Body = []byte("invalid request")
			req.Resp <- resp
		}
	}
}

func store_get(op *common.Operation) (resp *common.Response) {
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)
	resp = new(common.Response)

	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("error handling get from worker %d: %s",
			op.WID, err.Error())
		resp.ErrMsg = err.Error()
	} else {
		log.Printf("worker %d successfully completes GET", op.WID)
                if data != nil {
		        resp.KeyOK = true
                }
		resp.Body = data
	}
	return
}

func store_set(op *common.Operation) (resp *common.Response) {
	resp = new(common.Response)
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)

	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to read key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	}

	wopts := levigo.NewWriteOptions()
	wopts.SetSync(true)
	err = ldb.Put(wopts, op.Key, op.Val)
	if err != nil {
		log.Printf("worker %d failed to set key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	} else {
		log.Printf("worker %d successfully wrote key", op.WID)
		resp.KeyOK = len(data) > 0
		resp.Body = data
	}
	return
}

func store_del(op *common.Operation) (resp *common.Response) {
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)

	resp = new(common.Response)
	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to read key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	}

	wopts := levigo.NewWriteOptions()
	wopts.SetSync(true)
	err = ldb.Delete(wopts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to delete key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	} else {
		resp.KeyOK = len(data) > 0
		resp.Body = data
	}
	return
}

func store_lst(op *common.Operation) (resp *common.Response) {
	resp = new(common.Response)
	keys := make([]string, 0)
	ro := levigo.NewReadOptions()
	ro.SetFillCache(true)
	it := ldb.NewIterator(ro)
	for it.SeekToFirst(); it.Valid(); it.Next() {
		keys = append(keys, string(it.Key()))
	}

	if err := it.GetError(); err != nil {
		log.Printf("worker %d failed to iterate over keys: %s",
			op.WID, err.Error())
		resp.ErrMsg = err.Error()
	} else {
		resp.Body, err = json.Marshal(keys)
		if err != nil {
			log.Printf("worker %d failed to create JSON response: %s",
				op.WID, err.Error())
			resp.Body = []byte{}
		}
	}
	return
}
<commit_msg>go fmt<commit_after>package main

import "encoding/json"
import "github.com/jmhodges/levigo"
import "github.com/gokyle/kludge/common"
import "log"

var reqQ chan *common.Request

func startPool() {
	reqQ = make(chan *common.Request, reqBuf)
	for i := 0; i < poolSize; i++ {
		go requestHandler(i)
	}
}

func requestHandler(id int) {
	for {
		req, ok := <-reqQ
		if !ok {
			log.Printf("worker %d returns", id)
			return
		}
		req.Op.WID = id

		log.Printf("worker %d handling %s request", id,
			req.OpName())
		switch req.Op.OpCode {
		case common.OpGet:
			req.Resp <- store_get(req.Op)
		case common.OpSet:
			req.Resp <- store_set(req.Op)
		case common.OpDel:
			req.Resp <- store_del(req.Op)
		case common.OpLst:
			req.Resp <- store_lst(req.Op)
		default:
			log.Printf("worker %d received invalid operation %d",
				id, req.Op.OpCode)
			resp := new(common.Response)
			resp.Body = []byte("invalid request")
			req.Resp <- resp
		}
	}
}

func store_get(op *common.Operation) (resp *common.Response) {
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)
	resp = new(common.Response)

	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("error handling get from worker %d: %s",
			op.WID, err.Error())
		resp.ErrMsg = err.Error()
	} else {
		log.Printf("worker %d successfully completes GET", op.WID)
		if data != nil {
			resp.KeyOK = true
		}
		resp.Body = data
	}
	return
}

func store_set(op *common.Operation) (resp *common.Response) {
	resp = new(common.Response)
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)

	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to read key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	}

	wopts := levigo.NewWriteOptions()
	wopts.SetSync(true)
	err = ldb.Put(wopts, op.Key, op.Val)
	if err != nil {
		log.Printf("worker %d failed to set key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	} else {
		log.Printf("worker %d successfully wrote key", op.WID)
		resp.KeyOK = data == nil
		resp.Body = data
	}
	return
}

func store_del(op *common.Operation) (resp *common.Response) {
	ropts := levigo.NewReadOptions()
	ropts.SetVerifyChecksums(true)

	resp = new(common.Response)
	data, err := ldb.Get(ropts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to read key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	}

	wopts := levigo.NewWriteOptions()
	wopts.SetSync(true)
	err = ldb.Delete(wopts, op.Key)
	if err != nil {
		log.Printf("worker %d failed to delete key: %s", op.WID,
			err.Error())
		resp.ErrMsg = err.Error()
		return
	} else {
		resp.KeyOK = data == nil
		resp.Body = data
	}
	return
}

func store_lst(op *common.Operation) (resp *common.Response) {
	resp = new(common.Response)
	keys := make([]string, 0)
	ro := levigo.NewReadOptions()
	ro.SetFillCache(true)
	it := ldb.NewIterator(ro)
	for it.SeekToFirst(); it.Valid(); it.Next() {
		keys = append(keys, string(it.Key()))
	}

	if err := it.GetError(); err != nil {
		log.Printf("worker %d failed to iterate over keys: %s",
			op.WID, err.Error())
		resp.ErrMsg = err.Error()
	} else {
		resp.Body, err = json.Marshal(keys)
		if err != nil {
			log.Printf("worker %d failed to create JSON response: %s",
				op.WID, err.Error())
			resp.Body = []byte{}
		}
	}
	return
}
<|endoftext|>


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

package safehttp

import (
	"net/http"
)

// The HTTP request methods defined by RFC.
const (
	MethodConnect = "CONNECT" // RFC 7231, 4.3.6
	MethodDelete  = "DELETE"  // RFC 7231, 4.3.5
	MethodGet     = "GET"     // RFC 7231, 4.3.1
	MethodHead    = "HEAD"    // RFC 7231, 4.3.2
	MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
	MethodPatch   = "PATCH"   // RFC 5789
	MethodPost    = "POST"    // RFC 7231, 4.3.3
	MethodPut     = "PUT"     // RFC 7231, 4.3.4
	MethodTrace   = "TRACE"   // RFC 7231, 4.3.8
)

// ServeMux is an HTTP request multiplexer. It matches the URL of each incoming
// request against a list of registered patterns and calls the handler for
// the pattern that most closely matches the URL.
//
// Patterns names are fixed, rooted paths, like "/favicon.ico", or rooted
// subtrees like "/images/" (note the trailing slash). Longer patterns take
// precedence over shorter ones, so that if there are handlers registered for
// both "/images/" and "/images/thumbnails/", the latter handler will be called
// for paths beginning "/images/thumbnails/" and the former will receive
// requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted subtree, the
// pattern "/" matches all paths not matched by other registered patterns,
// not just the URL with Path == "/".
//
// If a subtree has been registered and a request is received naming the subtree
// root without its trailing slash, ServeMux redirects that request to
// the subtree root (adding the trailing slash). This behavior can be overridden
// with a separate registration for the path without the trailing slash. For
// example, registering "/images/" causes ServeMux to redirect a request for
// "/images" to "/images/", unless "/images" has been registered separately.
//
// Patterns may optionally begin with a host name, restricting matches to URLs
// on that host only.  Host-specific patterns take precedence over general
// patterns, so that a handler might register for the two patterns "/codesearch"
// and "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// ServeMux also takes care of sanitizing the URL request path and the Host
// header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL.
//
// Multiple handlers can be registered for a single pattern, as long as they
// handle different HTTP methods.
type ServeMux struct {
	mux  *http.ServeMux
	disp Dispatcher

	// Maps patterns to handlers supporting multiple HTTP methods.
	handlers  map[string]standardHandler
	interceps []Interceptor
}

// newServeMux allocates and returns a new ServeMux. If the provided dispatcher
// is nil, the DefaultDispatcher is used.
func newServeMux(d Dispatcher) *ServeMux {
	if d == nil {
		d = DefaultDispatcher{}
	}
	return &ServeMux{
		mux:      http.NewServeMux(),
		disp:     d,
		handlers: map[string]standardHandler{},
	}
}

func (m *ServeMux) handle(pattern string, method string, h Handler, cfgs ...InterceptorConfig) {
	var interceps []ConfiguredInterceptor
	for _, it := range m.interceps {
		var cfg InterceptorConfig
		for _, c := range cfgs {
			if c.Match(it) {
				cfg = c
				break
			}
		}
		interceps = append(interceps, ConfiguredInterceptor{Interceptor: it, Config: cfg})
	}
	hi := handler{
		handler:   h,
		interceps: interceps,
		disp:      m.disp,
	}

	mh, ok := m.handlers[pattern]
	if !ok {
		mh := standardHandler{
			handlers: map[string]handler{method: hi},
		}

		m.handlers[pattern] = mh
		m.mux.Handle(pattern, mh)
		return
	}

	if _, ok := mh.handlers[method]; ok {
		panic("method already registered")
	}
	mh.handlers[method] = hi
}

func (m *ServeMux) install(i Interceptor) {
	m.interceps = append(m.interceps, i)
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
//
//  For each incoming request:
//  - [Before Phase] Interceptor.Before methods are called for every installed
//    interceptor, until an interceptor writes to a ResponseWriter (including
//    errors) or panics,
//  - the handler is called after a [Before Phase] if no writes or panics occured,
//  - the handler triggers the [Commit Phase] by writing to the ResponseWriter,
//  - [Commit Phase] Interceptor.Commit methods run for every interceptor whose
//    Before method was called,
//  - [Dispatcher Phase] after the [Commit Phase], the Dispatcher's appropriate
//    write method is called; the Dispatcher is responsible for determining whether
//    the response is indeed safe and writing it,
//  - if the handler attempts to write more than once, it is treated as an
//    unrecoverable error; the request processing ends abrubptly with a panic and
//    nothing else happens (note: this will change as soon as [After Phase] is
//    introduced)
//
// Interceptors should NOT rely on the order they're run.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// ServeMuxBuilder is a builder for ServeMux.
type ServeMuxConfig struct {
	dispatcher   Dispatcher
	handlers     []handlerRegistration
	interceptors []Interceptor
}

type handlerRegistration struct {
	pattern string
	method  string
	handler Handler
	cfgs    []InterceptorConfig
}

// Handle registers a handler for the given pattern and method. If a handler is
// registered twice for the same pattern and method, Build will panic.
//
// InterceptorConfigs can be passed in order to modify the behavior of the
// interceptors on a registered handler. Passing an InterceptorConfig whose
// corresponding Interceptor was not installed will produce no effect. If
// multiple configurations are passed for the same Interceptor, only the first
// one will take effect.
func (s *ServeMuxConfig) Handle(pattern string, method string, h Handler, cfgs ...InterceptorConfig) {
	s.handlers = append(s.handlers, handlerRegistration{
		pattern: pattern,
		method:  method,
		handler: h,
		cfgs:    cfgs,
	})
}

// Intercept installs an Interceptor.
//
// Interceptors order is undetermined and should not be relied on.
func (s *ServeMuxConfig) Intercept(i Interceptor) {
	s.interceptors = append(s.interceptors, i)
}

// Mux returns the ServeMux with a copy of the current configuration.
func (s *ServeMuxConfig) Mux() *ServeMux {
	m := newServeMux(s.dispatcher)
	for _, it := range s.interceptors {
		m.install(it)
	}
	for _, hr := range s.handlers {
		m.handle(hr.pattern, hr.method, hr.handler, hr.cfgs...)
	}
	return m
}

// Clone creates a copy of the current config.
// This can be used to create several instances of Mux that share the same set of
// plugins and some common handlers.
func (s *ServeMuxConfig) Clone() *ServeMuxConfig {
	c := &ServeMuxConfig{
		dispatcher:   s.dispatcher,
		handlers:     make([]handlerRegistration, len(s.handlers)),
		interceptors: make([]Interceptor, len(s.interceptors)),
	}
	copy(c.handlers, s.handlers)
	copy(c.interceptors, s.interceptors)
	return c
}

// standardHandler is a collection of handler based on the request method.
type standardHandler struct {
	// Maps an HTTP method to its handler
	handlers map[string]handler
}

// ServeHTTP dispatches the request to the handler associated
// with the IncomingRequest method.
func (sh standardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h, ok := sh.handlers[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(w, r)
}

// handler encapsulates a handler and its corresponding
// interceptors.
type handler struct {
	handler   Handler
	interceps []ConfiguredInterceptor
	disp      Dispatcher
}

// ServeHTTP calls the Before method of all the interceptors and then calls the
// underlying handler. Any panics that occur during the Before phase, during handler
// execution or during the Commit phase are recovered here and a 500 Internal Server
// Error response is sent.
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ir := NewIncomingRequest(r)
	rw := NewResponseWriter(h.disp, w, ir)
	rw.handler = h

	// The `net/http` package recovers handler panics, but we cannot rely on that behavior here.
	// The reason is, we might need to run After/Commit stages of the interceptors before we
	// respond with a 500 Internal Server Error.
	defer func() {
		if r := recover(); r != nil {
			rw.WriteError(StatusInternalServerError)
		}
	}()

	for _, it := range h.interceps {
		it.Interceptor.Before(rw, ir, it.Config)
		if rw.written {
			return
		}
	}

	h.handler.ServeHTTP(rw, ir)
	if !rw.written {
		rw.NoContent()
	}
}

// commitPhase calls the Commit phases of all the interceptors. This stage will
// run before a response is written to the ResponseWriter. If a response is
// written to the ResponseWriter in a Commit phase then the Commit phases of the
// remaining interceptors won't execute.
//
// TODO: BIG WARNING, if ResponseWriter.Write and ResponseWriter.WriteTemplate
// are called in Commit then this will recurse. CommitResponseWriter was an
// attempt to prevent this by not giving access to Write and WriteTemplate in
// the Commit phase.
func (h handler) commitPhase(w *ResponseWriter, resp Response) {
	for i := len(h.interceps) - 1; i >= 0; i-- {
		it := h.interceps[i]
		it.Interceptor.Commit(w, w.req, resp, it.Config)
		if w.written {
			return
		}
	}
}

// errorPhase calls the OnError phases of all the interceptors associated with
// a handler. This stage runs before an error response is written to the
// ResponseWriter.
//
// TODO: BIG WARNING, if an interceptor attempts to write to the ResponseWriter
// in the OnError phase will result in an irrecoverable error.
func (h handler) errorPhase(w *ResponseWriter, resp Response) {
	for i := len(h.interceps) - 1; i >= 0; i-- {
		it := h.interceps[i]
		it.Interceptor.OnError(w, w.req, resp, it.Config)
	}
}
<commit_msg>Correct mistake in SeveMuxConfig godoc<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package safehttp

import (
	"net/http"
)

// The HTTP request methods defined by RFC.
const (
	MethodConnect = "CONNECT" // RFC 7231, 4.3.6
	MethodDelete  = "DELETE"  // RFC 7231, 4.3.5
	MethodGet     = "GET"     // RFC 7231, 4.3.1
	MethodHead    = "HEAD"    // RFC 7231, 4.3.2
	MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
	MethodPatch   = "PATCH"   // RFC 5789
	MethodPost    = "POST"    // RFC 7231, 4.3.3
	MethodPut     = "PUT"     // RFC 7231, 4.3.4
	MethodTrace   = "TRACE"   // RFC 7231, 4.3.8
)

// ServeMux is an HTTP request multiplexer. It matches the URL of each incoming
// request against a list of registered patterns and calls the handler for
// the pattern that most closely matches the URL.
//
// Patterns names are fixed, rooted paths, like "/favicon.ico", or rooted
// subtrees like "/images/" (note the trailing slash). Longer patterns take
// precedence over shorter ones, so that if there are handlers registered for
// both "/images/" and "/images/thumbnails/", the latter handler will be called
// for paths beginning "/images/thumbnails/" and the former will receive
// requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted subtree, the
// pattern "/" matches all paths not matched by other registered patterns,
// not just the URL with Path == "/".
//
// If a subtree has been registered and a request is received naming the subtree
// root without its trailing slash, ServeMux redirects that request to
// the subtree root (adding the trailing slash). This behavior can be overridden
// with a separate registration for the path without the trailing slash. For
// example, registering "/images/" causes ServeMux to redirect a request for
// "/images" to "/images/", unless "/images" has been registered separately.
//
// Patterns may optionally begin with a host name, restricting matches to URLs
// on that host only.  Host-specific patterns take precedence over general
// patterns, so that a handler might register for the two patterns "/codesearch"
// and "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// ServeMux also takes care of sanitizing the URL request path and the Host
// header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL.
//
// Multiple handlers can be registered for a single pattern, as long as they
// handle different HTTP methods.
type ServeMux struct {
	mux  *http.ServeMux
	disp Dispatcher

	// Maps patterns to handlers supporting multiple HTTP methods.
	handlers  map[string]standardHandler
	interceps []Interceptor
}

// newServeMux allocates and returns a new ServeMux. If the provided dispatcher
// is nil, the DefaultDispatcher is used.
func newServeMux(d Dispatcher) *ServeMux {
	if d == nil {
		d = DefaultDispatcher{}
	}
	return &ServeMux{
		mux:      http.NewServeMux(),
		disp:     d,
		handlers: map[string]standardHandler{},
	}
}

func (m *ServeMux) handle(pattern string, method string, h Handler, cfgs ...InterceptorConfig) {
	var interceps []ConfiguredInterceptor
	for _, it := range m.interceps {
		var cfg InterceptorConfig
		for _, c := range cfgs {
			if c.Match(it) {
				cfg = c
				break
			}
		}
		interceps = append(interceps, ConfiguredInterceptor{Interceptor: it, Config: cfg})
	}
	hi := handler{
		handler:   h,
		interceps: interceps,
		disp:      m.disp,
	}

	mh, ok := m.handlers[pattern]
	if !ok {
		mh := standardHandler{
			handlers: map[string]handler{method: hi},
		}

		m.handlers[pattern] = mh
		m.mux.Handle(pattern, mh)
		return
	}

	if _, ok := mh.handlers[method]; ok {
		panic("method already registered")
	}
	mh.handlers[method] = hi
}

func (m *ServeMux) install(i Interceptor) {
	m.interceps = append(m.interceps, i)
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
//
//  For each incoming request:
//  - [Before Phase] Interceptor.Before methods are called for every installed
//    interceptor, until an interceptor writes to a ResponseWriter (including
//    errors) or panics,
//  - the handler is called after a [Before Phase] if no writes or panics occured,
//  - the handler triggers the [Commit Phase] by writing to the ResponseWriter,
//  - [Commit Phase] Interceptor.Commit methods run for every interceptor whose
//    Before method was called,
//  - [Dispatcher Phase] after the [Commit Phase], the Dispatcher's appropriate
//    write method is called; the Dispatcher is responsible for determining whether
//    the response is indeed safe and writing it,
//  - if the handler attempts to write more than once, it is treated as an
//    unrecoverable error; the request processing ends abrubptly with a panic and
//    nothing else happens (note: this will change as soon as [After Phase] is
//    introduced)
//
// Interceptors should NOT rely on the order they're run.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// ServeMuxConfig is a builder for ServeMux.
type ServeMuxConfig struct {
	dispatcher   Dispatcher
	handlers     []handlerRegistration
	interceptors []Interceptor
}

type handlerRegistration struct {
	pattern string
	method  string
	handler Handler
	cfgs    []InterceptorConfig
}

// Handle registers a handler for the given pattern and method. If a handler is
// registered twice for the same pattern and method, Build will panic.
//
// InterceptorConfigs can be passed in order to modify the behavior of the
// interceptors on a registered handler. Passing an InterceptorConfig whose
// corresponding Interceptor was not installed will produce no effect. If
// multiple configurations are passed for the same Interceptor, only the first
// one will take effect.
func (s *ServeMuxConfig) Handle(pattern string, method string, h Handler, cfgs ...InterceptorConfig) {
	s.handlers = append(s.handlers, handlerRegistration{
		pattern: pattern,
		method:  method,
		handler: h,
		cfgs:    cfgs,
	})
}

// Intercept installs an Interceptor.
//
// Interceptors order is undetermined and should not be relied on.
func (s *ServeMuxConfig) Intercept(i Interceptor) {
	s.interceptors = append(s.interceptors, i)
}

// Mux returns the ServeMux with a copy of the current configuration.
func (s *ServeMuxConfig) Mux() *ServeMux {
	m := newServeMux(s.dispatcher)
	for _, it := range s.interceptors {
		m.install(it)
	}
	for _, hr := range s.handlers {
		m.handle(hr.pattern, hr.method, hr.handler, hr.cfgs...)
	}
	return m
}

// Clone creates a copy of the current config.
// This can be used to create several instances of Mux that share the same set of
// plugins and some common handlers.
func (s *ServeMuxConfig) Clone() *ServeMuxConfig {
	c := &ServeMuxConfig{
		dispatcher:   s.dispatcher,
		handlers:     make([]handlerRegistration, len(s.handlers)),
		interceptors: make([]Interceptor, len(s.interceptors)),
	}
	copy(c.handlers, s.handlers)
	copy(c.interceptors, s.interceptors)
	return c
}

// standardHandler is a collection of handler based on the request method.
type standardHandler struct {
	// Maps an HTTP method to its handler
	handlers map[string]handler
}

// ServeHTTP dispatches the request to the handler associated
// with the IncomingRequest method.
func (sh standardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h, ok := sh.handlers[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(w, r)
}

// handler encapsulates a handler and its corresponding
// interceptors.
type handler struct {
	handler   Handler
	interceps []ConfiguredInterceptor
	disp      Dispatcher
}

// ServeHTTP calls the Before method of all the interceptors and then calls the
// underlying handler. Any panics that occur during the Before phase, during handler
// execution or during the Commit phase are recovered here and a 500 Internal Server
// Error response is sent.
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ir := NewIncomingRequest(r)
	rw := NewResponseWriter(h.disp, w, ir)
	rw.handler = h

	// The `net/http` package recovers handler panics, but we cannot rely on that behavior here.
	// The reason is, we might need to run After/Commit stages of the interceptors before we
	// respond with a 500 Internal Server Error.
	defer func() {
		if r := recover(); r != nil {
			rw.WriteError(StatusInternalServerError)
		}
	}()

	for _, it := range h.interceps {
		it.Interceptor.Before(rw, ir, it.Config)
		if rw.written {
			return
		}
	}

	h.handler.ServeHTTP(rw, ir)
	if !rw.written {
		rw.NoContent()
	}
}

// commitPhase calls the Commit phases of all the interceptors. This stage will
// run before a response is written to the ResponseWriter. If a response is
// written to the ResponseWriter in a Commit phase then the Commit phases of the
// remaining interceptors won't execute.
//
// TODO: BIG WARNING, if ResponseWriter.Write and ResponseWriter.WriteTemplate
// are called in Commit then this will recurse. CommitResponseWriter was an
// attempt to prevent this by not giving access to Write and WriteTemplate in
// the Commit phase.
func (h handler) commitPhase(w *ResponseWriter, resp Response) {
	for i := len(h.interceps) - 1; i >= 0; i-- {
		it := h.interceps[i]
		it.Interceptor.Commit(w, w.req, resp, it.Config)
		if w.written {
			return
		}
	}
}

// errorPhase calls the OnError phases of all the interceptors associated with
// a handler. This stage runs before an error response is written to the
// ResponseWriter.
//
// TODO: BIG WARNING, if an interceptor attempts to write to the ResponseWriter
// in the OnError phase will result in an irrecoverable error.
func (h handler) errorPhase(w *ResponseWriter, resp Response) {
	for i := len(h.interceps) - 1; i >= 0; i-- {
		it := h.interceps[i]
		it.Interceptor.OnError(w, w.req, resp, it.Config)
	}
}
<|endoftext|>


<commit_before>package docker

import (
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
	"os"
)

// StepExport exports the container to a flat tar file.
type StepExport struct{}

func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*Config)

	driver := state.Get("driver").(Driver)
	containerId := state.Get("container_id").(string)
	ui := state.Get("ui").(packer.Ui)

	// Open the file that we're going to write to
	f, err := os.Create(config.ExportPath)
	if err != nil {
		err := fmt.Errorf("Error creating output file: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Say("Exporting the container")
	if err := driver.Export(containerId, f); err != nil {
		f.Close()
		os.Remove(f.Name())

		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	f.Close()
	return multistep.ActionContinue
}

func (s *StepExport) Cleanup(state multistep.StateBag) {}
<commit_msg>Add an explicit error message when there is no output file specified<commit_after>package docker

import (
	"fmt"
	"os"

	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
)

// StepExport exports the container to a flat tar file.
type StepExport struct{}

func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*Config)

	driver := state.Get("driver").(Driver)
	containerId := state.Get("container_id").(string)
	ui := state.Get("ui").(packer.Ui)

	// We should catch this in validation, but guard anyway
	if config.ExportPath == "" {
		err := fmt.Errorf("No output file specified, we can't export anything")
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Open the file that we're going to write to
	f, err := os.Create(config.ExportPath)
	if err != nil {
		err := fmt.Errorf("Error creating output file: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	ui.Say("Exporting the container")
	if err := driver.Export(containerId, f); err != nil {
		f.Close()
		os.Remove(f.Name())

		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	f.Close()
	return multistep.ActionContinue
}

func (s *StepExport) Cleanup(state multistep.StateBag) {}
<|endoftext|>