cmd/routed: fix build

This commit is contained in:
Cadey Ratio 2018-01-21 08:22:10 -08:00
parent d2cb12201e
commit 0566205ec2
11 changed files with 354 additions and 180 deletions

View File

@ -3,13 +3,13 @@ package main
import ( import (
"context" "context"
"errors" "errors"
"net/http"
"time"
"git.xeserv.us/xena/route/internal/database" "git.xeserv.us/xena/route/internal/database"
"github.com/Xe/ln" "github.com/Xe/ln"
"github.com/twitchtv/twirp"
"golang.org/x/net/trace" "golang.org/x/net/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
) )
// errors // errors
@ -17,23 +17,92 @@ var (
ErrNotAuthorized = errors.New("server: not authorized") ErrNotAuthorized = errors.New("server: not authorized")
) )
func (s *Server) getAuth(ctx context.Context, operation, scope string) (database.Token, error) { func (s *Server) makeTwirpHooks() *twirp.ServerHooks {
var err error hooks := &twirp.ServerHooks{}
md, ok := metadata.FromIncomingContext(ctx) hooks.RequestRouted = func(ctx context.Context) (context.Context, error) {
ctx = withStartTime(ctx)
method, ok := twirp.MethodName(ctx)
if !ok { if !ok {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "valid token required.") return ctx, nil
} }
jwtToken, ok := md["authorization"] pkg, ok := twirp.PackageName(ctx)
if !ok { if !ok {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "valid token required.") return ctx, nil
} }
val := jwtToken[0]
t, err := s.db.GetToken(ctx, val) svc, ok := twirp.ServiceName(ctx)
if !ok {
return ctx, nil
}
ctx = ln.WithF(ctx, ln.F{
"twirp_method": method,
"twirp_package": pkg,
"twirp_service": svc,
})
hdr, ok := twirp.HTTPRequestHeaders(ctx)
if !ok {
return ctx, errors.New("can't get request headers")
}
req, _ := http.NewRequest("GET", "/", nil)
req.Header = hdr
ck, err := req.Cookie("routed")
if err != nil { if err != nil {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "valid token required.") return ctx, err
}
tok := ck.Value
t, err := s.db.GetToken(ctx, tok)
if err != nil {
return ctx, err
}
ctx = withAuthToken(ctx, t)
ctx = ln.WithF(ctx, t.F())
return ctx, nil
}
hooks.ResponseSent = func(ctx context.Context) {
f := ln.F{}
now := time.Now()
t, ok := getStartTime(ctx)
if ok {
f["response_time"] = now.Sub(t)
}
ln.Log(ctx, f, ln.Action("response sent"))
}
hooks.Error = func(ctx context.Context, e twirp.Error) context.Context {
f := ln.F{}
for k, v := range e.MetaMap() {
f["twirp_meta_"+k] = v
}
ln.Error(ctx, e, f, ln.Action("twirp error"), ln.F{
"twirp_error_code": e.Code(),
"twirp_error_msg": e.Msg(),
})
return ctx
}
return hooks
}
func (s *Server) getAuth(ctx context.Context, operation, scope string) (database.Token, error) {
t, ok := getAuthToken(ctx)
if !ok {
return database.Token{}, errors.New("no auth token in context")
} }
ok = false ok = false
@ -42,11 +111,12 @@ func (s *Server) getAuth(ctx context.Context, operation, scope string) (database
ok = true ok = true
} }
} }
if !ok { if !ok {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "invalid scope.") return database.Token{}, ErrNotAuthorized
} }
ln.Log(ctx, t) ln.WithF(ctx, ln.F{"operation": operation})
return t, nil return t, nil
} }

41
cmd/routed/ctx.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"context"
"time"
"git.xeserv.us/xena/route/internal/database"
)
type ctxKey int
const (
startTimeKey ctxKey = iota
tokenKey
)
func withStartTime(ctx context.Context) context.Context {
return context.WithValue(ctx, startTimeKey, time.Now())
}
func getStartTime(ctx context.Context) (time.Time, bool) {
t, ok := ctx.Value(startTimeKey).(time.Time)
if !ok {
return time.Time{}, false
}
return t, true
}
func withAuthToken(ctx context.Context, token database.Token) context.Context {
return context.WithValue(ctx, tokenKey, token)
}
func getAuthToken(ctx context.Context) (database.Token, bool) {
t, ok := ctx.Value(tokenKey).(database.Token)
if !ok {
return database.Token{}, false
}
return t, true
}

View File

