ice candidates gathering working, needs to get public ips

This commit is contained in:
2026-04-07 17:30:34 -04:00
parent 31646a315a
commit dff05dd596
2 changed files with 72 additions and 47 deletions

View File

@@ -417,7 +417,7 @@ public partial class MainPage : ContentPage
bool active = await ServerAPI.GetIsChannelActiveAsync(_currentChannelId); bool active = await ServerAPI.GetIsChannelActiveAsync(_currentChannelId);
SafeSendRawToWebView($"Rtc Channel {_currentChannelName} | {_currentChannelId} is active: {active}"); // SafeSendRawToWebView($"Rtc Channel {_currentChannelName} | {_currentChannelId} is active: {active}");
return active; return active;
} }
@@ -457,7 +457,7 @@ public partial class MainPage : ContentPage
public async void WriteRtcAnswer(string json) public async void WriteRtcAnswer(string json)
{ {
SafeSendRawToWebView("WriteRtcAnswer entered with: " + json); // SafeSendRawToWebView("WriteRtcAnswer entered with: " + json);
try try
{ {
@@ -477,6 +477,23 @@ public partial class MainPage : ContentPage
} }
} }
public async void WriteIceCandidate(string json)
{
IceCandidate? candidate = JsonSerializer.Deserialize<IceCandidate>(json);
await ServerAPI.PostIceCandidateAsync(candidate);
}
public async void IceCandidateCallback(string json)
{
try
{
await hybridWebView.InvokeJavaScriptAsync("IceCandidateAdded");
}
catch (Exception ex)
{
SafeSendRawToWebView("WriteIceCandidate failed: " + ex.Message);
}
}
public async Task AnswerCallback(RtcDescription answer) public async Task AnswerCallback(RtcDescription answer)
{ {
answer.sdp = answer.sdp.Replace("\r\n", "(rn)"); answer.sdp = answer.sdp.Replace("\r\n", "(rn)");
@@ -486,7 +503,7 @@ public partial class MainPage : ContentPage
} }
catch (Exception ex) catch (Exception ex)
{ {
SafeSendRawToWebView("WriteRtcAnswer failed: " + ex.Message); SafeSendRawToWebView("AnswerCallback failed: " + ex.Message);
} }
} }

View File

