cosmetics, make participantid a long plus avoid race condition...

This commit is contained in:
UbitUmarov
2026-03-15 23:23:45 +00:00
parent 8a279a91a7
commit 8685188d9b
8 changed files with 37 additions and 39 deletions

View File

@@ -26,8 +26,6 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Security.Cryptography; using System.Security.Cryptography;

View File

@@ -180,6 +180,7 @@ namespace osWebRtcVoice
int roomNumber = Math.Abs(hashed.GetHashCode()); int roomNumber = Math.Abs(hashed.GetHashCode());
return roomNumber; return roomNumber;
} }
public async Task<JanusRoom> SelectRoom(string pRegionId, string pChannelType, bool pSpatial, int pParcelLocalID, string pChannelID) public async Task<JanusRoom> SelectRoom(string pRegionId, string pChannelType, bool pSpatial, int pParcelLocalID, string pChannelID)
{ {
int roomNumber = CalcRoomNumber(pRegionId, pChannelType, pParcelLocalID, pChannelID); int roomNumber = CalcRoomNumber(pRegionId, pChannelType, pParcelLocalID, pChannelID);

View File

@@ -565,8 +565,7 @@ namespace osWebRtcVoice
{ {
} }
public int ParticipantId { get { return PluginRespDataInt("id"); } } public long ParticipantId { get { return PluginRespDataLong("id"); } }
// public long ParticipantId { get { return PluginRespDataLong("id"); } }
} }
// ============================================================== // ==============================================================
@@ -591,7 +590,7 @@ namespace osWebRtcVoice
// ============================================================== // ==============================================================
public class AudioBridgeLeaveRoomReq : PluginMsgReq public class AudioBridgeLeaveRoomReq : PluginMsgReq
{ {
public AudioBridgeLeaveRoomReq(int pRoomId, int pAttendeeId) : base(new OSDMap() { public AudioBridgeLeaveRoomReq(int pRoomId, long pAttendeeId) : base(new OSDMap() {
{ "request", "leave" }, { "request", "leave" },
{ "room", pRoomId }, { "room", pRoomId },
{ "id", pAttendeeId } { "id", pAttendeeId }
@@ -628,6 +627,7 @@ namespace osWebRtcVoice
{ {
} }
} }
// ============================================================== // ==============================================================
// The LongPoll request returns events from the plugins. These are formatted // The LongPoll request returns events from the plugins. These are formatted
// like the other responses but are not responses to requests. // like the other responses but are not responses to requests.

View File

@@ -75,8 +75,7 @@ namespace osWebRtcVoice
JanusMessageResp resp = await _AudioBridge.SendPluginMsg(joinReq); JanusMessageResp resp = await _AudioBridge.SendPluginMsg(joinReq);
AudioBridgeJoinRoomResp joinResp = new(resp); AudioBridgeJoinRoomResp joinResp = new(resp);
// if (joinResp is not null && joinResp.AudioBridgeReturnCode == "joined" && joinResp.ParticipantId > 0) if (joinResp is not null && joinResp.AudioBridgeReturnCode == "joined" && joinResp.ParticipantId > 0)
if (joinResp is not null && joinResp.AudioBridgeReturnCode == "joined")
{ {
pVSession.ParticipantId = joinResp.ParticipantId; pVSession.ParticipantId = joinResp.ParticipantId;
pVSession.Answer = joinResp.Jsep; pVSession.Answer = joinResp.Jsep;
@@ -95,8 +94,7 @@ namespace osWebRtcVoice
JanusMessageResp retryResp = await _AudioBridge.SendPluginMsg(retryJoinReq); JanusMessageResp retryResp = await _AudioBridge.SendPluginMsg(retryJoinReq);
AudioBridgeJoinRoomResp retryJoinResp = new(retryResp); AudioBridgeJoinRoomResp retryJoinResp = new(retryResp);
// if (retryJoinResp is not null && retryJoinResp.AudioBridgeReturnCode == "joined" && retryJoinResp.ParticipantId > 0) if (retryJoinResp is not null && retryJoinResp.AudioBridgeReturnCode == "joined" && retryJoinResp.ParticipantId > 0)
if (retryJoinResp is not null && retryJoinResp.AudioBridgeReturnCode == "joined")
{ {
pVSession.ParticipantId = retryJoinResp.ParticipantId; pVSession.ParticipantId = retryJoinResp.ParticipantId;
pVSession.Answer = retryJoinResp.Jsep; pVSession.Answer = retryJoinResp.Jsep;
@@ -115,7 +113,6 @@ namespace osWebRtcVoice
} }
else else
{ {
/*
if (joinResp is not null && joinResp.AudioBridgeReturnCode == "joined" && joinResp.ParticipantId <= 0) if (joinResp is not null && joinResp.AudioBridgeReturnCode == "joined" && joinResp.ParticipantId <= 0)
{ {
m_log.ErrorFormat("{0} JoinRoom. Joined response contains invalid participant id {1} for room {2}", m_log.ErrorFormat("{0} JoinRoom. Joined response contains invalid participant id {1} for room {2}",
@@ -123,7 +120,7 @@ namespace osWebRtcVoice
if (m_log.IsDebugEnabled) if (m_log.IsDebugEnabled)
m_log.DebugFormat("{0} JoinRoom. Invalid participant detail: {1}", LogHeader, joinResp.ToString()); m_log.DebugFormat("{0} JoinRoom. Invalid participant detail: {1}", LogHeader, joinResp.ToString());
} }
*/
m_log.ErrorFormat("{0} JoinRoom. Failed to join room {1}", LogHeader, RoomId); m_log.ErrorFormat("{0} JoinRoom. Failed to join room {1}", LogHeader, RoomId);
if (m_log.IsDebugEnabled) if (m_log.IsDebugEnabled)
m_log.DebugFormat("{0} JoinRoom. Failure detail: {1}", LogHeader, joinResp?.ToString() ?? "null"); m_log.DebugFormat("{0} JoinRoom. Failure detail: {1}", LogHeader, joinResp?.ToString() ?? "null");
@@ -176,10 +173,9 @@ namespace osWebRtcVoice
if (!string.Equals(display, pDisplay, StringComparison.Ordinal)) if (!string.Equals(display, pDisplay, StringComparison.Ordinal))
continue; continue;
// long participantId = participant.TryGetValue("id", out OSD idNode) ? idNode.AsLong() : 0L; long participantId = participant.TryGetValue("id", out OSD idNode) ? idNode.AsLong() : 0L;
// if (participantId <= 0) if (participantId <= 0)
// continue; continue;
int participantId = participant.TryGetValue("id", out OSD idNode) ? (int)idNode.AsLong() : 0;
JanusMessageResp leaveRespRaw = await _AudioBridge.SendPluginMsg(new AudioBridgeLeaveRoomReq(roomId, participantId)); JanusMessageResp leaveRespRaw = await _AudioBridge.SendPluginMsg(new AudioBridgeLeaveRoomReq(roomId, participantId));
AudioBridgeResp leaveResp = new(leaveRespRaw); AudioBridgeResp leaveResp = new(leaveRespRaw);

View File

@@ -66,7 +66,7 @@ namespace osWebRtcVoice
public string PluginId { get; set; } public string PluginId { get; set; }
private CancellationTokenSource _CancelTokenSource = new CancellationTokenSource(); // private CancellationTokenSource _CancelTokenSource = new();
public bool IsConnected { get; set; } public bool IsConnected { get; set; }
@@ -173,7 +173,7 @@ namespace osWebRtcVoice
m_log.Error($"{LogHeader} DestroySession: exception ", e); m_log.Error($"{LogHeader} DestroySession: exception ", e);
} }
IsConnected = false; IsConnected = false;
_CancelTokenSource.Cancel(); // _CancelTokenSource.Cancel();
return ret; return ret;
} }
@@ -265,8 +265,7 @@ namespace osWebRtcVoice
public async Task<JanusMessageResp> SendToJanus(JanusMessageReq pReq, string pURI, bool admin = false) public async Task<JanusMessageResp> SendToJanus(JanusMessageReq pReq, string pURI, bool admin = false)
{ {
AddJanusHeaders(pReq, admin); AddJanusHeaders(pReq, admin);
// m_log.DebugFormat("{0} SendToJanus", LogHeader); if (_MessageDetails) m_log.DebugFormat($"{LogHeader} SendToJanus. URI={pURI}, req={pReq.ToJson}");
if (_MessageDetails) m_log.DebugFormat("{0} SendToJanus. URI={1}, req={2}", LogHeader, pURI, pReq.ToJson());
// if (_MessageDetails) DebugLog("{0} SendToJanus. URI={1}, req={2}", LogHeader, pURI, pReq.ToJson()); // if (_MessageDetails) DebugLog("{0} SendToJanus. URI={1}, req={2}", LogHeader, pURI, pReq.ToJson());
JanusMessageResp ret = null; JanusMessageResp ret = null;
@@ -286,7 +285,8 @@ namespace osWebRtcVoice
HttpRequestMessage reqMsg = new(HttpMethod.Post, pURI); HttpRequestMessage reqMsg = new(HttpMethod.Post, pURI);
reqMsg.Content = new StringContent(reqStr, System.Text.Encoding.UTF8, MediaTypeNames.Application.Json); reqMsg.Content = new StringContent(reqStr, System.Text.Encoding.UTF8, MediaTypeNames.Application.Json);
reqMsg.Headers.TryAddWithoutValidation("Accept", "application/json"); reqMsg.Headers.TryAddWithoutValidation("Accept", "application/json");
HttpResponseMessage response = await httpClient.SendAsync(reqMsg, _CancelTokenSource.Token); // HttpResponseMessage response = await httpClient.SendAsync(reqMsg, _CancelTokenSource.Token);
HttpResponseMessage response = await httpClient.SendAsync(reqMsg);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -295,7 +295,7 @@ namespace osWebRtcVoice
if (ret.CheckReturnCode("ack")) if (ret.CheckReturnCode("ack"))
{ {
// Some messages are asynchronous and completed with an event // Some messages are asynchronous and completed with an event
if (_MessageDetails) m_log.DebugFormat("{0} SendToJanus: ack response {1}", LogHeader, respStr); if (_MessageDetails) m_log.Debug($"{LogHeader} SendToJanus: ack response {respStr}");
// if (_MessageDetails) DebugLog("{0} SendToJanus: ack response {1}", LogHeader, respStr); // if (_MessageDetails) DebugLog("{0} SendToJanus: ack response {1}", LogHeader, respStr);
/* /*
if (_OutstandingRequests.TryGetValue(pReq.TransactionId, out OutstandingRequest outstandingRequest)) if (_OutstandingRequests.TryGetValue(pReq.TransactionId, out OutstandingRequest outstandingRequest))
@@ -314,14 +314,14 @@ namespace osWebRtcVoice
{ {
// If the response is not an ack, that means a synchronous request/response so return the response // If the response is not an ack, that means a synchronous request/response so return the response
_= _OutstandingRequests.TryRemove(pReq.TransactionId, out _); _= _OutstandingRequests.TryRemove(pReq.TransactionId, out _);
if (_MessageDetails) m_log.DebugFormat("{0} SendToJanus: response {1}", LogHeader, respStr); if (_MessageDetails) m_log.Debug($"{LogHeader} SendToJanus: response {respStr}");
// if (_MessageDetails) DebugLog("{0} SendToJanus: response {1}", LogHeader, respStr); // if (_MessageDetails) DebugLog("{0} SendToJanus: response {1}", LogHeader, respStr);
} }
} }
else else
{ {
m_log.ErrorFormat("{0} SendToJanus: response not successful {1}", LogHeader, response); m_log.Error("{LogHeader} SendToJanus: response not successful {response}");
_= _OutstandingRequests.TryRemove(pReq.TransactionId, out _); _= _OutstandingRequests.TryRemove(pReq.TransactionId, out _);
} }
} }
@@ -362,7 +362,7 @@ namespace osWebRtcVoice
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("{0} SendToJanusNoWait: exception {1}", LogHeader, e.Message); m_log.Error($"{LogHeader} SendToJanusNoWait: exception {e.Message}");
} }
return ret; return ret;
@@ -399,12 +399,12 @@ namespace osWebRtcVoice
// The following two are required for the WebSocket interface. They are optional for the // The following two are required for the WebSocket interface. They are optional for the
// HTTP interface since the session and plugin handle are in the URL. // HTTP interface since the session and plugin handle are in the URL.
// SessionId is added to the message if not already there // SessionId is added to the message if not already there
if (!pReq.hasSessionId && !String.IsNullOrEmpty(SessionId)) if (!pReq.hasSessionId && !string.IsNullOrEmpty(SessionId))
{ {
pReq.AddSessionId(SessionId); pReq.AddSessionId(SessionId);
} }
// HandleId connects to the plugin // HandleId connects to the plugin
if (!pReq.hasHandleId && !String.IsNullOrEmpty(PluginId)) if (!pReq.hasHandleId && !string.IsNullOrEmpty(PluginId))
{ {
pReq.AddHandleId(PluginId); pReq.AddHandleId(PluginId);
} }
@@ -458,16 +458,18 @@ namespace osWebRtcVoice
HttpResponseMessage response = null; HttpResponseMessage response = null;
try try
{ {
response = await httpClient.SendAsync(reqMsg, _CancelTokenSource.Token); // response = await httpClient.SendAsync(reqMsg, _CancelTokenSource.Token);
response = await httpClient.SendAsync(reqMsg).ConfigureAwait(false);
if (response is not null && response.IsSuccessStatusCode) if (response is not null && response.IsSuccessStatusCode)
{ {
string respStr = await response.Content.ReadAsStringAsync(); string respStr = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
ret = JanusMessageResp.FromJson(respStr); ret = JanusMessageResp.FromJson(respStr);
// m_log.DebugFormat("{0} GetFromJanus: response {1}", LogHeader, respStr); // m_log.DebugFormat("{0} GetFromJanus: response {1}", LogHeader, respStr);
} }
else else
{ {
m_log.ErrorFormat("{0} GetFromJanus: response not successful {1}", LogHeader, response); m_log.Error($"{LogHeader} GetFromJanus: response not successful {response}");
// m_log.ErrorFormat("{0} GetFromJanus: response not successful", LogHeader); // m_log.ErrorFormat("{0} GetFromJanus: response not successful", LogHeader);
// if (m_log.IsDebugEnabled) // if (m_log.IsDebugEnabled)
// m_log.DebugFormat("{0} GetFromJanus: response detail {1}", LogHeader, response); // m_log.DebugFormat("{0} GetFromJanus: response detail {1}", LogHeader, response);
@@ -576,20 +578,21 @@ namespace osWebRtcVoice
break; break;
case "server_info": case "server_info":
// Just info on the Janus instance // Just info on the Janus instance
m_log.DebugFormat("{0} EventLongPoll: server_info {1}", LogHeader, resp.ToString()); m_log.Debug($"{LogHeader} EventLongPoll: server_info {resp}");
break; break;
case "ack": case "ack":
// 'ack' says the request was received and an event will follow // 'ack' says the request was received and an event will follow
if (_MessageDetails) m_log.DebugFormat("{0} EventLongPoll: ack {1}", LogHeader, resp.ToString()); if (_MessageDetails) m_log.Debug($"{LogHeader} EventLongPoll: ack {resp}");
break; break;
case "success": case "success":
// success is a sync response that says the request was completed // success is a sync response that says the request was completed
if (_MessageDetails) m_log.DebugFormat("{0} EventLongPoll: success {1}", LogHeader, resp.ToString()); if (_MessageDetails) m_log.Debug($"{LogHeader} EventLongPoll: success {resp}");
break; break;
case "trickle": case "trickle":
// got a trickle ICE candidate from Janus // got a trickle ICE candidate from Janus
// this is for reverse communication from Janus to the client and we don't do that // this is for reverse communication from Janus to the client and we don't do that
if (_MessageDetails) m_log.DebugFormat("{0} EventLongPoll: trickle {1}", LogHeader, resp.ToString()); if (_MessageDetails) m_log.Debug($"{LogHeader} EventLongPoll: trickle {resp}");
OnTrickle?.Invoke(eventResp); OnTrickle?.Invoke(eventResp);
break; break;
case "webrtcup": case "webrtcup":
@@ -652,11 +655,11 @@ namespace osWebRtcVoice
else else
{ {
OnError?.Invoke(eventResp); OnError?.Invoke(eventResp);
m_log.ErrorFormat("{0} EventLongPoll: error with no transaction. {1}", LogHeader, resp.ToString()); m_log.Error($"{LogHeader} EventLongPoll: error with no transaction. {resp}");
} }
break; break;
case "event": case "event":
if (_MessageDetails) m_log.DebugFormat("{0} EventLongPoll: event {1}", LogHeader, resp.ToString()); if (_MessageDetails) m_log.Debug($"{LogHeader} EventLongPoll: event {resp}");
if (TryGetOutstandingRequest(resp.TransactionId, out OutstandingRequest outstandingRequest2)) if (TryGetOutstandingRequest(resp.TransactionId, out OutstandingRequest outstandingRequest2))
{ {
// Someone is waiting for this event // Someone is waiting for this event

View File

@@ -54,8 +54,8 @@ namespace osWebRtcVoice
public OMV.UUID AgentId { get; set; } public OMV.UUID AgentId { get; set; }
// Janus keeps track of the user by this ID // Janus keeps track of the user by this ID
public int ParticipantId { get; set; } // public int ParticipantId { get; set; }
// public long ParticipantId { get; set; } public long ParticipantId { get; set; }
// Connections to the Janus server // Connections to the Janus server
public JanusSession Session { get; set; } public JanusSession Session { get; set; }

View File

@@ -333,7 +333,7 @@ namespace osWebRtcVoice
if (pRequest.TryGetOSDMap("jsep", out OSDMap jsep)) if (pRequest.TryGetOSDMap("jsep", out OSDMap jsep))
{ {
await viewerSession.ProvisionLock.WaitAsync().ConfigureAwait(false); await viewerSession.ProvisionLock.WaitAsync();
try try
{ {

View File

@@ -148,7 +148,7 @@ namespace osWebRtcVoice
{ "params", pParams } { "params", pParams }
}; };
OSDMap outerResponse = null; OSDMap outerResponse;
try try
{ {
if (m_MessageDetails) m_log.Debug($"{LogHeader}: request: {request}"); if (m_MessageDetails) m_log.Debug($"{LogHeader}: request: {request}");