package localserver import ( "context" "encoding/json" "strconv" "github.com/pion/webrtc/v3" ) const ( NEW_CHAT = "new_chat" CHAT_DELETED = "chat_deleted" CHAT_SYNCED = "chat_synced" SYNC_CHAT = "sync_chat" EXPORT_CHAT = "export_chat" CHAT_EXPORTED = "chat_exported" GET_NODE_CHATS = "get_node_chats" LEAVE_CHAT = "leave_chat" CHAT_WEBRTC_OFFER = "chat_webrtc_offer" CHAT_WEBRTC_ANSWER = "chat_webrtc_answer" CHAT_WEBRTC_COUNTER_OFFER = "chat_webrtc_counter_offer" CHAT_WEBRTC_RENNEGOTIATION_OFFER = "chat_webrtc_rennegotiation_offer" CHAT_WEBRTC_RENNEGOTIATION_ANSWER = "chat_werbtc_rennegotiation_answer" CHAT_WEBRTC_CANDIDATE = "chat_webrtc_candidate" ) type ChatGrpcMiddleware struct { Manager *ChatsManager stream SignalingService_LinkClient } func NewChatGrpcMiddleware(manager *ChatsManager) (chatGrpcMiddleware *ChatGrpcMiddleware) { chatGrpcMiddleware = &ChatGrpcMiddleware{ Manager: manager, } return } func (cm *ChatGrpcMiddleware) signalCandidate(to string, candidate *webrtc.ICECandidate) (err error) { bs, err := json.Marshal((map[string]string{ "from": NodeID, "to": to, "candidate": candidate.ToJSON().Candidate, "sdpMid": *candidate.ToJSON().SDPMid, "sdpMLineIndex": strconv.Itoa(int(*candidate.ToJSON().SDPMLineIndex)), })) if err != nil { return } err = cm.stream.Send(&SignalingMessage{ Type: CHAT_WEBRTC_CANDIDATE, From: NodeID, To: to, Payload: bs, }) return } func (cm *ChatGrpcMiddleware) Process(ctx context.Context, req *SignalingMessage, streram SignalingService_LinkClient) (err error) { done, errCh := make(chan struct{}), make(chan error) go func() { var payload map[string]string if e := json.Unmarshal(req.Payload, &payload); e != nil { errCh <- e return } switch req.GetType() { case NEW_CHAT: if err := validateRequest(payload, "chatID", "initiator", "target", "initiatorHostId", "targetHostId"); err != nil { errCh <- err return } chat, err := NewNodeChat(payload["chatID"], payload["chatID"], payload["initiator"], payload["target"], payload["initiatorHostId"], payload["targetHostId"], false) if err != nil { errCh <- err return } _ = atomicallyExecute(cm.Manager.chatsFlag, func() (err error) { cm.Manager.Chats[chat.ID] = chat return }) case CHAT_DELETED: if err := validateRequest(payload, "chatID"); err != nil { return } if err := cm.Manager.DeleteChat(payload["chatID"]); err != nil { errCh <- err return } case CHAT_EXPORTED: //todo: implement chat exported case EXPORT_CHAT: //todo: implement export chat exported case CHAT_SYNCED: //todo: implement chat synced case SYNC_CHAT: //todo: implement sync chat case CHAT_WEBRTC_OFFER: if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := cm.Manager.HandleOffer(ctx, req.GetFrom(), req.GetTo(), payload, cm.signalCandidate); err != nil { errCh <- err return } case CHAT_WEBRTC_ANSWER: if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := cm.Manager.HandleAnswer(ctx, req.GetFrom(), req.GetTo(), payload); err != nil { errCh <- err return } case CHAT_WEBRTC_COUNTER_OFFER: if err := cm.Manager.HandleCounterOffer(ctx, req.GetFrom(), req.GetTo(), payload); err != nil { errCh <- err return } case CHAT_WEBRTC_RENNEGOTIATION_OFFER: if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := cm.Manager.HandleRennegotiationOffer(req.GetFrom(), payload[SDP]); err != nil { errCh <- err return } case CHAT_WEBRTC_RENNEGOTIATION_ANSWER: if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := cm.Manager.HandleRennegotiationAnswer(req.GetFrom(), payload[SDP]); err != nil { errCh <- err return } case CHAT_WEBRTC_CANDIDATE: if err := validateRequest(payload, "candidate", "sdpMLineIndex", "sdpMid"); err != nil { errCh <- err return } logger.Println(payload) i, err := strconv.Atoi(payload["sdpMLineIndex"]) if err != nil { errCh <- err return } SDPMLineIndex := uint16(i) sdpMid := payload["sdpMid"] logger.Println(sdpMid, SDPMLineIndex) if err := cm.Manager.AddCandidate(&webrtc.ICECandidateInit{ Candidate: payload["candidate"], SDPMid: &sdpMid, SDPMLineIndex: &SDPMLineIndex, }, req.GetFrom()); err != nil { errCh <- err return } default: logger.Println("no request for chats grpc middleware") logger.Println(payload) logger.Println(req.Type) } }() select { case <-ctx.Done(): return ctx.Err() case err = <-errCh: return case <-done: return } }