【m】优化socket代码
This commit is contained in:
@@ -29,6 +29,14 @@ namespace Unity.RenderStreaming
|
||||
s_AddChannelHandler = Execute;
|
||||
private static readonly ExecuteEvents.EventFunction<IAddReceiverHandler>
|
||||
s_AddReceiverHandler = Execute;
|
||||
private static readonly ExecuteEvents.EventFunction<IParticipantJoinedHandler>
|
||||
s_ParticipantJoinedHandler = Execute;
|
||||
private static readonly ExecuteEvents.EventFunction<IParticipantLeftHandler>
|
||||
s_ParticipantLeftHandler = Execute;
|
||||
private static readonly ExecuteEvents.EventFunction<ICallRequestHandler>
|
||||
s_CallRequestHandler = Execute;
|
||||
private static readonly ExecuteEvents.EventFunction<IMessageHandler>
|
||||
s_MessageHandler = Execute;
|
||||
|
||||
private static void Execute(ICreatedConnectionHandler handler, BaseEventData eventData)
|
||||
{
|
||||
@@ -62,6 +70,22 @@ namespace Unity.RenderStreaming
|
||||
{
|
||||
handler.OnAddReceiver(ValidateEventData<SignalingEventData>(eventData));
|
||||
}
|
||||
private static void Execute(IParticipantJoinedHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnParticipantJoined(ValidateEventData<SignalingEventData>(eventData));
|
||||
}
|
||||
private static void Execute(IParticipantLeftHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnParticipantLeft(ValidateEventData<SignalingEventData>(eventData));
|
||||
}
|
||||
private static void Execute(ICallRequestHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnCallRequest(ValidateEventData<SignalingEventData>(eventData));
|
||||
}
|
||||
private static void Execute(IMessageHandler handler, BaseEventData eventData)
|
||||
{
|
||||
handler.OnMessage(ValidateEventData<SignalingEventData>(eventData));
|
||||
}
|
||||
|
||||
public static ExecuteEvents.EventFunction<ICreatedConnectionHandler> createdConnectionHandler
|
||||
{
|
||||
@@ -96,6 +120,22 @@ namespace Unity.RenderStreaming
|
||||
{
|
||||
get { return s_AddReceiverHandler; }
|
||||
}
|
||||
public static ExecuteEvents.EventFunction<IParticipantJoinedHandler> participantJoinedHandler
|
||||
{
|
||||
get { return s_ParticipantJoinedHandler; }
|
||||
}
|
||||
public static ExecuteEvents.EventFunction<IParticipantLeftHandler> participantLeftHandler
|
||||
{
|
||||
get { return s_ParticipantLeftHandler; }
|
||||
}
|
||||
public static ExecuteEvents.EventFunction<ICallRequestHandler> callRequestHandler
|
||||
{
|
||||
get { return s_CallRequestHandler; }
|
||||
}
|
||||
public static ExecuteEvents.EventFunction<IMessageHandler> messageHandler
|
||||
{
|
||||
get { return s_MessageHandler; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
243
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs
vendored
Normal file
243
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.RenderStreaming
|
||||
{
|
||||
/// <summary>
|
||||
/// Host模式的连接处理器
|
||||
/// 适用于私有模式下Unity作为Host(第一个加入房间的客户端)
|
||||
/// 支持多个Participant连接,每个Participant拥有独立的PeerConnection
|
||||
///
|
||||
/// 工作原理:
|
||||
/// - Host通过CreateConnection(connectionId)创建房间连接
|
||||
/// - 当Participant加入时,服务器发送participant-joined通知
|
||||
/// - WebSocketSignaling将participantId作为内部connectionId使用,
|
||||
/// 因此每个Participant会自动创建独立的PeerConnection
|
||||
/// - 当收到Participant的offer时,自动添加Stream并发送answer
|
||||
/// - 当Participant离开时,自动清理对应的连接资源
|
||||
/// </summary>
|
||||
[AddComponentMenu("Render Streaming/Host Connection")]
|
||||
public class HostConnection : SignalingHandlerBase,
|
||||
IOfferHandler, IAddChannelHandler, IDisconnectHandler, IDeletedConnectionHandler,
|
||||
IAddReceiverHandler, IParticipantJoinedHandler, IParticipantLeftHandler,
|
||||
ICallRequestHandler, IMessageHandler
|
||||
{
|
||||
[SerializeField] private List<Component> streams = new List<Component>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前连接的所有Participant的participantId列表
|
||||
/// </summary>
|
||||
private List<string> participantIds = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 房间的connectionId(Host创建连接时使用的ID)
|
||||
/// </summary>
|
||||
private string roomConnectionId;
|
||||
|
||||
public override IEnumerable<Component> Streams => streams;
|
||||
|
||||
public void AddComponent(Component component)
|
||||
{
|
||||
streams.Add(component);
|
||||
}
|
||||
|
||||
public void RemoveComponent(Component component)
|
||||
{
|
||||
streams.Remove(component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Host连接(即创建房间)
|
||||
/// Unity作为第一个连接的客户端,服务器会分配host角色(polite=false)
|
||||
/// </summary>
|
||||
/// <param name="connectionId">房间ID</param>
|
||||
public override void CreateConnection(string connectionId)
|
||||
{
|
||||
roomConnectionId = connectionId;
|
||||
base.CreateConnection(connectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除Host连接(关闭房间)
|
||||
/// Host离开时,服务器会自动断开所有Participant
|
||||
/// </summary>
|
||||
public override void DeleteConnection(string connectionId)
|
||||
{
|
||||
// 清理所有Participant连接
|
||||
foreach (var participantId in participantIds.ToList())
|
||||
{
|
||||
DisconnectParticipant(participantId);
|
||||
}
|
||||
participantIds.Clear();
|
||||
|
||||
if (connectionId == roomConnectionId)
|
||||
{
|
||||
base.DeleteConnection(connectionId);
|
||||
roomConnectionId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DeleteConnection(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDeletedConnection(SignalingEventData eventData)
|
||||
{
|
||||
Disconnect(eventData.connectionId);
|
||||
}
|
||||
|
||||
public void OnDisconnect(SignalingEventData eventData)
|
||||
{
|
||||
Disconnect(eventData.connectionId);
|
||||
}
|
||||
|
||||
private void Disconnect(string connectionId)
|
||||
{
|
||||
if (!participantIds.Contains(connectionId) && connectionId != roomConnectionId)
|
||||
return;
|
||||
|
||||
participantIds.Remove(connectionId);
|
||||
|
||||
foreach (var sender in streams.OfType<IStreamSender>())
|
||||
{
|
||||
RemoveSender(connectionId, sender);
|
||||
}
|
||||
foreach (var receiver in streams.OfType<IStreamReceiver>())
|
||||
{
|
||||
RemoveReceiver(connectionId, receiver);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == connectionId))
|
||||
{
|
||||
RemoveChannel(connectionId, channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开指定Participant的连接资源
|
||||
/// </summary>
|
||||
private void DisconnectParticipant(string participantId)
|
||||
{
|
||||
foreach (var sender in streams.OfType<IStreamSender>())
|
||||
{
|
||||
RemoveSender(participantId, sender);
|
||||
}
|
||||
foreach (var receiver in streams.OfType<IStreamReceiver>())
|
||||
{
|
||||
RemoveReceiver(participantId, receiver);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == participantId))
|
||||
{
|
||||
RemoveChannel(participantId, channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到Participant的offer时触发
|
||||
/// WebSocketSignaling已经将participantId作为内部connectionId
|
||||
/// 所以每个Participant的offer会自动创建独立的PeerConnection
|
||||
/// </summary>
|
||||
public void OnOffer(SignalingEventData data)
|
||||
{
|
||||
// 记录新的Participant连接
|
||||
if (!participantIds.Contains(data.connectionId))
|
||||
{
|
||||
participantIds.Add(data.connectionId);
|
||||
Debug.Log($"[HostConnection] Participant offer received: {data.connectionId}");
|
||||
}
|
||||
|
||||
// 为该Participant添加所有Stream
|
||||
foreach (var source in streams.OfType<IStreamSender>())
|
||||
{
|
||||
AddSender(data.connectionId, source);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.IsLocal))
|
||||
{
|
||||
AddChannel(data.connectionId, channel);
|
||||
}
|
||||
|
||||
// 发送answer给该Participant
|
||||
SendAnswer(data.connectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到远程Track时触发
|
||||
/// </summary>
|
||||
public void OnAddReceiver(SignalingEventData data)
|
||||
{
|
||||
var track = data.transceiver.Receiver.Track;
|
||||
IStreamReceiver receiver = GetReceiver(track.Kind);
|
||||
SetReceiver(data.connectionId, receiver, data.transceiver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到远程DataChannel时触发
|
||||
/// </summary>
|
||||
public void OnAddChannel(SignalingEventData data)
|
||||
{
|
||||
var channel = streams.OfType<IDataChannel>().
|
||||
FirstOrDefault(r => !r.IsConnected && !r.IsLocal);
|
||||
channel?.SetChannel(data.connectionId, data.channel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新Participant加入房间通知
|
||||
/// 在私有模式下,服务器会通知Host有新的Participant加入
|
||||
/// 此时不做额外处理,等收到Participant的offer时再建立连接
|
||||
/// </summary>
|
||||
public void OnParticipantJoined(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Participant joined: connectionId={eventData.connectionId}, participantId={eventData.participantId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Participant离开房间通知
|
||||
/// 清理该Participant的连接资源
|
||||
/// </summary>
|
||||
public void OnParticipantLeft(SignalingEventData eventData)
|
||||
{
|
||||
string participantId = eventData.participantId;
|
||||
if (!string.IsNullOrEmpty(participantId))
|
||||
{
|
||||
Debug.Log($"[HostConnection] Participant left: connectionId={eventData.connectionId}, participantId={participantId}");
|
||||
DisconnectParticipant(participantId);
|
||||
participantIds.Remove(participantId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到呼叫请求
|
||||
/// </summary>
|
||||
public void OnCallRequest(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Call request from: {eventData.connectionId}, data: {eventData.message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到自定义消息
|
||||
/// </summary>
|
||||
public void OnMessage(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Message from: {eventData.connectionId}, participantId: {eventData.participantId}, message: {eventData.message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前连接的Participant数量
|
||||
/// </summary>
|
||||
public int ParticipantCount => participantIds.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有Participant的ID列表
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> ParticipantIds => participantIds.AsReadOnly();
|
||||
|
||||
IStreamReceiver GetReceiver(WebRTC.TrackKind kind)
|
||||
{
|
||||
if (kind == WebRTC.TrackKind.Audio)
|
||||
return streams.OfType<AudioStreamReceiver>().FirstOrDefault();
|
||||
if (kind == WebRTC.TrackKind.Video)
|
||||
return streams.OfType<VideoStreamReceiver>().FirstOrDefault();
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs.meta
vendored
Normal file
11
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b839bc3e2809ef543963ff961d28ce91
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -50,6 +50,26 @@ namespace Unity.RenderStreaming
|
||||
///
|
||||
/// </summary>
|
||||
event Action<string, RTCDataChannel> onAddChannel;
|
||||
|
||||
/// <summary>
|
||||
/// 参与者加入事件 (connectionId, participantId)
|
||||
/// </summary>
|
||||
event Action<string, string> onParticipantJoined;
|
||||
|
||||
/// <summary>
|
||||
/// 参与者离开事件 (connectionId, participantId)
|
||||
/// </summary>
|
||||
event Action<string, string> onParticipantLeft;
|
||||
|
||||
/// <summary>
|
||||
/// 呼叫请求事件 (connectionId, data)
|
||||
/// </summary>
|
||||
event Action<string, string> onCallRequest;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义消息事件 (connectionId, participantId, message)
|
||||
/// </summary>
|
||||
event Action<string, string, string> onMessage;
|
||||
}
|
||||
|
||||
public interface IRenderStreamingHandler
|
||||
|
||||
@@ -41,4 +41,36 @@ namespace Unity.RenderStreaming
|
||||
{
|
||||
void OnAddReceiver(SignalingEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参与者加入事件处理器(仅Host收到)
|
||||
/// </summary>
|
||||
public interface IParticipantJoinedHandler : IEventSystemHandler
|
||||
{
|
||||
void OnParticipantJoined(SignalingEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参与者离开事件处理器
|
||||
/// </summary>
|
||||
public interface IParticipantLeftHandler : IEventSystemHandler
|
||||
{
|
||||
void OnParticipantLeft(SignalingEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 呼叫请求事件处理器
|
||||
/// </summary>
|
||||
public interface ICallRequestHandler : IEventSystemHandler
|
||||
{
|
||||
void OnCallRequest(SignalingEventData eventData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义消息事件处理器
|
||||
/// </summary>
|
||||
public interface IMessageHandler : IEventSystemHandler
|
||||
{
|
||||
void OnMessage(SignalingEventData eventData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,12 @@ namespace Unity.RenderStreaming.Signaling
|
||||
public event OnOfferHandler OnOffer;
|
||||
public event OnAnswerHandler OnAnswer;
|
||||
public event OnIceCandidateHandler OnIceCandidate;
|
||||
#pragma warning disable 0067
|
||||
public event OnParticipantJoinedHandler OnParticipantJoined;
|
||||
public event OnParticipantLeftHandler OnParticipantLeft;
|
||||
public event OnCallRequestHandler OnCallRequest;
|
||||
public event OnMessageHandler OnMessage;
|
||||
#pragma warning restore 0067
|
||||
|
||||
public void SendOffer(string connectionId, RTCSessionDescription offer)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,10 @@ namespace Unity.RenderStreaming.Signaling
|
||||
public delegate void OnOfferHandler(ISignaling signaling, DescData e);
|
||||
public delegate void OnAnswerHandler(ISignaling signaling, DescData e);
|
||||
public delegate void OnIceCandidateHandler(ISignaling signaling, CandidateData e);
|
||||
public delegate void OnParticipantJoinedHandler(ISignaling signaling, ParticipantEventData e);
|
||||
public delegate void OnParticipantLeftHandler(ISignaling signaling, ParticipantEventData e);
|
||||
public delegate void OnCallRequestHandler(ISignaling signaling, CallRequestData e);
|
||||
public delegate void OnMessageHandler(ISignaling signaling, OnMessageData e);
|
||||
|
||||
public interface ISignaling
|
||||
{
|
||||
@@ -20,6 +24,10 @@ namespace Unity.RenderStreaming.Signaling
|
||||
event OnOfferHandler OnOffer;
|
||||
event OnAnswerHandler OnAnswer;
|
||||
event OnIceCandidateHandler OnIceCandidate;
|
||||
event OnParticipantJoinedHandler OnParticipantJoined;
|
||||
event OnParticipantLeftHandler OnParticipantLeft;
|
||||
event OnCallRequestHandler OnCallRequest;
|
||||
event OnMessageHandler OnMessage;
|
||||
|
||||
string Url { get; }
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Unity.RenderStreaming
|
||||
public string sdp;
|
||||
public bool polite;
|
||||
public DateTime dateTime;
|
||||
public string participantId;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -36,6 +37,9 @@ namespace Unity.RenderStreaming
|
||||
public string candidate;
|
||||
public string sdpMid;
|
||||
public int sdpMLineIndex;
|
||||
public string role;
|
||||
public string reason;
|
||||
public string data;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -106,5 +110,36 @@ namespace Unity.RenderStreaming
|
||||
public string datetime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参与者加入/离开事件数据
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ParticipantEventData
|
||||
{
|
||||
public string connectionId;
|
||||
public string participantId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 呼叫请求数据
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CallRequestData
|
||||
{
|
||||
public string connectionId;
|
||||
public string data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义消息数据
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class OnMessageData
|
||||
{
|
||||
public string connectionId;
|
||||
public string participantId;
|
||||
public string message;
|
||||
}
|
||||
|
||||
#pragma warning restore 0649
|
||||
}
|
||||
|
||||
@@ -24,6 +24,23 @@ namespace Unity.RenderStreaming.Signaling
|
||||
public string participantId;
|
||||
public string Url { get { return m_url; } }
|
||||
|
||||
/// <summary>
|
||||
/// 当前客户端是否为Host角色(由服务器在connect响应中分配)
|
||||
/// </summary>
|
||||
public bool isHost { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Host连接时使用的房间connectionId
|
||||
/// </summary>
|
||||
private string m_roomConnectionId;
|
||||
|
||||
/// <summary>
|
||||
/// 参与者连接ID到房间connectionId的映射
|
||||
/// Key: participantId, Value: roomConnectionId
|
||||
/// 用于Host向特定Participant发送消息时,将内部connectionId还原为服务器格式
|
||||
/// </summary>
|
||||
private Dictionary<string, string> m_participantToRoom = new Dictionary<string, string>();
|
||||
|
||||
public WebSocketSignaling(SignalingSettings signalingSettings, SynchronizationContext mainThreadContext)
|
||||
{
|
||||
if (signalingSettings == null)
|
||||
@@ -89,46 +106,97 @@ namespace Unity.RenderStreaming.Signaling
|
||||
public event OnAnswerHandler OnAnswer;
|
||||
#pragma warning restore 0067
|
||||
public event OnIceCandidateHandler OnIceCandidate;
|
||||
public event OnParticipantJoinedHandler OnParticipantJoined;
|
||||
public event OnParticipantLeftHandler OnParticipantLeft;
|
||||
public event OnCallRequestHandler OnCallRequest;
|
||||
public event OnMessageHandler OnMessage;
|
||||
|
||||
/// <summary>
|
||||
/// 判断一个connectionId是否为参与者连接ID(而非房间connectionId)
|
||||
/// </summary>
|
||||
private bool IsParticipantConnectionId(string connectionId)
|
||||
{
|
||||
return m_participantToRoom.ContainsKey(connectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取参与者对应的房间connectionId
|
||||
/// </summary>
|
||||
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();
|
||||
data.connectionId = connectionId;
|
||||
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
|
||||
// 而不是内部participantId(participantId仅通过routedMessage.participantId传递用于目标选择)
|
||||
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
|
||||
data.sdp = offer.sdp;
|
||||
data.dateTime = DateTime.Now;
|
||||
|
||||
RoutedMessage<DescData> routedMessage = new RoutedMessage<DescData>();
|
||||
routedMessage.from = connectionId;
|
||||
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
|
||||
if (IsParticipantConnectionId(connectionId))
|
||||
{
|
||||
routedMessage.from = GetRoomConnectionId(connectionId);
|
||||
routedMessage.participantId = connectionId;
|
||||
}
|
||||
else
|
||||
{
|
||||
routedMessage.from = connectionId;
|
||||
routedMessage.participantId = participantId;
|
||||
}
|
||||
routedMessage.data = data;
|
||||
routedMessage.type = "offer";
|
||||
routedMessage.participantId =participantId;
|
||||
WSSend(routedMessage);
|
||||
}
|
||||
|
||||
public void SendAnswer(string connectionId, RTCSessionDescription answer)
|
||||
{
|
||||
DescData data = new DescData();
|
||||
data.connectionId = connectionId;
|
||||
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
|
||||
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
|
||||
data.sdp = answer.sdp;
|
||||
|
||||
RoutedMessage<DescData> routedMessage = new RoutedMessage<DescData>();
|
||||
routedMessage.from = connectionId;
|
||||
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
|
||||
if (IsParticipantConnectionId(connectionId))
|
||||
{
|
||||
routedMessage.from = GetRoomConnectionId(connectionId);
|
||||
routedMessage.participantId = connectionId;
|
||||
}
|
||||
else
|
||||
{
|
||||
routedMessage.from = connectionId;
|
||||
routedMessage.participantId = participantId;
|
||||
}
|
||||
routedMessage.data = data;
|
||||
routedMessage.type = "answer";
|
||||
routedMessage.participantId =participantId;
|
||||
WSSend(routedMessage);
|
||||
}
|
||||
|
||||
public void SendCandidate(string connectionId, RTCIceCandidate candidate)
|
||||
{
|
||||
CandidateData data = new CandidateData();
|
||||
data.connectionId = connectionId;
|
||||
// data.connectionId必须使用房间connectionId(服务器用此查找连接组进行路由)
|
||||
data.connectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
|
||||
data.candidate = candidate.Candidate;
|
||||
data.sdpMLineIndex = candidate.SdpMLineIndex.GetValueOrDefault(0);
|
||||
data.sdpMid = candidate.SdpMid;
|
||||
|
||||
RoutedMessage<CandidateData> routedMessage = new RoutedMessage<CandidateData>();
|
||||
routedMessage.from = connectionId;
|
||||
// 如果connectionId是参与者ID,使用房间connectionId作为from,并设置目标participantId
|
||||
if (IsParticipantConnectionId(connectionId))
|
||||
{
|
||||
routedMessage.from = GetRoomConnectionId(connectionId);
|
||||
routedMessage.participantId = connectionId;
|
||||
}
|
||||
else
|
||||
{
|
||||
routedMessage.from = connectionId;
|
||||
}
|
||||
routedMessage.data = data;
|
||||
routedMessage.type = "candidate";
|
||||
|
||||
@@ -137,12 +205,16 @@ namespace Unity.RenderStreaming.Signaling
|
||||
|
||||
public void OpenConnection(string connectionId)
|
||||
{
|
||||
m_roomConnectionId = connectionId;
|
||||
this.WSSend($"{{\"type\":\"connect\", \"connectionId\":\"{connectionId}\"}}");
|
||||
}
|
||||
|
||||
public void CloseConnection(string connectionId)
|
||||
{
|
||||
this.WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{connectionId}\"}}");
|
||||
// 如果关闭的是参与者连接,使用房间connectionId发送disconnect
|
||||
string actualConnectionId = IsParticipantConnectionId(connectionId) ? GetRoomConnectionId(connectionId) : connectionId;
|
||||
m_participantToRoom.Remove(connectionId);
|
||||
this.WSSend($"{{\"type\":\"disconnect\", \"connectionId\":\"{actualConnectionId}\"}}");
|
||||
}
|
||||
|
||||
private void WSManage()
|
||||
@@ -211,28 +283,51 @@ namespace Unity.RenderStreaming.Signaling
|
||||
if (routedMessage.type == "connect")
|
||||
{
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
isHost = msg.role == "host";
|
||||
participantId = msg.participantId;
|
||||
m_mainThreadContext.Post(d => OnCreateConnection?.Invoke(this, msg.connectionId, msg.polite), null);
|
||||
participantId=msg.participantId;
|
||||
}
|
||||
else if (routedMessage.type == "disconnect")
|
||||
{
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
m_mainThreadContext.Post(d => OnDestroyConnection?.Invoke(this, msg.connectionId), null);
|
||||
string disconnectConnectionId = msg.connectionId;
|
||||
// 如果断开的是参与者连接,用participantId查找内部connectionId
|
||||
if (!string.IsNullOrEmpty(routedMessage.participantId) && isHost)
|
||||
{
|
||||
disconnectConnectionId = routedMessage.participantId;
|
||||
m_participantToRoom.Remove(routedMessage.participantId);
|
||||
}
|
||||
m_mainThreadContext.Post(d => OnDestroyConnection?.Invoke(this, disconnectConnectionId), null);
|
||||
}
|
||||
else if (routedMessage.type == "offer")
|
||||
{
|
||||
DescData offer = new DescData();
|
||||
offer.connectionId = routedMessage.from;
|
||||
// Host收到带participantId的offer时,使用participantId作为内部connectionId
|
||||
// 这样每个participant会创建独立的PeerConnection
|
||||
if (!string.IsNullOrEmpty(routedMessage.participantId) && isHost)
|
||||
{
|
||||
offer.connectionId = routedMessage.participantId;
|
||||
m_participantToRoom[routedMessage.participantId] = routedMessage.from ?? m_roomConnectionId;
|
||||
}
|
||||
else
|
||||
{
|
||||
offer.connectionId = routedMessage.from;
|
||||
}
|
||||
offer.sdp = msg.sdp;
|
||||
offer.polite = msg.polite;
|
||||
offer.participantId = routedMessage.participantId;
|
||||
m_mainThreadContext.Post(d => OnOffer?.Invoke(this, offer), null);
|
||||
}
|
||||
else if (routedMessage.type == "answer")
|
||||
{
|
||||
DescData answer = new DescData
|
||||
{
|
||||
connectionId = routedMessage.from,
|
||||
sdp = msg.sdp
|
||||
// Host收到带participantId的answer时,使用participantId作为内部connectionId
|
||||
connectionId = !string.IsNullOrEmpty(routedMessage.participantId) && isHost
|
||||
? routedMessage.participantId
|
||||
: routedMessage.from,
|
||||
sdp = msg.sdp,
|
||||
participantId = routedMessage.participantId
|
||||
};
|
||||
m_mainThreadContext.Post(d => OnAnswer?.Invoke(this, answer), null);
|
||||
}
|
||||
@@ -240,13 +335,68 @@ namespace Unity.RenderStreaming.Signaling
|
||||
{
|
||||
CandidateData candidate = new CandidateData
|
||||
{
|
||||
connectionId = routedMessage.@from,
|
||||
// Host收到带participantId的candidate时,使用participantId作为内部connectionId
|
||||
connectionId = !string.IsNullOrEmpty(routedMessage.participantId) && isHost
|
||||
? routedMessage.participantId
|
||||
: routedMessage.@from,
|
||||
candidate = msg.candidate,
|
||||
sdpMLineIndex = msg.sdpMLineIndex,
|
||||
sdpMid = msg.sdpMid
|
||||
sdpMid = msg.sdpMid,
|
||||
participantId = routedMessage.participantId
|
||||
};
|
||||
m_mainThreadContext.Post(d => OnIceCandidate?.Invoke(this, candidate), null);
|
||||
}
|
||||
else if (routedMessage.type == "participant-joined")
|
||||
{
|
||||
// Host收到新参与者加入通知
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
ParticipantEventData participantData = new ParticipantEventData
|
||||
{
|
||||
connectionId = msg.connectionId ?? routedMessage.from,
|
||||
participantId = msg.participantId ?? routedMessage.participantId
|
||||
};
|
||||
// 记录参与者映射
|
||||
if (!string.IsNullOrEmpty(participantData.participantId))
|
||||
{
|
||||
m_participantToRoom[participantData.participantId] = participantData.connectionId;
|
||||
}
|
||||
RenderStreaming.Logger.Log($"Signaling: Participant joined - connectionId: {participantData.connectionId}, participantId: {participantData.participantId}");
|
||||
m_mainThreadContext.Post(d => OnParticipantJoined?.Invoke(this, participantData), null);
|
||||
}
|
||||
else if (routedMessage.type == "participant-left")
|
||||
{
|
||||
// Host/Participant收到参与者离开通知
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
ParticipantEventData participantData = new ParticipantEventData
|
||||
{
|
||||
connectionId = msg.connectionId ?? routedMessage.from,
|
||||
participantId = msg.participantId ?? routedMessage.participantId
|
||||
};
|
||||
m_participantToRoom.Remove(participantData.participantId);
|
||||
RenderStreaming.Logger.Log($"Signaling: Participant left - connectionId: {participantData.connectionId}, participantId: {participantData.participantId}");
|
||||
m_mainThreadContext.Post(d => OnParticipantLeft?.Invoke(this, participantData), null);
|
||||
}
|
||||
else if (routedMessage.type == "call-request")
|
||||
{
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
CallRequestData callData = new CallRequestData
|
||||
{
|
||||
connectionId = routedMessage.from,
|
||||
data = msg.data
|
||||
};
|
||||
m_mainThreadContext.Post(d => OnCallRequest?.Invoke(this, callData), null);
|
||||
}
|
||||
else if (routedMessage.type == "on-message")
|
||||
{
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
OnMessageData messageData = new OnMessageData
|
||||
{
|
||||
connectionId = routedMessage.from,
|
||||
participantId = routedMessage.participantId,
|
||||
message = msg.message
|
||||
};
|
||||
m_mainThreadContext.Post(d => OnMessage?.Invoke(this, messageData), null);
|
||||
}
|
||||
else if (routedMessage.type == "error")
|
||||
{
|
||||
msg = JsonUtility.FromJson<SignalingMessage>(content);
|
||||
|
||||
@@ -28,6 +28,21 @@ namespace Unity.RenderStreaming
|
||||
/// </summary>
|
||||
public string sdp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 参与者ID
|
||||
/// </summary>
|
||||
public string participantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色 (host/participant)
|
||||
/// </summary>
|
||||
public string role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义消息内容
|
||||
/// </summary>
|
||||
public string message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
@@ -20,6 +20,10 @@ namespace Unity.RenderStreaming
|
||||
handler.onGotAnswer += OnGotAnswer;
|
||||
handler.onAddChannel += OnAddChannel;
|
||||
handler.onAddTransceiver += OnAddReceiver;
|
||||
handler.onParticipantJoined += OnParticipantJoined;
|
||||
handler.onParticipantLeft += OnParticipantLeft;
|
||||
handler.onCallRequest += OnCallRequest;
|
||||
handler.onMessage += OnMessage;
|
||||
}
|
||||
|
||||
public bool Subscribe(Component comp)
|
||||
@@ -137,5 +141,46 @@ namespace Unity.RenderStreaming
|
||||
};
|
||||
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.addReceiverHandler);
|
||||
}
|
||||
|
||||
private void OnParticipantJoined(string connectionId, string participantId)
|
||||
{
|
||||
var data = new SignalingEventData(EventSystem.current)
|
||||
{
|
||||
connectionId = connectionId,
|
||||
participantId = participantId
|
||||
};
|
||||
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.participantJoinedHandler);
|
||||
}
|
||||
|
||||
private void OnParticipantLeft(string connectionId, string participantId)
|
||||
{
|
||||
var data = new SignalingEventData(EventSystem.current)
|
||||
{
|
||||
connectionId = connectionId,
|
||||
participantId = participantId
|
||||
};
|
||||
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.participantLeftHandler);
|
||||
}
|
||||
|
||||
private void OnCallRequest(string connectionId, string callData)
|
||||
{
|
||||
var data = new SignalingEventData(EventSystem.current)
|
||||
{
|
||||
connectionId = connectionId,
|
||||
message = callData
|
||||
};
|
||||
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.callRequestHandler);
|
||||
}
|
||||
|
||||
private void OnMessage(string connectionId, string participantId, string message)
|
||||
{
|
||||
var data = new SignalingEventData(EventSystem.current)
|
||||
{
|
||||
connectionId = connectionId,
|
||||
participantId = participantId,
|
||||
message = message
|
||||
};
|
||||
ExecuteEventToAllTargets(data, ExecuteSignalingEvents.messageHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,26 @@ namespace Unity.RenderStreaming
|
||||
/// </summary>
|
||||
public event Action<string, RTCDataChannel> onAddChannel;
|
||||
|
||||
/// <summary>
|
||||
/// 参与者加入事件 (connectionId, participantId)
|
||||
/// </summary>
|
||||
public event Action<string, string> onParticipantJoined;
|
||||
|
||||
/// <summary>
|
||||
/// 参与者离开事件 (connectionId, participantId)
|
||||
/// </summary>
|
||||
public event Action<string, string> onParticipantLeft;
|
||||
|
||||
/// <summary>
|
||||
/// 呼叫请求事件 (connectionId, data)
|
||||
/// </summary>
|
||||
public event Action<string, string> onCallRequest;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义消息事件 (connectionId, participantId, message)
|
||||
/// </summary>
|
||||
public event Action<string, string, string> onMessage;
|
||||
|
||||
private bool _disposed;
|
||||
private readonly ISignaling _signaling;
|
||||
private RTCConfiguration _config;
|
||||
@@ -122,6 +142,10 @@ namespace Unity.RenderStreaming
|
||||
_signaling.OnOffer += OnOffer;
|
||||
_signaling.OnAnswer += OnAnswer;
|
||||
_signaling.OnIceCandidate += OnIceCandidate;
|
||||
_signaling.OnParticipantJoined += OnParticipantJoinedHandler;
|
||||
_signaling.OnParticipantLeft += OnParticipantLeftHandler;
|
||||
_signaling.OnCallRequest += OnCallRequestHandler;
|
||||
_signaling.OnMessage += OnMessageHandler;
|
||||
_signaling.Start();
|
||||
_startCoroutine(WebRTC.WebRTC.Update());
|
||||
}
|
||||
@@ -153,6 +177,10 @@ namespace Unity.RenderStreaming
|
||||
_signaling.OnOffer -= OnOffer;
|
||||
_signaling.OnAnswer -= OnAnswer;
|
||||
_signaling.OnIceCandidate -= OnIceCandidate;
|
||||
_signaling.OnParticipantJoined -= OnParticipantJoinedHandler;
|
||||
_signaling.OnParticipantLeft -= OnParticipantLeftHandler;
|
||||
_signaling.OnCallRequest -= OnCallRequestHandler;
|
||||
_signaling.OnMessage -= OnMessageHandler;
|
||||
|
||||
foreach (var pair in _mapConnectionIdAndPeer)
|
||||
pair.Value.Dispose();
|
||||
@@ -428,5 +456,30 @@ namespace Unity.RenderStreaming
|
||||
RTCSessionDescription description = new RTCSessionDescription { type = RTCSdpType.Offer, sdp = e.sdp };
|
||||
_startCoroutine(pc.OnGotDescription(description, () => onGotOffer?.Invoke(connectionId, e.sdp)));
|
||||
}
|
||||
|
||||
void OnParticipantJoinedHandler(ISignaling signaling, ParticipantEventData e)
|
||||
{
|
||||
onParticipantJoined?.Invoke(e.connectionId, e.participantId);
|
||||
}
|
||||
|
||||
void OnParticipantLeftHandler(ISignaling signaling, ParticipantEventData e)
|
||||
{
|
||||
// 参与者离开时,销毁对应的PeerConnection
|
||||
if (_mapConnectionIdAndPeer.ContainsKey(e.participantId))
|
||||
{
|
||||
DestroyConnection(e.participantId);
|
||||
}
|
||||
onParticipantLeft?.Invoke(e.connectionId, e.participantId);
|
||||
}
|
||||
|
||||
void OnCallRequestHandler(ISignaling signaling, CallRequestData e)
|
||||
{
|
||||
onCallRequest?.Invoke(e.connectionId, e.data);
|
||||
}
|
||||
|
||||
void OnMessageHandler(ISignaling signaling, OnMessageData e)
|
||||
{
|
||||
onMessage?.Invoke(e.connectionId, e.participantId, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user