Zippytal-Node/webrtcCallChatManager.go

137 lines
3.5 KiB
Go

package localserver
import (
"encoding/json"
"fmt"
"sync/atomic"
)
const (
CHAT_MESSAGE_BROADCAST = "chat_message_broadcast"
CHAT_MESSAGE_PRIVATE = "chat_message_private"
)
type WebrtcCallChatManager struct{}
func NewWebrtcCallChatManager() *WebrtcCallChatManager {
return new(WebrtcCallChatManager)
}
func (w *WebrtcCallChatManager) HandleCallEvent(from string, squadId string, eventId string, payload map[string]interface{}, data []byte, manager *WebRTCCallManager) (err error) {
done, errCh := make(chan struct{}), make(chan error)
go func() {
logger.Println("got an event in call chat manager", from, eventId, payload)
switch eventId {
case CHAT_MESSAGE_BROADCAST:
if e := validateEvent(payload, "message"); e != nil {
errCh <- e
return
}
if e := w.sendBrodcastChatMessage(from, payload["message"].(string), squadId, manager); e != nil {
errCh <- e
return
}
case CHAT_MESSAGE_PRIVATE:
if e := validateEvent(payload, "message", "dst"); e != nil {
errCh <- e
return
}
if e := w.sendPrivateChatMessage(from, payload["message"].(string), squadId, manager, payload["message"].([]string)...); e != nil {
errCh <- e
return
}
}
done <- struct{}{}
}()
select {
case <-done:
return nil
case err = <-errCh:
return
}
}
func (w WebrtcCallChatManager) sendBrodcastChatMessage(from string, message string, squadId string, manager *WebRTCCallManager) (err error) {
if _, ok := manager.Squads[squadId]; !ok {
err = fmt.Errorf("no correponding squad found")
return
}
for _, member := range manager.Squads[squadId].Members {
if _, ok := manager.DataChannels[member]; ok && member != from {
bs, marshalErr := json.Marshal(map[string]interface{}{
"type": "send_chat_message",
"from": from,
"payload": map[string]string{
"message": message,
},
})
if marshalErr != nil {
logger.Println(err)
continue
}
lock:
for {
if atomic.CompareAndSwapUint32(manager.DataChannels[member].l, 0, 1) {
defer atomic.SwapUint32(manager.DataChannels[member].l, 0)
if sendErr := manager.DataChannels[member].DataChannel.SendText(string(bs)); sendErr != nil {
logger.Println(sendErr)
}
break lock
} else {
continue
}
}
}
}
return
}
func (w WebrtcCallChatManager) sendPrivateChatMessage(from string, message string, squadId string, manager *WebRTCCallManager, dst ...string) (err error) {
if _, ok := manager.Squads[squadId]; !ok {
err = fmt.Errorf("no correponding squad found")
return
}
for _, member := range manager.Squads[squadId].Members {
for _, id := range dst {
if id == member {
if _, ok := manager.DataChannels[member]; ok && member != from {
bs, marshalErr := json.Marshal(map[string]interface{}{
"type": "",
"from": from,
"payload": map[string]string{
"message": message,
},
})
if marshalErr != nil {
logger.Println(err)
continue
}
lock:
for {
if atomic.CompareAndSwapUint32(manager.DataChannels[member].l, 0, 1) {
defer atomic.SwapUint32(manager.DataChannels[member].l, 0)
if sendErr := manager.DataChannels[member].DataChannel.SendText(string(bs)); sendErr != nil {
logger.Println(sendErr)
}
break lock
} else {
continue
}
}
}
}
}
}
return
}
func validateEvent(event map[string]interface{}, fields ...string) (err error) {
for _, field := range fields {
if _, ok := event[field]; !ok {
err = fmt.Errorf("no field %s in req payload", field)
return
}
}
return
}