@@ -20,7 +20,6 @@ window.setUsername = function(name) {
currentUsername = name; currentUsername = name;
LogMessage("Username set to: " + currentUsername); LogMessage("Username set to: " + currentUsername);
}; };
window.setChannelId = function(channelId) { window.setChannelId = function(channelId) {
currentChannelId = channelId; currentChannelId = channelId;
LogMessage("Channel set to: " + currentChannelId); LogMessage("Channel set to: " + currentChannelId);
@@ -166,10 +165,10 @@ async function ensureLocalMedia() {
async function joinChannelCall() { async function joinChannelCall() {
LogMessage("Current username: " + currentUsername); LogMessage("Current username: " + currentUsername);
LogMessage("Current channel: " + currentChannelId); LogMessage("Current channel: " + currentChannelId);
LogMessage("Joining RTCChannel"); // LogMessage("Joining RTCChannel");
let active = await window.HybridWebView.InvokeDotNet("JoinRtcChannel"); let active = await window.HybridWebView.InvokeDotNet("JoinRtcChannel");
await channelCallJoin(active); await channelCallJoin(active);
LogMessage("Joined RTCChannel"); // LogMessage("Joined RTCChannel");
// return; // return;
// try { // try {
// if (!currentChannelId) { // if (!currentChannelId) {
@@ -200,28 +199,57 @@ async function ensurePeerConnection2()
if (peerConnection) return; if (peerConnection) return;
peerConnection = new RTCPeerConnection(configuration); peerConnection = new RTCPeerConnection(configuration);
peerConnection.addEventListener('icegatheringstatechange', () => { peerConnection.onicegatheringstatechange = () => {
console.log( console.log(`ICE gathering state changed: ${peerConnection.iceGatheringState}`);
`ICE gathering state changed: ${peerConnection.iceGatheringState}`); };
}); peerConnection.onconnectionstatechange = () => {
peerConnection.addEventListener('connectionstatechange', () => {
console.log(`Connection state change: ${peerConnection.connectionState}`); console.log(`Connection state change: ${peerConnection.connectionState}`);
}); };
peerConnection.onsignalingstatechange = () => {
peerConnection.addEventListener('signalingstatechange', () => {
console.log(`Signaling state change: ${peerConnection.signalingState}`); console.log(`Signaling state change: ${peerConnection.signalingState}`);
}); };
peerConnection.oniceconnectionstatechange = () => {
console.log(`ICE connection state change: ${peerConnection.iceConnectionState}`);
};
peerConnection.addEventListener('iceconnectionstatechange ', () => { peerConnection.onicecandidate = (event) => {
console.log( console.log(`Ice Candidate: ${JSON.stringify(event.candidate)}`);
`ICE connection state change: ${peerConnection.iceConnectionState}`); LogMessage(`Ice Candidate: ${JSON.stringify(event.candidate)}`);
}); };
peerConnection.ontrack = (event) => {
LogMessage("Remote track received");
const remoteVideo = document.getElementById("remoteVideo");
const remoteVideoStatus = document.getElementById("remoteVideoStatus");
const remoteMediaStatus = document.getElementById("remoteMediaStatus");
const stream = event.streams[0];
const hasVideo = stream.getVideoTracks().length > 0;
const hasAudio = stream.getAudioTracks().length > 0;
if (hasVideo) {
remoteVideo.srcObject = stream;
} else {
remoteVideo.srcObject = null;
}
if (remoteVideoStatus) {
remoteVideoStatus.textContent = hasVideo
? "Remote video: active"
: "Remote video: unavailable";
}
if (remoteMediaStatus) {
remoteMediaStatus.textContent = `Remote media: audio=${hasAudio} video=${hasVideo}`;
}
};
} }
async function channelCallJoin(activeCall) async function channelCallJoin(activeCall)
{ {
LogMessage("Active call: " + activeCall); // LogMessage("Active call: " + activeCall);
await ensurePeerConnection2(); await ensurePeerConnection2();
await ensureLocalMedia();
if (activeCall) if (activeCall)
{ {
@@ -231,8 +259,8 @@ async function channelCallJoin(activeCall)
const answer = await peerConnection.createAnswer(); const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer); await peerConnection.setLocalDescription(answer);
LogMessage("Joining call with media answer: " + JSON.stringify(answer)); // LogMessage("Joining call with media answer: " + JSON.stringify(answer));
LogMessage("Calling C# WriteRtcAnswer with: " + JSON.stringify(answer)); // LogMessage("Calling C# WriteRtcAnswer with: " + JSON.stringify(answer));
await window.HybridWebView.InvokeDotNet("WriteRtcAnswer", [JSON.stringify(answer)]); await window.HybridWebView.InvokeDotNet("WriteRtcAnswer", [JSON.stringify(answer)]);
LogMessage("C# WriteRtcAnswer invoked"); LogMessage("C# WriteRtcAnswer invoked");
//TODO: Update offer in SurrealDB to include answer //TODO: Update offer in SurrealDB to include answer
@@ -244,33 +272,14 @@ async function channelCallJoin(activeCall)
await window.HybridWebView.InvokeDotNet("WriteRtcOffer", [JSON.stringify(offer)]); await window.HybridWebView.InvokeDotNet("WriteRtcOffer", [JSON.stringify(offer)]);
LogMessage(`Joining call with media offer: ${JSON.stringify(offer)}`); LogMessage(`Joining call with media offer: ${JSON.stringify(offer)}`);
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});
peerConnection.addEventListener('track', event => {
LogMessage("Received track: " + event.streams[0]);
event.streams[0].getTracks().forEach(track => {
LogMessage(`Add a track to the remoteStream: ${track}`);
remoteStream.addTrack(track);
});
});
} }
} }
async function CSharpCallTest(value)
{
LogMessage("Called from C#: " + value);
// let test = JSON.parse(value);
// LogMessage("JSON : " + JSON.stringify(test));
}
async function AnswerCallbackJS(answer) async function AnswerCallbackJS(answer)
{ {
answer.sdp = answer.sdp.replaceAll("(rn)", "\r\n"); answer.sdp = answer.sdp.replaceAll("(rn)", "\r\n");
LogMessage("Answer: " + JSON.stringify(answer)); // LogMessage("Answer: " + JSON.stringify(answer));
LogMessage("RemoteDescription: " + peerConnection.currentRemoteDescription); // LogMessage("RemoteDescription: " + peerConnection.currentRemoteDescription);
if (!peerConnection.currentRemoteDescription && answer) if (!peerConnection.currentRemoteDescription && answer)
{ {
@@ -279,10 +288,9 @@ async function AnswerCallbackJS(answer)
await peerConnection.setRemoteDescription(desc); await peerConnection.setRemoteDescription(desc);
} }
} }
async function IceCandidateAdded(candidate)
async function CollectIceCandidates()
{ {
//TODO: collect ICE candidates await peerConnection.addIceCandidate(candidate);
} }
async function handleRtcSignal(rawJson) { async function handleRtcSignal(rawJson) {
try { try {