mirror of
git://f0xx.org/ac/ac-ms-sfu-signaling
synced 2026-07-29 05:18:47 +03:00
sfu-signaling: real Janus signaling service implementation
- JanusClient.php: HTTP REST client for Janus Gateway API - SfuRoomRepository.php: room + participant + stats persistence - bootstrap.php: PDO, auth, Janus client factory - public/index.php: front-controller routing - public/health.php: Janus online check - public/api/rooms.php: list/create/destroy rooms - public/api/join.php: SDP offer relay → Janus VideoRoom - public/api/stats.php: bitrate/packet-loss analytics ingest - public/dashboard.php: SFU rooms UI (common BE dark-theme styles) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
68
public/api/join.php
Normal file
68
public/api/join.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SFU join API — POST /api/join
|
||||
*
|
||||
* Client sends: { room_id, jsep: { type: "offer", sdp: "..." }, role: "publisher"|"subscriber" }
|
||||
* Server relays to Janus VideoRoom, returns: { jsep: { type: "answer", sdp: "..." }, handle_id, session_id }
|
||||
*
|
||||
* Client subsequently maintains a WebSocket to Janus directly (proxied via nginx /sfu/ws).
|
||||
*/
|
||||
require_once dirname(__DIR__, 2) . '/src/bootstrap.php';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
sfuJsonErr('method not allowed', 405);
|
||||
}
|
||||
|
||||
$user = sfuRequireAuth();
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
|
||||
$janusRoomId = (int) ($input['room_id'] ?? 0);
|
||||
$jsep = $input['jsep'] ?? null;
|
||||
$role = in_array($input['role'] ?? '', ['publisher', 'subscriber'], true)
|
||||
? $input['role'] : 'publisher';
|
||||
|
||||
if (!$janusRoomId) { sfuJsonErr('room_id required'); }
|
||||
if (!$jsep || empty($jsep['sdp'])) { sfuJsonErr('jsep.sdp required'); }
|
||||
|
||||
$repo = new \AndroidCast\Sfu\SfuRoomRepository(sfuPdo());
|
||||
$janus = janusClient();
|
||||
|
||||
$room = $repo->getByJanusId($janusRoomId);
|
||||
if (!$room) { sfuJsonErr('room not found', 404); }
|
||||
|
||||
/* Create a fresh Janus session + handle for this participant */
|
||||
$sid = $janus->createSession();
|
||||
if (!$sid) { sfuJsonErr('Janus session failed'); }
|
||||
$hid = $janus->attachVideoRoom($sid);
|
||||
if (!$hid) { sfuJsonErr('Janus attach failed'); }
|
||||
|
||||
/* Send join + offer to Janus */
|
||||
$joinBody = [
|
||||
'request' => 'join',
|
||||
'room' => $janusRoomId,
|
||||
'ptype' => $role === 'publisher' ? 'publisher' : 'subscriber',
|
||||
'display' => $user['email'] ?? 'anon',
|
||||
];
|
||||
$resp = $janus->sendJsep($sid, $hid, $joinBody, [
|
||||
'type' => $jsep['type'],
|
||||
'sdp' => $jsep['sdp'],
|
||||
]);
|
||||
|
||||
/* Record participant in DB */
|
||||
$participantId = $repo->joinRoom(
|
||||
(int) $room['id'],
|
||||
(int) $user['id'],
|
||||
$hid,
|
||||
$role
|
||||
);
|
||||
|
||||
/* Return negotiated JSEP answer + WS connection details */
|
||||
$answer = $resp['jsep'] ?? null;
|
||||
sfuJsonOk([
|
||||
'session_id' => $sid,
|
||||
'handle_id' => $hid,
|
||||
'participant_id' => $participantId,
|
||||
'jsep' => $answer,
|
||||
'ws_url' => '/app/androidcast_project/sfu/ws',
|
||||
]);
|
||||
Reference in New Issue
Block a user