Example #1
0
// NewGameHub creates a new GameHub for a given log contenxt.
func NewGameHub(ctx log.Interface) GameHub {
	return GameHub{
		Log:      ctx.WithField("module", "GameHub"),
		games:    make(map[string]Game),
		register: make(chan GameRegistrationRequest),
	}
}
Example #2
0
// GetHandlerManager gets a new HandlerManager for ttnctl
func GetHandlerManager(ctx log.Interface, appID string) (*grpc.ClientConn, *handler.ManagerClient) {
	ctx.WithField("Handler", viper.GetString("handler-id")).Info("Discovering Handler...")
	dscConn, client := GetDiscovery(ctx)
	defer dscConn.Close()
	handlerAnnouncement, err := client.Get(GetContext(ctx), &discovery.GetRequest{
		ServiceName: "handler",
		Id:          viper.GetString("handler-id"),
	})
	if err != nil {
		ctx.WithError(errors.FromGRPCError(err)).Fatal("Could not find Handler")
	}

	token := TokenForScope(ctx, scope.App(appID))

	ctx.WithField("Handler", handlerAnnouncement.NetAddress).Info("Connecting with Handler...")
	hdlConn, err := handlerAnnouncement.Dial()
	if err != nil {
		ctx.WithError(err).Fatal("Could not connect to Handler")
	}
	managerClient, err := handler.NewManagerClient(hdlConn, token)
	if err != nil {
		ctx.WithError(err).Fatal("Could not create Handler Manager")
	}
	return hdlConn, managerClient
}
Example #3
0
// SetApp stores the app ID and app EUI preferences
func SetApp(ctx log.Interface, appID string, appEUI types.AppEUI) {
	config := readData(appFilename)
	config[idKey] = appID
	config[euiKey] = appEUI.String()
	err := writeData(appFilename, config)
	if err != nil {
		ctx.WithError(err).Fatal("Could not save app preference")
	}
}
Example #4
0
// ForceRefreshToken forces a refresh of the access token
func ForceRefreshToken(ctx log.Interface) {
	tokenSource := GetTokenSource(ctx).(*ttnctlTokenSource)
	token, err := tokenSource.Token()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get access token")
	}
	token.Expiry = time.Now().Add(-1 * time.Second)
	tokenSource.source = oauth2.ReuseTokenSource(token, getAccountServerTokenSource(token))
	tokenSource.Token()
}
Example #5
0
// NewGateway creates a new in-memory Gateway structure
func NewGateway(ctx log.Interface, id string) *Gateway {
	ctx = ctx.WithField("GatewayID", id)
	return &Gateway{
		ID:          id,
		Status:      NewStatusStore(),
		Utilization: NewUtilization(),
		Schedule:    NewSchedule(ctx),
		Ctx:         ctx,
	}
}
Example #6
0
// NewGameState creates a new game state given a logging context.
func NewGameState(ctx log.Interface) GameState {
	return GameState{
		Users:          make(map[*User]bool),
		Shots:          make(map[*Shot]bool),
		Log:            ctx.WithField("module", "GameState"),
		UpdateInterval: DefaultStateUpdateLoopInterval,
		simulate:       make(chan []Command),
		updateState:    make(chan *GameState),
	}
}
Example #7
0
func saveToken(ctx log.Interface, token *oauth2.Token) {
	data, err := json.Marshal(token)
	if err != nil {
		ctx.WithError(err).Fatal("Could not save access token")
	}
	err = GetTokenCache().Set(tokenName(), data)
	if err != nil {
		ctx.WithError(err).Fatal("Could not save access token")
	}
}
Example #8
0
// GetAccount gets a new Account server client for ttnctl
func GetAccount(ctx log.Interface) *account.Account {
	token, err := GetTokenSource(ctx).Token()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get access token")
	}

	server := viper.GetString("auth-server")
	manager := GetTokenManager(token.AccessToken)

	return account.NewWithManager(server, token.AccessToken, manager).WithHeader("User-Agent", GetUserAgent())
}
Example #9
0
// NewServer sets up a new server instance.
func NewServer(ctx log.Interface, address, templateFilename string) Server {
	return Server{
		Log: ctx.WithFields(log.Fields{
			"module":  "Server",
			"address": address,
		}),
		IndexTemplate: template.Must(template.ParseFiles(templateFilename)),
		Address:       address,
		Hub:           NewGameHub(ctx),
	}
}
Example #10
0
// NewUser creates a new user with a new Gopher to manage the user's new ws
// connection.
func NewUser(ctx log.Interface, ws *websocket.Conn) User {
	id := uuid.NewRandom().String()[:3]

	return User{
		ID:     id,
		Gopher: NewGopher(id, RandomCoordinates(boardSize)),
		Log:    ctx.WithField("module", "User"),
		send:   make(chan []byte, 256),
		ws:     ws,
	}
}
Example #11
0
func TokenForScope(ctx log.Interface, scope string) string {
	token, err := GetTokenSource(ctx).Token()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get token")
	}

	restricted, err := GetTokenManager(token.AccessToken).TokenForScope(scope)
	if err != nil {
		ctx.WithError(err).Fatal("Could not get correct rights")
	}

	return restricted
}
Example #12
0
// GetContext returns a new context
func GetContext(ctx log.Interface, extraPairs ...string) context.Context {
	token, err := GetTokenSource(ctx).Token()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get token")
	}
	md := metadata.Pairs(
		"id", GetID(),
		"service-name", "ttnctl",
		"service-version", fmt.Sprintf("%s-%s (%s)", viper.GetString("version"), viper.GetString("gitCommit"), viper.GetString("buildDate")),
		"token", token.AccessToken,
	)
	return metadata.NewContext(context.Background(), md)
}
Example #13
0
// GetDiscovery gets the Discovery client for ttnctl
func GetDiscovery(ctx log.Interface) (*grpc.ClientConn, discovery.DiscoveryClient) {
	path := path.Join(GetDataDir(), "/ca.cert")
	cert, err := ioutil.ReadFile(path)
	if err == nil && !api.RootCAs.AppendCertsFromPEM(cert) {
		ctx.Warnf("Could not add root certificates from %s", path)
	}

	conn, err := api.Dial(viper.GetString("discovery-address"))
	if err != nil {
		ctx.WithError(err).Fatal("Could not connect to Discovery server")
	}
	return conn, discovery.NewDiscoveryClient(conn)
}
Example #14
0
// GetAppID returns the AppID that must be set in the command options or config
func GetAppID(ctx log.Interface) string {
	appID := viper.GetString("app-id")
	if appID == "" {
		appData := readData(appFilename)
		id, ok := appData[idKey].(string)
		if !ok {
			ctx.Fatal("Invalid appID in config file.")
		}
		appID = id
	}

	if appID == "" {
		ctx.Fatal("Missing AppID. You should select an application to use with \"ttnctl applications select\"")
	}
	return appID
}
Example #15
0
// NewGame creates a new game instance.
func NewGame(ctx log.Interface, id string) Game {
	gs := NewGameState(ctx)
	cp := NewCommandProcessor(&gs)

	return Game{
		Log: ctx.WithFields(log.Fields{
			"module": "Game",
			"id":     id,
		}),
		State:            &gs,
		CommandProcessor: &cp,
		register:         make(chan *User),
		unregister:       make(chan *User),
		commands:         make(chan Command),
	}
}
Example #16
0
// GetRouterManager starts a management connection with the router
func GetRouterManager(ctx log.Interface) (*grpc.ClientConn, router.RouterManagerClient) {
	ctx.Info("Discovering Router...")
	dscConn, client := GetDiscovery(ctx)
	defer dscConn.Close()
	routerAnnouncement, err := client.Get(GetContext(ctx), &discovery.GetRequest{
		ServiceName: "router",
		Id:          viper.GetString("router-id"),
	})
	if err != nil {
		ctx.WithError(errors.FromGRPCError(err)).Fatal("Could not get Router from Discovery")
	}
	ctx.Info("Connecting with Router...")
	rtrConn, err := routerAnnouncement.Dial()
	if err != nil {
		ctx.WithError(err).Fatal("Could not connect to Router")
	}
	ctx.Info("Connected to Router")
	return rtrConn, router.NewRouterManagerClient(rtrConn)
}
Example #17
0
func getStoredToken(ctx log.Interface) *oauth2.Token {
	tokenCache := GetTokenCache()
	data, err := tokenCache.Get(tokenName())
	if err != nil {
		ctx.WithError(err).Fatal("Could not read stored token")
	}
	if data == nil {
		ctx.Fatal("No account information found. Please login with ttnctl user login [access code]")
	}

	token := &oauth2.Token{}
	err = json.Unmarshal(data, token)
	if err != nil {
		ctx.Fatal("Account information invalid. Please login with ttnctl user login [access code]")
	}
	return token
}
Example #18
0
// GetAppEUI returns the AppEUI that must be set in the command options or config
func GetAppEUI(ctx log.Interface) types.AppEUI {
	appEUIString := viper.GetString("app-eui")
	if appEUIString == "" {
		appData := readData(appFilename)
		eui, ok := appData[euiKey].(string)
		if !ok {
			ctx.Fatal("Invalid AppEUI in config file")
		}
		appEUIString = eui
	}

	if appEUIString == "" {
		ctx.Fatal("Missing AppEUI. You should select an application to use with \"ttnctl applications select\"")
	}

	eui, err := types.ParseAppEUI(appEUIString)
	if err != nil {
		ctx.WithError(err).Fatal("Invalid AppEUI")
	}
	return eui
}
Example #19
0
File: trace.go Project: leobcn/log
func work(ctx log.Interface) (err error) {
	path := "Readme.md"
	defer ctx.WithField("path", path).Trace("opening").Stop(&err)
	_, err = os.Open(path)
	return
}
Example #20
0
func (h *handler) ConvertFromLoRaWAN(ctx log.Interface, ttnUp *pb_broker.DeduplicatedUplinkMessage, appUp *types.UplinkMessage) error {
	// Find Device
	dev, err := h.devices.Get(ttnUp.AppId, ttnUp.DevId)
	if err != nil {
		return err
	}

	// Check for LoRaWAN
	if lorawan := ttnUp.ProtocolMetadata.GetLorawan(); lorawan == nil {
		return errors.NewErrInvalidArgument("Activation", "does not contain LoRaWAN metadata")
	}

	// LoRaWAN: Unmarshal Uplink
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(ttnUp.Payload)
	if err != nil {
		return err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return errors.NewErrInvalidArgument("Uplink", "does not contain a MAC payload")
	}
	macPayload.FHDR.FCnt = ttnUp.ProtocolMetadata.GetLorawan().FCnt
	appUp.FCnt = macPayload.FHDR.FCnt

	ctx = ctx.WithField("FCnt", appUp.FCnt)

	// LoRaWAN: Validate MIC
	ok, err = phyPayload.ValidateMIC(lorawan.AES128Key(dev.NwkSKey))
	if err != nil {
		return err
	}
	if !ok {
		return errors.NewErrNotFound("device that validates MIC")
	}

	// LoRaWAN: Decrypt
	if macPayload.FPort != nil && *macPayload.FPort != 0 && len(macPayload.FRMPayload) == 1 {
		appUp.FPort = *macPayload.FPort
		ctx = ctx.WithField("FCnt", appUp.FPort)
		if err := phyPayload.DecryptFRMPayload(lorawan.AES128Key(dev.AppSKey)); err != nil {
			return errors.NewErrInternal("Could not decrypt payload")
		}
		if len(macPayload.FRMPayload) == 1 {
			payload, ok := macPayload.FRMPayload[0].(*lorawan.DataPayload)
			if !ok {
				return errors.NewErrInvalidArgument("Uplink FRMPayload", "must be of type *lorawan.DataPayload")
			}
			appUp.PayloadRaw = payload.Bytes
		}
	}

	// LoRaWAN: Publish ACKs as events
	if macPayload.FHDR.FCtrl.ACK {
		h.mqttEvent <- &types.DeviceEvent{
			AppID: appUp.AppID,
			DevID: appUp.DevID,
			Event: types.DownlinkAckEvent,
		}
	}

	return nil
}
Example #21
0
// SetApp stores the app EUI preference
func SetAppEUI(ctx log.Interface, appEUI types.AppEUI) {
	err := setData(appFilename, euiKey, appEUI.String())
	if err != nil {
		ctx.WithError(err).Fatal("Could not save app EUI")
	}
}
Example #22
0
// New creates a new Component
func New(ctx log.Interface, serviceName string, announcedAddress string) (*Component, error) {
	go func() {
		memstats := new(runtime.MemStats)
		for range time.Tick(time.Minute) {
			runtime.ReadMemStats(memstats)
			ctx.WithFields(log.Fields{
				"Goroutines": runtime.NumGoroutine(),
				"Memory":     float64(memstats.Alloc) / 1000000,
			}).Debugf("Stats")
		}
	}()

	// Disable gRPC tracing
	// SEE: https://github.com/grpc/grpc-go/issues/695
	grpc.EnableTracing = false

	component := &Component{
		Config: ConfigFromViper(),
		Ctx:    ctx,
		Identity: &pb_discovery.Announcement{
			Id:             viper.GetString("id"),
			Description:    viper.GetString("description"),
			ServiceName:    serviceName,
			ServiceVersion: fmt.Sprintf("%s-%s (%s)", viper.GetString("version"), viper.GetString("gitCommit"), viper.GetString("buildDate")),
			NetAddress:     announcedAddress,
			Public:         viper.GetBool("public"),
		},
		AccessToken: viper.GetString("auth-token"),
	}

	if err := component.InitAuth(); err != nil {
		return nil, err
	}

	if serviceName != "discovery" && serviceName != "networkserver" {
		var err error
		component.Discovery, err = pb_discovery.NewClient(
			viper.GetString("discovery-address"),
			component.Identity,
			func() string {
				token, _ := component.BuildJWT()
				return token
			},
		)
		if err != nil {
			return nil, err
		}
	}

	if healthPort := viper.GetInt("health-port"); healthPort > 0 {
		http.HandleFunc("/healthz", func(w http.ResponseWriter, req *http.Request) {
			switch component.GetStatus() {
			case StatusHealthy:
				w.WriteHeader(200)
				w.Write([]byte("Status is HEALTHY"))
				return
			case StatusUnhealthy:
				w.WriteHeader(503)
				w.Write([]byte("Status is UNHEALTHY"))
				return
			}
		})
		go http.ListenAndServe(fmt.Sprintf(":%d", healthPort), nil)
	}

	if monitors := viper.GetStringMapString("monitor-servers"); len(monitors) != 0 {
		component.Monitors = make(map[string]*pb_monitor.Client)
		for name, addr := range monitors {
			var err error
			component.Monitors[name], err = pb_monitor.NewClient(ctx.WithField("Monitor", name), addr)
			if err != nil {
				return nil, err
			}
		}
	}

	return component, nil
}
Example #23
0
// continue looking at dns entry for changes in config
func configLoop(ctx log.Interface, cfgURL string) {
	ticker := time.Tick(15 * time.Second)

	for {
		select {
		case <-ticker:
			newIPs, err := dnscfg.Get(dnsAddr, ldPort)
			if err != nil {
				ctx.WithError(err).Error("dns lookup")
				continue
			}

			if len(newIPs) == 0 {
				ctx.Error("no ip addresses found")
				continue
			}

			oldIPs, err := httpcfg.Get(cfgURL)
			if err != nil {
				ctx.WithError(err).Error("getting config")
				continue
			}

			if eq(newIPs, oldIPs) {
				ctx.Info("config up to date")
				continue
			}

			err = httpcfg.Set(cfgURL, newIPs)
			if err != nil {
				ctx.WithError(err).Error("setting config")
				continue
			}

			ctx.WithField("ips", newIPs).Info("setting config")
		}
	}
}
Example #24
0
	jsonHandler "github.com/apex/log/handlers/json"
	levelHandler "github.com/apex/log/handlers/level"
	multiHandler "github.com/apex/log/handlers/multi"
	"github.com/mitchellh/go-homedir"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/tj/go-elastic"
	"google.golang.org/grpc/grpclog"
	"gopkg.in/redis.v5"
)

