feat(calls): implement Linux LAN peer calls over SRTP
Reuse existing ChatHub consent and Podcast LibVLC capture for direct bidirectional H.264/AAC media, with embedded call controls and cleanup. Require HTTPS key exchange and reject IP-masking policies for this opt-in LAN/VPN transport. Add native SRTP, signaling and lifecycle tests; document setup and remaining physical-device validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
5e48831d6d
commit
cc28ee8b29
20 changed files with 1394 additions and 29 deletions
|
|
@ -9,22 +9,30 @@ namespace Yavsc.Server.Hubs;
|
|||
|
||||
public partial class ChatHub
|
||||
{
|
||||
public async Task<CallSession> InviteCall(string roomName, string callee)
|
||||
public Task<CallSession> InviteCall(string roomName, string callee) =>
|
||||
InviteCoreAsync(roomName, callee, CallTransports.WebRtc);
|
||||
|
||||
public Task<CallSession> InviteLanCall(string roomName, string callee) =>
|
||||
InviteCoreAsync(roomName, callee, CallTransports.LanSrtp);
|
||||
|
||||
private async Task<CallSession> InviteCoreAsync(string roomName, string callee, string transport)
|
||||
{
|
||||
var caller = CallUser();
|
||||
RequireSecureLanControl(transport);
|
||||
if (string.IsNullOrWhiteSpace(roomName) || !InputValidator.ValidateRoomName(roomName) ||
|
||||
string.IsNullOrWhiteSpace(callee) || !InputValidator.ValidateUserName(callee))
|
||||
throw new HubException("Invalid call participant or room.");
|
||||
RequireCallPresence(roomName, caller, callee);
|
||||
var relayOnly = await RequiresRelayAsync(caller, callee);
|
||||
return await _calls.InviteAsync(roomName, caller, callee, Context.ConnectionId,
|
||||
_cxManager.GetConnexionIds(callee)?.Distinct().ToArray() ?? [], relayOnly);
|
||||
_cxManager.GetConnexionIds(callee)?.Distinct().ToArray() ?? [], relayOnly, transport);
|
||||
}
|
||||
|
||||
public async Task AcceptCall(Guid callId)
|
||||
{
|
||||
var user = CallUser();
|
||||
var session = await _calls.GetSessionAsync(callId, user, Context.ConnectionId);
|
||||
RequireSecureLanControl(session.Transport);
|
||||
RequireCallPresence(session.RoomName, session.Caller, session.Callee);
|
||||
await _calls.AcceptAsync(callId, user, Context.ConnectionId,
|
||||
await RequiresRelayAsync(session.Caller, session.Callee));
|
||||
|
|
@ -36,6 +44,7 @@ public partial class ChatHub
|
|||
{
|
||||
var user = CallUser();
|
||||
var session = await _calls.GetSessionAsync(callId, user, Context.ConnectionId);
|
||||
RequireSecureLanControl(session.Transport);
|
||||
RequireCallPresence(session.RoomName, session.Caller, session.Callee);
|
||||
if (!session.RelayOnly && await RequiresRelayAsync(session.Caller, session.Callee))
|
||||
{
|
||||
|
|
@ -53,6 +62,12 @@ public partial class ChatHub
|
|||
return user;
|
||||
}
|
||||
|
||||
private void RequireSecureLanControl(string transport)
|
||||
{
|
||||
if (transport == CallTransports.LanSrtp && Context.GetHttpContext()?.Request.IsHttps != true)
|
||||
throw new HubException("LAN calls require HTTPS signaling to protect SRTP keys.");
|
||||
}
|
||||
|
||||
private void RequireCallPresence(string room, string caller, string callee)
|
||||
{
|
||||
if (!_cxManager.IsConnected(caller) || !_cxManager.IsConnected(callee) ||
|
||||
|
|
|
|||
Loading…
Reference in a new issue