251 lines
7.3 KiB
Go
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
|
|
}
|
|
}
|