Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Runtime/Scripts/Room.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ public class Room : IDisposable
public delegate void SipDtmfDelegate(Participant participant, UInt32 code, string digit);
public delegate void ConnectionStateChangeDelegate(ConnectionState connectionState);
public delegate void ConnectionDelegate(Room room);
public delegate void DisconnectDelegate(Room room, DisconnectReason reason);
public delegate void ParticipantDisconnectDelegate(Participant participant, DisconnectReason reason);
public delegate void E2EeStateChangedDelegate(Participant participant, EncryptionState state);
public delegate void DataTrackPublishedDelegate(RemoteDataTrack track);
public delegate void DataTrackUnpublishedDelegate(string sid);
Expand All @@ -137,11 +139,13 @@ public class Room : IDisposable
public LocalParticipant LocalParticipant { private set; get; }
public ConnectionState ConnectionState { private set; get; }
public bool IsConnected => RoomHandle != null && ConnectionState != ConnectionState.ConnDisconnected;
public DisconnectReason DisconnectReason { private set; get; }
public E2EEManager E2EEManager { internal set; get; }
public IReadOnlyDictionary<string, RemoteParticipant> RemoteParticipants => _participants;

public event ParticipantDelegate ParticipantConnected;
public event ParticipantDelegate ParticipantDisconnected;
public event ParticipantDisconnectDelegate ParticipantDisconnectedWithReason;
public event LocalPublishDelegate LocalTrackPublished;
public event LocalPublishDelegate LocalTrackUnpublished;
public event PublishDelegate TrackPublished;
Expand All @@ -157,6 +161,7 @@ public class Room : IDisposable
public event ConnectionStateChangeDelegate ConnectionStateChanged;
public event ConnectionDelegate Connected;
public event ConnectionDelegate Disconnected;
public event DisconnectDelegate DisconnectedWithReason;
public event ConnectionDelegate Reconnecting;
public event ConnectionDelegate Reconnected;
public event E2EeStateChangedDelegate E2EeStateChanged;
Expand Down Expand Up @@ -366,6 +371,7 @@ internal void OnEventReceived(RoomEvent e)
var participant = RemoteParticipants[sid];
_participants.Remove(sid);
ParticipantDisconnected?.Invoke(participant);
ParticipantDisconnectedWithReason?.Invoke(participant, e.ParticipantDisconnected.DisconnectReason);
}
break;
case RoomEvent.MessageOneofCase.TrackPublished:
Expand Down Expand Up @@ -536,7 +542,9 @@ internal void OnEventReceived(RoomEvent e)
ConnectionStateChanged?.Invoke(e.ConnectionStateChanged.State);
break;
case RoomEvent.MessageOneofCase.Disconnected:
DisconnectReason = e.Disconnected.Reason;
Disconnected?.Invoke(this);
DisconnectedWithReason?.Invoke(this, DisconnectReason);
OnDisconnect();
break;
case RoomEvent.MessageOneofCase.Reconnecting:
Expand Down
10 changes: 8 additions & 2 deletions Samples~/Meet/Assets/Runtime/MeetManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ private IEnumerator ConnectToRoom()
_room.TrackMuted += OnTrackMuted;
_room.TrackUnmuted += OnTrackUnmuted;
_room.ParticipantConnected += OnParticipantConnected;
_room.ParticipantDisconnected += OnParticipantDisconnected;
_room.ParticipantDisconnectedWithReason += OnParticipantDisconnected;
_room.Disconnected += OnDisconnected;
_room.DataReceived += OnDataReceived;

var connect = _room.Connect(details.ServerUrl, details.ParticipantToken, new RoomOptions());
Expand Down Expand Up @@ -400,8 +401,10 @@ private void OnDataReceived(byte[] data, Participant participant, DataPacketKind
private void OnParticipantConnected(Participant participant)
=> EnsureParticipantTile(participant.Identity);

private void OnParticipantDisconnected(Participant participant)
private void OnParticipantDisconnected(Participant participant, DisconnectReason reason)
{
Debug.Log($"Participant {participant.Identity} disconnected: {reason}");

var owned = new List<string>();
foreach (var kv in _extraVideoOwners)
if (kv.Value == participant.Identity) owned.Add(kv.Key);
Expand All @@ -410,6 +413,9 @@ private void OnParticipantDisconnected(Participant participant)
DestroyParticipantTile(participant.Identity);
}

private void OnDisconnected(Room room)
=> Debug.Log($"Disconnected from room: {room.DisconnectReason}");

private void OnTrackMuted(TrackPublication publication, Participant participant)
{
if (publication.Kind == TrackKind.KindAudio
Expand Down
87 changes: 87 additions & 0 deletions Tests/EditMode/RoomDisconnectReasonTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using LiveKit.Internal;
using LiveKit.Proto;
using NUnit.Framework;

namespace LiveKit.EditModeTests
{
// Drives Room.OnEventReceived with synthetic FFI events to verify that the
// DisconnectReason carried by the native layer is surfaced through the public
// API. A zero FfiHandle is treated as invalid by the SafeHandle, so disposal
// is a no-op and no native FFI drop is attempted; matching the event's
// RoomHandle to it (also 0) lets OnEventReceived process the event.
public class RoomDisconnectReasonTests
{
[Test]
public void DisconnectReason_DefaultsToUnknown()
{
var room = new Room();
Assert.AreEqual(DisconnectReason.UnknownReason, room.DisconnectReason);
}

[Test]
public void Disconnected_SurfacesReasonOnPropertyAndEvent()
{
var room = new Room();
room.RoomHandle = new FfiHandle(IntPtr.Zero);

DisconnectReason? eventReason = null;
Room eventRoom = null;
room.DisconnectedWithReason += (r, reason) =>
{
eventRoom = r;
eventReason = reason;
};

room.OnEventReceived(new RoomEvent
{
RoomHandle = 0,
Disconnected = new Disconnected { Reason = DisconnectReason.ServerShutdown }
});

Assert.AreEqual(DisconnectReason.ServerShutdown, room.DisconnectReason,
"Room.DisconnectReason should reflect the reason from the FFI event.");
Assert.AreEqual(DisconnectReason.ServerShutdown, eventReason,
"DisconnectedWithReason should fire carrying the reason.");
Assert.AreSame(room, eventRoom);
}

[Test]
public void ParticipantDisconnected_SurfacesReasonOnEvent()
{
var room = new Room();
room.RoomHandle = new FfiHandle(IntPtr.Zero);

const string identity = "remote-participant";
// Id 0 -> invalid FfiHandle, so the participant carries no live native handle.
room.CreateRemoteParticipant(new OwnedParticipant
{
Handle = new FfiOwnedHandle { Id = 0 },
Info = new ParticipantInfo { Identity = identity }
});

DisconnectReason? eventReason = null;
Participant eventParticipant = null;
room.ParticipantDisconnectedWithReason += (participant, reason) =>
{
eventParticipant = participant;
eventReason = reason;
};

room.OnEventReceived(new RoomEvent
{
RoomHandle = 0,
ParticipantDisconnected = new ParticipantDisconnected
{
ParticipantIdentity = identity,
DisconnectReason = DisconnectReason.ParticipantRemoved
}
});

Assert.AreEqual(DisconnectReason.ParticipantRemoved, eventReason,
"ParticipantDisconnectedWithReason should fire carrying the reason.");
Assert.IsNotNull(eventParticipant);
Assert.AreEqual(identity, eventParticipant.Identity);
}
}
}
11 changes: 11 additions & 0 deletions Tests/EditMode/RoomDisconnectReasonTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading