From f67a456d1ec46a4765f57a021980b0d8ca88457b Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Tue, 6 May 2025 21:38:14 +0200 Subject: [PATCH] wip: refactor: API --- go.mod | 4 + go.sum | 2 + internal/app/app.go | 21 + internal/generated/grpc/proto/api.pb.go | 1691 ++++++++++++++++++ internal/generated/grpc/proto/api_grpc.pb.go | 135 ++ internal/server/server.go | 7 + mise/config.toml | 6 + proto/api.proto | 105 ++ 8 files changed, 1971 insertions(+) create mode 100644 internal/generated/grpc/proto/api.pb.go create mode 100644 internal/generated/grpc/proto/api_grpc.pb.go create mode 100644 internal/server/server.go create mode 100644 proto/api.proto diff --git a/go.mod b/go.mod index 56cb2df..81d5088 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,8 @@ require ( github.com/stretchr/testify v1.10.0 github.com/testcontainers/testcontainers-go v0.35.0 golang.design/x/clipboard v0.7.0 + google.golang.org/grpc v1.69.4 + google.golang.org/protobuf v1.36.3 gopkg.in/yaml.v3 v3.0.1 ) @@ -95,12 +97,14 @@ require ( golang.org/x/image v0.26.0 // indirect golang.org/x/mobile v0.0.0-20250408133729-978277e7eaf7 // indirect golang.org/x/mod v0.24.0 // indirect + golang.org/x/net v0.39.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.32.0 // indirect golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.32.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index 2e59131..f8574d0 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/internal/app/app.go b/internal/app/app.go index 0f8a17e..779875c 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -5,7 +5,9 @@ import ( "context" "errors" "fmt" + "log" "log/slog" + "net" "slices" "time" @@ -13,10 +15,13 @@ import ( "git.netflux.io/rob/octoplex/internal/container" "git.netflux.io/rob/octoplex/internal/domain" "git.netflux.io/rob/octoplex/internal/event" + pb "git.netflux.io/rob/octoplex/internal/generated/grpc/proto" "git.netflux.io/rob/octoplex/internal/mediaserver" "git.netflux.io/rob/octoplex/internal/replicator" + "git.netflux.io/rob/octoplex/internal/server" "git.netflux.io/rob/octoplex/internal/terminal" "github.com/docker/docker/client" + "google.golang.org/grpc" ) // App is an instance of the app. @@ -120,6 +125,19 @@ func (a *App) Run(ctx context.Context) error { <-a.dispatchC } + const grpcAddr = ":50051" + lis, err := net.Listen("tcp", grpcAddr) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + grpcServer := grpc.NewServer() + grpcDone := make(chan error, 1) + pb.RegisterInternalAPIServer(grpcServer, server.Server{}) + go func() { + a.logger.Info("gRPC server started", "addr", grpcAddr) + grpcDone <- grpcServer.Serve(lis) + }() + containerClient, err := container.NewClient(ctx, a.dockerClient, a.logger.With("component", "container_client")) if err != nil { err = fmt.Errorf("create container client: %w", err) @@ -192,6 +210,9 @@ func (a *App) Run(ctx context.Context) error { select { case <-ctx.Done(): return ctx.Err() + case grpcErr := <-grpcDone: + a.logger.Error("gRPC server exited", "err", grpcErr) + return grpcErr case <-startMediaServerC: if err = srv.Start(ctx); err != nil { return fmt.Errorf("start mediaserver: %w", err) diff --git a/internal/generated/grpc/proto/api.pb.go b/internal/generated/grpc/proto/api.pb.go new file mode 100644 index 0000000..f308548 --- /dev/null +++ b/internal/generated/grpc/proto/api.pb.go @@ -0,0 +1,1691 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.6 +// source: proto/api.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Envelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *Envelope_Command + // *Envelope_Event + Payload isEnvelope_Payload `protobuf_oneof:"payload"` +} + +func (x *Envelope) Reset() { + *x = Envelope{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Envelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Envelope) ProtoMessage() {} + +func (x *Envelope) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Envelope.ProtoReflect.Descriptor instead. +func (*Envelope) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{0} +} + +func (m *Envelope) GetPayload() isEnvelope_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *Envelope) GetCommand() *Command { + if x, ok := x.GetPayload().(*Envelope_Command); ok { + return x.Command + } + return nil +} + +func (x *Envelope) GetEvent() *Event { + if x, ok := x.GetPayload().(*Envelope_Event); ok { + return x.Event + } + return nil +} + +type isEnvelope_Payload interface { + isEnvelope_Payload() +} + +type Envelope_Command struct { + Command *Command `protobuf:"bytes,1,opt,name=command,proto3,oneof"` +} + +type Envelope_Event struct { + Event *Event `protobuf:"bytes,2,opt,name=event,proto3,oneof"` +} + +func (*Envelope_Command) isEnvelope_Payload() {} + +func (*Envelope_Event) isEnvelope_Payload() {} + +type Command struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to CommandType: + // + // *Command_AddDestinaion + // *Command_RemoveDestination + // *Command_StartDestination + // *Command_StopDestination + // *Command_CloseOtherInstances + // *Command_Quit + CommandType isCommand_CommandType `protobuf_oneof:"command_type"` +} + +func (x *Command) Reset() { + *x = Command{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command) ProtoMessage() {} + +func (x *Command) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command.ProtoReflect.Descriptor instead. +func (*Command) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{1} +} + +func (m *Command) GetCommandType() isCommand_CommandType { + if m != nil { + return m.CommandType + } + return nil +} + +func (x *Command) GetAddDestinaion() *AddDestinationCommand { + if x, ok := x.GetCommandType().(*Command_AddDestinaion); ok { + return x.AddDestinaion + } + return nil +} + +func (x *Command) GetRemoveDestination() *RemoveDestinationCommand { + if x, ok := x.GetCommandType().(*Command_RemoveDestination); ok { + return x.RemoveDestination + } + return nil +} + +func (x *Command) GetStartDestination() *StartDestinationCommand { + if x, ok := x.GetCommandType().(*Command_StartDestination); ok { + return x.StartDestination + } + return nil +} + +func (x *Command) GetStopDestination() *StopDestinationCommand { + if x, ok := x.GetCommandType().(*Command_StopDestination); ok { + return x.StopDestination + } + return nil +} + +func (x *Command) GetCloseOtherInstances() *CloseOtherInstancesCommand { + if x, ok := x.GetCommandType().(*Command_CloseOtherInstances); ok { + return x.CloseOtherInstances + } + return nil +} + +func (x *Command) GetQuit() *QuitCommand { + if x, ok := x.GetCommandType().(*Command_Quit); ok { + return x.Quit + } + return nil +} + +type isCommand_CommandType interface { + isCommand_CommandType() +} + +type Command_AddDestinaion struct { + AddDestinaion *AddDestinationCommand `protobuf:"bytes,1,opt,name=add_destinaion,json=addDestinaion,proto3,oneof"` +} + +type Command_RemoveDestination struct { + RemoveDestination *RemoveDestinationCommand `protobuf:"bytes,2,opt,name=remove_destination,json=removeDestination,proto3,oneof"` +} + +type Command_StartDestination struct { + StartDestination *StartDestinationCommand `protobuf:"bytes,3,opt,name=start_destination,json=startDestination,proto3,oneof"` +} + +type Command_StopDestination struct { + StopDestination *StopDestinationCommand `protobuf:"bytes,4,opt,name=stop_destination,json=stopDestination,proto3,oneof"` +} + +type Command_CloseOtherInstances struct { + CloseOtherInstances *CloseOtherInstancesCommand `protobuf:"bytes,5,opt,name=close_other_instances,json=closeOtherInstances,proto3,oneof"` +} + +type Command_Quit struct { + Quit *QuitCommand `protobuf:"bytes,6,opt,name=quit,proto3,oneof"` +} + +func (*Command_AddDestinaion) isCommand_CommandType() {} + +func (*Command_RemoveDestination) isCommand_CommandType() {} + +func (*Command_StartDestination) isCommand_CommandType() {} + +func (*Command_StopDestination) isCommand_CommandType() {} + +func (*Command_CloseOtherInstances) isCommand_CommandType() {} + +func (*Command_Quit) isCommand_CommandType() {} + +type AddDestinationCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *AddDestinationCommand) Reset() { + *x = AddDestinationCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddDestinationCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddDestinationCommand) ProtoMessage() {} + +func (x *AddDestinationCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddDestinationCommand.ProtoReflect.Descriptor instead. +func (*AddDestinationCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{2} +} + +func (x *AddDestinationCommand) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *AddDestinationCommand) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type RemoveDestinationCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *RemoveDestinationCommand) Reset() { + *x = RemoveDestinationCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveDestinationCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveDestinationCommand) ProtoMessage() {} + +func (x *RemoveDestinationCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveDestinationCommand.ProtoReflect.Descriptor instead. +func (*RemoveDestinationCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{3} +} + +func (x *RemoveDestinationCommand) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type StartDestinationCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *StartDestinationCommand) Reset() { + *x = StartDestinationCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StartDestinationCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartDestinationCommand) ProtoMessage() {} + +func (x *StartDestinationCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartDestinationCommand.ProtoReflect.Descriptor instead. +func (*StartDestinationCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{4} +} + +func (x *StartDestinationCommand) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type StopDestinationCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *StopDestinationCommand) Reset() { + *x = StopDestinationCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StopDestinationCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StopDestinationCommand) ProtoMessage() {} + +func (x *StopDestinationCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StopDestinationCommand.ProtoReflect.Descriptor instead. +func (*StopDestinationCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{5} +} + +func (x *StopDestinationCommand) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type CloseOtherInstancesCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CloseOtherInstancesCommand) Reset() { + *x = CloseOtherInstancesCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CloseOtherInstancesCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseOtherInstancesCommand) ProtoMessage() {} + +func (x *CloseOtherInstancesCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CloseOtherInstancesCommand.ProtoReflect.Descriptor instead. +func (*CloseOtherInstancesCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{6} +} + +type QuitCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QuitCommand) Reset() { + *x = QuitCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QuitCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QuitCommand) ProtoMessage() {} + +func (x *QuitCommand) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QuitCommand.ProtoReflect.Descriptor instead. +func (*QuitCommand) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{7} +} + +type Event struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to EventType: + // + // *Event_AppStateChanged + // *Event_DestinationStreamExited + // *Event_DestinationAdded + // *Event_AddDestinationFailed + // *Event_DestinationRemoved + // *Event_RemoveDestinationFailed + // *Event_StartDestinationFailed + // *Event_MediaServerStarted + // *Event_OtherInstanceDetected + // *Event_FatalError + EventType isEvent_EventType `protobuf_oneof:"event_type"` +} + +func (x *Event) Reset() { + *x = Event{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Event) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Event) ProtoMessage() {} + +func (x *Event) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Event.ProtoReflect.Descriptor instead. +func (*Event) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{8} +} + +func (m *Event) GetEventType() isEvent_EventType { + if m != nil { + return m.EventType + } + return nil +} + +func (x *Event) GetAppStateChanged() *AppStateChangedEvent { + if x, ok := x.GetEventType().(*Event_AppStateChanged); ok { + return x.AppStateChanged + } + return nil +} + +func (x *Event) GetDestinationStreamExited() *DestinationStreamExitedEvent { + if x, ok := x.GetEventType().(*Event_DestinationStreamExited); ok { + return x.DestinationStreamExited + } + return nil +} + +func (x *Event) GetDestinationAdded() *DestinationAddedEvent { + if x, ok := x.GetEventType().(*Event_DestinationAdded); ok { + return x.DestinationAdded + } + return nil +} + +func (x *Event) GetAddDestinationFailed() *AddDestinationFailedEvent { + if x, ok := x.GetEventType().(*Event_AddDestinationFailed); ok { + return x.AddDestinationFailed + } + return nil +} + +func (x *Event) GetDestinationRemoved() *DestinationRemovedEvent { + if x, ok := x.GetEventType().(*Event_DestinationRemoved); ok { + return x.DestinationRemoved + } + return nil +} + +func (x *Event) GetRemoveDestinationFailed() *RemoveDestinationFailedEvent { + if x, ok := x.GetEventType().(*Event_RemoveDestinationFailed); ok { + return x.RemoveDestinationFailed + } + return nil +} + +func (x *Event) GetStartDestinationFailed() *StartDestinationFailedEvent { + if x, ok := x.GetEventType().(*Event_StartDestinationFailed); ok { + return x.StartDestinationFailed + } + return nil +} + +func (x *Event) GetMediaServerStarted() *MediaServerStartedEvent { + if x, ok := x.GetEventType().(*Event_MediaServerStarted); ok { + return x.MediaServerStarted + } + return nil +} + +func (x *Event) GetOtherInstanceDetected() *OtherInstanceDetectedEvent { + if x, ok := x.GetEventType().(*Event_OtherInstanceDetected); ok { + return x.OtherInstanceDetected + } + return nil +} + +func (x *Event) GetFatalError() *FatalErrorEvent { + if x, ok := x.GetEventType().(*Event_FatalError); ok { + return x.FatalError + } + return nil +} + +type isEvent_EventType interface { + isEvent_EventType() +} + +type Event_AppStateChanged struct { + AppStateChanged *AppStateChangedEvent `protobuf:"bytes,1,opt,name=app_state_changed,json=appStateChanged,proto3,oneof"` +} + +type Event_DestinationStreamExited struct { + DestinationStreamExited *DestinationStreamExitedEvent `protobuf:"bytes,2,opt,name=destination_stream_exited,json=destinationStreamExited,proto3,oneof"` +} + +type Event_DestinationAdded struct { + DestinationAdded *DestinationAddedEvent `protobuf:"bytes,3,opt,name=destination_added,json=destinationAdded,proto3,oneof"` +} + +type Event_AddDestinationFailed struct { + AddDestinationFailed *AddDestinationFailedEvent `protobuf:"bytes,4,opt,name=add_destination_failed,json=addDestinationFailed,proto3,oneof"` +} + +type Event_DestinationRemoved struct { + DestinationRemoved *DestinationRemovedEvent `protobuf:"bytes,5,opt,name=destination_removed,json=destinationRemoved,proto3,oneof"` +} + +type Event_RemoveDestinationFailed struct { + RemoveDestinationFailed *RemoveDestinationFailedEvent `protobuf:"bytes,6,opt,name=remove_destination_failed,json=removeDestinationFailed,proto3,oneof"` +} + +type Event_StartDestinationFailed struct { + StartDestinationFailed *StartDestinationFailedEvent `protobuf:"bytes,7,opt,name=start_destination_failed,json=startDestinationFailed,proto3,oneof"` +} + +type Event_MediaServerStarted struct { + MediaServerStarted *MediaServerStartedEvent `protobuf:"bytes,8,opt,name=media_server_started,json=mediaServerStarted,proto3,oneof"` +} + +type Event_OtherInstanceDetected struct { + OtherInstanceDetected *OtherInstanceDetectedEvent `protobuf:"bytes,9,opt,name=other_instance_detected,json=otherInstanceDetected,proto3,oneof"` +} + +type Event_FatalError struct { + FatalError *FatalErrorEvent `protobuf:"bytes,10,opt,name=fatal_error,json=fatalError,proto3,oneof"` +} + +func (*Event_AppStateChanged) isEvent_EventType() {} + +func (*Event_DestinationStreamExited) isEvent_EventType() {} + +func (*Event_DestinationAdded) isEvent_EventType() {} + +func (*Event_AddDestinationFailed) isEvent_EventType() {} + +func (*Event_DestinationRemoved) isEvent_EventType() {} + +func (*Event_RemoveDestinationFailed) isEvent_EventType() {} + +func (*Event_StartDestinationFailed) isEvent_EventType() {} + +func (*Event_MediaServerStarted) isEvent_EventType() {} + +func (*Event_OtherInstanceDetected) isEvent_EventType() {} + +func (*Event_FatalError) isEvent_EventType() {} + +// TODO: complete +type AppStateChangedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AppStateChangedEvent) Reset() { + *x = AppStateChangedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppStateChangedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppStateChangedEvent) ProtoMessage() {} + +func (x *AppStateChangedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppStateChangedEvent.ProtoReflect.Descriptor instead. +func (*AppStateChangedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{9} +} + +type DestinationStreamExitedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *DestinationStreamExitedEvent) Reset() { + *x = DestinationStreamExitedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationStreamExitedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationStreamExitedEvent) ProtoMessage() {} + +func (x *DestinationStreamExitedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationStreamExitedEvent.ProtoReflect.Descriptor instead. +func (*DestinationStreamExitedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{10} +} + +func (x *DestinationStreamExitedEvent) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DestinationStreamExitedEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type DestinationAddedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *DestinationAddedEvent) Reset() { + *x = DestinationAddedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationAddedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationAddedEvent) ProtoMessage() {} + +func (x *DestinationAddedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationAddedEvent.ProtoReflect.Descriptor instead. +func (*DestinationAddedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{11} +} + +func (x *DestinationAddedEvent) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type AddDestinationFailedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *AddDestinationFailedEvent) Reset() { + *x = AddDestinationFailedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddDestinationFailedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddDestinationFailedEvent) ProtoMessage() {} + +func (x *AddDestinationFailedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddDestinationFailedEvent.ProtoReflect.Descriptor instead. +func (*AddDestinationFailedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{12} +} + +func (x *AddDestinationFailedEvent) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *AddDestinationFailedEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type DestinationRemovedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *DestinationRemovedEvent) Reset() { + *x = DestinationRemovedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DestinationRemovedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestinationRemovedEvent) ProtoMessage() {} + +func (x *DestinationRemovedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DestinationRemovedEvent.ProtoReflect.Descriptor instead. +func (*DestinationRemovedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{13} +} + +func (x *DestinationRemovedEvent) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type RemoveDestinationFailedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *RemoveDestinationFailedEvent) Reset() { + *x = RemoveDestinationFailedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveDestinationFailedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveDestinationFailedEvent) ProtoMessage() {} + +func (x *RemoveDestinationFailedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveDestinationFailedEvent.ProtoReflect.Descriptor instead. +func (*RemoveDestinationFailedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{14} +} + +func (x *RemoveDestinationFailedEvent) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *RemoveDestinationFailedEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type StartDestinationFailedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *StartDestinationFailedEvent) Reset() { + *x = StartDestinationFailedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StartDestinationFailedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartDestinationFailedEvent) ProtoMessage() {} + +func (x *StartDestinationFailedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartDestinationFailedEvent.ProtoReflect.Descriptor instead. +func (*StartDestinationFailedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{15} +} + +func (x *StartDestinationFailedEvent) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *StartDestinationFailedEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +type MediaServerStartedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RtmpUrl string `protobuf:"bytes,1,opt,name=rtmp_url,json=rtmpUrl,proto3" json:"rtmp_url,omitempty"` + RtmpsUrl string `protobuf:"bytes,2,opt,name=rtmps_url,json=rtmpsUrl,proto3" json:"rtmps_url,omitempty"` +} + +func (x *MediaServerStartedEvent) Reset() { + *x = MediaServerStartedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MediaServerStartedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MediaServerStartedEvent) ProtoMessage() {} + +func (x *MediaServerStartedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MediaServerStartedEvent.ProtoReflect.Descriptor instead. +func (*MediaServerStartedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{16} +} + +func (x *MediaServerStartedEvent) GetRtmpUrl() string { + if x != nil { + return x.RtmpUrl + } + return "" +} + +func (x *MediaServerStartedEvent) GetRtmpsUrl() string { + if x != nil { + return x.RtmpsUrl + } + return "" +} + +type OtherInstanceDetectedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *OtherInstanceDetectedEvent) Reset() { + *x = OtherInstanceDetectedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OtherInstanceDetectedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OtherInstanceDetectedEvent) ProtoMessage() {} + +func (x *OtherInstanceDetectedEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OtherInstanceDetectedEvent.ProtoReflect.Descriptor instead. +func (*OtherInstanceDetectedEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{17} +} + +type FatalErrorEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *FatalErrorEvent) Reset() { + *x = FatalErrorEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_api_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FatalErrorEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FatalErrorEvent) ProtoMessage() {} + +func (x *FatalErrorEvent) ProtoReflect() protoreflect.Message { + mi := &file_proto_api_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FatalErrorEvent.ProtoReflect.Descriptor instead. +func (*FatalErrorEvent) Descriptor() ([]byte, []int) { + return file_proto_api_proto_rawDescGZIP(), []int{18} +} + +func (x *FatalErrorEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +var File_proto_api_proto protoreflect.FileDescriptor + +var file_proto_api_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, 0x22, 0x63, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x0a, 0x05, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xc4, 0x03, 0x0a, 0x07, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x5f, 0x64, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x0d, 0x61, + 0x64, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x12, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x11, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x10, 0x73, 0x74, 0x6f, + 0x70, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x48, 0x00, 0x52, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x15, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x6f, 0x74, 0x68, + 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x4f, 0x74, + 0x68, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x13, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x4f, 0x74, 0x68, 0x65, + 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x71, 0x75, + 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x51, + 0x75, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x04, 0x71, 0x75, + 0x69, 0x74, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x22, 0x3d, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x6c, 0x22, 0x2c, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, + 0x2b, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x2a, 0x0a, 0x16, + 0x53, 0x74, 0x6f, 0x70, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x1c, 0x0a, 0x1a, 0x43, 0x6c, 0x6f, 0x73, + 0x65, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x0d, 0x0a, 0x0b, 0x51, 0x75, 0x69, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0xd8, 0x06, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x47, 0x0a, 0x11, 0x61, 0x70, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x5f, 0x0a, 0x19, 0x64, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x65, + 0x78, 0x69, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x45, 0x78, 0x69, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x17, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x45, 0x78, 0x69, 0x74, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x11, 0x64, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x64, 0x64, 0x65, 0x64, 0x12, 0x56, 0x0a, 0x16, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, 0x61, 0x64, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x13, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x5f, 0x0a, + 0x19, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x5c, + 0x0a, 0x18, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x50, 0x0a, 0x14, + 0x6d, 0x65, 0x64, 0x69, 0x61, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x6d, 0x65, 0x64, 0x69, + 0x61, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x59, + 0x0a, 0x17, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x15, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0b, 0x66, 0x61, 0x74, + 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x61, 0x74, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x61, 0x74, 0x61, 0x6c, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x42, 0x0c, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x22, 0x16, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x1c, 0x44, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x78, 0x69, + 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x29, 0x0a, 0x15, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x64, 0x64, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x43, 0x0a, + 0x19, 0x41, 0x64, 0x64, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x2b, 0x0a, 0x17, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, + 0x46, 0x0a, 0x1c, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x45, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x51, + 0x0a, 0x17, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x74, 0x6d, + 0x70, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x74, 0x6d, + 0x70, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x74, 0x6d, 0x70, 0x73, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x74, 0x6d, 0x70, 0x73, 0x55, 0x72, + 0x6c, 0x22, 0x1c, 0x0a, 0x1a, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, + 0x27, 0x0a, 0x0f, 0x46, 0x61, 0x74, 0x61, 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0x3e, 0x0a, 0x0b, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x50, 0x49, 0x12, 0x2f, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x75, + 0x6e, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x1a, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x76, 0x65, + 0x6c, 0x6f, 0x70, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x2e, + 0x6e, 0x65, 0x74, 0x66, 0x6c, 0x75, 0x78, 0x2e, 0x69, 0x6f, 0x2f, 0x72, 0x6f, 0x62, 0x2f, 0x6f, + 0x63, 0x74, 0x6f, 0x70, 0x6c, 0x65, 0x78, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_api_proto_rawDescOnce sync.Once + file_proto_api_proto_rawDescData = file_proto_api_proto_rawDesc +) + +func file_proto_api_proto_rawDescGZIP() []byte { + file_proto_api_proto_rawDescOnce.Do(func() { + file_proto_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_api_proto_rawDescData) + }) + return file_proto_api_proto_rawDescData +} + +var file_proto_api_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_proto_api_proto_goTypes = []interface{}{ + (*Envelope)(nil), // 0: api.Envelope + (*Command)(nil), // 1: api.Command + (*AddDestinationCommand)(nil), // 2: api.AddDestinationCommand + (*RemoveDestinationCommand)(nil), // 3: api.RemoveDestinationCommand + (*StartDestinationCommand)(nil), // 4: api.StartDestinationCommand + (*StopDestinationCommand)(nil), // 5: api.StopDestinationCommand + (*CloseOtherInstancesCommand)(nil), // 6: api.CloseOtherInstancesCommand + (*QuitCommand)(nil), // 7: api.QuitCommand + (*Event)(nil), // 8: api.Event + (*AppStateChangedEvent)(nil), // 9: api.AppStateChangedEvent + (*DestinationStreamExitedEvent)(nil), // 10: api.DestinationStreamExitedEvent + (*DestinationAddedEvent)(nil), // 11: api.DestinationAddedEvent + (*AddDestinationFailedEvent)(nil), // 12: api.AddDestinationFailedEvent + (*DestinationRemovedEvent)(nil), // 13: api.DestinationRemovedEvent + (*RemoveDestinationFailedEvent)(nil), // 14: api.RemoveDestinationFailedEvent + (*StartDestinationFailedEvent)(nil), // 15: api.StartDestinationFailedEvent + (*MediaServerStartedEvent)(nil), // 16: api.MediaServerStartedEvent + (*OtherInstanceDetectedEvent)(nil), // 17: api.OtherInstanceDetectedEvent + (*FatalErrorEvent)(nil), // 18: api.FatalErrorEvent +} +var file_proto_api_proto_depIdxs = []int32{ + 1, // 0: api.Envelope.command:type_name -> api.Command + 8, // 1: api.Envelope.event:type_name -> api.Event + 2, // 2: api.Command.add_destinaion:type_name -> api.AddDestinationCommand + 3, // 3: api.Command.remove_destination:type_name -> api.RemoveDestinationCommand + 4, // 4: api.Command.start_destination:type_name -> api.StartDestinationCommand + 5, // 5: api.Command.stop_destination:type_name -> api.StopDestinationCommand + 6, // 6: api.Command.close_other_instances:type_name -> api.CloseOtherInstancesCommand + 7, // 7: api.Command.quit:type_name -> api.QuitCommand + 9, // 8: api.Event.app_state_changed:type_name -> api.AppStateChangedEvent + 10, // 9: api.Event.destination_stream_exited:type_name -> api.DestinationStreamExitedEvent + 11, // 10: api.Event.destination_added:type_name -> api.DestinationAddedEvent + 12, // 11: api.Event.add_destination_failed:type_name -> api.AddDestinationFailedEvent + 13, // 12: api.Event.destination_removed:type_name -> api.DestinationRemovedEvent + 14, // 13: api.Event.remove_destination_failed:type_name -> api.RemoveDestinationFailedEvent + 15, // 14: api.Event.start_destination_failed:type_name -> api.StartDestinationFailedEvent + 16, // 15: api.Event.media_server_started:type_name -> api.MediaServerStartedEvent + 17, // 16: api.Event.other_instance_detected:type_name -> api.OtherInstanceDetectedEvent + 18, // 17: api.Event.fatal_error:type_name -> api.FatalErrorEvent + 0, // 18: api.InternalAPI.Communicate:input_type -> api.Envelope + 0, // 19: api.InternalAPI.Communicate:output_type -> api.Envelope + 19, // [19:20] is the sub-list for method output_type + 18, // [18:19] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name +} + +func init() { file_proto_api_proto_init() } +func file_proto_api_proto_init() { + if File_proto_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Envelope); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddDestinationCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveDestinationCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartDestinationCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StopDestinationCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CloseOtherInstancesCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QuitCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Event); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppStateChangedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DestinationStreamExitedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DestinationAddedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddDestinationFailedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DestinationRemovedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveDestinationFailedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartDestinationFailedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MediaServerStartedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OtherInstanceDetectedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_api_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FatalErrorEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_proto_api_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*Envelope_Command)(nil), + (*Envelope_Event)(nil), + } + file_proto_api_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*Command_AddDestinaion)(nil), + (*Command_RemoveDestination)(nil), + (*Command_StartDestination)(nil), + (*Command_StopDestination)(nil), + (*Command_CloseOtherInstances)(nil), + (*Command_Quit)(nil), + } + file_proto_api_proto_msgTypes[8].OneofWrappers = []interface{}{ + (*Event_AppStateChanged)(nil), + (*Event_DestinationStreamExited)(nil), + (*Event_DestinationAdded)(nil), + (*Event_AddDestinationFailed)(nil), + (*Event_DestinationRemoved)(nil), + (*Event_RemoveDestinationFailed)(nil), + (*Event_StartDestinationFailed)(nil), + (*Event_MediaServerStarted)(nil), + (*Event_OtherInstanceDetected)(nil), + (*Event_FatalError)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_api_proto_rawDesc, + NumEnums: 0, + NumMessages: 19, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_api_proto_goTypes, + DependencyIndexes: file_proto_api_proto_depIdxs, + MessageInfos: file_proto_api_proto_msgTypes, + }.Build() + File_proto_api_proto = out.File + file_proto_api_proto_rawDesc = nil + file_proto_api_proto_goTypes = nil + file_proto_api_proto_depIdxs = nil +} diff --git a/internal/generated/grpc/proto/api_grpc.pb.go b/internal/generated/grpc/proto/api_grpc.pb.go new file mode 100644 index 0000000..431ebaf --- /dev/null +++ b/internal/generated/grpc/proto/api_grpc.pb.go @@ -0,0 +1,135 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.6 +// source: proto/api.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// InternalAPIClient is the client API for InternalAPI service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type InternalAPIClient interface { + Communicate(ctx context.Context, opts ...grpc.CallOption) (InternalAPI_CommunicateClient, error) +} + +type internalAPIClient struct { + cc grpc.ClientConnInterface +} + +func NewInternalAPIClient(cc grpc.ClientConnInterface) InternalAPIClient { + return &internalAPIClient{cc} +} + +func (c *internalAPIClient) Communicate(ctx context.Context, opts ...grpc.CallOption) (InternalAPI_CommunicateClient, error) { + stream, err := c.cc.NewStream(ctx, &InternalAPI_ServiceDesc.Streams[0], "/api.InternalAPI/Communicate", opts...) + if err != nil { + return nil, err + } + x := &internalAPICommunicateClient{stream} + return x, nil +} + +type InternalAPI_CommunicateClient interface { + Send(*Envelope) error + Recv() (*Envelope, error) + grpc.ClientStream +} + +type internalAPICommunicateClient struct { + grpc.ClientStream +} + +func (x *internalAPICommunicateClient) Send(m *Envelope) error { + return x.ClientStream.SendMsg(m) +} + +func (x *internalAPICommunicateClient) Recv() (*Envelope, error) { + m := new(Envelope) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// InternalAPIServer is the server API for InternalAPI service. +// All implementations should embed UnimplementedInternalAPIServer +// for forward compatibility +type InternalAPIServer interface { + Communicate(InternalAPI_CommunicateServer) error +} + +// UnimplementedInternalAPIServer should be embedded to have forward compatible implementations. +type UnimplementedInternalAPIServer struct { +} + +func (UnimplementedInternalAPIServer) Communicate(InternalAPI_CommunicateServer) error { + return status.Errorf(codes.Unimplemented, "method Communicate not implemented") +} + +// UnsafeInternalAPIServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InternalAPIServer will +// result in compilation errors. +type UnsafeInternalAPIServer interface { + mustEmbedUnimplementedInternalAPIServer() +} + +func RegisterInternalAPIServer(s grpc.ServiceRegistrar, srv InternalAPIServer) { + s.RegisterService(&InternalAPI_ServiceDesc, srv) +} + +func _InternalAPI_Communicate_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(InternalAPIServer).Communicate(&internalAPICommunicateServer{stream}) +} + +type InternalAPI_CommunicateServer interface { + Send(*Envelope) error + Recv() (*Envelope, error) + grpc.ServerStream +} + +type internalAPICommunicateServer struct { + grpc.ServerStream +} + +func (x *internalAPICommunicateServer) Send(m *Envelope) error { + return x.ServerStream.SendMsg(m) +} + +func (x *internalAPICommunicateServer) Recv() (*Envelope, error) { + m := new(Envelope) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// InternalAPI_ServiceDesc is the grpc.ServiceDesc for InternalAPI service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var InternalAPI_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "api.InternalAPI", + HandlerType: (*InternalAPIServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "Communicate", + Handler: _InternalAPI_Communicate_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "proto/api.proto", +} diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 0000000..7311bd2 --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,7 @@ +package server + +import pb "git.netflux.io/rob/octoplex/internal/generated/grpc/proto" + +type Server struct { + pb.UnimplementedInternalAPIServer +} diff --git a/mise/config.toml b/mise/config.toml index 38f1a91..999624d 100644 --- a/mise/config.toml +++ b/mise/config.toml @@ -40,3 +40,9 @@ description = "Generate mocks" dir = "{{cwd}}" run = "go tool mockery" alias = "m" + +[tasks.generate_proto] +description = "Generate gRPC files from proto" +dir = "{{cwd}}" +run = "protoc --go_out=./generated/grpc --go-grpc_out=./generated/grpc proto/*.proto" +alias = "p" diff --git a/proto/api.proto b/proto/api.proto new file mode 100644 index 0000000..190ea64 --- /dev/null +++ b/proto/api.proto @@ -0,0 +1,105 @@ +syntax = "proto3"; + +package api; + +option go_package = "git.netflux.io/rob/octoplex/internal/generated/grpc/proto"; + +service InternalAPI { + rpc Communicate(stream Envelope) returns (stream Envelope); +} + +message Envelope { + oneof payload { + Command command = 1; + Event event = 2; + } +} + +message Command { + oneof command_type { + AddDestinationCommand add_destinaion = 1; + RemoveDestinationCommand remove_destination = 2; + StartDestinationCommand start_destination = 3; + StopDestinationCommand stop_destination = 4; + CloseOtherInstancesCommand close_other_instances = 5; + QuitCommand quit = 6; + } +} + +message AddDestinationCommand { + string name = 1; + string url = 2; +} + +message RemoveDestinationCommand { + string url= 1; +} + +message StartDestinationCommand { + string url = 1; +} + +message StopDestinationCommand { + string url = 1; +} + +message CloseOtherInstancesCommand {} + +message QuitCommand {} + +message Event { + oneof event_type { + AppStateChangedEvent app_state_changed = 1; + DestinationStreamExitedEvent destination_stream_exited = 2; + DestinationAddedEvent destination_added = 3; + AddDestinationFailedEvent add_destination_failed = 4; + DestinationRemovedEvent destination_removed = 5; + RemoveDestinationFailedEvent remove_destination_failed = 6; + StartDestinationFailedEvent start_destination_failed = 7; + MediaServerStartedEvent media_server_started = 8; + OtherInstanceDetectedEvent other_instance_detected = 9; + FatalErrorEvent fatal_error = 10; + } +} + +// TODO: complete +message AppStateChangedEvent {} + +message DestinationStreamExitedEvent { + string name = 1; + string error = 2; +} + +message DestinationAddedEvent { + string url = 1; +} + +message AddDestinationFailedEvent { + string url = 1; + string error = 2; +} + +message DestinationRemovedEvent { + string url = 1; +} + +message RemoveDestinationFailedEvent { + string url = 1; + string error = 2; +} + +message StartDestinationFailedEvent { + string url = 1; + string error = 2; +} + +message MediaServerStartedEvent { + string rtmp_url = 1; + string rtmps_url = 2; +} + +message OtherInstanceDetectedEvent {} + +message FatalErrorEvent { + string error = 1; +}