diff --git a/go.mod b/go.mod index 63e9b8b3..a294f32d 100644 --- a/go.mod +++ b/go.mod @@ -120,6 +120,7 @@ require ( github.com/refraction-networking/utls v1.6.7 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.10.0 // indirect github.com/tetratelabs/wazero v1.8.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect diff --git a/go.sum b/go.sum index d7210c48..90805132 100644 --- a/go.sum +++ b/go.sum @@ -338,8 +338,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -348,8 +349,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= diff --git a/internal/model/member.go b/internal/model/member.go index 73d11e77..27888640 100644 --- a/internal/model/member.go +++ b/internal/model/member.go @@ -54,10 +54,13 @@ const ( PermissionSetCurrentMovie PermissionSetCurrentStatus PermissionSendChatMessage + PermissionWebRTC AllPermissions RoomMemberPermission = math.MaxUint32 NoPermission RoomMemberPermission = 0 - DefaultPermissions RoomMemberPermission = PermissionGetMovieList | PermissionSendChatMessage + DefaultPermissions RoomMemberPermission = PermissionGetMovieList | + PermissionSendChatMessage | + PermissionWebRTC ) func (p RoomMemberPermission) Has(permission RoomMemberPermission) bool { diff --git a/internal/op/client.go b/internal/op/client.go index 91f65274..188431d9 100644 --- a/internal/op/client.go +++ b/internal/op/client.go @@ -6,24 +6,28 @@ import ( "sync/atomic" "time" + "github.com/google/uuid" "github.com/gorilla/websocket" "github.com/synctv-org/synctv/internal/model" pb "github.com/synctv-org/synctv/proto/message" ) type Client struct { - u *User - r *Room - h *Hub - c chan Message - conn *websocket.Conn - wg sync.WaitGroup - timeOut time.Duration - closed uint32 + u *User + r *Room + h *Hub + c chan Message + conn *websocket.Conn + connID string + wg sync.WaitGroup + timeOut time.Duration + closed uint32 + rtcJoined atomic.Bool } func newClient(user *User, room *Room, h *Hub, conn *websocket.Conn) *Client { return &Client{ + connID: uuid.New().String(), r: room, u: user, h: h, @@ -33,6 +37,18 @@ func newClient(user *User, room *Room, h *Hub, conn *websocket.Conn) *Client { } } +func (c *Client) ConnID() string { + return c.connID +} + +func (c *Client) RTCJoined() bool { + return c.rtcJoined.Load() +} + +func (c *Client) SetRTCJoined(joined bool) { + c.rtcJoined.Store(joined) +} + func (c *Client) User() *User { return c.u } @@ -115,5 +131,5 @@ func (c *Client) SetStatus(playing bool, seek float64, rate float64, timeDiff fl PlaybackRate: status.PlaybackRate, }, }, - }, WithIgnoreClient(c)) + }, WithIgnoreConnID(c.ConnID())) } diff --git a/internal/op/hub.go b/internal/op/hub.go index 106855a7..4c4b8676 100644 --- a/internal/op/hub.go +++ b/internal/op/hub.go @@ -14,7 +14,7 @@ import ( ) type clients struct { - m map[*Client]struct{} + m map[string]*Client lock sync.RWMutex } @@ -30,21 +30,28 @@ type Hub struct { type broadcastMessage struct { data Message - ignoreClient []*Client - ignoreID []string + ignoreConnID []string + ignoreUserID []string + rtcJoined bool } type BroadcastConf func(*broadcastMessage) -func WithIgnoreClient(cli ...*Client) BroadcastConf { +func WithRTCJoined() BroadcastConf { return func(bm *broadcastMessage) { - bm.ignoreClient = cli + bm.rtcJoined = true + } +} + +func WithIgnoreConnID(connID ...string) BroadcastConf { + return func(bm *broadcastMessage) { + bm.ignoreConnID = connID } } func WithIgnoreID(id ...string) BroadcastConf { return func(bm *broadcastMessage) { - bm.ignoreID = id + bm.ignoreUserID = id } } @@ -72,9 +79,12 @@ func (h *Hub) serve() { h.clients.Range(func(id string, clients *clients) bool { clients.lock.RLock() defer clients.lock.RUnlock() - for c := range clients.m { - if utils.In(message.ignoreID, c.u.ID) || - utils.In(message.ignoreClient, c) { + for _, c := range clients.m { + if utils.In(message.ignoreUserID, c.u.ID) || + utils.In(message.ignoreConnID, c.ConnID()) { + continue + } + if message.rtcJoined && !c.RTCJoined() { continue } if err := c.Send(message.data); err != nil { @@ -145,8 +155,8 @@ func (h *Hub) Close() error { h.clients.CompareAndDelete(id, clients) clients.lock.Lock() defer clients.lock.Unlock() - for c := range clients.m { - delete(clients.m, c) + for id, c := range clients.m { + delete(clients.m, id) c.Close() } return true @@ -191,11 +201,11 @@ func (h *Hub) RegClient(cli *Client) error { return h.RegClient(cli) } if c.m == nil { - c.m = make(map[*Client]struct{}) - } else if _, ok := c.m[cli]; ok { + c.m = make(map[string]*Client) + } else if _, ok := c.m[cli.ConnID()]; ok { return errors.New("client already exists") } - c.m[cli] = struct{}{} + c.m[cli.ConnID()] = cli return nil } @@ -212,10 +222,10 @@ func (h *Hub) UnRegClient(cli *Client) error { } c.lock.Lock() defer c.lock.Unlock() - if _, ok := c.m[cli]; !ok { + if _, ok := c.m[cli.ConnID()]; !ok { return errors.New("client not found") } - delete(c.m, cli) + delete(c.m, cli.ConnID()) if len(c.m) == 0 { h.clients.CompareAndDelete(cli.u.ID, c) } @@ -236,7 +246,7 @@ func (h *Hub) SendToUser(userID string, data Message) (err error) { } cli.lock.RLock() defer cli.lock.RUnlock() - for c := range cli.m { + for _, c := range cli.m { if err = c.Send(data); err != nil { c.Close() } @@ -244,6 +254,23 @@ func (h *Hub) SendToUser(userID string, data Message) (err error) { return } +func (h *Hub) SendToConnID(userID, connID string, data Message) error { + cli, ok := h.GetClientByConnID(userID, connID) + if !ok { + return nil + } + return cli.Send(data) +} + +func (h *Hub) GetClientByConnID(userID, connID string) (*Client, bool) { + c, ok := h.clients.Load(userID) + if !ok { + return nil, false + } + client, ok := c.m[connID] + return client, ok +} + func (h *Hub) IsOnline(userID string) bool { _, ok := h.clients.Load(userID) return ok @@ -272,7 +299,7 @@ func (h *Hub) KickUser(userID string) error { } cli.lock.RLock() defer cli.lock.RUnlock() - for c := range cli.m { + for _, c := range cli.m { c.Close() } return nil diff --git a/internal/op/room.go b/internal/op/room.go index f3124f2b..f6d70491 100644 --- a/internal/op/room.go +++ b/internal/op/room.go @@ -72,6 +72,13 @@ func (r *Room) SendToUserWithID(userID string, data Message) error { return r.lazyInitHub().SendToUser(userID, data) } +func (r *Room) SendToConnID(userID, connID string, data Message) error { + if r.HubIsNotInited() { + return nil + } + return r.lazyInitHub().SendToConnID(userID, connID, data) +} + func (r *Room) GetChannel(channelName string) (*rtmps.Channel, error) { return r.movies.GetChannel(channelName) } diff --git a/internal/op/user.go b/internal/op/user.go index d2119302..4436767b 100644 --- a/internal/op/user.go +++ b/internal/op/user.go @@ -225,6 +225,10 @@ func (u *User) IsRoomCreator(room *Room) bool { return room.IsCreator(u.ID) } +func (u *User) HasRoomWebRTCPermission(room *Room) bool { + return u.HasRoomPermission(room, model.PermissionWebRTC) +} + func (u *User) DeleteRoom(room *RoomEntry) error { if !u.HasRoomAdminPermission(room.Value(), model.PermissionDeleteRoom) { return model.ErrNoPermission diff --git a/proto/message/message.pb.go b/proto/message/message.pb.go index 6f381cb1..2f697e75 100644 --- a/proto/message/message.pb.go +++ b/proto/message/message.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.2 +// protoc-gen-go v1.36.0 +// protoc v5.29.1 // source: proto/message/message.proto package pb @@ -23,17 +23,22 @@ const ( type MessageType int32 const ( - MessageType_UNKNOWN MessageType = 0 - MessageType_ERROR MessageType = 1 - MessageType_CHAT MessageType = 2 - MessageType_STATUS MessageType = 3 - MessageType_CHECK_STATUS MessageType = 4 - MessageType_EXPIRED MessageType = 5 - MessageType_CURRENT MessageType = 6 - MessageType_MOVIES MessageType = 7 - MessageType_VIEWER_COUNT MessageType = 8 - MessageType_SYNC MessageType = 9 - MessageType_MY_STATUS MessageType = 10 + MessageType_UNKNOWN MessageType = 0 + MessageType_ERROR MessageType = 1 + MessageType_CHAT MessageType = 2 + MessageType_STATUS MessageType = 3 + MessageType_CHECK_STATUS MessageType = 4 + MessageType_EXPIRED MessageType = 5 + MessageType_CURRENT MessageType = 6 + MessageType_MOVIES MessageType = 7 + MessageType_VIEWER_COUNT MessageType = 8 + MessageType_SYNC MessageType = 9 + MessageType_MY_STATUS MessageType = 10 + MessageType_WEBRTC_OFFER MessageType = 11 + MessageType_WEBRTC_ANSWER MessageType = 12 + MessageType_WEBRTC_ICE_CANDIDATE MessageType = 13 + MessageType_WEBRTC_JOIN MessageType = 14 + MessageType_WEBRTC_LEAVE MessageType = 15 ) // Enum value maps for MessageType. @@ -50,19 +55,29 @@ var ( 8: "VIEWER_COUNT", 9: "SYNC", 10: "MY_STATUS", + 11: "WEBRTC_OFFER", + 12: "WEBRTC_ANSWER", + 13: "WEBRTC_ICE_CANDIDATE", + 14: "WEBRTC_JOIN", + 15: "WEBRTC_LEAVE", } MessageType_value = map[string]int32{ - "UNKNOWN": 0, - "ERROR": 1, - "CHAT": 2, - "STATUS": 3, - "CHECK_STATUS": 4, - "EXPIRED": 5, - "CURRENT": 6, - "MOVIES": 7, - "VIEWER_COUNT": 8, - "SYNC": 9, - "MY_STATUS": 10, + "UNKNOWN": 0, + "ERROR": 1, + "CHAT": 2, + "STATUS": 3, + "CHECK_STATUS": 4, + "EXPIRED": 5, + "CURRENT": 6, + "MOVIES": 7, + "VIEWER_COUNT": 8, + "SYNC": 9, + "MY_STATUS": 10, + "WEBRTC_OFFER": 11, + "WEBRTC_ANSWER": 12, + "WEBRTC_ICE_CANDIDATE": 13, + "WEBRTC_JOIN": 14, + "WEBRTC_LEAVE": 15, } ) @@ -94,12 +109,11 @@ func (MessageType) EnumDescriptor() ([]byte, []int) { } type Sender struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` unknownFields protoimpl.UnknownFields - - UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Sender) Reset() { @@ -147,13 +161,12 @@ func (x *Sender) GetUsername() string { } type Status struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + IsPlaying bool `protobuf:"varint,1,opt,name=is_playing,json=isPlaying,proto3" json:"is_playing,omitempty"` + CurrentTime float64 `protobuf:"fixed64,2,opt,name=current_time,json=currentTime,proto3" json:"current_time,omitempty"` + PlaybackRate float64 `protobuf:"fixed64,3,opt,name=playback_rate,json=playbackRate,proto3" json:"playback_rate,omitempty"` unknownFields protoimpl.UnknownFields - - IsPlaying bool `protobuf:"varint,1,opt,name=is_playing,json=isPlaying,proto3" json:"is_playing,omitempty"` - CurrentTime float64 `protobuf:"fixed64,2,opt,name=current_time,json=currentTime,proto3" json:"current_time,omitempty"` - PlaybackRate float64 `protobuf:"fixed64,3,opt,name=playback_rate,json=playbackRate,proto3" json:"playback_rate,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Status) Reset() { @@ -207,27 +220,87 @@ func (x *Status) GetPlaybackRate() float64 { return 0 } -type Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache +type WebRTCData struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` + From string `protobuf:"bytes,3,opt,name=from,proto3" json:"from,omitempty"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WebRTCData) Reset() { + *x = WebRTCData{} + mi := &file_proto_message_message_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WebRTCData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WebRTCData) ProtoMessage() {} + +func (x *WebRTCData) ProtoReflect() protoreflect.Message { + mi := &file_proto_message_message_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WebRTCData.ProtoReflect.Descriptor instead. +func (*WebRTCData) Descriptor() ([]byte, []int) { + return file_proto_message_message_proto_rawDescGZIP(), []int{2} +} + +func (x *WebRTCData) GetData() string { + if x != nil { + return x.Data + } + return "" +} + +func (x *WebRTCData) GetTo() string { + if x != nil { + return x.To + } + return "" +} - Type MessageType `protobuf:"varint,1,opt,name=type,proto3,enum=proto.MessageType" json:"type,omitempty"` - Timestamp int64 `protobuf:"fixed64,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Sender *Sender `protobuf:"bytes,3,opt,name=sender,proto3,oneof" json:"sender,omitempty"` - // Types that are assignable to Payload: +func (x *WebRTCData) GetFrom() string { + if x != nil { + return x.From + } + return "" +} + +type Message struct { + state protoimpl.MessageState `protogen:"open.v1"` + Type MessageType `protobuf:"varint,1,opt,name=type,proto3,enum=proto.MessageType" json:"type,omitempty"` + Timestamp int64 `protobuf:"fixed64,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Sender *Sender `protobuf:"bytes,3,opt,name=sender,proto3,oneof" json:"sender,omitempty"` + // Types that are valid to be assigned to Payload: // // *Message_ErrorMessage // *Message_ChatContent // *Message_PlaybackStatus // *Message_ExpirationId // *Message_ViewerCount - Payload isMessage_Payload `protobuf_oneof:"payload"` + // *Message_WebrtcData + Payload isMessage_Payload `protobuf_oneof:"payload"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Message) Reset() { *x = Message{} - mi := &file_proto_message_message_proto_msgTypes[2] + mi := &file_proto_message_message_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -239,7 +312,7 @@ func (x *Message) String() string { func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { - mi := &file_proto_message_message_proto_msgTypes[2] + mi := &file_proto_message_message_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -252,7 +325,7 @@ func (x *Message) ProtoReflect() protoreflect.Message { // Deprecated: Use Message.ProtoReflect.Descriptor instead. func (*Message) Descriptor() ([]byte, []int) { - return file_proto_message_message_proto_rawDescGZIP(), []int{2} + return file_proto_message_message_proto_rawDescGZIP(), []int{3} } func (x *Message) GetType() MessageType { @@ -276,48 +349,67 @@ func (x *Message) GetSender() *Sender { return nil } -func (m *Message) GetPayload() isMessage_Payload { - if m != nil { - return m.Payload +func (x *Message) GetPayload() isMessage_Payload { + if x != nil { + return x.Payload } return nil } func (x *Message) GetErrorMessage() string { - if x, ok := x.GetPayload().(*Message_ErrorMessage); ok { - return x.ErrorMessage + if x != nil { + if x, ok := x.Payload.(*Message_ErrorMessage); ok { + return x.ErrorMessage + } } return "" } func (x *Message) GetChatContent() string { - if x, ok := x.GetPayload().(*Message_ChatContent); ok { - return x.ChatContent + if x != nil { + if x, ok := x.Payload.(*Message_ChatContent); ok { + return x.ChatContent + } } return "" } func (x *Message) GetPlaybackStatus() *Status { - if x, ok := x.GetPayload().(*Message_PlaybackStatus); ok { - return x.PlaybackStatus + if x != nil { + if x, ok := x.Payload.(*Message_PlaybackStatus); ok { + return x.PlaybackStatus + } } return nil } func (x *Message) GetExpirationId() uint64 { - if x, ok := x.GetPayload().(*Message_ExpirationId); ok { - return x.ExpirationId + if x != nil { + if x, ok := x.Payload.(*Message_ExpirationId); ok { + return x.ExpirationId + } } return 0 } func (x *Message) GetViewerCount() int64 { - if x, ok := x.GetPayload().(*Message_ViewerCount); ok { - return x.ViewerCount + if x != nil { + if x, ok := x.Payload.(*Message_ViewerCount); ok { + return x.ViewerCount + } } return 0 } +func (x *Message) GetWebrtcData() *WebRTCData { + if x != nil { + if x, ok := x.Payload.(*Message_WebrtcData); ok { + return x.WebrtcData + } + } + return nil +} + type isMessage_Payload interface { isMessage_Payload() } @@ -342,6 +434,10 @@ type Message_ViewerCount struct { ViewerCount int64 `protobuf:"varint,8,opt,name=viewer_count,json=viewerCount,proto3,oneof"` } +type Message_WebrtcData struct { + WebrtcData *WebRTCData `protobuf:"bytes,9,opt,name=webrtc_data,json=webrtcData,proto3,oneof"` +} + func (*Message_ErrorMessage) isMessage_Payload() {} func (*Message_ChatContent) isMessage_Payload() {} @@ -352,6 +448,8 @@ func (*Message_ExpirationId) isMessage_Payload() {} func (*Message_ViewerCount) isMessage_Payload() {} +func (*Message_WebrtcData) isMessage_Payload() {} + var File_proto_message_message_proto protoreflect.FileDescriptor var file_proto_message_message_proto_rawDesc = []byte{ @@ -368,40 +466,54 @@ var file_proto_message_message_proto_rawDesc = []byte{ 0x28, 0x01, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, - 0x52, 0x61, 0x74, 0x65, 0x22, 0xe3, 0x02, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x26, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x10, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x48, 0x01, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x88, - 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x63, 0x68, 0x61, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, - 0x0a, 0x0f, 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x0e, 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, - 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x06, 0x48, - 0x00, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x23, 0x0a, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0b, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, - 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2a, 0x9e, 0x01, 0x0a, 0x0b, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x48, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x48, 0x45, 0x43, - 0x4b, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, - 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x55, 0x52, 0x52, 0x45, - 0x4e, 0x54, 0x10, 0x06, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x4f, 0x56, 0x49, 0x45, 0x53, 0x10, 0x07, - 0x12, 0x10, 0x0a, 0x0c, 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, - 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, - 0x4d, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x0a, 0x42, 0x06, 0x5a, 0x04, 0x2e, - 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x61, 0x74, 0x65, 0x22, 0x44, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x52, 0x54, 0x43, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0x99, 0x03, 0x0a, 0x07, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x10, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2a, 0x0a, 0x06, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x48, 0x01, 0x52, 0x06, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x23, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0f, 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x0e, + 0x70, 0x6c, 0x61, 0x79, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, + 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x06, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0b, 0x76, + 0x69, 0x65, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x0b, 0x77, 0x65, + 0x62, 0x72, 0x74, 0x63, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x57, 0x65, 0x62, 0x52, 0x54, 0x43, 0x44, 0x61, + 0x74, 0x61, 0x48, 0x00, 0x52, 0x0a, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x44, 0x61, 0x74, 0x61, + 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2a, 0x80, 0x02, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x08, + 0x0a, 0x04, 0x43, 0x48, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x50, 0x49, 0x52, 0x45, + 0x44, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x55, 0x52, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x06, + 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x4f, 0x56, 0x49, 0x45, 0x53, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, + 0x56, 0x49, 0x45, 0x57, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x08, 0x12, 0x08, + 0x0a, 0x04, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x09, 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x59, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x45, 0x42, 0x52, 0x54, + 0x43, 0x5f, 0x4f, 0x46, 0x46, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x11, 0x0a, 0x0d, 0x57, 0x45, 0x42, + 0x52, 0x54, 0x43, 0x5f, 0x41, 0x4e, 0x53, 0x57, 0x45, 0x52, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, + 0x57, 0x45, 0x42, 0x52, 0x54, 0x43, 0x5f, 0x49, 0x43, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x44, 0x49, + 0x44, 0x41, 0x54, 0x45, 0x10, 0x0d, 0x12, 0x0f, 0x0a, 0x0b, 0x57, 0x45, 0x42, 0x52, 0x54, 0x43, + 0x5f, 0x4a, 0x4f, 0x49, 0x4e, 0x10, 0x0e, 0x12, 0x10, 0x0a, 0x0c, 0x57, 0x45, 0x42, 0x52, 0x54, + 0x43, 0x5f, 0x4c, 0x45, 0x41, 0x56, 0x45, 0x10, 0x0f, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x3b, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -417,22 +529,24 @@ func file_proto_message_message_proto_rawDescGZIP() []byte { } var file_proto_message_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_message_message_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_proto_message_message_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_proto_message_message_proto_goTypes = []any{ - (MessageType)(0), // 0: proto.MessageType - (*Sender)(nil), // 1: proto.Sender - (*Status)(nil), // 2: proto.Status - (*Message)(nil), // 3: proto.Message + (MessageType)(0), // 0: proto.MessageType + (*Sender)(nil), // 1: proto.Sender + (*Status)(nil), // 2: proto.Status + (*WebRTCData)(nil), // 3: proto.WebRTCData + (*Message)(nil), // 4: proto.Message } var file_proto_message_message_proto_depIdxs = []int32{ 0, // 0: proto.Message.type:type_name -> proto.MessageType 1, // 1: proto.Message.sender:type_name -> proto.Sender 2, // 2: proto.Message.playback_status:type_name -> proto.Status - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 3, // 3: proto.Message.webrtc_data:type_name -> proto.WebRTCData + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_proto_message_message_proto_init() } @@ -440,12 +554,13 @@ func file_proto_message_message_proto_init() { if File_proto_message_message_proto != nil { return } - file_proto_message_message_proto_msgTypes[2].OneofWrappers = []any{ + file_proto_message_message_proto_msgTypes[3].OneofWrappers = []any{ (*Message_ErrorMessage)(nil), (*Message_ChatContent)(nil), (*Message_PlaybackStatus)(nil), (*Message_ExpirationId)(nil), (*Message_ViewerCount)(nil), + (*Message_WebrtcData)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -453,7 +568,7 @@ func file_proto_message_message_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_message_message_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/message/message.proto b/proto/message/message.proto index 3ec36dec..e11024f6 100644 --- a/proto/message/message.proto +++ b/proto/message/message.proto @@ -15,6 +15,11 @@ enum MessageType { VIEWER_COUNT = 8; SYNC = 9; MY_STATUS = 10; + WEBRTC_OFFER = 11; + WEBRTC_ANSWER = 12; + WEBRTC_ICE_CANDIDATE = 13; + WEBRTC_JOIN = 14; + WEBRTC_LEAVE = 15; } message Sender { @@ -28,6 +33,12 @@ message Status { double playback_rate = 3; } +message WebRTCData { + string data = 1; + string to = 2; + string from = 3; +} + message Message { MessageType type = 1; sfixed64 timestamp = 2; @@ -39,5 +50,6 @@ message Message { Status playback_status = 6; fixed64 expiration_id = 7; int64 viewer_count = 8; + WebRTCData webrtc_data = 9; } } diff --git a/proto/provider/plugin.pb.go b/proto/provider/plugin.pb.go index 81c9e9f0..9f549afd 100644 --- a/proto/provider/plugin.pb.go +++ b/proto/provider/plugin.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.2 +// protoc-gen-go v1.36.0 +// protoc v5.29.1 // source: proto/provider/plugin.proto package providerpb @@ -21,13 +21,12 @@ const ( ) type InitReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + ClientSecret string `protobuf:"bytes,2,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"` + RedirectUrl string `protobuf:"bytes,3,opt,name=redirect_url,json=redirectUrl,proto3" json:"redirect_url,omitempty"` unknownFields protoimpl.UnknownFields - - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - ClientSecret string `protobuf:"bytes,2,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"` - RedirectUrl string `protobuf:"bytes,3,opt,name=redirect_url,json=redirectUrl,proto3" json:"redirect_url,omitempty"` + sizeCache protoimpl.SizeCache } func (x *InitReq) Reset() { @@ -82,11 +81,10 @@ func (x *InitReq) GetRedirectUrl() string { } type GetTokenReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` unknownFields protoimpl.UnknownFields - - Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetTokenReq) Reset() { @@ -127,11 +125,10 @@ func (x *GetTokenReq) GetCode() string { } type RefreshTokenReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` unknownFields protoimpl.UnknownFields - - RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RefreshTokenReq) Reset() { @@ -172,11 +169,10 @@ func (x *RefreshTokenReq) GetRefreshToken() string { } type ProviderResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ProviderResp) Reset() { @@ -217,11 +213,10 @@ func (x *ProviderResp) GetName() string { } type NewAuthURLReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` unknownFields protoimpl.UnknownFields - - State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + sizeCache protoimpl.SizeCache } func (x *NewAuthURLReq) Reset() { @@ -262,11 +257,10 @@ func (x *NewAuthURLReq) GetState() string { } type NewAuthURLResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` unknownFields protoimpl.UnknownFields - - Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + sizeCache protoimpl.SizeCache } func (x *NewAuthURLResp) Reset() { @@ -307,11 +301,10 @@ func (x *NewAuthURLResp) GetUrl() string { } type GetUserInfoReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` unknownFields protoimpl.UnknownFields - - Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetUserInfoReq) Reset() { @@ -352,12 +345,11 @@ func (x *GetUserInfoReq) GetCode() string { } type GetUserInfoResp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` - ProviderUserId string `protobuf:"bytes,2,opt,name=provider_user_id,json=providerUserId,proto3" json:"provider_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + ProviderUserId string `protobuf:"bytes,2,opt,name=provider_user_id,json=providerUserId,proto3" json:"provider_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetUserInfoResp) Reset() { @@ -405,9 +397,9 @@ func (x *GetUserInfoResp) GetProviderUserId() string { } type Enpty struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Enpty) Reset() { diff --git a/proto/provider/plugin_grpc.pb.go b/proto/provider/plugin_grpc.pb.go index a893324a..90f03b9f 100644 --- a/proto/provider/plugin_grpc.pb.go +++ b/proto/provider/plugin_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.28.2 +// - protoc v5.29.1 // source: proto/provider/plugin.proto package providerpb diff --git a/server/handlers/websocket.go b/server/handlers/websocket.go index 2e16bc6f..81ac04b2 100644 --- a/server/handlers/websocket.go +++ b/server/handlers/websocket.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io" + "strings" "time" "github.com/gin-gonic/gin" @@ -174,11 +175,145 @@ func handleElementMsg(cli *op.Client, msg *pb.Message) error { return handleExpiredMessage(cli, msg.GetExpirationId()) case pb.MessageType_CHECK_STATUS: return handleCheckStatusMessage(cli, msg, timeDiff) + case pb.MessageType_WEBRTC_OFFER: + return handleWebRTCOffer(cli, msg.GetWebrtcData()) + case pb.MessageType_WEBRTC_ANSWER: + return handleWebRTCAnswer(cli, msg.GetWebrtcData()) + case pb.MessageType_WEBRTC_ICE_CANDIDATE: + return handleWebRTCIceCandidate(cli, msg.GetWebrtcData()) + case pb.MessageType_WEBRTC_JOIN: + return handleWebRTCJoin(cli) + case pb.MessageType_WEBRTC_LEAVE: + return handleWebRTCLeave(cli) default: return sendErrorMessage(cli, fmt.Sprintf("unknown message type: %v", msg.Type)) } } +func handleWebRTCOffer(cli *op.Client, data *pb.WebRTCData) error { + if !cli.User().HasRoomWebRTCPermission(cli.Room()) { + return sendErrorMessage(cli, "no permission to send webrtc offer") + } + + if data == nil { + return sendErrorMessage(cli, "webrtc data is nil") + } + + sp := strings.Split(data.To, ":") + if len(sp) != 2 { + return sendErrorMessage(cli, "target user id is invalid") + } + + data.From = fmt.Sprintf("%s:%s", cli.User().ID, cli.ConnID()) + + return cli.Room().SendToConnID(sp[0], sp[1], &pb.Message{ + Type: pb.MessageType_WEBRTC_OFFER, + Sender: &pb.Sender{ + UserId: cli.User().ID, + Username: cli.User().Username, + }, + Payload: &pb.Message_WebrtcData{ + WebrtcData: data, + }, + }) +} + +func handleWebRTCAnswer(cli *op.Client, data *pb.WebRTCData) error { + if !cli.User().HasRoomWebRTCPermission(cli.Room()) { + return sendErrorMessage(cli, "no permission to send webrtc answer") + } + + if data == nil { + return sendErrorMessage(cli, "webrtc data is nil") + } + + sp := strings.Split(data.To, ":") + if len(sp) != 2 { + return sendErrorMessage(cli, "target user id is invalid") + } + + data.From = fmt.Sprintf("%s:%s", cli.User().ID, cli.ConnID()) + + return cli.Room().SendToConnID(sp[0], sp[1], &pb.Message{ + Type: pb.MessageType_WEBRTC_ANSWER, + Sender: &pb.Sender{ + UserId: cli.User().ID, + Username: cli.User().Username, + }, + Payload: &pb.Message_WebrtcData{ + WebrtcData: data, + }, + }) +} + +func handleWebRTCIceCandidate(cli *op.Client, data *pb.WebRTCData) error { + if !cli.User().HasRoomWebRTCPermission(cli.Room()) { + return sendErrorMessage(cli, "no permission to send webrtc ice candidate") + } + + if data == nil { + return sendErrorMessage(cli, "webrtc data is nil") + } + + sp := strings.Split(data.To, ":") + if len(sp) != 2 { + return sendErrorMessage(cli, "target user id is invalid") + } + + data.From = fmt.Sprintf("%s:%s", cli.User().ID, cli.ConnID()) + + return cli.Room().SendToConnID(sp[0], sp[1], &pb.Message{ + Type: pb.MessageType_WEBRTC_ICE_CANDIDATE, + Sender: &pb.Sender{ + UserId: cli.User().ID, + Username: cli.User().Username, + }, + Payload: &pb.Message_WebrtcData{ + WebrtcData: data, + }, + }) +} + +func handleWebRTCJoin(cli *op.Client) error { + if !cli.User().HasRoomWebRTCPermission(cli.Room()) { + return sendErrorMessage(cli, "no permission to join webrtc") + } + + cli.SetRTCJoined(true) + return cli.Broadcast(&pb.Message{ + Type: pb.MessageType_WEBRTC_JOIN, + Sender: &pb.Sender{ + UserId: cli.User().ID, + Username: cli.User().Username, + }, + Payload: &pb.Message_WebrtcData{ + WebrtcData: &pb.WebRTCData{ + From: fmt.Sprintf("%s:%s", cli.User().ID, cli.ConnID()), + }, + }, + }, op.WithIgnoreConnID(cli.ConnID()), op.WithRTCJoined()) +} + +func handleWebRTCLeave(cli *op.Client) error { + if !cli.User().HasRoomWebRTCPermission(cli.Room()) { + return sendErrorMessage(cli, "no permission to leave webrtc") + } + + cli.SetRTCJoined(false) + return cli.Broadcast(&pb.Message{ + Type: pb.MessageType_WEBRTC_LEAVE, + Sender: &pb.Sender{ + UserId: cli.User().ID, + Username: cli.User().Username, + }, + Payload: &pb.Message_WebrtcData{ + WebrtcData: &pb.WebRTCData{ + From: fmt.Sprintf("%s:%s", cli.User().ID, cli.ConnID()), + }, + }, + }, op.WithIgnoreConnID(cli.ConnID()), op.WithRTCJoined()) +} + func calculateTimeDiff(timestamp int64) float64 { if timestamp == 0 { return 0.0