139 lines
5.4 KiB
C#
139 lines
5.4 KiB
C#
using RelayServer.Models.Rtc;
|
|
using RelayServer.Services.Rtc;
|
|
|
|
namespace RelayServer.Endpoints;
|
|
|
|
public static class RtcEndpoints
|
|
{
|
|
/// <summary>
|
|
/// Maps all RTC-related HTTP endpoints used for storing offers and answers,
|
|
/// writing ICE candidates, checking active calls, and leaving active calls.
|
|
/// </summary>
|
|
/// <param name="app">The web application to map endpoints onto.</param>
|
|
public static void MapRtcEndpoints(this WebApplication app)
|
|
{
|
|
// Store or update the current SDP offer for a channel call.
|
|
app.MapPost("/api/rtc/offer", async (RtcOffer request, RtcCallService rtcCallService) =>
|
|
{
|
|
await rtcCallService.WriteOfferAsync(request.ChannelId, request.Username, request.SessionDescription);
|
|
|
|
RtcNotificationService.Broadcast(new RtcNotificationMessage
|
|
{
|
|
Type = "rtc_offer_updated",
|
|
ChannelId = request.ChannelId,
|
|
Username = request.Username
|
|
});
|
|
|
|
return Results.Ok();
|
|
});
|
|
|
|
// List all offers.
|
|
app.MapGet("/api/rtc/offers", async (RtcCallService rtcCallService) =>
|
|
{
|
|
return Results.Ok(await rtcCallService.GetOffersAsync());
|
|
});
|
|
|
|
// Return whether the specified channel currently has an active call.
|
|
app.MapGet("/api/rtc/active/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
|
|
{
|
|
return Results.Ok(await rtcCallService.HasActiveCallAsync(channelId));
|
|
});
|
|
|
|
// Return the latest stored SDP offer for the specified channel.
|
|
app.MapGet("/api/rtc/offers/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
|
|
{
|
|
var offer = await rtcCallService.GetOfferAsync(channelId);
|
|
return offer is null ? Results.NotFound() : Results.Ok(offer);
|
|
});
|
|
|
|
// Store a new SDP answer for the specified channel call.
|
|
app.MapPost("/api/rtc/answer", async (RtcOffer request, RtcCallService rtcCallService) =>
|
|
{
|
|
await rtcCallService.WriteAnswerAsync(request.ChannelId, request.SessionDescription);
|
|
//DON'T FUCKING HARDCODE STRINGS INTO API REQUESTS
|
|
// await rtcCallService.WriteAnswerAsync(
|
|
// request.ChannelId,
|
|
// new RtcSessionDescription
|
|
// {
|
|
// Type = "answer",
|
|
// Sdp = request.Sdp
|
|
// });
|
|
|
|
RtcNotificationService.Broadcast(new RtcNotificationMessage
|
|
{
|
|
Type = "rtc_answer_updated",
|
|
ChannelId = request.ChannelId
|
|
});
|
|
|
|
return Results.Ok();
|
|
});
|
|
|
|
// Return all answers stored for the specified channel.
|
|
app.MapGet("/api/rtc/answers/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
|
|
{
|
|
return Results.Ok(await rtcCallService.GetAnswersAsync(channelId));
|
|
});
|
|
|
|
// Return the latest answer stored for the specified channel.
|
|
app.MapGet("/api/rtc/answer/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
|
|
{
|
|
var answer = await rtcCallService.GetLatestAnswerAsync(channelId);
|
|
return answer is null ? Results.NotFound() : Results.Ok(answer);
|
|
});
|
|
|
|
// Store a new ICE candidate for the specified channel call.
|
|
app.MapPost("/api/rtc/candidate", async (RtcIceCandidate request, RtcCallService rtcCallService) =>
|
|
{
|
|
await rtcCallService.WriteIceCandidateAsync(
|
|
request.ChannelId,
|
|
request.Username,
|
|
request.Candidate,
|
|
request.SdpMid,
|
|
request.SdpMLineIndex,
|
|
request.Direction
|
|
);
|
|
|
|
RtcNotificationService.Broadcast(new RtcNotificationMessage
|
|
{
|
|
Type = "rtc_candidate_added",
|
|
ChannelId = request.ChannelId,
|
|
Username = request.Username,
|
|
Direction = request.Direction
|
|
});
|
|
|
|
return Results.Ok();
|
|
});
|
|
|
|
// Return all ICE candidates stored for the specified channel.
|
|
app.MapGet("/api/rtc/candidates/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
|
|
{
|
|
return Results.Ok(await rtcCallService.GetIceCandidatesAsync(channelId));
|
|
});
|
|
|
|
// Return ICE candidates for the specified channel that belong to other users
|
|
// and match the requested direction.
|
|
app.MapGet("/api/rtc/candidates/{channelId}/{username}/{direction}", async (
|
|
string channelId,
|
|
string username,
|
|
string direction,
|
|
RtcCallService rtcCallService) =>
|
|
{
|
|
return Results.Ok(await rtcCallService.GetIceCandidatesForOthersAsync(channelId, username, direction));
|
|
});
|
|
|
|
// Leave the active call for the specified channel.
|
|
app.MapPost("/api/rtc/leave", async (RtcLeaveRequest request, RtcCallService rtcCallService) =>
|
|
{
|
|
await rtcCallService.LeaveCallAsync(request.ChannelId, request.Username);
|
|
|
|
RtcNotificationService.Broadcast(new RtcNotificationMessage
|
|
{
|
|
Type = "rtc_call_left",
|
|
ChannelId = request.ChannelId,
|
|
Username = request.Username
|
|
});
|
|
|
|
return Results.Ok();
|
|
});
|
|
}
|
|
} |