var cfgFile string

var logFile *os.File

var ctx log.Interface

// RootCmd is executed when ttn is executed without a subcommand
var RootCmd = &cobra.Command{
	Use:   "ttn",
	Short: "The Things Network's backend servers",
	Long:  `ttn launches The Things Network's backend servers`,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		var logLevel = log.InfoLevel
		if viper.GetBool("debug") {
			logLevel = log.DebugLevel
		}

		var logHandlers []log.Handler

		if !viper.GetBool("no-cli-logs") {
Example #25
0
// Selfupdate runs a self-update for the current binary
func Selfupdate(ctx log.Interface, component string) {
	if viper.GetString("gitBranch") == "unknown" {
		ctx.Infof("You are not using an official %s build. Not proceeding with the update", component)
		return
	}

	info, err := GetLatestInfo()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get version information from the server")
	}

	if viper.GetString("gitCommit") == info.Commit {
		ctx.Info("The git commit of the build on the server is the same as yours")
		ctx.Info("Not proceeding with the update")
		return
	}

	if date, err := time.Parse(time.RFC3339, viper.GetString("buildDate")); err == nil {
		if date.Equal(info.Date) {
			ctx.Infof("You have the latest version of %s", component)
			ctx.Info("Nothing to update")
			return
		}
		if date.After(info.Date) {
			ctx.Infof("Your build is %s newer than the build on the server", date.Sub(info.Date))
			ctx.Info("Not proceeding with the update")
			return
		}
		ctx.Infof("The build on the server is %s newer than yours", info.Date.Sub(date))
	}

	ctx.Infof("Downloading the latest %s...", component)
	binary, err := GetLatest(component)
	if err != nil {
		ctx.WithError(err).Fatal("Could not download latest binary")
	}
	filename, err := osext.Executable()
	if err != nil {
		ctx.WithError(err).Fatal("Could not get path to local binary")
	}
	stat, err := os.Stat(filename)
	if err != nil {
		ctx.WithError(err).Fatal("Could not stat local binary")
	}
	ctx.Info("Replacing local binary...")
	if err := ioutil.WriteFile(filename+".new", binary, stat.Mode()); err != nil {
		ctx.WithError(err).Fatal("Could not write new binary to filesystem")
	}
	if err := os.Rename(filename, filename+".old"); err != nil {
		ctx.WithError(err).Fatal("Could not rename binary")
	}
	if err := os.Rename(filename+".new", filename); err != nil {
		ctx.WithError(err).Fatal("Could not rename binary")
	}
	ctx.Infof("Updated %s to the latest version", component)
}