diff --git a/doc/api.oa3 b/doc/api.oa3 index a544eca0..c74beb0f 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -3618,7 +3618,7 @@ paths: $ref: '#/components/schemas/Subject' /talk/calls: - post: + post: tags: - talk description: Add new call entry @@ -3649,6 +3649,11 @@ paths: description: account disabled '500': description: internal server error + requestBody: + content: + application/json: + schema: + type: string /talk/calls/{callId}: put: diff --git a/net/server/internal/api_addCall.go b/net/server/internal/api_addCall.go index 708cf4af..e3739840 100644 --- a/net/server/internal/api_addCall.go +++ b/net/server/internal/api_addCall.go @@ -1,9 +1,70 @@ package databag import ( - "net/http" + "databag/internal/store" + "github.com/google/uuid" + "encoding/hex" + "github.com/theckman/go-securerandom" + "gorm.io/gorm" + "net/http" + "errors" ) //AddCall adds an active call with ice signal and relay func AddCall(w http.ResponseWriter, r *http.Request) { -} + + account, code, err := ParamAgentToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + + var cardId string + if err := ParseRequest(r, w, &cardId); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + // verify card is present + var cardSlot store.CardSlot + if err := store.DB.Preload("Card.CardSlot").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&cardSlot).Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusInternalServerError, err) + } else { + ErrResponse(w, http.StatusNotFound, err) + } + return + } + if cardSlot.Card == nil { + ErrResponse(w, http.StatusNotFound, errors.New("card has been deleted")) + return + } + + // generate call params + callerBin, callerErr := securerandom.Bytes(APPTokenSize) + if callerErr != nil { + ErrResponse(w, http.StatusInternalServerError, callerErr) + return + } + calleeBin, calleeErr := securerandom.Bytes(APPTokenSize) + if calleeErr != nil { + ErrResponse(w, http.StatusInternalServerError, calleeErr) + return + } + callId := uuid.New().String() + + // allocate bridge + callerToken := hex.EncodeToString(callerBin); + calleeToken := hex.EncodeToString(calleeBin); + bridgeRelay.AddBridge(callId, callerToken, calleeToken); + + // create response + call := Call{ + Id: callId, + CardId: cardId, + CallerToken: callerToken, + CalleeToken: calleeToken, + KeepAlive: BridgeKeepAlive, + } + WriteResponse(w, call); +} diff --git a/net/server/internal/api_signal.go b/net/server/internal/api_signal.go index 97257789..7881944f 100644 --- a/net/server/internal/api_signal.go +++ b/net/server/internal/api_signal.go @@ -7,7 +7,6 @@ import ( "errors" ) -var bridgeRelay BridgeRelay; var relayUpgrader = websocket.Upgrader{} //Status handler for websocket connection diff --git a/net/server/internal/bridge.go b/net/server/internal/bridge.go index 9b70ce4c..e719216c 100644 --- a/net/server/internal/bridge.go +++ b/net/server/internal/bridge.go @@ -7,14 +7,15 @@ import ( "time" ) -const bridgeKeepAlive = 6 +var bridgeRelay BridgeRelay; +const BridgeKeepAlive = 6 type BridgeStatus struct { status string } type Bridge struct { - bridgeId string + callId string expires int64 callerToken string calleeToken string @@ -27,12 +28,12 @@ type BridgeRelay struct { bridges []Bridge } -func (s BridgeRelay) AddBridge(bridgeId string, callerToken string, calleeToken string) { +func (s *BridgeRelay) AddBridge(callId string, callerToken string, calleeToken string) { s.sync.Lock() defer s.sync.Unlock() bridge := Bridge{ - bridgeId: bridgeId, - expires: time.Now().Unix() + (bridgeKeepAlive * 3), + callId: callId, + expires: time.Now().Unix() + (BridgeKeepAlive * 3), callerToken: callerToken, calleeToken: calleeToken, } @@ -53,7 +54,7 @@ func setStatus(bridge Bridge, status string) { } } -func (s BridgeRelay) KeepAlive(bridgeId string) { +func (s *BridgeRelay) KeepAlive(callId string) { s.sync.Lock() defer s.sync.Unlock() now := time.Now().Unix() @@ -61,8 +62,8 @@ func (s BridgeRelay) KeepAlive(bridgeId string) { for _, bridge := range s.bridges { if bridge.expires > now { bridges = append(bridges, bridge) - if bridge.bridgeId == bridgeId { - bridge.expires = now + (bridgeKeepAlive * 3) + if bridge.callId == callId { + bridge.expires = now + (BridgeKeepAlive * 3) if bridge.caller != nil { if err := bridge.caller.WriteMessage(websocket.PingMessage, nil); err != nil { LogMsg("failed to ping caller signal"); @@ -81,12 +82,12 @@ func (s BridgeRelay) KeepAlive(bridgeId string) { s.bridges = bridges } -func (s BridgeRelay) RemoveBridge(bridgeId string) { +func (s *BridgeRelay) RemoveBridge(callId string) { s.sync.Lock() defer s.sync.Unlock() var bridges []Bridge for _, bridge := range s.bridges { - if bridge.bridgeId == bridgeId { + if bridge.callId == callId { setStatus(bridge, "closed"); } else { bridges = append(bridges, bridge) @@ -95,7 +96,7 @@ func (s BridgeRelay) RemoveBridge(bridgeId string) { s.bridges = bridges } -func (s BridgeRelay) SetConnection(conn *websocket.Conn, token string) { +func (s *BridgeRelay) SetConnection(conn *websocket.Conn, token string) { s.sync.Lock() defer s.sync.Unlock() for _, bridge := range s.bridges { @@ -118,7 +119,7 @@ func (s BridgeRelay) SetConnection(conn *websocket.Conn, token string) { } } -func (s BridgeRelay) ClearConnection(conn *websocket.Conn) { +func (s *BridgeRelay) ClearConnection(conn *websocket.Conn) { s.sync.Lock() defer s.sync.Unlock() for _, bridge := range s.bridges { @@ -133,7 +134,7 @@ func (s BridgeRelay) ClearConnection(conn *websocket.Conn) { } } -func (s BridgeRelay) RelayMessage(conn *websocket.Conn, msg []byte) { +func (s *BridgeRelay) RelayMessage(conn *websocket.Conn, msg []byte) { s.sync.Lock() defer s.sync.Unlock() for _, bridge := range s.bridges { @@ -149,3 +150,4 @@ func (s BridgeRelay) RelayMessage(conn *websocket.Conn, msg []byte) { } } } +