Skip to content

Commit

Permalink
feat(sip-dialout): Add API endpoint for the SIP bridge to cancel a Di…
Browse files Browse the repository at this point in the history
…al-out

Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen committed Oct 13, 2023
1 parent 2bbcf26 commit ef7a367
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 2 deletions.
2 changes: 2 additions & 0 deletions appinfo/routes/routesRoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
['name' => 'Room#verifyDialOutNumber', 'url' => '/api/{apiVersion}/room/{token}/verify-dialout', 'verb' => 'POST', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::createGuestByDialIn() */
['name' => 'Room#createGuestByDialIn', 'url' => '/api/{apiVersion}/room/{token}/open-dial-in', 'verb' => 'POST', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::rejectedDialOutRequest() */
['name' => 'Room#rejectedDialOutRequest', 'url' => '/api/{apiVersion}/room/{token}/rejected-dialout', 'verb' => 'DELETE', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::setNotificationLevel() */
['name' => 'Room#setNotificationLevel', 'url' => '/api/{apiVersion}/room/{token}/notify', 'verb' => 'POST', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::setNotificationCalls() */
Expand Down
22 changes: 22 additions & 0 deletions docs/participant.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,28 @@ Note: This is only allowed as validate SIP bridge requests

- Data: See array definition in `Get user´s conversations`

## Reset call ID of rejected dial-out

Note: This is only allowed as validate SIP bridge requests

* Required capability: `sip-support-dialout`
* Method: `DELETE`
* Endpoint: `/room/{token}/rejected-dialout`
* Data:

| field | type | Description |
|--------------|--------|---------------------------------------------|
| `attendeeId` | int | The attendee ID of the dial-out participant |
| `callId` | string | The call ID that was rejected |

* Response:
- Status code:
+ `200 OK` Call ID reset
+ `400 Bad Request` Call ID mismatch
+ `401 Unauthorized` SIP request invalid
+ `404 Not Found` Participant was not found
+ `501 Not Implemented` When SIP or SIP dial-out is not configured

## Set display name as a guest

* API: Only `v1`
Expand Down
43 changes: 43 additions & 0 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,49 @@ public function createGuestByDialIn(): DataResponse {
return new DataResponse($this->formatRoom($this->room, $participant));
}

/**
* Reset call ID of a dial-out participant when the SIP gateway rejected it
*
* @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST|Http::STATUS_UNAUTHORIZED|Http::STATUS_NOT_FOUND, array<empty>, array{}>

Check failure on line 1632 in lib/Controller/RoomController.php

View workflow job for this annotation

GitHub Actions / Nextcloud

InvalidReturnType

lib/Controller/RoomController.php:1632:13: InvalidReturnType: The declared return type 'OCP\AppFramework\Http\DataResponse<200|400|401|404, array<array-key, never>, array<never, never>>' for OCA\Talk\Controller\RoomController::rejectedDialOutRequest is incorrect, got 'OCP\AppFramework\Http\DataResponse<200|400|401|404|501, array<never, never>, array<never, never>>' (see https://psalm.dev/011)
*
* 200: Call ID reset
* 400: Call ID mismatch
* 401: SIP request invalid
* 404: Participant was not found
* 501: SIP dial-out is not configured
*/
#[IgnoreOpenAPI]
#[PublicPage]
#[BruteForceProtection(action: 'talkSipBridgeSecret')]
#[RequireRoom]
public function rejectedDialOutRequest(int $attendeeId, string $callId): DataResponse {
try {
if (!$this->validateSIPBridgeRequest($this->room->getToken())) {
$response = new DataResponse([], Http::STATUS_UNAUTHORIZED);
$response->throttle(['action' => 'talkSipBridgeSecret']);
return $response;
}
} catch (UnauthorizedException $e) {
$response = new DataResponse([], Http::STATUS_UNAUTHORIZED);
$response->throttle(['action' => 'talkSipBridgeSecret']);
return $response;
}

if (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->isSIPDialOutEnabled()) {
return new DataResponse([], Http::STATUS_NOT_IMPLEMENTED);

Check failure on line 1658 in lib/Controller/RoomController.php

View workflow job for this annotation

GitHub Actions / Nextcloud

InvalidReturnStatement

lib/Controller/RoomController.php:1658:11: InvalidReturnStatement: The inferred type 'OCP\AppFramework\Http\DataResponse<501, array<never, never>, array<never, never>>' does not match the declared return type 'OCP\AppFramework\Http\DataResponse<200|400|401|404, array<array-key, never>, array<never, never>>' for OCA\Talk\Controller\RoomController::rejectedDialOutRequest (see https://psalm.dev/128)
}

try {
$this->participantService->resetDialOutRequest($this->room, $attendeeId, $callId);
} catch (ParticipantNotFoundException) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (\InvalidArgumentException) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}

return new DataResponse([], Http::STATUS_OK);
}

/**
* Set active state for a session
*
Expand Down
4 changes: 2 additions & 2 deletions lib/Model/Attendee.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
* @method void setRemoteId(string $remoteId)
* @method string getRemoteId()
* @method void setPhoneNumber(?string $phoneNumber)
* @method ?string getPhoneNumber()
* @method null|string getPhoneNumber()
* @method void setCallId(?string $callId)
* @method ?string getCallId()
* @method null|string getCallId()
*/
class Attendee extends Entity {
public const ACTOR_USERS = 'users';
Expand Down
28 changes: 28 additions & 0 deletions lib/Service/ParticipantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,34 @@ public function startDialOutRequest(SIPDialOutService $dialOutService, Room $roo
$this->attendeeMapper->update($attendee);
}

/**
* @throws \InvalidArgumentException
* @throws ParticipantNotFoundException
*/
public function resetDialOutRequest(Room $room, int $targetAttendeeId, string $callId): void {
try {
$attendee = $this->attendeeMapper->getById($targetAttendeeId);
} catch (DoesNotExistException|MultipleObjectsReturnedException|Exception) {
throw new ParticipantNotFoundException();
}

if ($attendee->getRoomId() !== $room->getId()) {
throw new ParticipantNotFoundException();
}

if ($attendee->getActorType() !== Attendee::ACTOR_PHONES) {
throw new ParticipantNotFoundException();
}

if ($callId === $attendee->getCallId()) {
$attendee->setCallId(null);
$this->attendeeMapper->update($attendee);
} else {
throw new \InvalidArgumentException('callId');
}

}

public function updateCallFlags(Room $room, Participant $participant, int $flags): void {
$session = $participant->getSession();
if (!$session instanceof Session) {
Expand Down

0 comments on commit ef7a367

Please sign in to comment.