Finished. Have at it.

This commit is contained in:
2026-04-02 17:16:05 -04:00
parent e4e7a70b2c
commit fe2473be21
11 changed files with 546 additions and 387 deletions

View File

@@ -5,38 +5,60 @@ namespace RelayServer.Endpoints;
public static class RtcEndpoints
{
/// <summary>
/// Maps all RTC-related HTTP endpoints used for joining calls, storing offers and answers,
/// writing ICE candidates, and leaving active calls.
/// </summary>
/// <param name="app">The web application to map endpoints onto.</param>
public static void MapRtcEndpoints(this WebApplication app)
{
// Join a channel call and determine whether the caller should become the offerer.
app.MapPost("/api/rtc/join", async (RtcJoinRequest request, RtcCallService rtcCallService) =>
{
return Results.Ok(await rtcCallService.JoinCallAsync(request.ChannelId, request.Username));
});
// 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.Sdp);
return Results.Ok();
});
//TODO: Add call for if channelId has active call returning boolean value
// 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/offer/{channelId}", async (string channelId, RtcCallService rtcCallService) =>
{
var offer = await rtcCallService.GetOfferAsync(channelId);
return offer is null ? Results.NotFound() : Results.Ok(offer);
//TODO: Needs to include offer data as JSON
});
// Store a new SDP answer for the specified channel call.
app.MapPost("/api/rtc/answer", async (RtcAnswer request, RtcCallService rtcCallService) =>
{
await rtcCallService.WriteAnswerAsync(request.ChannelId, request.OfferUser, request.AnswerUser, request.Sdp);
//TODO: Add call to clients already in call that a new answer has been made with answer details
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(
@@ -47,16 +69,28 @@ public static class RtcEndpoints
request.SdpMLineIndex,
request.Direction
);
//TODO: Add call to clients already in call that a new ICE candidate has been made with ICE candidate details
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);