feat: webrtc audio support

pull/269/merge v0.9.0-beta.1
zijiren233 2 months ago
parent 6e2585da39
commit 5632b6738b

@ -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

@ -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=

@ -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 {

@ -6,6 +6,7 @@ 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"
@ -17,13 +18,16 @@ type Client struct {
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()))
}

@ -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

@ -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)
}

@ -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

@ -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
@ -34,6 +34,11 @@ const (
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,6 +55,11 @@ 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,
@ -63,6 +73,11 @@ var (
"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
unknownFields protoimpl.UnknownFields
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
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
unknownFields protoimpl.UnknownFields
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
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 ""
}
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 assignable to Payload:
// Types that are valid to be assigned to Payload:
//
// *Message_ErrorMessage
// *Message_ChatContent
// *Message_PlaybackStatus
// *Message_ExpirationId
// *Message_ViewerCount
// *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 {
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 {
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 {
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 {
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 {
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
(*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,
},

@ -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;
}
}

@ -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
unknownFields protoimpl.UnknownFields
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
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
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
unknownFields protoimpl.UnknownFields
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
unknownFields protoimpl.UnknownFields
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
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
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
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
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"`
unknownFields protoimpl.UnknownFields
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
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
unknownFields protoimpl.UnknownFields
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
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
unknownFields protoimpl.UnknownFields
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
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() {

@ -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

@ -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

Loading…
Cancel
Save