diff --git a/RelayClient/MainPage.xaml.cs b/RelayClient/MainPage.xaml.cs index 546f9e6..9d66f62 100644 --- a/RelayClient/MainPage.xaml.cs +++ b/RelayClient/MainPage.xaml.cs @@ -234,6 +234,16 @@ public partial class MainPage : ContentPage } case "rtc_candidate_added": { + try + { + IceCandidate? iceCandidate = JsonSerializer.Deserialize(rtcNotification.Direction); + IceCandidateCallback(iceCandidate); + } + catch (Exception ex) + { + SafeSendRawToWebView($"Candidate rejected: {ex.Message}"); + } + break; } case "rtc_call_left": @@ -254,7 +264,7 @@ public partial class MainPage : ContentPage if (pyload is null) return; - if (pyload.RecipientUsername != _username) + if (pyload.RecipientUsername == _username) return; Console.WriteLine($"[{_username}] received encrypted payload for {pyload.RecipientUsername}"); @@ -488,6 +498,7 @@ public partial class MainPage : ContentPage Username = _username, Candidate = candidate }; + if (candidate == null) return; await ServerAPI.PostIceCandidateAsync(DBCandidate); } catch (Exception ex) @@ -496,11 +507,11 @@ public partial class MainPage : ContentPage } } - public async void IceCandidateCallback(string json) + public async void IceCandidateCallback(IceCandidate candidate) { try { - await hybridWebView.InvokeJavaScriptAsync("IceCandidateAdded"); + await hybridWebView.InvokeJavaScriptAsync("IceCandidateAdded", [candidate], [HybridJSType.Default.IceCandidate]); } catch (Exception ex) { @@ -610,6 +621,8 @@ public partial class MainPage : ContentPage [JsonSourceGenerationOptions(WriteIndented = false)] [JsonSerializable(typeof(RtcDescription))] [JsonSerializable(typeof(List))] + [JsonSerializable(typeof(IceCandidate))] + [JsonSerializable(typeof(List))] [JsonSerializable(typeof(string))] internal partial class HybridJSType : JsonSerializerContext { diff --git a/RelayClient/Models/RtcNotificationMessage.cs b/RelayClient/Models/RtcNotificationMessage.cs index 519ee34..4113254 100644 --- a/RelayClient/Models/RtcNotificationMessage.cs +++ b/RelayClient/Models/RtcNotificationMessage.cs @@ -6,4 +6,4 @@ public sealed class RtcNotificationMessage public string? ChannelId { get; set; } public string? Username { get; set; } public string? Direction { get; set; } -} \ No newline at end of file +} diff --git a/RelayClient/Resources/Raw/wwwroot/index.js b/RelayClient/Resources/Raw/wwwroot/index.js index ee060e7..da5125d 100644 --- a/RelayClient/Resources/Raw/wwwroot/index.js +++ b/RelayClient/Resources/Raw/wwwroot/index.js @@ -4,6 +4,7 @@ let currentUsername = null; let currentChannelId = null; let availableCameras = []; let availableMics = []; +let candidateQueue = []; const configuration = { iceServers:[ { @@ -262,6 +263,7 @@ async function ensurePeerConnection2() console.log(`Ice Candidate: ${JSON.stringify(event.candidate)}`); LogMessage(`Ice Candidate: ${JSON.stringify(event.candidate)}`); await window.HybridWebView.InvokeDotNet("WriteIceCandidate", [JSON.stringify(event.candidate)]); + await IceCandidateAdded(event.candidate); }; peerConnection.ontrack = (event) => { @@ -334,11 +336,22 @@ async function AnswerCallbackJS(answer) LogMessage("Current answer: " + JSON.stringify(answer)); const desc = new RTCSessionDescription(answer); await peerConnection.setRemoteDescription(desc); + for (const candidate of candidateQueue) { + await peerConnection.addIceCandidate(candidate); + } } } async function IceCandidateAdded(candidate) { - await peerConnection.addIceCandidate(candidate); + if (peerConnection.currentRemoteDescription) { + await peerConnection.addIceCandidate(candidate); + LogMessage("ICE CANDIDATE ADDED: " + JSON.stringify(candidate)); + } + else { + LogMessage("RemoteDescription Missing") + candidateQueue.push(candidate); + + } } async function handleRtcSignal(rawJson) { try { diff --git a/RelayServer/Endpoints/RtcEndpoints.cs b/RelayServer/Endpoints/RtcEndpoints.cs index 8eef93d..e44f176 100644 --- a/RelayServer/Endpoints/RtcEndpoints.cs +++ b/RelayServer/Endpoints/RtcEndpoints.cs @@ -1,4 +1,5 @@ -using RelayServer.Models.Rtc; +using System.Text.Json; +using RelayServer.Models.Rtc; using RelayServer.Services.Rtc; namespace RelayServer.Endpoints; @@ -86,7 +87,6 @@ public static class RtcEndpoints request.Candidate.candidate, request.Candidate.sdpMid, request.Candidate.sdpMLineIndex - // request.Candidate.direction ); RtcNotificationService.BroadcastToChannel(new RtcNotificationMessage @@ -94,7 +94,7 @@ public static class RtcEndpoints Type = "rtc_candidate_added", ChannelId = request.ChannelId, Username = request.Username, - /*Direction = request.Direction*/ + Direction = JsonSerializer.Serialize(request.Candidate) }); return Results.Ok(); diff --git a/RelayServer/Models/Rtc/RtcNotificationMessage.cs b/RelayServer/Models/Rtc/RtcNotificationMessage.cs index 89ab5e9..dc22983 100644 --- a/RelayServer/Models/Rtc/RtcNotificationMessage.cs +++ b/RelayServer/Models/Rtc/RtcNotificationMessage.cs @@ -6,4 +6,12 @@ public sealed class RtcNotificationMessage public required string ChannelId { get; set; } public string? Username { get; set; } public string? Direction { get; set; } +} + +public sealed class RtcIceNotificationMessage +{ + public required string Type { get; set; } + public required string ChannelId { get; set; } + public string? Username { get; set; } + public required IceCandidate Candidate { get; set; } } \ No newline at end of file diff --git a/RelayServer/Services/Rtc/RtcNotificationService.cs b/RelayServer/Services/Rtc/RtcNotificationService.cs index 9968d74..1a6652b 100644 --- a/RelayServer/Services/Rtc/RtcNotificationService.cs +++ b/RelayServer/Services/Rtc/RtcNotificationService.cs @@ -25,4 +25,22 @@ public static class RtcNotificationService host.Sessions.SendTo(json, sessionId); } } + + public static void BroadcastToChannel(RtcIceNotificationMessage message) + { + if (Server is null) + return; + + var host = Server.WebSocketServices["/"]; + if (host is null) + return; + + var json = JsonSerializer.Serialize(message); + var sessionIds = RtcChannelPresenceService.GetSessionsInChannel(message.ChannelId); + + foreach (var sessionId in sessionIds) + { + host.Sessions.SendTo(json, sessionId); + } + } } \ No newline at end of file