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.CompareAndSwapInt32(manager.DataChannels[member].l, 0, 1) { defer atomic.SwapInt32(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.CompareAndSwapInt32(manager.DataChannels[member].l, 0, 1) { defer atomic.SwapInt32(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 }