Merge branch 'master' into lickx
This commit is contained in:
@@ -71,20 +71,20 @@ namespace osWebRtcVoice
|
||||
{
|
||||
ViewerSessionID = OMV.UUID.Random().ToString();
|
||||
VoiceService = pVoiceService;
|
||||
m_log.DebugFormat("{0} JanusViewerSession created {1}", LogHeader, ViewerSessionID);
|
||||
m_log.Debug($"{LogHeader} JanusViewerSession created {ViewerSessionID}");
|
||||
}
|
||||
public JanusViewerSession(string pViewerSessionID, IWebRtcVoiceService pVoiceService)
|
||||
{
|
||||
ViewerSessionID = pViewerSessionID;
|
||||
VoiceService = pVoiceService;
|
||||
m_log.DebugFormat("{0} JanusViewerSession created {1}", LogHeader, ViewerSessionID);
|
||||
m_log.Debug($"{LogHeader} JanusViewerSession created {ViewerSessionID}");
|
||||
}
|
||||
|
||||
// Send the messages to the voice service to try and get rid of the session
|
||||
// IVoiceViewerSession.Shutdown
|
||||
public async Task Shutdown()
|
||||
{
|
||||
m_log.DebugFormat("{0} JanusViewerSession shutdown {1}", LogHeader, ViewerSessionID);
|
||||
m_log.DebugFormat($"{LogHeader} JanusViewerSession shutdown {ViewerSessionID}");
|
||||
if (Room is not null)
|
||||
{
|
||||
var rm = Room;
|
||||
@@ -101,7 +101,7 @@ namespace osWebRtcVoice
|
||||
{
|
||||
var s = Session;
|
||||
Session = null;
|
||||
await s.DestroySession();
|
||||
_ = await s.DestroySession().ConfigureAwait(false);
|
||||
s.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +48,10 @@ namespace osWebRtcVoice
|
||||
private readonly IConfigSource _Config;
|
||||
private bool _Enabled = false;
|
||||
|
||||
private string _JanusServerURI = String.Empty;
|
||||
private string _JanusAPIToken = String.Empty;
|
||||
private string _JanusAdminURI = String.Empty;
|
||||
private string _JanusAdminToken = String.Empty;
|
||||
private string _JanusServerURI = string.Empty;
|
||||
private string _JanusAPIToken = string.Empty;
|
||||
private string _JanusAdminURI = string.Empty;
|
||||
private string _JanusAdminToken = string.Empty;
|
||||
|
||||
private bool _MessageDetails = false;
|
||||
|
||||
@@ -74,86 +74,84 @@ namespace osWebRtcVoice
|
||||
IConfig janusConfig = _Config.Configs["JanusWebRtcVoice"];
|
||||
if (_Enabled && janusConfig is not null)
|
||||
{
|
||||
_JanusServerURI = janusConfig.GetString("JanusGatewayURI", String.Empty);
|
||||
_JanusAPIToken = janusConfig.GetString("APIToken", String.Empty);
|
||||
_JanusAdminURI = janusConfig.GetString("JanusGatewayAdminURI", String.Empty);
|
||||
_JanusAdminToken = janusConfig.GetString("AdminAPIToken", String.Empty);
|
||||
_JanusServerURI = janusConfig.GetString("JanusGatewayURI", string.Empty);
|
||||
_JanusAPIToken = janusConfig.GetString("APIToken", string.Empty);
|
||||
_JanusAdminURI = janusConfig.GetString("JanusGatewayAdminURI", string.Empty);
|
||||
_JanusAdminToken = janusConfig.GetString("AdminAPIToken", string.Empty);
|
||||
// Debugging options
|
||||
_MessageDetails = janusConfig.GetBoolean("MessageDetails", false);
|
||||
|
||||
if (String.IsNullOrEmpty(_JanusServerURI) || String.IsNullOrEmpty(_JanusAPIToken) ||
|
||||
String.IsNullOrEmpty(_JanusAdminURI) || String.IsNullOrEmpty(_JanusAdminToken))
|
||||
if (string.IsNullOrEmpty(_JanusServerURI) || string.IsNullOrEmpty(_JanusAPIToken) ||
|
||||
string.IsNullOrEmpty(_JanusAdminURI) || string.IsNullOrEmpty(_JanusAdminToken))
|
||||
{
|
||||
_log.ErrorFormat("{0} JanusWebRtcVoice configuration section missing required fields", LogHeader);
|
||||
_log.Error($"{LogHeader} JanusWebRtcVoice configuration section missing required fields");
|
||||
_Enabled = false;
|
||||
}
|
||||
|
||||
if (_Enabled)
|
||||
{
|
||||
_log.DebugFormat("{0} Enabled", LogHeader);
|
||||
StartConnectionToJanus();
|
||||
if(!StartConnectionToJanus())
|
||||
{
|
||||
_log.Error($"{LogHeader} failed connection to Janus Gateway. Disabled");
|
||||
_Enabled=false;
|
||||
return;
|
||||
}
|
||||
RegisterConsoleCommands();
|
||||
_log.Info($"{LogHeader} Enabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.ErrorFormat("{0} No JanusWebRtcVoice configuration section", LogHeader);
|
||||
_log.Error($"{LogHeader} No JanusWebRtcVoice configuration section");
|
||||
_Enabled = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.ErrorFormat("{0} No WebRtcVoice configuration section", LogHeader);
|
||||
_log.Error($"{LogHeader} No WebRtcVoice configuration section");
|
||||
_Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start a thread to do the connection to the Janus server.
|
||||
// Here an initial session is created and then a handle to the audio bridge plugin
|
||||
// is created for the console commands. Since webrtc PeerConnections that are created
|
||||
// my Janus are per-session, the other sessions will be created by the viewer requests.
|
||||
private void StartConnectionToJanus()
|
||||
private bool StartConnectionToJanus()
|
||||
{
|
||||
_log.DebugFormat("{0} StartConnectionToJanus", LogHeader);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_ViewerSession = new JanusViewerSession(this);
|
||||
await ConnectToSessionAndAudioBridge(_ViewerSession);
|
||||
});
|
||||
//bad
|
||||
return ConnectToSessionAndAudioBridge(_ViewerSession).Result;
|
||||
}
|
||||
|
||||
private async Task ConnectToSessionAndAudioBridge(JanusViewerSession pViewerSession)
|
||||
private async Task<bool> ConnectToSessionAndAudioBridge(JanusViewerSession pViewerSession)
|
||||
{
|
||||
JanusSession janusSession = new JanusSession(_JanusServerURI, _JanusAPIToken, _JanusAdminURI, _JanusAdminToken, _MessageDetails);
|
||||
if (await janusSession.CreateSession())
|
||||
if (await janusSession.CreateSession().ConfigureAwait(false))
|
||||
{
|
||||
_log.DebugFormat("{0} JanusSession created", LogHeader);
|
||||
janusSession.OnDisconnect += Handle_Hangup;
|
||||
|
||||
// Once the session is created, create a handle to the plugin for rooms
|
||||
JanusAudioBridge audioBridge = new JanusAudioBridge(janusSession);
|
||||
janusSession.AddPlugin(audioBridge);
|
||||
|
||||
pViewerSession.VoiceServiceSessionId = janusSession.SessionId;
|
||||
pViewerSession.Session = janusSession;
|
||||
pViewerSession.AudioBridge = audioBridge;
|
||||
|
||||
janusSession.OnHangup += Handle_Hangup;
|
||||
|
||||
if (await audioBridge.Activate(_Config))
|
||||
if (await audioBridge.Activate(_Config).ConfigureAwait(false))
|
||||
{
|
||||
_log.DebugFormat("{0} AudioBridgePluginHandle created", LogHeader);
|
||||
_log.Debug($"{LogHeader} AudioBridgePluginHandle created");
|
||||
// Requests through the capabilities will create rooms
|
||||
|
||||
janusSession.AddPlugin(audioBridge);
|
||||
|
||||
pViewerSession.VoiceServiceSessionId = janusSession.SessionId;
|
||||
pViewerSession.Session = janusSession;
|
||||
pViewerSession.AudioBridge = audioBridge;
|
||||
janusSession.OnDisconnect += Handle_Hangup;
|
||||
janusSession.OnHangup += Handle_Hangup;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.ErrorFormat("{0} JanusPluginHandle not created", LogHeader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.ErrorFormat("{0} JanusSession not created", LogHeader);
|
||||
_log.Error($"{LogHeader} JanusPluginHandle not created");
|
||||
}
|
||||
_log.Error($"{LogHeader} JanusSession not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Handle_Hangup(EventResp pResp)
|
||||
@@ -161,7 +159,7 @@ namespace osWebRtcVoice
|
||||
if (pResp is not null)
|
||||
{
|
||||
var sessionId = pResp.sessionId;
|
||||
_log.DebugFormat("{0} Handle_Hangup: {1}, sessionId={2}", LogHeader, pResp.RawBody.ToString(), sessionId);
|
||||
_log.Debug($"{LogHeader} Handle_Hangup: {pResp.RawBody}, sessionId={sessionId}");
|
||||
if (VoiceViewerSession.TryGetViewerSessionByVSSessionId(sessionId, out IVoiceViewerSession viewerSession))
|
||||
{
|
||||
// There is a viewer session associated with this session
|
||||
@@ -169,7 +167,7 @@ namespace osWebRtcVoice
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.DebugFormat("{0} Handle_Hangup: no session found. SessionId={1}", LogHeader, sessionId);
|
||||
_log.Debug($"{LogHeader} Handle_Hangup: no session found. SessionId={sessionId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +190,12 @@ namespace osWebRtcVoice
|
||||
// This is the logic that takes the client's request and converts it into
|
||||
// operations on rooms in the audio bridge.
|
||||
// IWebRtcVoiceService.ProvisionVoiceAccountRequest
|
||||
public async Task<OSDMap> ProvisionVoiceAccountRequest(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
return ProvisionVoiceAccountRequestBAD(pSession, pRequest, pUserID, pSceneID).Result;
|
||||
}
|
||||
|
||||
public async Task<OSDMap> ProvisionVoiceAccountRequestBAD(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
OSDMap ret = null;
|
||||
string errorMsg = null;
|
||||
@@ -202,11 +205,11 @@ namespace osWebRtcVoice
|
||||
if (viewerSession.Session is null)
|
||||
{
|
||||
// This is a new session so we must create a new session and handle to the audio bridge
|
||||
await ConnectToSessionAndAudioBridge(viewerSession);
|
||||
await ConnectToSessionAndAudioBridge(viewerSession).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// TODO: need to keep count of users in a room to know when to close a room
|
||||
bool isLogout = pRequest.ContainsKey("logout") && pRequest["logout"].AsBoolean();
|
||||
bool isLogout = pRequest.TryGetBool("logout", out bool lgout) && lgout;
|
||||
if (isLogout)
|
||||
{
|
||||
// The client is logging out. Exit the room.
|
||||
@@ -223,16 +226,16 @@ namespace osWebRtcVoice
|
||||
|
||||
// Get the parameters that select the room
|
||||
// To get here, voice_server_type has already been checked to be 'webrtc' and channel_type='local'
|
||||
int parcel_local_id = pRequest.ContainsKey("parcel_local_id") ? pRequest["parcel_local_id"].AsInteger() : JanusAudioBridge.REGION_ROOM_ID;
|
||||
string channel_id = pRequest.ContainsKey("channel_id") ? pRequest["channel_id"].AsString() : String.Empty;
|
||||
string channel_credentials = pRequest.ContainsKey("credentials") ? pRequest["credentials"].AsString() : String.Empty;
|
||||
int parcel_local_id = pRequest.TryGetInt("parcel_local_id", out int pli) ? pli : JanusAudioBridge.REGION_ROOM_ID;
|
||||
string channel_id = pRequest.TryGetString("channel_id", out string cli) ? cli : string.Empty;
|
||||
string channel_credentials = pRequest.TryGetString("credentials", out string cred) ? cred : string.Empty;
|
||||
string channel_type = pRequest["channel_type"].AsString();
|
||||
bool isSpatial = channel_type == "local";
|
||||
string voice_server_type = pRequest["voice_server_type"].AsString();
|
||||
|
||||
_log.DebugFormat("{0} ProvisionVoiceAccountRequest: parcel_id={1} channel_id={2} channel_type={3} voice_server_type={4}", LogHeader, parcel_local_id, channel_id, channel_type, voice_server_type);
|
||||
|
||||
if (pRequest.ContainsKey("jsep") && pRequest["jsep"] is OSDMap jsep)
|
||||
if (pRequest.TryGetOSDMap("jsep", out OSDMap jsep))
|
||||
{
|
||||
// The jsep is the SDP from the client. This is the client's request to connect to the audio bridge.
|
||||
string jsepType = jsep["type"].AsString();
|
||||
@@ -242,17 +245,17 @@ namespace osWebRtcVoice
|
||||
// The client is sending an offer. Find the right room and join it.
|
||||
// _log.DebugFormat("{0} ProvisionVoiceAccountRequest: jsep type={1} sdp={2}", LogHeader, jsepType, jsepSdp);
|
||||
viewerSession.Room = await viewerSession.AudioBridge.SelectRoom(pSceneID.ToString(),
|
||||
channel_type, isSpatial, parcel_local_id, channel_id);
|
||||
channel_type, isSpatial, parcel_local_id, channel_id).ConfigureAwait(false);
|
||||
if (viewerSession.Room is null)
|
||||
{
|
||||
errorMsg = "room selection failed";
|
||||
_log.ErrorFormat("{0} ProvisionVoiceAccountRequest: room selection failed", LogHeader);
|
||||
_log.Error($"{LogHeader} ProvisionVoiceAccountRequest: room selection failed");
|
||||
}
|
||||
else {
|
||||
viewerSession.Offer = jsepSdp;
|
||||
viewerSession.OfferOrig = jsepSdp;
|
||||
viewerSession.AgentId = pUserID;
|
||||
if (await viewerSession.Room.JoinRoom(viewerSession))
|
||||
if (await viewerSession.Room.JoinRoom(viewerSession).ConfigureAwait(false))
|
||||
{
|
||||
ret = new OSDMap
|
||||
{
|
||||
@@ -263,29 +266,29 @@ namespace osWebRtcVoice
|
||||
else
|
||||
{
|
||||
errorMsg = "JoinRoom failed";
|
||||
_log.ErrorFormat("{0} ProvisionVoiceAccountRequest: JoinRoom failed", LogHeader);
|
||||
_log.Error($"{LogHeader} ProvisionVoiceAccountRequest: JoinRoom failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMsg = "jsep type not offer";
|
||||
_log.ErrorFormat("{0} ProvisionVoiceAccountRequest: jsep type={1} not offer", LogHeader, jsepType);
|
||||
_log.Error($"{LogHeader} ProvisionVoiceAccountRequest: jsep type={jsepType} not offer");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMsg = "no jsep";
|
||||
_log.DebugFormat("{0} ProvisionVoiceAccountRequest: no jsep. req={1}", LogHeader, pRequest.ToString());
|
||||
_log.Debug($"{LogHeader} ProvisionVoiceAccountRequest: no jsep. req={pRequest}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMsg = "viewersession not JanusViewerSession";
|
||||
_log.ErrorFormat("{0} ProvisionVoiceAccountRequest: viewersession not JanusViewerSession", LogHeader);
|
||||
_log.Error("{LogHeader} ProvisionVoiceAccountRequest: viewersession not JanusViewerSession");
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(errorMsg) && ret is null)
|
||||
if (!string.IsNullOrEmpty(errorMsg) && ret is null)
|
||||
{
|
||||
// The provision failed so build an error messgage to return
|
||||
ret = new OSDMap
|
||||
@@ -299,7 +302,12 @@ namespace osWebRtcVoice
|
||||
}
|
||||
|
||||
// IWebRtcVoiceService.VoiceAccountBalanceRequest
|
||||
public async Task<OSDMap> VoiceSignalingRequest(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
return VoiceSignalingRequestBAD(pSession, pRequest, pUserID, pSceneID).Result;
|
||||
}
|
||||
|
||||
public async Task<OSDMap> VoiceSignalingRequestBAD(IVoiceViewerSession pSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
OSDMap ret = null;
|
||||
JanusViewerSession viewerSession = pSession as JanusViewerSession;
|
||||
@@ -307,19 +315,19 @@ namespace osWebRtcVoice
|
||||
if (viewerSession is not null)
|
||||
{
|
||||
// The request should be an array of candidates
|
||||
if (pRequest.ContainsKey("candidate") && pRequest["candidate"] is OSDMap candidate)
|
||||
if (pRequest.TryGetOSDMap("candidate", out OSDMap candidate))
|
||||
{
|
||||
if (candidate.ContainsKey("completed") && candidate["completed"].AsBoolean())
|
||||
if (candidate.TryGetBool("completed", out bool iscompleted) && iscompleted)
|
||||
{
|
||||
// The client has finished sending candidates
|
||||
resp = await viewerSession.Session.TrickleCompleted(viewerSession);
|
||||
_log.DebugFormat("{0} VoiceSignalingRequest: candidate completed", LogHeader);
|
||||
resp = await viewerSession.Session.TrickleCompleted(viewerSession).ConfigureAwait(false);
|
||||
_log.DebugFormat($"{LogHeader} VoiceSignalingRequest: candidate completed");
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
else if (pRequest.ContainsKey("candidates") && pRequest["candidates"] is OSDArray candidates)
|
||||
else if (pRequest.TryGetOSDArray("candidates", out OSDArray candidates))
|
||||
{
|
||||
OSDArray candidatesArray = new OSDArray();
|
||||
foreach (OSDMap cand in candidates)
|
||||
@@ -330,17 +338,17 @@ namespace osWebRtcVoice
|
||||
{ "sdpMLineIndex", cand["sdpMLineIndex"].AsLong() }
|
||||
});
|
||||
}
|
||||
resp = await viewerSession.Session.TrickleCandidates(viewerSession, candidatesArray);
|
||||
_log.DebugFormat("{0} VoiceSignalingRequest: {1} candidates", LogHeader, candidatesArray.Count);
|
||||
resp = await viewerSession.Session.TrickleCandidates(viewerSession, candidatesArray).ConfigureAwait(false);
|
||||
_log.Debug($"{LogHeader} VoiceSignalingRequest: {candidatesArray.Count} candidates");
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.ErrorFormat("{0} VoiceSignalingRequest: no 'candidate' or 'candidates'", LogHeader);
|
||||
_log.Error($"{LogHeader} VoiceSignalingRequest: no 'candidate' or 'candidates'");
|
||||
}
|
||||
}
|
||||
if (resp is null)
|
||||
{
|
||||
_log.ErrorFormat("{0} VoiceSignalingRequest: no response so returning error", LogHeader);
|
||||
_log.ErrorFormat($"{LogHeader} VoiceSignalingRequest: no response so returning error");
|
||||
ret = new OSDMap
|
||||
{
|
||||
{ "response", "error" }
|
||||
@@ -355,14 +363,14 @@ namespace osWebRtcVoice
|
||||
|
||||
// This module should not be invoked with this signature
|
||||
// IWebRtcVoiceService.ProvisionVoiceAccountRequest
|
||||
public Task<OSDMap> ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// This module should not be invoked with this signature
|
||||
// IWebRtcVoiceService.VoiceSignalingRequest
|
||||
public Task<OSDMap> VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -395,24 +403,26 @@ namespace osWebRtcVoice
|
||||
}
|
||||
}
|
||||
|
||||
private async void HandleJanusInfo(string module, string[] cmdparms)
|
||||
private void HandleJanusInfo(string module, string[] cmdparms)
|
||||
{
|
||||
if (_ViewerSession is not null && _ViewerSession.Session is not null)
|
||||
{
|
||||
WriteOut("{0} Janus session: {1}", LogHeader, _ViewerSession.Session.SessionId);
|
||||
string infoURI = _ViewerSession.Session.JanusServerURI + "/info";
|
||||
var resp = await _ViewerSession.Session.GetFromJanus(infoURI);
|
||||
|
||||
var resp = _ViewerSession.Session.GetFromJanus(infoURI).Result;
|
||||
|
||||
if (resp is not null)
|
||||
MainConsole.Instance.Output(resp.ToJson());
|
||||
}
|
||||
}
|
||||
|
||||
private async void HandleJanusListRooms(string module, string[] cmdparms)
|
||||
private void HandleJanusListRooms(string module, string[] cmdparms)
|
||||
{
|
||||
if (_ViewerSession is not null && _ViewerSession.Session is not null && _ViewerSession.AudioBridge is not null)
|
||||
{
|
||||
var ab = _ViewerSession.AudioBridge;
|
||||
var resp = await ab.SendAudioBridgeMsg(new AudioBridgeListRoomsReq());
|
||||
var resp = ab.SendAudioBridgeMsg(new AudioBridgeListRoomsReq()).Result;
|
||||
if (resp is not null && resp.isSuccess)
|
||||
{
|
||||
if (resp.PluginRespData.TryGetValue("list", out OSD list))
|
||||
@@ -423,11 +433,14 @@ namespace osWebRtcVoice
|
||||
"Room", "Description", "Num", "SampleRate", "Spatial", "Recording");
|
||||
foreach (OSDMap room in list as OSDArray)
|
||||
{
|
||||
int roomid = room["room"].AsInteger();
|
||||
MainConsole.Instance.Output(
|
||||
" {0,10} {1,15} {2,5} {3,10} {4,7} {5,7}",
|
||||
room["room"], room["description"], room["num_participants"],
|
||||
roomid, room["description"], room["num_participants"],
|
||||
room["sampling_rate"], room["spatial_audio"], room["record"]);
|
||||
var participantResp = await ab.SendAudioBridgeMsg(new AudioBridgeListParticipantsReq(room["room"].AsInteger()));
|
||||
|
||||
var participantResp = ab.SendAudioBridgeMsg(new AudioBridgeListParticipantsReq(roomid)).Result;
|
||||
|
||||
if (participantResp is not null && participantResp.AudioBridgeReturnCode == "participants")
|
||||
{
|
||||
if (participantResp.PluginRespData.TryGetValue("participants", out OSD participants))
|
||||
|
||||
@@ -25,11 +25,8 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OpenSim.Framework;
|
||||
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace osWebRtcVoice
|
||||
{
|
||||
@@ -45,12 +42,12 @@ namespace osWebRtcVoice
|
||||
// If there are problems, the returned map will contain an error message.
|
||||
|
||||
// Initial calls to the voice server to get the user connected
|
||||
public Task<OSDMap> ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public Task<OSDMap> VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public OSDMap ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public OSDMap VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
|
||||
// Once connection state is looked up, the viewer session is passed in
|
||||
public Task<OSDMap> ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public Task<OSDMap> VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public OSDMap ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
public OSDMap VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
|
||||
// Create a viewer session with all the variables needed for the underlying implementation
|
||||
public IVoiceViewerSession CreateViewerSession(OSDMap pRequest, UUID pUserID, UUID pScene);
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace osWebRtcVoice
|
||||
m_log.ErrorFormat("{0} PVAR: no local service", LogHeader);
|
||||
return false;
|
||||
}
|
||||
OSDMap resp = m_WebRtcVoiceService.ProvisionVoiceAccountRequest(request, userID, sceneID).Result;
|
||||
OSDMap resp = m_WebRtcVoiceService.ProvisionVoiceAccountRequest(request, userID, sceneID);
|
||||
|
||||
pResponse = new JsonRpcResponse();
|
||||
pResponse.Result = resp;
|
||||
@@ -147,7 +147,7 @@ namespace osWebRtcVoice
|
||||
|
||||
try
|
||||
{
|
||||
OSDMap resp = m_WebRtcVoiceService.VoiceSignalingRequest(request, userID, sceneID).Result;
|
||||
OSDMap resp = m_WebRtcVoiceService.VoiceSignalingRequest(request, userID, sceneID);
|
||||
|
||||
pResponse = new JsonRpcResponse();
|
||||
pResponse.Result = resp;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using OpenSim.Framework;
|
||||
|
||||
@@ -36,7 +35,6 @@ using OpenMetaverse.StructuredData;
|
||||
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using OSHttpServer;
|
||||
|
||||
namespace osWebRtcVoice
|
||||
{
|
||||
@@ -65,12 +63,12 @@ namespace osWebRtcVoice
|
||||
m_serverURI = moduleConfig.GetString("WebRtcVoiceServerURI", string.Empty);
|
||||
if (string.IsNullOrWhiteSpace(m_serverURI))
|
||||
{
|
||||
m_log.ErrorFormat("{0} WebRtcVoiceServiceConnector enabled but no WebRtcVoiceServerURI specified", LogHeader);
|
||||
m_log.Error($"{LogHeader} WebRtcVoiceServiceConnector enabled but no WebRtcVoiceServerURI specified");
|
||||
m_Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.InfoFormat("{0} WebRtcVoiceServiceConnector enabled", LogHeader);
|
||||
m_log.Info($"{LogHeader} WebRtcVoiceServiceConnector enabled");
|
||||
}
|
||||
|
||||
m_MessageDetails = moduleConfig.GetBoolean("MessageDetails", false);
|
||||
@@ -83,50 +81,49 @@ namespace osWebRtcVoice
|
||||
// so that the viewer session ID is the same here as from the WebRTC service.
|
||||
public IVoiceViewerSession CreateViewerSession(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
m_log.DebugFormat("{0} CreateViewerSession", LogHeader);
|
||||
m_log.Debug($"{LogHeader} CreateViewerSession");
|
||||
return new VoiceViewerSession(this, pUserID, pSceneID);
|
||||
}
|
||||
|
||||
public Task<OSDMap> ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
m_log.DebugFormat("{0} ProvisionVoiceAccountRequest without ViewerSession. uID={1}, sID={2}", LogHeader, pUserID, pSceneID);
|
||||
m_log.Debug($"{LogHeader} ProvisionVoiceAccountRequest without ViewerSession. uID={pUserID}, sID={pSceneID}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Received a ProvisionVoiceAccountRequest from a viewer. Forward it to the WebRTC service.
|
||||
public async Task<OSDMap> ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
m_log.DebugFormat("{0} VoiceSignalingRequest. uID={1}, sID={2}", LogHeader, pUserID, pSceneID);
|
||||
OSDMap req = new OSDMap()
|
||||
m_log.Debug($"{LogHeader} VoiceSignalingRequest. uID={pUserID}, sID={pSceneID}");
|
||||
OSDMap req = new()
|
||||
{
|
||||
{ "request", pRequest },
|
||||
{ "userID", pUserID.ToString() },
|
||||
{ "scene", pSceneID.ToString() }
|
||||
};
|
||||
var resp = await JsonRpcRequest("provision_voice_account_request", m_serverURI, req);
|
||||
var resp = JsonRpcRequest("provision_voice_account_request", m_serverURI, req);
|
||||
|
||||
// Kludge to sync the viewer session number in our IVoiceViewerSession with the one from the WebRTC service.
|
||||
if (resp.ContainsKey("viewer_session"))
|
||||
if (resp.TryGetString("viewer_session", out string otherViewerSessionId))
|
||||
{
|
||||
string otherViewerSessionId = resp["viewer_session"].AsString();
|
||||
m_log.DebugFormat("{0} ProvisionVoiceAccountRequest: syncing viewSessionID. old={1}, new={2}",
|
||||
LogHeader, pVSession.ViewerSessionID, otherViewerSessionId);
|
||||
m_log.Debug(
|
||||
$"{LogHeader} ProvisionVoiceAccountRequest: syncing viewSessionID. old={pVSession.ViewerSessionID}, new={otherViewerSessionId}");
|
||||
VoiceViewerSession.UpdateViewerSessionId(pVSession, otherViewerSessionId);
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
public Task<OSDMap> VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
m_log.DebugFormat("{0} VoiceSignalingRequest without ViewerSession. uID={1}, sID={2}", LogHeader, pUserID, pSceneID);
|
||||
m_log.Debug($"{LogHeader} VoiceSignalingRequest without ViewerSession. uID={pUserID}, sID={pSceneID}");
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<OSDMap> VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
m_log.DebugFormat("{0} VoiceSignalingRequest. uID={1}, sID={2}", LogHeader, pUserID, pSceneID);
|
||||
OSDMap req = new OSDMap()
|
||||
OSDMap req = new()
|
||||
{
|
||||
{ "request", pRequest },
|
||||
{ "userID", pUserID.ToString() },
|
||||
@@ -135,16 +132,13 @@ namespace osWebRtcVoice
|
||||
return JsonRpcRequest("voice_signaling_request", m_serverURI, req);
|
||||
}
|
||||
|
||||
public Task<OSDMap> JsonRpcRequest(string method, string uri, OSDMap pParams)
|
||||
public OSDMap JsonRpcRequest(string method, string uri, OSDMap pParams)
|
||||
{
|
||||
string jsonId = UUID.Random().ToString();
|
||||
|
||||
if(string.IsNullOrWhiteSpace(uri))
|
||||
return null;
|
||||
|
||||
TaskCompletionSource<OSDMap> tcs = new TaskCompletionSource<OSDMap>();
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
OSDMap request = new()
|
||||
{
|
||||
{ "jsonrpc", OSD.FromString("2.0") },
|
||||
@@ -156,61 +150,54 @@ namespace osWebRtcVoice
|
||||
OSDMap outerResponse = null;
|
||||
try
|
||||
{
|
||||
if (m_MessageDetails) m_log.DebugFormat("{0}: request: {1}", LogHeader, request);
|
||||
if (m_MessageDetails) m_log.Debug($"{LogHeader}: request: {request}");
|
||||
|
||||
outerResponse = WebUtil.PostToService(uri, request, 10000, true);
|
||||
if (m_MessageDetails) m_log.DebugFormat("{0}: response: {1}", LogHeader, outerResponse);
|
||||
|
||||
if (m_MessageDetails) m_log.Debug($"{LogHeader}: response: {outerResponse}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0}: JsonRpc request '{1}' to {2} failed: {3}", LogHeader, method, uri, e);
|
||||
m_log.DebugFormat("{0}: request: {1}", LogHeader, request);
|
||||
tcs.SetResult(new OSDMap()
|
||||
m_log.Error($"{LogHeader}: JsonRpc request '{method}' to {uri} failed: {e.Message}");
|
||||
m_log.Debug($"{LogHeader}: request: {request}");
|
||||
return new OSDMap()
|
||||
{
|
||||
{ "error", OSD.FromString(e.Message) }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (!outerResponse.TryGetOSDMap("_Result", out OSDMap response))
|
||||
{
|
||||
string errm = $"JsonRpc request '{method}' to {1} returned an invalid response: {OSDParser.SerializeJsonString(outerResponse)}";
|
||||
m_log.Error(errm);
|
||||
return new OSDMap()
|
||||
{
|
||||
{ "error", errm }
|
||||
};
|
||||
}
|
||||
|
||||
OSD osdtmp;
|
||||
if (!outerResponse.TryGetValue("_Result", out osdtmp) || (osdtmp is not OSDMap))
|
||||
{
|
||||
string errm = String.Format("JsonRpc request '{0}' to {1} returned an invalid response: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(outerResponse));
|
||||
m_log.ErrorFormat(errm);
|
||||
tcs.SetResult(new OSDMap()
|
||||
{
|
||||
{ "error", errm }
|
||||
});
|
||||
}
|
||||
|
||||
OSDMap response = osdtmp as OSDMap;
|
||||
if (response.TryGetValue("error", out osdtmp))
|
||||
{
|
||||
string errm = String.Format("JsonRpc request '{0}' to {1} returned an error: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(osdtmp));
|
||||
m_log.ErrorFormat(errm);
|
||||
tcs.SetResult(new OSDMap()
|
||||
string errm = $"JsonRpc request '{method}' to {uri} returned an error: {OSDParser.SerializeJsonString(osdtmp)}";
|
||||
m_log.Error(errm);
|
||||
return new OSDMap()
|
||||
{
|
||||
{ "error", errm }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
OSDMap resultmap = null;
|
||||
if (!response.TryGetValue("result", out osdtmp) || (osdtmp is not OSDMap))
|
||||
if (!response.TryGetOSDMap("result", out OSDMap resultmap ))
|
||||
{
|
||||
string errm = String.Format("JsonRpc request '{0}' to {1} returned result as non-OSDMap: {2}",
|
||||
method, uri, OSDParser.SerializeJsonString(outerResponse));
|
||||
m_log.ErrorFormat(errm);
|
||||
tcs.SetResult(new OSDMap()
|
||||
string errm = $"JsonRpc request '{method}' to {uri} returned result as non-OSDMap: {OSDParser.SerializeJsonString(outerResponse)}";
|
||||
m_log.Error(errm);
|
||||
return new OSDMap()
|
||||
{
|
||||
{ "error", errm }
|
||||
});
|
||||
};
|
||||
}
|
||||
resultmap = osdtmp as OSDMap;
|
||||
|
||||
tcs.SetResult(resultmap);
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
return resultmap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using Mono.Addins;
|
||||
@@ -306,7 +304,7 @@ namespace osWebRtcVoice
|
||||
}
|
||||
|
||||
// The checks passed. Send the request to the voice service.
|
||||
OSDMap resp = voiceService.ProvisionVoiceAccountRequest(map, agentID, scene.RegionInfo.RegionID).Result;
|
||||
OSDMap resp = voiceService.ProvisionVoiceAccountRequest(map, agentID, scene.RegionInfo.RegionID);
|
||||
|
||||
if(resp is not null)
|
||||
{
|
||||
@@ -364,7 +362,7 @@ namespace osWebRtcVoice
|
||||
}
|
||||
}
|
||||
|
||||
OSDMap resp = voiceService.VoiceSignalingRequest(map, agentID, scene.RegionInfo.RegionID).Result;
|
||||
OSDMap resp = voiceService.VoiceSignalingRequest(map, agentID, scene.RegionInfo.RegionID);
|
||||
|
||||
if (_MessageDetails) m_log.Debug($"{logHeader}[VoiceSignalingRequest]: Response: {resp}");
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ namespace osWebRtcVoice
|
||||
// IWebRtcVoiceService
|
||||
|
||||
// IWebRtcVoiceService.ProvisionVoiceAccountRequest
|
||||
public async Task<OSDMap> ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
OSDMap response = null;
|
||||
IVoiceViewerSession vSession = null;
|
||||
@@ -246,13 +246,13 @@ namespace osWebRtcVoice
|
||||
}
|
||||
if (vSession is not null)
|
||||
{
|
||||
response = await vSession.VoiceService.ProvisionVoiceAccountRequest(vSession, pRequest, pUserID, pSceneID);
|
||||
response = vSession.VoiceService.ProvisionVoiceAccountRequest(vSession, pRequest, pUserID, pSceneID);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
// IWebRtcVoiceService.VoiceSignalingRequest
|
||||
public async Task<OSDMap> VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
OSDMap response = null;
|
||||
IVoiceViewerSession vSession = null;
|
||||
@@ -261,7 +261,7 @@ namespace osWebRtcVoice
|
||||
// request has a viewer session. Use that to find the voice service
|
||||
if (VoiceViewerSession.TryGetViewerSession(viewerSessionId, out vSession))
|
||||
{
|
||||
response = await vSession.VoiceService.VoiceSignalingRequest(vSession, pRequest, pUserID, pSceneID);
|
||||
response = vSession.VoiceService.VoiceSignalingRequest(vSession, pRequest, pUserID, pSceneID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -276,13 +276,13 @@ namespace osWebRtcVoice
|
||||
}
|
||||
|
||||
// This module should never be called with this signature
|
||||
public Task<OSDMap> ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap ProvisionVoiceAccountRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// This module should never be called with this signature
|
||||
public Task<OSDMap> VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
public OSDMap VoiceSignalingRequest(IVoiceViewerSession pVSession, OSDMap pRequest, UUID pUserID, UUID pSceneID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ namespace OpenSim.Framework
|
||||
{
|
||||
OSHHTPHost tmp = new OSHHTPHost(stuns[i].Trim(), false);
|
||||
if (tmp.IsValidHost)
|
||||
stunsarr.Add(tmp.URI);
|
||||
stunsarr.Add("stun:" + tmp.HostAndPort);
|
||||
}
|
||||
m_StunServers = stunsarr.Count > 0 ? stunsarr.ToArray() : null;
|
||||
}
|
||||
@@ -785,7 +785,7 @@ namespace OpenSim.Framework
|
||||
{
|
||||
OSHHTPHost tmp = new OSHHTPHost(value[i].Trim(), false);
|
||||
if (tmp.IsValidHost)
|
||||
values.Add(tmp.URI);
|
||||
values.Add("stun:" + tmp.HostAndPort);
|
||||
}
|
||||
m_StunServers = values.Count > 0 ? values.ToArray() : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user