/// <summary> /// Connects to the media server. /// </summary> /// <param name="roomId">The room on the media server</param> /// <param name="callback">An optional callback to be called when connection is finished.</param> /// <remarks> /// The connection process is complicated, due to the fact that we have to first connect to the control port (4521), /// and then if that is successful, we then connect to the data port (4522). And of course, both connection attempts are /// asynchronous. The result is that the logic in a successful connection attempt flows like this: /// Connect() -> controlClient.Connect() => /// HandleControlConnect() -> RegisterClientOnServer() -> controlClient.Send() => /// HandleControlData() -> rtpClient.Connect() => /// HandleRtpConnect() -> rtpClient.Send() => /// HandleRtpData() -> FinalizeConnection() -> connectionCallback() /// An error anywhere in that flow will result in control being transferred to FinalizeConnection(). /// </remarks> public virtual void Connect(string roomId, Action <Exception> callback = null) { if (_isActive) { MediaConnection.Connect(roomId, callback); _roomId = roomId; } else { if (callback != null) { callback(null); } } }