Zippytal-Node/zoneGrpcMiddleware.go

260 lines
7.6 KiB
Go

package localserver
import (
"context"
"encoding/json"
"fmt"
"strconv"
"github.com/pion/webrtc/v3"
)
const (
ZONE_OFFER ReqType = "zone_offer"
ZONE_ANSWER ReqType = "zone_answer"
ZONE_COUNTER_OFFER ReqType = "zone_counter_offer"
JOIN_ZONE ReqType = "join_hosted_squad"
ZONE_ACCESS_DENIED ReqType = "zone_squad_access_denied"
QUIT_ZONE ReqType = "zone_stop_call"
ZONE_ACCESS_GRANTED ReqType = "zone_access_granted"
INCOMING_ZONE_MEMBER ReqType = "incoming_zone_member"
LEAVING_ZONE_MEMBER ReqType = "leaving_zone_member"
ZONE_WEBRTC_RENNEGOTIATION_OFFER ReqType = "zone_rennegotiation_offer"
ZONE_WEBRTC_RENNEGOTIATION_ANSWER ReqType = "zone_rennegotiation_answer"
ZONE_WEBRTC_CANDIDATE ReqType = "zone_webrtc_candidate"
NEW_ZONE ReqType = "new_zone"
NEW_AUTHORIZED_ZONE_MEMBER ReqType = "new_authorized_zone_member"
REMOVED_ZONE_AUTHORIZED_MEMBER ReqType = "removed_zone_authorized_member"
DELETE_ZONE = "delete_zone"
DISCONNECT_ZONE_MEMBER = "disconnect_zone_member"
)
type ZoneGrpcMiddleware struct {
Manager *ZoneManager
stream SignalingService_LinkClient
}
func NewZoneGrpcMiddleware(manager *ZoneManager) (zoneGrpcMiddleware *ZoneGrpcMiddleware) {
zoneGrpcMiddleware = &ZoneGrpcMiddleware{
Manager: manager,
}
return
}
func (zm *ZoneGrpcMiddleware) 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(ZONE_WEBRTC_CANDIDATE),
From: zm.Manager.ID,
To: to,
Payload: bs,
})
return
}
func (zm *ZoneGrpcMiddleware) Process(ctx context.Context, req *SignalingMessage, stream SignalingService_LinkClient) (err error) {
done, errCh := make(chan struct{}), make(chan error)
fmt.Println("got req", req.Type, string(req.Payload))
go func() {
var payload map[string]string
if e := json.Unmarshal(req.Payload, &payload); e != nil {
errCh <- e
return
}
switch req.Type {
case string(INCOMING_ZONE_MEMBER):
case string(DELETE_ZONE):
if err := validateRequest(payload, "zoneId"); err != nil {
return
}
if err := zm.Manager.DeleteZone(payload["zoneId"]); err != nil {
errCh <- err
return
}
case string(LEAVING_ZONE_MEMBER):
if err := validateRequest(payload, "zoneId"); err != nil {
return
}
if err := zm.Manager.HandleLeavingMember(req.GetFrom(), payload["zoneId"], false); err != nil {
errCh <- err
return
}
case string(REMOVED_ZONE_AUTHORIZED_MEMBER):
if err := validateRequest(payload, "zoneId", "userId"); err != nil {
return
}
if _, ok := zm.Manager.Zones[payload["zoneId"]]; !ok {
err = fmt.Errorf("no such zone")
return
}
reqChan := make(chan *ZoneRequest)
if _, ok := zm.Manager.Zones[payload["zoneId"]]; !ok {
err = fmt.Errorf("no such zone")
return
}
done, e := zm.Manager.Zones[payload["zoneId"]].ZoneRequestScheduler.Schedule(reqChan)
go func() {
defer close(reqChan)
reqChan <- &ZoneRequest{
ReqType: string(REMOVED_ZONE_AUTHORIZED_MEMBER),
From: payload["userId"],
Payload: map[string]interface{}{
"userId": payload["userId"],
},
}
// reqChan <- &ZoneRequest{
// ReqType: string(REMOVE_USER),
// From: payload["userId"],
// Payload: map[string]interface{}{
// "userId": payload["userId"],
// },
// }
fmt.Println("done here uwu")
}()
select {
case <-done:
fmt.Println("done triggered")
case err = <-e:
fmt.Println("error in schedule")
}
case string(NEW_AUTHORIZED_ZONE_MEMBER):
if err := validateRequest(payload, "zoneId", "userId"); err != nil {
return
}
if _, ok := zm.Manager.Zones[payload["zoneId"]]; !ok {
err = fmt.Errorf("no such zone")
return
}
reqChan := make(chan *ZoneRequest)
done, e := zm.Manager.Zones[payload["zoneId"]].ZoneRequestScheduler.Schedule(reqChan)
go func() {
defer close(reqChan)
// reqChan <- &ZoneRequest{
// ReqType: string(ADD_USER),
// From: payload["userId"],
// Payload: map[string]interface{}{
// "userId": payload["userId"],
// },
// }
reqChan <- &ZoneRequest{
ReqType: string(NEW_AUTHORIZED_ZONE_MEMBER),
From: payload["userId"],
Payload: map[string]interface{}{
"userId": payload["userId"],
},
}
fmt.Println("done here uwu")
}()
select {
case <-done:
fmt.Println("done triggered")
case err = <-e:
fmt.Println("error in schedule")
}
case string(NEW_ZONE):
// logger.Println(payload)
if err := validateRequest(payload, "zoneId", "zoneName", "zoneImageURL", "zoneOwner", "zoneCreationDate"); err != nil {
errCh <- err
return
}
zone, err := NewZone(zm.Manager.ID, payload["zoneId"], payload["zoneName"], payload["zoneImageURL"], payload["zoneOwner"], payload["zoneCreationDate"], true, []string{payload["zoneOwner"]})
if err != nil {
errCh <- err
return
}
_ = atomicallyExecute(zm.Manager.zoneFlag, func() (err error) {
zm.Manager.Zones[zone.ID] = zone
return
})
case string(ZONE_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(ZONE_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(ZONE_COUNTER_OFFER):
if err := zm.Manager.HandleCounterOffer(ctx, req.GetFrom(), req.GetTo(), payload); err != nil {
errCh <- err
return
}
case string(ZONE_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(ZONE_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(ZONE_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 zone grpc middleware")
// logger.Println(payload)
// logger.Println(req.Type)
}
done <- struct{}{}
}()
select {
case <-ctx.Done():
return ctx.Err()
case err = <-errCh:
return
case <-done:
return
}
}