^W>(
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
literal 0
HcmV?d00001
diff --git a/Assets/Sprite/Meeting - Contacts/容器 110@1x.png.meta b/Assets/Sprite/Meeting - Contacts/容器 110@1x.png.meta
new file mode 100644
index 0000000..cbb98bc
--- /dev/null
+++ b/Assets/Sprite/Meeting - Contacts/容器 110@1x.png.meta
@@ -0,0 +1,140 @@
+fileFormatVersion: 2
+guid: 265c317f817ccff49a4bf89b8f440710
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Sprite/Meeting - Contacts/容器 95@1x 1.png b/Assets/Sprite/Meeting - Contacts/容器 95@1x 1.png
new file mode 100644
index 0000000000000000000000000000000000000000..35d1817fa1202468604402cb54e24d264b517d08
GIT binary patch
literal 2360
zcmcImc~n#B75|b55oipHg&ACe$dOu=C?KLN0mUUchB-50JSbpgidsZOV3M#s&>~SB
z7tkV$fYz1{D1ifrK=6SE5DCVr3>wiufCNw>B#;F{UcU$bIe+&%CwV9LyYJrL-F`P0
zzh~{HSUOq)04U5oK|jD}C;WsiHizG~o@Yk@Sd1})0uOKrU-}8xT$nj7Oxx`8{HEPO
zK~Ygr2SecD;72F^f1Cu|G@FfkiHh2_E9mb{h543}@1oe8L=Godg1h|guAU~+UY>ll
z@1=B~(@K)>qIkPA6vd)rb|VdA$d;4)XBNlVJfg;tRSDw3wZju5SLSZt+l53OvC2_=uSFz6agwQWH
zr0c&`>7wIiwipDYbUppp#O-5SQ$Z{FDC0&&d
zQ9hVKZ8;U+6N1@@{8cfv#5a}ElO{ygILhsn-@l5q-=yL35(;#p%k$Akx*8T}1>ctM5mTgBVNwf{DzUL?n
z$Qk@RB?D;w%8xvf*n_ynTTEJn7R`8>QeogMZP>E=%7}||f$$D&s3?O#AZYk!m2X%qYv6Tdk1&~
zr*JS|ka|26`VHz!xxQXg1gs@l&B^CNl6}u?fPk>4&El@edxH)UueRT3U7%FWo1`_0?oPP^0X!HG8m@&<0AY28Lz7sQFUJpMuRBdz0)
zfKRT{v8q>=TzQArg<(4@Zp_-_qa*+kNk8($bv0sxo6nzKEA=+C0U#&9931$Zh4)Me
zGx)V}=qUgq4<2tkF%WGHVTYONr)$0E3V}Rd=!@NMnLX1J!X~8T*_VBE2mlY)by?}0
z@pfltG_=Tv>T=c)xIAs0QyR=g;}}6*SLdzqA*$4U4(a|k=S9ZM&?1v3)G|@i*~8@(
zl}V+HH}W?Xo!ZMihJB^qvcnR4NZfAYn@zm8sl3ox4``=cY5p(aIq2WNg@gO@+mf!k
z$yTCEH5RZjLnIVYUT1}dae_h|x@BvEW8=_ba<<
zBaI*s!=z330n?%I+t?=YdpOAuuQkI>@B&$@u!9W>?eOWjc}f{s&ss2~daSORRo7~d
zFJRisGkaHDy$!MOoQDMj`6b)d0J;PtsLF8->Qq)}QPO6Z!*Q#C64<6;)4;TS0}Ckt
zLf_d?YqWb_WRQjy8CDS9R<5V_WqWtxwNwzZb9?s|;Po~6Wa!{@Ruc7Y8(7WsbnY6u
zq}gp`3l0#V#r9>0U4U;o+oAZ<-1iVA<}rG*pd{rRkj@3PF#S(MbUEH$HU2x7xuV|y
zsM^fAG_6k%;|znnCJfH3k~R!1hw5%H50>H%yuoPsg5TPIy*gkCMDddY?>=4Rx>rG5
zbJ*D+#p+s~!mSb-qJ@X+omH+l1D4#Pzi$6Ec<9~lrY2SVDe_*V0~bz>RsZn#?2cJ4
z93*Kt3vxmsj|KP+Pr9s7v$Pmo?5;_cdQTVl(!ZYKfBXH3{-ABLOe2JBN2E&-pn3o^
zjO~0yj!sh_=9+K<5xAvzXvz2#*QXTPm-%1AIl{SWLV9%TEJ?Hv2kNi~=^j^&HI6s#
z2;T@q+0S+>PcNEVCAWv(k^1*l5h2UUCWbOe0mgOQMD6uMD7oSEMA2?|La&9bN$amF$^`c9$K&vEUnP
z;wM>MYm({a0s~6aF-II3yL!Vo&rr(OdqLoLFZhjds9rSzHyL#ZGU0jD$|!|c5V9uu
zKf*lwj*=Ji>m(zuX@dGilM#)tC`a8L0$
literal 0
HcmV?d00001
diff --git a/Assets/Sprite/Meeting - Contacts/容器 95@1x 1.png.meta b/Assets/Sprite/Meeting - Contacts/容器 95@1x 1.png.meta
new file mode 100644
index 0000000..e1dc05e
--- /dev/null
+++ b/Assets/Sprite/Meeting - Contacts/容器 95@1x 1.png.meta
@@ -0,0 +1,140 @@
+fileFormatVersion: 2
+guid: 8391008d8c962434eb1ae3fe2235ee2a
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Android
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/webRtc.asset b/Assets/webRtc.asset
index cd0fe7b..45bbeaf 100644
--- a/Assets/webRtc.asset
+++ b/Assets/webRtc.asset
@@ -14,14 +14,14 @@ MonoBehaviour:
m_EditorClassIdentifier:
automaticStreaming: 0
signalingSettings:
- rid: 9043491426209103878
+ rid: 236153504754827269
references:
version: 2
RefIds:
- - rid: 9043491426209103878
+ - rid: 236153504754827269
type: {class: WebSocketSignalingSettings, ns: Unity.RenderStreaming, asm: Unity.RenderStreaming}
data:
- m_url: wss://192.168.31.16:8080
+ m_url: ws://192.168.31.16:8080
m_iceServers:
- m_urls:
- stun:stun.l.google.com:19302
diff --git a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs
index a90cf93..816e82c 100644
--- a/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs
+++ b/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/Signaling/WebSocketSignaling.cs
@@ -12,34 +12,29 @@ namespace Unity.RenderStreaming.Signaling
{
public class WebSocketSignaling : ISignaling
{
- private static HashSet instances = new HashSet();
-
- private readonly string m_url;
- private readonly float m_timeout;
+ private static readonly HashSet instances = new();
private readonly SynchronizationContext m_mainThreadContext;
- private bool m_running;
- private Thread m_signalingThread;
- private readonly AutoResetEvent m_wsCloseEvent;
- private WebSocket m_webSocket;
- public string participantId;
- public string Url { get { return m_url; } }
///
- /// 当前客户端是否为Host角色(由服务器在connect响应中分配)
+ /// 参与者连接ID到房间connectionId的映射
+ /// Key: participantId, Value: roomConnectionId
+ /// 用于Host向特定Participant发送消息时,将内部connectionId还原为服务器格式
///
- public bool isHost { get; private set; }
+ private readonly Dictionary m_participantToRoom = new();
+
+ private readonly float m_timeout;
+
+ private readonly AutoResetEvent m_wsCloseEvent;
///
- /// Host连接时使用的房间connectionId
+ /// Host连接时使用的房间connectionId
///
private string m_roomConnectionId;
- ///
- /// 参与者连接ID到房间connectionId的映射
- /// Key: participantId, Value: roomConnectionId
- /// 用于Host向特定Participant发送消息时,将内部connectionId还原为服务器格式
- ///
- private Dictionary m_participantToRoom = new Dictionary();
+ private bool m_running;
+ private Thread m_signalingThread;
+ private WebSocket m_webSocket;
+ public string participantId;
public WebSocketSignaling(SignalingSettings signalingSettings, SynchronizationContext mainThreadContext)
{
@@ -47,26 +42,24 @@ namespace Unity.RenderStreaming.Signaling
throw new ArgumentNullException(nameof(signalingSettings));
if (!(signalingSettings is WebSocketSignalingSettings settings))
throw new ArgumentException("signalingSettings is not WebSocketSignalingSettings");
- m_url = settings.url;
+ Url = settings.url;
m_timeout = 5.0f;
m_mainThreadContext = mainThreadContext;
m_wsCloseEvent = new AutoResetEvent(false);
- if (instances.Any(x => x.Url == m_url))
- {
- RenderStreaming.Logger.Log(LogType.Warning, $"Other {nameof(WebSocketSignaling)} exists with same URL:{m_url}. Signaling process may be in conflict.");
- }
+ if (instances.Any(x => x.Url == Url))
+ RenderStreaming.Logger.Log(LogType.Warning,
+ $"Other {nameof(WebSocketSignaling)} exists with same URL:{Url}. Signaling process may be in conflict.");
instances.Add(this);
}
- ~WebSocketSignaling()
- {
- if (m_running)
- Stop();
+ ///
+ /// 当前客户端是否为Host角色(由服务器在connect响应中分配)
+ ///
+ public bool isHost { get; private set; }
- instances.Remove(this);
- }
+ public string Url { get; }
public void Start()
{
@@ -86,13 +79,9 @@ namespace Unity.RenderStreaming.Signaling
m_webSocket?.Close();
if (m_signalingThread.ThreadState == ThreadState.WaitSleepJoin)
- {
m_signalingThread.Abort();
- }
else
- {
m_signalingThread.Join(1000);
- }
m_signalingThread = null;
}
}
@@ -111,32 +100,18 @@ namespace Unity.RenderStreaming.Signaling
public event OnCallRequestHandler OnCallRequest;
public event OnMessageHandler OnMessage;
- ///
- /// 判断一个connectionId是否为参与者连接ID(而非房间connectionId)
- ///
- private bool IsParticipantConnectionId(string connectionId)
- {
- return m_participantToRoom.ContainsKey(connectionId);
- }
-
- ///
- /// 获取参与者对应的房间connectionId
- ///
- private string GetRoomConnectionId(string participantConnectionId)
- {
- return m_participantToRoom.TryGetValue(participantConnectionId, out var roomId) ? roomId : participantConnectionId;
- }
-
public void SendOffer(string connectionId, RTCSessionDescription offer)
{
- DescData data = new DescData();
+ var data = new DescData();
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
// 而不是内部participantId(participantId仅通过routedMessage.participantId传递用于目标选择)
- data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
+ data.connectionId = IsParticipantConnectionId(connectionId)
+ ? GetRoomConnectionId(connectionId)
+ : connectionId;
data.sdp = offer.sdp;
data.dateTime = DateTime.Now;
- RoutedMessage routedMessage = new RoutedMessage();
+ var routedMessage = new RoutedMessage();
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
@@ -148,6 +123,7 @@ namespace Unity.RenderStreaming.Signaling
routedMessage.from = connectionId;
routedMessage.participantId = participantId;
}
+
routedMessage.data = data;
routedMessage.type = "offer";
WSSend(routedMessage);
@@ -155,12 +131,14 @@ namespace Unity.RenderStreaming.Signaling
public void SendAnswer(string connectionId, RTCSessionDescription answer)
{
- DescData data = new DescData();
+ var data = new DescData();
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
- data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
+ data.connectionId = IsParticipantConnectionId(connectionId)
+ ? GetRoomConnectionId(connectionId)
+ : connectionId;
data.sdp = answer.sdp;
- RoutedMessage routedMessage = new RoutedMessage();
+ var routedMessage = new RoutedMessage();
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
@@ -172,6 +150,7 @@ namespace Unity.RenderStreaming.Signaling
routedMessage.from = connectionId;
routedMessage.participantId = participantId;
}
+
routedMessage.data = data;
routedMessage.type = "answer";
WSSend(routedMessage);
@@ -179,14 +158,16 @@ namespace Unity.RenderStreaming.Signaling
public void SendCandidate(string connectionId, RTCIceCandidate candidate)
{
- CandidateData data = new CandidateData();
+ var data = new CandidateData();
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
- data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
+ data.connectionId = IsParticipantConnectionId(connectionId)
+ ? GetRoomConnectionId(connectionId)
+ : connectionId;
data.candidate = candidate.Candidate;
data.sdpMLineIndex = candidate.SdpMLineIndex.GetValueOrDefault(0);
data.sdpMid = candidate.SdpMid;
- RoutedMessage routedMessage = new RoutedMessage();
+ var routedMessage = new RoutedMessage();
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
if (IsParticipantConnectionId(connectionId))
{
@@ -197,6 +178,7 @@ namespace Unity.RenderStreaming.Signaling
{
routedMessage.from = connectionId;
}
+
routedMessage.data = data;
routedMessage.type = "candidate";
@@ -206,15 +188,85 @@ namespace Unity.RenderStreaming.Signaling
public void OpenConnection(string connectionId)
{
m_roomConnectionId = connectionId;
- this.WSSend($"{{\"type\":\"connect\", \"connectionId\":\"{connectionId}\"}}");
+ WSSend($"{{\"type\":\"connect\", \"connectionId\":\"{connectionId}\"}}");
}
public void CloseConnection(string connectionId)
{
// 如果关闭的是参与者连接,使用房间connectionId发送disconnect
- string actualConnectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
+ var actualConnectionId = IsParticipantConnectionId(connectionId)
+ ? GetRoomConnectionId(connectionId)
+ : connectionId;
m_participantToRoom.Remove(connectionId);
- this.WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{actualConnectionId}\"}}");
+ WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{actualConnectionId}\"}}");
+ }
+
+ ~WebSocketSignaling()
+ {
+ if (m_running)
+ Stop();
+
+ instances.Remove(this);
+ }
+
+ ///
+ /// 判断一个connectionId是否为参与者连接ID(而非房间connectionId)
+ ///
+ private bool IsParticipantConnectionId(string connectionId)
+ {
+ return m_participantToRoom.ContainsKey(connectionId);
+ }
+
+ ///
+ /// 获取参与者对应的房间connectionId
+ ///
+ private string GetRoomConnectionId(string participantConnectionId)
+ {
+ return m_participantToRoom.TryGetValue(participantConnectionId, out var roomId)
+ ? roomId
+ : participantConnectionId;
+ }
+
+ // ///
+ // /// 发送自定义消息
+ // ///
+ // /// 目标连接ID
+ // /// 消息对象或字符串
+ // public void SendMessage(string connectionId, object message)
+ // {
+ // if (message == null)
+ // {
+ // RenderStreaming.Logger.Log(LogType.Warning, "Signaling: Cannot send null message");
+ // return;
+ // }
+ //
+ // var actualConnectionId = IsParticipantConnectionId(connectionId)
+ // ? GetRoomConnectionId(connectionId)
+ // : connectionId;
+ //
+ // var routedMessage = new RoutedMessage