Zippytal-Node/zoneGrpcMiddleware.go
2022-08-28 22:17:30 +02:00

251 lines
7.3 KiB
Go

package localserver
import (
"context"
"encoding/json"
"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)
go func() {
var payload map[string]string
if e := json.Unmarshal(req.Payload, &payload); err != 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"]); err != nil {
errCh <- err
return
}
case string(REMOVED_ZONE_AUTHORIZED_MEMBER):
if err := validateRequest(payload, "zoneId", "userId"); err != nil {
return
}
if err = atomicallyExecute(zm.Manager.zoneFlag, func() (err error) {
reqChan := make(chan *ZoneRequest)
done, e := zm.Manager.Zones[payload["zoneId"]].ZoneRequestScheduler.Schedule(reqChan)
go func() {
defer close(reqChan)
reqChan <- &ZoneRequest{
ReqType: string(REMOVE_USER),
From: payload["userId"],
Payload: map[string]interface{}{
"userId": payload["userId"],
},
}
reqChan <- &ZoneRequest{
ReqType: string(REMOVED_ZONE_AUTHORIZED_MEMBER),
From: payload["userId"],
Payload: map[string]interface{}{
"userId": payload["userId"],
},
}
}()
select {
case <-done:
case err = <-e:
}
return
}); err != nil {
errCh <- err
return
}
case string(NEW_AUTHORIZED_ZONE_MEMBER):
if err := validateRequest(payload, "zoneId", "userId"); err != nil {
return
}
if err = atomicallyExecute(zm.Manager.zoneFlag, func() (err error) {
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"],
},
}
}()
select {
case <-done:
case err = <-e:
}
return
}); err != nil {
errCh <- err
return
}
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 zon 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
}
}