package localserver import ( "context" "encoding/json" "fmt" "strconv" "github.com/pion/webrtc/v3" ) const ( HOSTED_SQUAD_OFFER ReqType = "hosted_squad_offer" HOSTED_SQUAD_ANSWER ReqType = "hosted_squad_answer" HOSTED_SQUAD_COUNTER_OFFER ReqType = "hosted_squad_counter_offer" JOIN_SQUAD ReqType = "join_hosted_squad" HOSTED_SQUAD_ACCESS_DENIED ReqType = "hosted_squad_hosted_squad_access_denied" QUIT_SQUAD ReqType = "hosted_squad_stop_call" HOSTED_SQUAD_ACCESS_GRANTED ReqType = "hosted_squad_access_granted" INCOMING_HOSTED_SQUAD_MEMBER ReqType = "incoming_hosted_squad_member" LEAVING_HOSTED_SQUAD_MEMBER ReqType = "leaving_hosted_squad_member" HOSTED_SQUAD_WEBRTC_RENNEGOTIATION_OFFER ReqType = "hosted_squad_rennegotiation_offer" HOSTED_SQUAD_WEBRTC_RENNEGOTIATION_ANSWER ReqType = "hosted_squad_rennegotiation_answer" HOSTED_SQUAD_WEBRTC_CANDIDATE ReqType = "hosted_squad_webrtc_candidate" NEW_SQUAD ReqType = "new_hosted_squad" NEW_AUTHORIZED_SQUAD_MEMBER = "new_authorized_squad_member" REMOVED_SQUAD_AUTHORIZED_MEMBER = "removed_squad_authorized_member" DELETE_SQUAD = "delete_hosted_squad" DISCONNECT_SQUAD_MEMBER = "disconnect_squad_member" UPDATE_SQUAD_LAST_INTERACTION_TIME = "update_squad_last_interaction_time" NEW_SQUAD_CHAT_ACTIVITY = "new_squad_chat_activity" ) type SquadGrpcMiddleware struct { Manager *SquadManager stream SignalingService_LinkClient } func NewSquadGrpcMiddleware(manager *SquadManager) (squadGrpcMiddleware *SquadGrpcMiddleware) { squadGrpcMiddleware = &SquadGrpcMiddleware{ Manager: manager, } return } func (zm *SquadGrpcMiddleware) signalCandidate(to string, candidate *webrtc.ICECandidate) (err error) { bs, err := json.Marshal(map[string]string{ "from": zm.Manager.ID, "to": to, "candidate": candidate.ToJSON().Candidate, "sdpMid": *candidate.ToJSON().SDPMid, "sdpMLineIndex": strconv.Itoa(int(*candidate.ToJSON().SDPMLineIndex)), }) if err != nil { return } err = zm.stream.Send(&SignalingMessage{ Type: string(HOSTED_SQUAD_WEBRTC_CANDIDATE), From: zm.Manager.ID, To: to, Payload: bs, }) return } func (zm *SquadGrpcMiddleware) Process(ctx context.Context, req *SignalingMessage, stream SignalingService_LinkClient) (err error) { done, errCh := make(chan struct{}), make(chan error) go func() { defer func() { done <- struct{}{} }() var payload map[string]string if e := json.Unmarshal(req.Payload, &payload); e != nil { errCh <- e return } switch req.Type { case string(INCOMING_HOSTED_SQUAD_MEMBER): case string(DELETE_SQUAD): if err := validateRequest(payload, "squadId"); err != nil { return } if err := zm.Manager.DeleteSquad(payload["squadId"]); err != nil { errCh <- err return } case string(LEAVING_HOSTED_SQUAD_MEMBER): if err := validateRequest(payload, "squadId"); err != nil { return } if err := zm.Manager.HandleLeavingMember(req.GetFrom(), payload["squadId"], false); err != nil { errCh <- err return } case string(REMOVED_SQUAD_AUTHORIZED_MEMBER): fmt.Println("got there biatch") if err := validateRequest(payload, "squadId", "userId"); err != nil { return } if _, ok := zm.Manager.Squads[payload["squadId"]]; !ok { err = fmt.Errorf("no such squad") return } reqChan := make(chan *SquadRequest) d, e := zm.Manager.Squads[payload["squadId"]].SquadRequestScheduler.Schedule(reqChan) go func() { defer func() { if _, closed := <-reqChan; !closed { close(reqChan) } }() reqChan <- &SquadRequest{ ReqType: string(REMOVED_SQUAD_AUTHORIZED_MEMBER), From: payload["userId"], Payload: map[string]interface{}{ "userId": payload["userId"], }, } }() select { case <-d: fmt.Println("uwuwuwuwuwuwuw donnnnee") case ee := <-e: fmt.Println("uuuuuuwuuuuuu", ee) } return case string(NEW_AUTHORIZED_SQUAD_MEMBER): if err := validateRequest(payload, "squadId", "userId"); err != nil { return } if _, ok := zm.Manager.Squads[payload["squadId"]]; !ok { err = fmt.Errorf("no such squad") return } reqChan := make(chan *SquadRequest) d, e := zm.Manager.Squads[payload["squadId"]].SquadRequestScheduler.Schedule(reqChan) go func() { defer func() { if _, closed := <-reqChan; !closed { close(reqChan) } }() reqChan <- &SquadRequest{ ReqType: string(NEW_AUTHORIZED_SQUAD_MEMBER), From: payload["userId"], Payload: map[string]interface{}{ "userId": payload["userId"], }, } }() select { case <-d: case <-e: } return case string(NEW_SQUAD): // logger.Println(payload) if err := validateRequest(payload, "squadId", "squadName", "squadImageURL", "squadOwner", "squadCreationDate"); err != nil { errCh <- err return } squad, err := NewSquad(zm.Manager.ID, payload["squadId"], payload["squadName"], payload["squadImageURL"], payload["squadOwner"], payload["squadCreationDate"], true, []string{payload["squadOwner"]}) if err != nil { errCh <- err return } _ = atomicallyExecute(zm.Manager.squadFlag, func() (err error) { zm.Manager.Squads[squad.ID] = squad return }) case string(HOSTED_SQUAD_OFFER): if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := zm.Manager.HandleOffer(ctx, req.GetFrom(), req.GetTo(), payload, zm.signalCandidate); err != nil { errCh <- err return } case string(HOSTED_SQUAD_ANSWER): if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := zm.Manager.HandleAnswer(ctx, req.GetFrom(), req.GetTo(), payload); err != nil { errCh <- err return } case string(HOSTED_SQUAD_COUNTER_OFFER): if err := zm.Manager.HandleCounterOffer(ctx, req.GetFrom(), req.GetTo(), payload); err != nil { errCh <- err return } case string(HOSTED_SQUAD_WEBRTC_RENNEGOTIATION_OFFER): // logger.Println("received negotiation offer") if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := zm.Manager.HandleRennegotiationOffer(req.GetFrom(), payload[SDP]); err != nil { errCh <- err return } case string(HOSTED_SQUAD_WEBRTC_RENNEGOTIATION_ANSWER): // logger.Println("received negotiation answer") if err := validateRequest(payload, SDP); err != nil { errCh <- err return } if err := zm.Manager.HandleRennegotiationAnswer(req.GetFrom(), payload[SDP]); err != nil { errCh <- err return } case string(HOSTED_SQUAD_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 := zm.Manager.AddCandidate(&webrtc.ICECandidateInit{ Candidate: payload["candidate"], SDPMid: &sdpMid, SDPMLineIndex: &SDPMLineIndex, }, req.GetFrom()); err != nil { errCh <- err return } default: // logger.Println("no request for squad grpc middleware") // logger.Println(payload) // logger.Println(req.Type) } }() select { case <-ctx.Done(): return ctx.Err() case err = <-errCh: return case <-done: return } }