@ -117,7 +117,7 @@ func setupQuic(ctx context.Context, s *Server, scfg Config) {
qs := &h2quic.Server{ qs := &h2quic.Server{
Server: &http.Server{ Server: &http.Server{
Handler: middleware.Trace(s), Handler: middleware.Trace("http-quic")(s),
Addr: scfg.QuicAddr, Addr: scfg.QuicAddr,
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
GetCertificate: s.GetCertificate, GetCertificate: s.GetCertificate,
@ -156,7 +156,7 @@ func setupTLS(ctx context.Context, s *Server, scfg Config) {
} }
hs := &http.Server{ hs := &http.Server{
Handler: middleware.Trace(s), Handler: middleware.Trace("https")(s),
Addr: scfg.SSLAddr, Addr: scfg.SSLAddr,
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
GetCertificate: s.GetCertificate, GetCertificate: s.GetCertificate,

View File

@ -14,7 +14,7 @@ type Route struct {
// interface assertions // interface assertions
var ( var (
_ proto.RoutesServer = &Route{} _ proto.Routes = &Route{}
) )
// Get fetches a route from the database. // Get fetches a route from the database.

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"git.xeserv.us/xena/route/internal/database" "git.xeserv.us/xena/route/internal/database"
"git.xeserv.us/xena/route/internal/middleware"
"git.xeserv.us/xena/route/internal/tun2" "git.xeserv.us/xena/route/internal/tun2"
proto "git.xeserv.us/xena/route/proto" proto "git.xeserv.us/xena/route/proto"
"github.com/Xe/ln" "github.com/Xe/ln"
@ -17,8 +18,6 @@ import (
kcp "github.com/xtaci/kcp-go" kcp "github.com/xtaci/kcp-go"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
) )
// RPC constants // RPC constants
@ -149,19 +148,22 @@ func New(cfg Config) (*Server, error) {
go s.listenKCP(context.Background(), cfg.BackendKCPAddr, tc) go s.listenKCP(context.Background(), cfg.BackendKCPAddr, tc)
go s.listenTCP(context.Background(), cfg.BackendTCPAddr, tc) go s.listenTCP(context.Background(), cfg.BackendTCPAddr, tc)
// gRPC setup bhdr := proto.NewBackendsServer(&Backend{Server: s}, s.makeTwirpHooks())
gs := grpc.NewServer(grpc.Creds(credentials.NewTLS(tc))) rhdr := proto.NewRoutesServer(&Route{Server: s}, s.makeTwirpHooks())
thdr := proto.NewTokensServer(&Token{Server: s}, s.makeTwirpHooks())
mux := http.NewServeMux()
proto.RegisterBackendsServer(gs, &Backend{Server: s}) mux.Handle(proto.BackendsPathPrefix, bhdr)
proto.RegisterRoutesServer(gs, &Route{Server: s}) mux.Handle(proto.RoutesPathPrefix, rhdr)
proto.RegisterTokensServer(gs, &Token{Server: s}) mux.Handle(proto.TokensPathPrefix, thdr)
l, err := net.Listen("tcp", cfg.GRPCAddr) hs := &http.Server{
if err != nil { TLSConfig: tc,
return nil, err Addr: cfg.GRPCAddr,
Handler: middleware.Trace("twirp-https")(mux),
} }
go gs.Serve(l) go hs.ListenAndServeTLS("", "")
return s, nil return s, nil
} }

View File

@ -16,7 +16,7 @@ type Token struct {
// interface assertions // interface assertions
var ( var (
_ proto.TokensServer = &Token{} _ proto.Tokens = &Token{}
) )
func (t *Token) Get(ctx context.Context, req *proto.GetTokenRequest) (*proto.Token, error) { func (t *Token) Get(ctx context.Context, req *proto.GetTokenRequest) (*proto.Token, error) {

View File

@ -3,7 +3,6 @@ package middleware
import ( import (
"context" "context"
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"time" "time"
@ -12,20 +11,23 @@ import (
) )
// Trace adds go stdlib tracing to this http handler. // Trace adds go stdlib tracing to this http handler.
func Trace(next http.Handler) http.Handler { func Trace(family string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sp := trace.New(filepath.Base(os.Args[0]+"-https"), r.Host+r.RequestURI) sp := trace.New(filepath.Base(family), r.Host+r.RequestURI)
defer sp.Finish() defer sp.Finish()
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second) ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel() defer cancel()
ctx = trace.NewContext(ctx, sp) ctx = trace.NewContext(ctx, sp)
f := ln.F{ f := ln.F{
"family": family,
"method": r.Method, "method": r.Method,
"path": r.URL.Path, "path": r.URL.Path,
"remote_addr": r.RemoteAddr, "remote_addr": r.RemoteAddr,
"user_agent": r.UserAgent(), "user_agent": r.UserAgent(),
} }
ctx = ln.WithF(ctx, f)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
@ -39,3 +41,4 @@ func Trace(next http.Handler) http.Handler {
ln.Log(ctx, f) ln.Log(ctx, f)
}) })
} }
}

55
proto/client/client.go Normal file
View File

@ -0,0 +1,55 @@
// Package route is a higher level client for routed suitable to embed into
// Go programs.
package route
import (
"net/http"
"git.xeserv.us/xena/route/proto"
)
// New creates a new instance of the routed client with a given token and service
// URL.
func New(routedURL, token string, underlying *http.Client) *Client {
c := &Client{
underlying: underlying,
authToken: token,
serverURL: routedURL,
}
c.Backends = proto.NewBackendsProtobufClient(routedURL, c.hClient())
c.Routes = proto.NewRoutesProtobufClient(routedURL, c.hClient())
c.Tokens = proto.NewTokensProtobufClient(routedURL, c.hClient())
return c
}
// Client is a higher level client for routed
type Client struct {
Backends proto.Backends
Routes proto.Routes
Tokens proto.Tokens
underlying *http.Client
authToken string
serverURL string
}
// RoundTrip executes a HTTP request, adding authentication headers and then
// executing it using the underlying http client.
func (c *Client) RoundTrip(r *http.Request) (*http.Response, error) {
ck := &http.Cookie{
Name: "routed",
Value: c.authToken,
}
r.AddCookie(ck)
return c.underlying.Do(r)
}
func (c *Client) hClient() *http.Client {
return &http.Client{
Transport: c,
}
}

View File

@ -2,7 +2,7 @@
// source: route.proto // source: route.proto
/* /*
Package route is a generated protocol buffer package. Package proto is a generated protocol buffer package.
It is generated from these files: It is generated from these files:
route.proto route.proto
@ -20,14 +20,14 @@ It has these top-level messages:
BackendSelector BackendSelector
BackendID BackendID
*/ */
package route package proto
import proto "github.com/golang/protobuf/proto" import proto1 "github.com/golang/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto1.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
@ -35,14 +35,14 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the // A compilation error at this line likely means your copy of the
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
// Nil represents nothing. // Nil represents nothing.
type Nil struct { type Nil struct {
} }
func (m *Nil) Reset() { *m = Nil{} } func (m *Nil) Reset() { *m = Nil{} }
func (m *Nil) String() string { return proto.CompactTextString(m) } func (m *Nil) String() string { return proto1.CompactTextString(m) }
func (*Nil) ProtoMessage() {} func (*Nil) ProtoMessage() {}
func (*Nil) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Nil) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
@ -54,7 +54,7 @@ type GetRouteRequest struct {
} }
func (m *GetRouteRequest) Reset() { *m = GetRouteRequest{} } func (m *GetRouteRequest) Reset() { *m = GetRouteRequest{} }
func (m *GetRouteRequest) String() string { return proto.CompactTextString(m) } func (m *GetRouteRequest) String() string { return proto1.CompactTextString(m) }
func (*GetRouteRequest) ProtoMessage() {} func (*GetRouteRequest) ProtoMessage() {}
func (*GetRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (*GetRouteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
@ -80,7 +80,7 @@ type Route struct {
} }
func (m *Route) Reset() { *m = Route{} } func (m *Route) Reset() { *m = Route{} }
func (m *Route) String() string { return proto.CompactTextString(m) } func (m *Route) String() string { return proto1.CompactTextString(m) }
func (*Route) ProtoMessage() {} func (*Route) ProtoMessage() {}
func (*Route) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (*Route) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
@ -111,7 +111,7 @@ type GetAllRoutesResponse struct {
} }
func (m *GetAllRoutesResponse) Reset() { *m = GetAllRoutesResponse{} } func (m *GetAllRoutesResponse) Reset() { *m = GetAllRoutesResponse{} }
func (m *GetAllRoutesResponse) String() string { return proto.CompactTextString(m) } func (m *GetAllRoutesResponse) String() string { return proto1.CompactTextString(m) }
func (*GetAllRoutesResponse) ProtoMessage() {} func (*GetAllRoutesResponse) ProtoMessage() {}
func (*GetAllRoutesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (*GetAllRoutesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
@ -132,7 +132,7 @@ type Token struct {
} }
func (m *Token) Reset() { *m = Token{} } func (m *Token) Reset() { *m = Token{} }
func (m *Token) String() string { return proto.CompactTextString(m) } func (m *Token) String() string { return proto1.CompactTextString(m) }
func (*Token) ProtoMessage() {} func (*Token) ProtoMessage() {}
func (*Token) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (*Token) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
@ -170,7 +170,7 @@ type TokenSet struct {
} }
func (m *TokenSet) Reset() { *m = TokenSet{} } func (m *TokenSet) Reset() { *m = TokenSet{} }
func (m *TokenSet) String() string { return proto.CompactTextString(m) } func (m *TokenSet) String() string { return proto1.CompactTextString(m) }
func (*TokenSet) ProtoMessage() {} func (*TokenSet) ProtoMessage() {}
func (*TokenSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (*TokenSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
@ -187,7 +187,7 @@ type GetTokenRequest struct {
} }
func (m *GetTokenRequest) Reset() { *m = GetTokenRequest{} } func (m *GetTokenRequest) Reset() { *m = GetTokenRequest{} }
func (m *GetTokenRequest) String() string { return proto.CompactTextString(m) } func (m *GetTokenRequest) String() string { return proto1.CompactTextString(m) }
func (*GetTokenRequest) ProtoMessage() {} func (*GetTokenRequest) ProtoMessage() {}
func (*GetTokenRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (*GetTokenRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
@ -216,7 +216,7 @@ type Backend struct {
} }
func (m *Backend) Reset() { *m = Backend{} } func (m *Backend) Reset() { *m = Backend{} }
func (m *Backend) String() string { return proto.CompactTextString(m) } func (m *Backend) String() string { return proto1.CompactTextString(m) }
func (*Backend) ProtoMessage() {} func (*Backend) ProtoMessage() {}
func (*Backend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (*Backend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
@ -275,7 +275,7 @@ type BackendList struct {
} }
func (m *BackendList) Reset() { *m = BackendList{} } func (m *BackendList) Reset() { *m = BackendList{} }
func (m *BackendList) String() string { return proto.CompactTextString(m) } func (m *BackendList) String() string { return proto1.CompactTextString(m) }
func (*BackendList) ProtoMessage() {} func (*BackendList) ProtoMessage() {}
func (*BackendList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (*BackendList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
@ -299,7 +299,7 @@ type BackendSelector struct {
} }
func (m *BackendSelector) Reset() { *m = BackendSelector{} } func (m *BackendSelector) Reset() { *m = BackendSelector{} }
func (m *BackendSelector) String() string { return proto.CompactTextString(m) } func (m *BackendSelector) String() string { return proto1.CompactTextString(m) }
func (*BackendSelector) ProtoMessage() {} func (*BackendSelector) ProtoMessage() {}
func (*BackendSelector) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (*BackendSelector) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
@ -322,7 +322,7 @@ type BackendID struct {
} }
func (m *BackendID) Reset() { *m = BackendID{} } func (m *BackendID) Reset() { *m = BackendID{} }
func (m *BackendID) String() string { return proto.CompactTextString(m) } func (m *BackendID) String() string { return proto1.CompactTextString(m) }
func (*BackendID) ProtoMessage() {} func (*BackendID) ProtoMessage() {}
func (*BackendID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (*BackendID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
@ -334,56 +334,58 @@ func (m *BackendID) GetId() string {
} }
func init() { func init() {
proto.RegisterType((*Nil)(nil), "route.Nil") proto1.RegisterType((*Nil)(nil), "xeserv.us.route.Nil")
proto.RegisterType((*GetRouteRequest)(nil), "route.GetRouteRequest") proto1.RegisterType((*GetRouteRequest)(nil), "xeserv.us.route.GetRouteRequest")
proto.RegisterType((*Route)(nil), "route.Route") proto1.RegisterType((*Route)(nil), "xeserv.us.route.Route")
proto.RegisterType((*GetAllRoutesResponse)(nil), "route.GetAllRoutesResponse") proto1.RegisterType((*GetAllRoutesResponse)(nil), "xeserv.us.route.GetAllRoutesResponse")
proto.RegisterType((*Token)(nil), "route.Token") proto1.RegisterType((*Token)(nil), "xeserv.us.route.Token")
proto.RegisterType((*TokenSet)(nil), "route.TokenSet") proto1.RegisterType((*TokenSet)(nil), "xeserv.us.route.TokenSet")
proto.RegisterType((*GetTokenRequest)(nil), "route.GetTokenRequest") proto1.RegisterType((*GetTokenRequest)(nil), "xeserv.us.route.GetTokenRequest")
proto.RegisterType((*Backend)(nil), "route.Backend") proto1.RegisterType((*Backend)(nil), "xeserv.us.route.Backend")
proto.RegisterType((*BackendList)(nil), "route.BackendList") proto1.RegisterType((*BackendList)(nil), "xeserv.us.route.BackendList")
proto.RegisterType((*BackendSelector)(nil), "route.BackendSelector") proto1.RegisterType((*BackendSelector)(nil), "xeserv.us.route.BackendSelector")
proto.RegisterType((*BackendID)(nil), "route.BackendID") proto1.RegisterType((*BackendID)(nil), "xeserv.us.route.BackendID")
} }
func init() { proto.RegisterFile("route.proto", fileDescriptor0) } func init() { proto1.RegisterFile("route.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 556 bytes of a gzipped FileDescriptorProto // 579 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xd1, 0x6a, 0xdb, 0x4a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0xb5, 0x24, 0x4b, 0xb1, 0xc7, 0x97, 0x38, 0x0c, 0x26, 0x08, 0xe7, 0xc5, 0xec, 0x0d, 0xa9, 0x10, 0x8d, 0xed, 0xd8, 0x49, 0x27, 0x12, 0x41, 0xa3, 0xa8, 0x32, 0x81, 0x83, 0xb5, 0x12, 0x52,
0x29, 0x34, 0x14, 0xa7, 0x50, 0x0a, 0xed, 0x43, 0x8b, 0x8b, 0x09, 0x2d, 0xa1, 0xc8, 0x7d, 0xeb, 0x4e, 0x16, 0x0a, 0x48, 0x85, 0x02, 0x87, 0x56, 0x81, 0x50, 0x81, 0x2a, 0xe4, 0x70, 0x82, 0x93,
0x93, 0x64, 0x0d, 0x58, 0x44, 0xf5, 0xba, 0xda, 0x55, 0xa1, 0x9f, 0xd2, 0x2f, 0xe9, 0x97, 0xf4, 0x1d, 0x8f, 0x54, 0xab, 0x26, 0x0e, 0xde, 0x75, 0x05, 0x5f, 0xc0, 0x95, 0x2b, 0x9f, 0xc2, 0xdf,
0x7f, 0xca, 0xce, 0xae, 0x63, 0xcb, 0x4a, 0xfb, 0x36, 0x33, 0x67, 0x76, 0x74, 0xce, 0xcc, 0x11, 0x21, 0xcf, 0x6e, 0xda, 0x12, 0xc7, 0xa9, 0x38, 0x65, 0x66, 0xf6, 0xcd, 0xfa, 0xbd, 0xb7, 0x33,
0x0c, 0x2a, 0x59, 0x6b, 0xba, 0xde, 0x56, 0x52, 0x4b, 0x0c, 0x39, 0x11, 0x21, 0x04, 0x77, 0x45, 0x81, 0x41, 0x59, 0x54, 0x8a, 0xc2, 0x75, 0x59, 0xa8, 0x02, 0x87, 0xdf, 0x49, 0x52, 0x79, 0x15,
0x29, 0x5e, 0xc1, 0x70, 0x41, 0x3a, 0x31, 0xa5, 0x84, 0xbe, 0xd5, 0xa4, 0x34, 0x9e, 0x43, 0x54, 0x56, 0x32, 0xe4, 0xb2, 0x70, 0xc1, 0x39, 0xcf, 0x72, 0xf1, 0x02, 0x86, 0x73, 0x52, 0x51, 0x5d,
0x6f, 0x6a, 0x45, 0x79, 0xec, 0x4d, 0xbc, 0x69, 0x3f, 0x71, 0x19, 0x9e, 0x82, 0x5f, 0xe4, 0xb1, 0x8a, 0xe8, 0x5b, 0x45, 0x52, 0xe1, 0x21, 0x78, 0xd5, 0xaa, 0x92, 0x94, 0xfa, 0x56, 0x60, 0x4d,
0xcf, 0x35, 0xbf, 0xc8, 0xc5, 0x7b, 0x08, 0xf9, 0x9d, 0x03, 0xbc, 0x1d, 0x80, 0x31, 0x9c, 0xac, 0x0e, 0x22, 0x93, 0xe1, 0x3d, 0xb0, 0xb3, 0xd4, 0xb7, 0xb9, 0x66, 0x67, 0xa9, 0x78, 0x03, 0x2e,
0x2a, 0x4a, 0xb5, 0xac, 0x5c, 0xf7, 0x2e, 0x45, 0x84, 0xee, 0x5a, 0x2a, 0x1d, 0x07, 0x5c, 0xe6, 0xf7, 0x99, 0x03, 0x6b, 0x73, 0x80, 0x3e, 0xf4, 0x96, 0x25, 0xc5, 0xaa, 0x28, 0x0d, 0x7a, 0x93,
0x58, 0xbc, 0x86, 0xd1, 0x82, 0xf4, 0xdb, 0xb2, 0xe4, 0x61, 0x2a, 0x21, 0xb5, 0x95, 0x1b, 0x45, 0x22, 0x42, 0xf7, 0xa2, 0x90, 0xca, 0x77, 0xb8, 0xcc, 0xb1, 0x78, 0x0b, 0xa3, 0x39, 0xa9, 0x93,
0x78, 0x09, 0x11, 0x33, 0x55, 0xb1, 0x37, 0x09, 0xa6, 0x83, 0xd9, 0x7f, 0xd7, 0x56, 0x85, 0xe5, 0x3c, 0xe7, 0xcb, 0x64, 0x44, 0x72, 0x5d, 0xac, 0x24, 0x61, 0x08, 0x1e, 0x33, 0x95, 0xbe, 0x15,
0xea, 0x30, 0xf1, 0x05, 0xc2, 0xcf, 0xf2, 0x9e, 0x36, 0x2d, 0x12, 0x08, 0xdd, 0x4c, 0xe6, 0x3f, 0x38, 0x93, 0xc1, 0xf4, 0x30, 0xdc, 0x92, 0x10, 0x6a, 0xd6, 0x06, 0x25, 0xbe, 0x80, 0xfb, 0xa9,
0x1c, 0x03, 0x8e, 0x8d, 0x32, 0xb5, 0x92, 0x5b, 0x52, 0x71, 0x30, 0x09, 0x8c, 0x32, 0x9b, 0x99, 0xb8, 0xa4, 0x55, 0x83, 0x0e, 0x42, 0x37, 0x29, 0xd2, 0x1f, 0x86, 0x0b, 0xc7, 0xb5, 0x46, 0xb9,
0x7a, 0xba, 0xd2, 0xc5, 0x77, 0x8a, 0xbb, 0x13, 0x6f, 0xda, 0x4b, 0x5c, 0x26, 0x9e, 0x43, 0x8f, 0x2c, 0xd6, 0x24, 0x7d, 0x27, 0x70, 0x6a, 0x8d, 0x3a, 0xab, 0xeb, 0xf1, 0x52, 0x65, 0x57, 0xe4,
0x87, 0x2f, 0x49, 0x1b, 0x3a, 0xda, 0xc4, 0xc7, 0x74, 0xb8, 0x21, 0x71, 0x98, 0x78, 0xc9, 0xeb, 0x77, 0x03, 0x6b, 0xd2, 0x8f, 0x4c, 0x26, 0x8e, 0xa1, 0xcf, 0x97, 0x2f, 0x48, 0xd5, 0xc4, 0x54,
0xb4, 0x35, 0xb7, 0xce, 0x11, 0x84, 0x0c, 0x3a, 0x6e, 0x36, 0x69, 0x2d, 0xf3, 0xa7, 0x07, 0x27, 0x1d, 0xb7, 0x13, 0x63, 0x68, 0x64, 0x50, 0xe2, 0x88, 0x2d, 0xd6, 0x35, 0x63, 0xf1, 0x08, 0x5c,
0xef, 0xd2, 0xd5, 0x3d, 0x6d, 0xf2, 0x96, 0x94, 0x11, 0x84, 0x7c, 0x3a, 0xd7, 0x6e, 0x13, 0x23, 0x3e, 0x34, 0x2c, 0x75, 0xd2, 0x30, 0xf8, 0xb7, 0x05, 0xbd, 0xd3, 0x78, 0x79, 0x49, 0xab, 0xb4,
0xb0, 0x56, 0x54, 0xed, 0x76, 0x69, 0x62, 0x23, 0x24, 0x97, 0x5f, 0xd3, 0x62, 0xc3, 0x42, 0xfa, 0x21, 0x6a, 0x04, 0x2e, 0x3f, 0xac, 0x81, 0xeb, 0xa4, 0x96, 0x5a, 0x49, 0x2a, 0x37, 0xfe, 0xd6,
0x89, 0xcb, 0xf0, 0x0c, 0x82, 0xed, 0xba, 0x88, 0xc3, 0x89, 0x37, 0xf5, 0x13, 0x13, 0x3e, 0x5c, 0x71, 0x2d, 0x29, 0x2d, 0xbe, 0xc6, 0xd9, 0x8a, 0x25, 0x1d, 0x44, 0x26, 0xc3, 0xfb, 0xe0, 0xac,
0x22, 0xda, 0x5f, 0x82, 0x0f, 0xaf, 0xd2, 0xac, 0xa4, 0xf8, 0xc4, 0xae, 0xc1, 0x66, 0x22, 0x85, 0x2f, 0x32, 0xdf, 0x0d, 0xac, 0x89, 0x1d, 0xd5, 0xe1, 0xf5, 0xeb, 0x78, 0x37, 0xaf, 0xc3, 0xc3,
0x81, 0xa3, 0xf6, 0xb1, 0x50, 0x1a, 0xaf, 0xc0, 0xcf, 0x14, 0xd3, 0x1b, 0xcc, 0xce, 0xdd, 0x16, 0x20, 0xe3, 0x24, 0x27, 0xbf, 0xa7, 0x0d, 0xd1, 0x99, 0xa8, 0x60, 0x60, 0xa8, 0x7d, 0xc8, 0xa4,
0x1c, 0xbe, 0xa4, 0x92, 0x56, 0x5a, 0x56, 0x89, 0x9f, 0x29, 0x7c, 0x0a, 0xbd, 0xcc, 0x96, 0x55, 0xc2, 0x27, 0x60, 0x27, 0x92, 0xe9, 0x0d, 0xa6, 0x41, 0xc3, 0x0f, 0x83, 0x5c, 0x50, 0x4e, 0x4b,
0xec, 0xf3, 0xce, 0x4e, 0x9b, 0xdd, 0xc9, 0x03, 0x2e, 0xde, 0xc0, 0xf0, 0x68, 0xc4, 0x81, 0x16, 0x55, 0x94, 0x91, 0x9d, 0x48, 0x7c, 0x06, 0xfd, 0x44, 0x97, 0xa5, 0x6f, 0xb3, 0x8f, 0x7e, 0x5b,
0xaf, 0xa1, 0x65, 0xa7, 0xdb, 0xdf, 0xeb, 0x16, 0x17, 0xd0, 0x77, 0xcf, 0x6f, 0xe7, 0xc7, 0xeb, 0x5f, 0x74, 0x8d, 0x14, 0xaf, 0x61, 0xb8, 0x75, 0xd9, 0x2d, 0x7d, 0xd6, 0x3f, 0xfa, 0x36, 0x5e,
0x9b, 0xfd, 0xf2, 0x20, 0xb2, 0xde, 0xc2, 0x67, 0x10, 0x2c, 0x48, 0xe3, 0x8e, 0xf5, 0x91, 0xf3, 0xd8, 0x37, 0x5e, 0x88, 0x87, 0x70, 0x60, 0xda, 0xcf, 0x66, 0xdb, 0x96, 0x4e, 0x7f, 0xda, 0xe0,
0xc7, 0x0d, 0x8b, 0x89, 0x0e, 0xde, 0x40, 0x64, 0xad, 0x89, 0xe0, 0x90, 0xbb, 0xa2, 0x1c, 0x5f, 0xe9, 0x19, 0xc4, 0x13, 0x70, 0xe6, 0xa4, 0xb0, 0xa9, 0x64, 0x6b, 0x57, 0xc6, 0x2d, 0x43, 0x29,
0xec, 0x5f, 0xb7, 0x5c, 0x2b, 0x3a, 0xf8, 0x3f, 0x04, 0x9f, 0x6a, 0x8d, 0x8d, 0x59, 0xad, 0xc9, 0x3a, 0x38, 0x07, 0x4f, 0x8f, 0x35, 0x8e, 0x1a, 0x98, 0xf3, 0x2c, 0x1f, 0x3f, 0xde, 0x75, 0x77,
0x97, 0x10, 0xcd, 0xa9, 0x24, 0x4d, 0x47, 0x7d, 0x07, 0xdf, 0x11, 0x9d, 0xd9, 0x6f, 0x0f, 0x22, 0x63, 0x0b, 0x44, 0x07, 0x8f, 0xc0, 0xf9, 0x58, 0x29, 0x6c, 0xf9, 0xd2, 0x1e, 0x06, 0xcf, 0xc1,
0xf6, 0xd2, 0x63, 0xcc, 0x0f, 0x4d, 0x36, 0x6e, 0xb8, 0x51, 0x74, 0xf0, 0xc9, 0xa3, 0xcc, 0x87, 0x9b, 0x51, 0x4e, 0x8a, 0x5a, 0x7b, 0x77, 0x32, 0x13, 0x9d, 0xe9, 0x1f, 0x1b, 0x3c, 0x9e, 0xd7,
0x87, 0x5d, 0x4b, 0xd2, 0x6d, 0xb6, 0x8c, 0xb4, 0xa6, 0xb5, 0xd9, 0xda, 0xbe, 0x06, 0x5b, 0x9c, 0xfd, 0x4e, 0xdc, 0x1e, 0xe9, 0x71, 0xcb, 0x16, 0x88, 0x0e, 0xbe, 0xbc, 0xc3, 0x89, 0x07, 0xbb,
0x02, 0xcc, 0x89, 0xff, 0x9c, 0xf4, 0xdf, 0x9d, 0xb3, 0x35, 0xf4, 0xdc, 0xb9, 0x14, 0xbe, 0x80, 0x3b, 0x17, 0xa4, 0xf6, 0xa9, 0x67, 0xcc, 0x9e, 0xaf, 0xee, 0x53, 0xaf, 0x7b, 0x5b, 0xd4, 0xe3,
0x2e, 0xbb, 0xea, 0x2f, 0x4e, 0x1a, 0x63, 0xb3, 0x6e, 0x7a, 0x45, 0x07, 0xaf, 0xa0, 0xfb, 0xa1, 0x2b, 0x80, 0x19, 0xf1, 0xde, 0xc7, 0xff, 0xdf, 0x3d, 0xfd, 0x65, 0x41, 0xdf, 0xcc, 0x98, 0xc4,
0x28, 0x4b, 0x3c, 0x6b, 0xa2, 0xb7, 0xf3, 0xe6, 0x97, 0xb2, 0x88, 0xff, 0x95, 0x9b, 0x3f, 0x01, 0x77, 0xd0, 0xe5, 0xf5, 0xb8, 0x73, 0x25, 0xc6, 0x8f, 0xda, 0x10, 0x75, 0xbf, 0xe8, 0xe0, 0x31,
0x00, 0x00, 0xff, 0xff, 0x48, 0xf0, 0xaf, 0x88, 0x02, 0x05, 0x00, 0x00, 0x74, 0xdf, 0x67, 0x79, 0x8e, 0xe3, 0x36, 0xdc, 0xd9, 0xac, 0x8d, 0xd2, 0x69, 0xef, 0xb3, 0xfe,
0x7b, 0x48, 0x3c, 0xfe, 0x79, 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x50, 0x5f, 0x13, 0x1a,
0x06, 0x00, 0x00,
} }

View File

@ -1,8 +1,7 @@
syntax = "proto3"; syntax = "proto3";
// option go_package = "git.xeserv.us/xena/route/routerpc/routegrpc;routegrpc"; package xeserv.us.route;
option go_package = "proto";
package route;
// Nil represents nothing. // Nil represents nothing.
message Nil {} message Nil {}

View File

@ -2,13 +2,13 @@
// source: route.proto // source: route.proto
/* /*
Package route is a generated twirp stub package. Package proto is a generated twirp stub package.
This code was generated with github.com/twitchtv/twirp/protoc-gen-twirp v5.0.0. This code was generated with github.com/twitchtv/twirp/protoc-gen-twirp v5.0.0.
It is generated from these files: It is generated from these files:
route.proto route.proto
*/ */
package route package proto
import bytes "bytes" import bytes "bytes"
import context "context" import context "context"
@ -164,11 +164,11 @@ func (s *routesServer) writeError(ctx context.Context, resp http.ResponseWriter,
// RoutesPathPrefix is used for all URL paths on a twirp Routes server. // RoutesPathPrefix is used for all URL paths on a twirp Routes server.
// Requests are always: POST RoutesPathPrefix/method // Requests are always: POST RoutesPathPrefix/method
// It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes. // It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes.
const RoutesPathPrefix = "/twirp/route.Routes/" const RoutesPathPrefix = "/twirp/xeserv.us.route.Routes/"
func (s *routesServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (s *routesServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
ctx := req.Context() ctx := req.Context()
ctx = ctxsetters.WithPackageName(ctx, "route") ctx = ctxsetters.WithPackageName(ctx, "xeserv.us.route")
ctx = ctxsetters.WithServiceName(ctx, "Routes") ctx = ctxsetters.WithServiceName(ctx, "Routes")
ctx = ctxsetters.WithResponseWriter(ctx, resp) ctx = ctxsetters.WithResponseWriter(ctx, resp)
@ -187,16 +187,16 @@ func (s *routesServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
} }
switch req.URL.Path { switch req.URL.Path {
case "/twirp/route.Routes/Get": case "/twirp/xeserv.us.route.Routes/Get":
s.serveGet(ctx, resp, req) s.serveGet(ctx, resp, req)
return return
case "/twirp/route.Routes/GetAll": case "/twirp/xeserv.us.route.Routes/GetAll":
s.serveGetAll(ctx, resp, req) s.serveGetAll(ctx, resp, req)
return return
case "/twirp/route.Routes/Put": case "/twirp/xeserv.us.route.Routes/Put":
s.servePut(ctx, resp, req) s.servePut(ctx, resp, req)
return return
case "/twirp/route.Routes/Delete": case "/twirp/xeserv.us.route.Routes/Delete":
s.serveDelete(ctx, resp, req) s.serveDelete(ctx, resp, req)
return return
default: default:
@ -903,11 +903,11 @@ func (s *tokensServer) writeError(ctx context.Context, resp http.ResponseWriter,
// TokensPathPrefix is used for all URL paths on a twirp Tokens server. // TokensPathPrefix is used for all URL paths on a twirp Tokens server.
// Requests are always: POST TokensPathPrefix/method // Requests are always: POST TokensPathPrefix/method
// It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes. // It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes.
const TokensPathPrefix = "/twirp/route.Tokens/" const TokensPathPrefix = "/twirp/xeserv.us.route.Tokens/"
func (s *tokensServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (s *tokensServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
ctx := req.Context() ctx := req.Context()
ctx = ctxsetters.WithPackageName(ctx, "route") ctx = ctxsetters.WithPackageName(ctx, "xeserv.us.route")
ctx = ctxsetters.WithServiceName(ctx, "Tokens") ctx = ctxsetters.WithServiceName(ctx, "Tokens")
ctx = ctxsetters.WithResponseWriter(ctx, resp) ctx = ctxsetters.WithResponseWriter(ctx, resp)
@ -926,19 +926,19 @@ func (s *tokensServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
} }
switch req.URL.Path { switch req.URL.Path {
case "/twirp/route.Tokens/Get": case "/twirp/xeserv.us.route.Tokens/Get":
s.serveGet(ctx, resp, req) s.serveGet(ctx, resp, req)
return return
case "/twirp/route.Tokens/GetAll": case "/twirp/xeserv.us.route.Tokens/GetAll":
s.serveGetAll(ctx, resp, req) s.serveGetAll(ctx, resp, req)
return return
case "/twirp/route.Tokens/Put": case "/twirp/xeserv.us.route.Tokens/Put":
s.servePut(ctx, resp, req) s.servePut(ctx, resp, req)
return return
case "/twirp/route.Tokens/Delete": case "/twirp/xeserv.us.route.Tokens/Delete":
s.serveDelete(ctx, resp, req) s.serveDelete(ctx, resp, req)
return return
case "/twirp/route.Tokens/Deactivate": case "/twirp/xeserv.us.route.Tokens/Deactivate":
s.serveDeactivate(ctx, resp, req) s.serveDeactivate(ctx, resp, req)
return return
default: default:
@ -1731,11 +1731,11 @@ func (s *backendsServer) writeError(ctx context.Context, resp http.ResponseWrite
// BackendsPathPrefix is used for all URL paths on a twirp Backends server. // BackendsPathPrefix is used for all URL paths on a twirp Backends server.
// Requests are always: POST BackendsPathPrefix/method // Requests are always: POST BackendsPathPrefix/method
// It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes. // It can be used in an HTTP mux to route twirp requests along with non-twirp requests on other routes.
const BackendsPathPrefix = "/twirp/route.Backends/" const BackendsPathPrefix = "/twirp/xeserv.us.route.Backends/"
func (s *backendsServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (s *backendsServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
ctx := req.Context() ctx := req.Context()
ctx = ctxsetters.WithPackageName(ctx, "route") ctx = ctxsetters.WithPackageName(ctx, "xeserv.us.route")
ctx = ctxsetters.WithServiceName(ctx, "Backends") ctx = ctxsetters.WithServiceName(ctx, "Backends")
ctx = ctxsetters.WithResponseWriter(ctx, resp) ctx = ctxsetters.WithResponseWriter(ctx, resp)
@ -1754,10 +1754,10 @@ func (s *backendsServer) ServeHTTP(resp http.ResponseWriter, req *http.Request)
} }
switch req.URL.Path { switch req.URL.Path {
case "/twirp/route.Backends/List": case "/twirp/xeserv.us.route.Backends/List":
s.serveList(ctx, resp, req) s.serveList(ctx, resp, req)
return return
case "/twirp/route.Backends/Kill": case "/twirp/xeserv.us.route.Backends/Kill":
s.serveKill(ctx, resp, req) s.serveKill(ctx, resp, req)
return return
default: default:
@ -2447,40 +2447,42 @@ func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) conte
} }
var twirpFileDescriptor0 = []byte{ var twirpFileDescriptor0 = []byte{
// 556 bytes of a gzipped FileDescriptorProto // 579 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xd1, 0x6a, 0xdb, 0x4a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0xb5, 0x24, 0x4b, 0xb1, 0xc7, 0x97, 0x38, 0x0c, 0x26, 0x08, 0xe7, 0xc5, 0xec, 0x0d, 0xa9, 0x10, 0x8d, 0xed, 0xd8, 0x49, 0x27, 0x12, 0x41, 0xa3, 0xa8, 0x32, 0x81, 0x83, 0xb5, 0x12, 0x52,
0x29, 0x34, 0x14, 0xa7, 0x50, 0x0a, 0xed, 0x43, 0x8b, 0x8b, 0x09, 0x2d, 0xa1, 0xc8, 0x7d, 0xeb, 0x4e, 0x16, 0x0a, 0x48, 0x85, 0x02, 0x87, 0x56, 0x81, 0x50, 0x81, 0x2a, 0xe4, 0x70, 0x82, 0x93,
0x93, 0x64, 0x0d, 0x58, 0x44, 0xf5, 0xba, 0xda, 0x55, 0xa1, 0x9f, 0xd2, 0x2f, 0xe9, 0x97, 0xf4, 0x1d, 0x8f, 0x54, 0xab, 0x26, 0x0e, 0xde, 0x75, 0x05, 0x5f, 0xc0, 0x95, 0x2b, 0x9f, 0xc2, 0xdf,
0x7f, 0xca, 0xce, 0xae, 0x63, 0xcb, 0x4a, 0xfb, 0x36, 0x33, 0x67, 0x76, 0x74, 0xce, 0xcc, 0x11, 0x21, 0xcf, 0x6e, 0xda, 0x12, 0xc7, 0xa9, 0x38, 0x65, 0x66, 0xf6, 0xcd, 0xfa, 0xbd, 0xb7, 0x33,
0x0c, 0x2a, 0x59, 0x6b, 0xba, 0xde, 0x56, 0x52, 0x4b, 0x0c, 0x39, 0x11, 0x21, 0x04, 0x77, 0x45, 0x81, 0x41, 0x59, 0x54, 0x8a, 0xc2, 0x75, 0x59, 0xa8, 0x02, 0x87, 0xdf, 0x49, 0x52, 0x79, 0x15,
0x29, 0x5e, 0xc1, 0x70, 0x41, 0x3a, 0x31, 0xa5, 0x84, 0xbe, 0xd5, 0xa4, 0x34, 0x9e, 0x43, 0x54, 0x56, 0x32, 0xe4, 0xb2, 0x70, 0xc1, 0x39, 0xcf, 0x72, 0xf1, 0x02, 0x86, 0x73, 0x52, 0x51, 0x5d,
0x6f, 0x6a, 0x45, 0x79, 0xec, 0x4d, 0xbc, 0x69, 0x3f, 0x71, 0x19, 0x9e, 0x82, 0x5f, 0xe4, 0xb1, 0x8a, 0xe8, 0x5b, 0x45, 0x52, 0xe1, 0x21, 0x78, 0xd5, 0xaa, 0x92, 0x94, 0xfa, 0x56, 0x60, 0x4d,
0xcf, 0x35, 0xbf, 0xc8, 0xc5, 0x7b, 0x08, 0xf9, 0x9d, 0x03, 0xbc, 0x1d, 0x80, 0x31, 0x9c, 0xac, 0x0e, 0x22, 0x93, 0xe1, 0x3d, 0xb0, 0xb3, 0xd4, 0xb7, 0xb9, 0x66, 0x67, 0xa9, 0x78, 0x03, 0x2e,
0x2a, 0x4a, 0xb5, 0xac, 0x5c, 0xf7, 0x2e, 0x45, 0x84, 0xee, 0x5a, 0x2a, 0x1d, 0x07, 0x5c, 0xe6, 0xf7, 0x99, 0x03, 0x6b, 0x73, 0x80, 0x3e, 0xf4, 0x96, 0x25, 0xc5, 0xaa, 0x28, 0x0d, 0x7a, 0x93,
0x58, 0xbc, 0x86, 0xd1, 0x82, 0xf4, 0xdb, 0xb2, 0xe4, 0x61, 0x2a, 0x21, 0xb5, 0x95, 0x1b, 0x45, 0x22, 0x42, 0xf7, 0xa2, 0x90, 0xca, 0x77, 0xb8, 0xcc, 0xb1, 0x78, 0x0b, 0xa3, 0x39, 0xa9, 0x93,
0x78, 0x09, 0x11, 0x33, 0x55, 0xb1, 0x37, 0x09, 0xa6, 0x83, 0xd9, 0x7f, 0xd7, 0x56, 0x85, 0xe5, 0x3c, 0xe7, 0xcb, 0x64, 0x44, 0x72, 0x5d, 0xac, 0x24, 0x61, 0x08, 0x1e, 0x33, 0x95, 0xbe, 0x15,
0xea, 0x30, 0xf1, 0x05, 0xc2, 0xcf, 0xf2, 0x9e, 0x36, 0x2d, 0x12, 0x08, 0xdd, 0x4c, 0xe6, 0x3f, 0x38, 0x93, 0xc1, 0xf4, 0x30, 0xdc, 0x92, 0x10, 0x6a, 0xd6, 0x06, 0x25, 0xbe, 0x80, 0xfb, 0xa9,
0x1c, 0x03, 0x8e, 0x8d, 0x32, 0xb5, 0x92, 0x5b, 0x52, 0x71, 0x30, 0x09, 0x8c, 0x32, 0x9b, 0x99, 0xb8, 0xa4, 0x55, 0x83, 0x0e, 0x42, 0x37, 0x29, 0xd2, 0x1f, 0x86, 0x0b, 0xc7, 0xb5, 0x46, 0xb9,
0x7a, 0xba, 0xd2, 0xc5, 0x77, 0x8a, 0xbb, 0x13, 0x6f, 0xda, 0x4b, 0x5c, 0x26, 0x9e, 0x43, 0x8f, 0x2c, 0xd6, 0x24, 0x7d, 0x27, 0x70, 0x6a, 0x8d, 0x3a, 0xab, 0xeb, 0xf1, 0x52, 0x65, 0x57, 0xe4,
0x87, 0x2f, 0x49, 0x1b, 0x3a, 0xda, 0xc4, 0xc7, 0x74, 0xb8, 0x21, 0x71, 0x98, 0x78, 0xc9, 0xeb, 0x77, 0x03, 0x6b, 0xd2, 0x8f, 0x4c, 0x26, 0x8e, 0xa1, 0xcf, 0x97, 0x2f, 0x48, 0xd5, 0xc4, 0x54,
0xb4, 0x35, 0xb7, 0xce, 0x11, 0x84, 0x0c, 0x3a, 0x6e, 0x36, 0x69, 0x2d, 0xf3, 0xa7, 0x07, 0x27, 0x1d, 0xb7, 0x13, 0x63, 0x68, 0x64, 0x50, 0xe2, 0x88, 0x2d, 0xd6, 0x35, 0x63, 0xf1, 0x08, 0x5c,
0xef, 0xd2, 0xd5, 0x3d, 0x6d, 0xf2, 0x96, 0x94, 0x11, 0x84, 0x7c, 0x3a, 0xd7, 0x6e, 0x13, 0x23, 0x3e, 0x34, 0x2c, 0x75, 0xd2, 0x30, 0xf8, 0xb7, 0x05, 0xbd, 0xd3, 0x78, 0x79, 0x49, 0xab, 0xb4,
0xb0, 0x56, 0x54, 0xed, 0x76, 0x69, 0x62, 0x23, 0x24, 0x97, 0x5f, 0xd3, 0x62, 0xc3, 0x42, 0xfa, 0x21, 0x6a, 0x04, 0x2e, 0x3f, 0xac, 0x81, 0xeb, 0xa4, 0x96, 0x5a, 0x49, 0x2a, 0x37, 0xfe, 0xd6,
0x89, 0xcb, 0xf0, 0x0c, 0x82, 0xed, 0xba, 0x88, 0xc3, 0x89, 0x37, 0xf5, 0x13, 0x13, 0x3e, 0x5c, 0x71, 0x2d, 0x29, 0x2d, 0xbe, 0xc6, 0xd9, 0x8a, 0x25, 0x1d, 0x44, 0x26, 0xc3, 0xfb, 0xe0, 0xac,
0x22, 0xda, 0x5f, 0x82, 0x0f, 0xaf, 0xd2, 0xac, 0xa4, 0xf8, 0xc4, 0xae, 0xc1, 0x66, 0x22, 0x85, 0x2f, 0x32, 0xdf, 0x0d, 0xac, 0x89, 0x1d, 0xd5, 0xe1, 0xf5, 0xeb, 0x78, 0x37, 0xaf, 0xc3, 0xc3,
0x81, 0xa3, 0xf6, 0xb1, 0x50, 0x1a, 0xaf, 0xc0, 0xcf, 0x14, 0xd3, 0x1b, 0xcc, 0xce, 0xdd, 0x16, 0x20, 0xe3, 0x24, 0x27, 0xbf, 0xa7, 0x0d, 0xd1, 0x99, 0xa8, 0x60, 0x60, 0xa8, 0x7d, 0xc8, 0xa4,
0x1c, 0xbe, 0xa4, 0x92, 0x56, 0x5a, 0x56, 0x89, 0x9f, 0x29, 0x7c, 0x0a, 0xbd, 0xcc, 0x96, 0x55, 0xc2, 0x27, 0x60, 0x27, 0x92, 0xe9, 0x0d, 0xa6, 0x41, 0xc3, 0x0f, 0x83, 0x5c, 0x50, 0x4e, 0x4b,
0xec, 0xf3, 0xce, 0x4e, 0x9b, 0xdd, 0xc9, 0x03, 0x2e, 0xde, 0xc0, 0xf0, 0x68, 0xc4, 0x81, 0x16, 0x55, 0x94, 0x91, 0x9d, 0x48, 0x7c, 0x06, 0xfd, 0x44, 0x97, 0xa5, 0x6f, 0xb3, 0x8f, 0x7e, 0x5b,
0xaf, 0xa1, 0x65, 0xa7, 0xdb, 0xdf, 0xeb, 0x16, 0x17, 0xd0, 0x77, 0xcf, 0x6f, 0xe7, 0xc7, 0xeb, 0x5f, 0x74, 0x8d, 0x14, 0xaf, 0x61, 0xb8, 0x75, 0xd9, 0x2d, 0x7d, 0xd6, 0x3f, 0xfa, 0x36, 0x5e,
0x9b, 0xfd, 0xf2, 0x20, 0xb2, 0xde, 0xc2, 0x67, 0x10, 0x2c, 0x48, 0xe3, 0x8e, 0xf5, 0x91, 0xf3, 0xd8, 0x37, 0x5e, 0x88, 0x87, 0x70, 0x60, 0xda, 0xcf, 0x66, 0xdb, 0x96, 0x4e, 0x7f, 0xda, 0xe0,
0xc7, 0x0d, 0x8b, 0x89, 0x0e, 0xde, 0x40, 0x64, 0xad, 0x89, 0xe0, 0x90, 0xbb, 0xa2, 0x1c, 0x5f, 0xe9, 0x19, 0xc4, 0x13, 0x70, 0xe6, 0xa4, 0xb0, 0xa9, 0x64, 0x6b, 0x57, 0xc6, 0x2d, 0x43, 0x29,
0xec, 0x5f, 0xb7, 0x5c, 0x2b, 0x3a, 0xf8, 0x3f, 0x04, 0x9f, 0x6a, 0x8d, 0x8d, 0x59, 0xad, 0xc9, 0x3a, 0x38, 0x07, 0x4f, 0x8f, 0x35, 0x8e, 0x1a, 0x98, 0xf3, 0x2c, 0x1f, 0x3f, 0xde, 0x75, 0x77,
0x97, 0x10, 0xcd, 0xa9, 0x24, 0x4d, 0x47, 0x7d, 0x07, 0xdf, 0x11, 0x9d, 0xd9, 0x6f, 0x0f, 0x22, 0x63, 0x0b, 0x44, 0x07, 0x8f, 0xc0, 0xf9, 0x58, 0x29, 0x6c, 0xf9, 0xd2, 0x1e, 0x06, 0xcf, 0xc1,
0xf6, 0xd2, 0x63, 0xcc, 0x0f, 0x4d, 0x36, 0x6e, 0xb8, 0x51, 0x74, 0xf0, 0xc9, 0xa3, 0xcc, 0x87, 0x9b, 0x51, 0x4e, 0x8a, 0x5a, 0x7b, 0x77, 0x32, 0x13, 0x9d, 0xe9, 0x1f, 0x1b, 0x3c, 0x9e, 0xd7,
0x87, 0x5d, 0x4b, 0xd2, 0x6d, 0xb6, 0x8c, 0xb4, 0xa6, 0xb5, 0xd9, 0xda, 0xbe, 0x06, 0x5b, 0x9c, 0xfd, 0x4e, 0xdc, 0x1e, 0xe9, 0x71, 0xcb, 0x16, 0x88, 0x0e, 0xbe, 0xbc, 0xc3, 0x89, 0x07, 0xbb,
0x02, 0xcc, 0x89, 0xff, 0x9c, 0xf4, 0xdf, 0x9d, 0xb3, 0x35, 0xf4, 0xdc, 0xb9, 0x14, 0xbe, 0x80, 0x3b, 0x17, 0xa4, 0xf6, 0xa9, 0x67, 0xcc, 0x9e, 0xaf, 0xee, 0x53, 0xaf, 0x7b, 0x5b, 0xd4, 0xe3,
0x2e, 0xbb, 0xea, 0x2f, 0x4e, 0x1a, 0x63, 0xb3, 0x6e, 0x7a, 0x45, 0x07, 0xaf, 0xa0, 0xfb, 0xa1, 0x2b, 0x80, 0x19, 0xf1, 0xde, 0xc7, 0xff, 0xdf, 0x3d, 0xfd, 0x65, 0x41, 0xdf, 0xcc, 0x98, 0xc4,
0x28, 0x4b, 0x3c, 0x6b, 0xa2, 0xb7, 0xf3, 0xe6, 0x97, 0xb2, 0x88, 0xff, 0x95, 0x9b, 0x3f, 0x01, 0x77, 0xd0, 0xe5, 0xf5, 0xb8, 0x73, 0x25, 0xc6, 0x8f, 0xda, 0x10, 0x75, 0xbf, 0xe8, 0xe0, 0x31,
0x00, 0x00, 0xff, 0xff, 0x48, 0xf0, 0xaf, 0x88, 0x02, 0x05, 0x00, 0x00, 0x74, 0xdf, 0x67, 0x79, 0x8e, 0xe3, 0x36, 0xdc, 0xd9, 0xac, 0x8d, 0xd2, 0x69, 0xef, 0xb3, 0xfe,
0x7b, 0x48, 0x3c, 0xfe, 0x79, 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x50, 0x5f, 0x13, 0x1a,
0x06, 0x00, 0x00,
} }