/// <summary> /// Connects to a remote shared object on the server through the specified connection. Use this method after /// issuing SharedObject.GetRemote(...). After a successful connection, the sync event is dispatched. /// </summary> /// <param name="connection">A NetConnection object (such as one used to communicate with Flash Media Server) that is using the Real-Time Messaging Protocol (RTMP).</param> /// <param name="parameters">Parameters.</param> public void Connect(NetConnection connection, string parameters) { if (_initialSyncReceived) { throw new InvalidOperationException("SharedObject already connected"); } ValidationUtils.ArgumentNotNull(connection, "connection"); ValidationUtils.ArgumentNotNull(connection.Uri, "connection"); ValidationUtils.ArgumentConditionTrue(connection.Uri.Scheme == "rtmp", "connection", "NetConnection object must use the Real-Time Messaging Protocol (RTMP)"); ValidationUtils.ArgumentConditionTrue(connection.Connected, "connection", "NetConnection object must be connected"); _connection = connection; _initialSyncReceived = false; FluorineFx.Messaging.Rtmp.SO.SharedObjectMessage message; if (connection.ObjectEncoding == ObjectEncoding.AMF0) { message = new FluorineFx.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO); } else { message = new FluorineFx.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO); } FluorineFx.Messaging.Rtmp.SO.SharedObjectEvent evt = new FluorineFx.Messaging.Rtmp.SO.SharedObjectEvent(FluorineFx.Messaging.Rtmp.SO.SharedObjectEventType.SERVER_CONNECT, null, null); message.AddEvent(evt); _connection.NetConnectionClient.Write(message); }
/// <summary> /// Closes the connection between a remote shared object and the server. /// </summary> public void Close() { if (_initialSyncReceived && _connection != null && _connection.Connected) { FluorineFx.Messaging.Rtmp.SO.SharedObjectMessage message; if (_connection.ObjectEncoding == ObjectEncoding.AMF0) { message = new FluorineFx.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO); } else { message = new FluorineFx.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO); } FluorineFx.Messaging.Rtmp.SO.SharedObjectEvent evt = new FluorineFx.Messaging.Rtmp.SO.SharedObjectEvent(FluorineFx.Messaging.Rtmp.SO.SharedObjectEventType.SERVER_DISCONNECT, null, null); message.AddEvent(evt); _connection.NetConnectionClient.Write(message); // clear collections base.RemoveAttributes(); _ownerMessage.Events.Clear(); } _initialSyncReceived = false; }
private static void SendSOPersistenceMismatch(RtmpConnection connection, string name, bool persistent) { SharedObjectMessage msg; if (connection.ObjectEncoding == ObjectEncoding.AMF0) msg = new SharedObjectMessage(name, 0, persistent); else msg = new FlexSharedObjectMessage(name, 0, persistent); msg.AddEvent(new SharedObjectEvent(SharedObjectEventType.CLIENT_STATUS, StatusASO.SO_PERSISTENCE_MISMATCH, "error")); connection.GetChannel((byte)3).Write(msg); }
private static void SendSOCreationFailed(RtmpConnection connection, string name, bool persistent) { SharedObjectMessage msg; if (connection.ObjectEncoding == ObjectEncoding.AMF0) msg = new SharedObjectMessage(name, 0, persistent); else msg = new FlexSharedObjectMessage(name, 0, persistent); msg.AddEvent(new SharedObjectEvent(SharedObjectEventType.CLIENT_STATUS, StatusASO.SO_CREATION_FAILED, "error")); connection.GetChannel((byte)3).Write(msg); }
/// <summary> /// Send update notification over data channel of RTMP connection /// </summary> private void SendUpdates() { int currentVersion = _version.Value; bool persist = this.IsPersistentObject; //Get read-only version of events ConcurrentLinkedQueue<ISharedObjectEvent> events = new ConcurrentLinkedQueue<ISharedObjectEvent>(_ownerMessage.Events); //clear out previous events _ownerMessage.Events.Clear(); if (events.Count != 0) { //Send update to "owner" of this update request if(_source != null) { RtmpConnection connection = _source as RtmpConnection; // Only send updates when issued through RTMP request RtmpChannel channel = connection.GetChannel((byte)3); // Send update to "owner" of this update request SharedObjectMessage syncOwner; if (connection.ObjectEncoding == ObjectEncoding.AMF0) syncOwner = new SharedObjectMessage(null, _name, currentVersion, persist); else syncOwner = new FlexSharedObjectMessage(null, _name, currentVersion, persist); syncOwner.AddEvents(events); if(channel != null) { channel.Write(syncOwner); } else { log.Warn(__Res.GetString(__Res.Channel_NotFound)); } } } //Clear owner events events.Clear(); //Get read-only version of sync events events.AddRange(_syncEvents); //Clear out previous events _syncEvents.Clear(); if (events.Count != 0) { // Synchronize updates with all registered clients of this shared foreach(IEventListener listener in _listeners) { if(listener == _source) { // Don't re-send update to active client continue; } if(!(listener is RtmpConnection)) { log.Warn(__Res.GetString(__Res.SharedObject_SyncConnError)); continue; } // Create a new sync message for every client to avoid // concurrent access through multiple threads // TODO: perhaps we could cache the generated message RtmpConnection connection = listener as RtmpConnection; SharedObjectMessage syncMessage; if (connection.ObjectEncoding == ObjectEncoding.AMF0) syncMessage = new SharedObjectMessage(null, _name, currentVersion, persist); else syncMessage = new FlexSharedObjectMessage(null, _name, currentVersion, persist); syncMessage.AddEvents(events); RtmpChannel channel = connection.GetChannel((byte)3); log.Debug(__Res.GetString(__Res.SharedObject_Sync, channel)); channel.Write(syncMessage); } } }
static ISharedObjectMessage DecodeFlexSharedObject(ByteBuffer stream) { // Unknown byte, always 0? stream.Skip(1); RtmpReader reader = new RtmpReader(stream); string name = reader.ReadString(); // Read version of SO to modify int version = reader.ReadInt32(); // Read persistence informations bool persistent = reader.ReadInt32() == 2; // Skip unknown bytes reader.ReadInt32(); SharedObjectMessage so = new FlexSharedObjectMessage(null, name, version, persistent); DecodeSharedObject(so, stream, reader); return so; }
private void SendUpdates() { RtmpConnection connection; RtmpChannel channel; if (this._ownerMessage.Events.Count != 0) { if (this._source != null) { SharedObjectMessage message; connection = this._source as RtmpConnection; channel = connection.GetChannel(3); if (connection.ObjectEncoding == ObjectEncoding.AMF0) { message = new SharedObjectMessage(null, this._name, this._version, this.IsPersistentObject); } else { message = new FlexSharedObjectMessage(null, this._name, this._version, this.IsPersistentObject); } message.AddEvents(this._ownerMessage.Events); if (channel != null) { channel.Write(message); } else { log.Warn(__Res.GetString("Channel_NotFound")); } } this._ownerMessage.Events.Clear(); } if (this._syncEvents.Count != 0) { foreach (IEventListener listener in this._listeners) { if (listener != this._source) { if (!(listener is RtmpConnection)) { log.Warn(__Res.GetString("SharedObject_SyncConnError")); } else { SharedObjectMessage message2; connection = listener as RtmpConnection; if (connection.ObjectEncoding == ObjectEncoding.AMF0) { message2 = new SharedObjectMessage(null, this._name, this._version, this.IsPersistentObject); } else { message2 = new FlexSharedObjectMessage(null, this._name, this._version, this.IsPersistentObject); } message2.AddEvents(this._syncEvents); channel = connection.GetChannel(3); log.Debug(__Res.GetString("SharedObject_Sync", new object[] { channel })); channel.Write(message2); } } } this._syncEvents.Clear(); } }
/// <summary> /// Send update notification over data channel of RTMP connection /// </summary> private void SendUpdates() { int currentVersion = _version.Value; bool persist = this.IsPersistentObject; //Get read-only version of events ConcurrentLinkedQueue <ISharedObjectEvent> events = new ConcurrentLinkedQueue <ISharedObjectEvent>(_ownerMessage.Events); //clear out previous events _ownerMessage.Events.Clear(); if (events.Count != 0) { //Send update to "owner" of this update request if (_source != null) { RtmpConnection connection = _source as RtmpConnection; // Only send updates when issued through RTMP request RtmpChannel channel = connection.GetChannel((byte)3); // Send update to "owner" of this update request SharedObjectMessage syncOwner; if (connection.ObjectEncoding == ObjectEncoding.AMF0) { syncOwner = new SharedObjectMessage(null, _name, currentVersion, persist); } else { syncOwner = new FlexSharedObjectMessage(null, _name, currentVersion, persist); } syncOwner.AddEvents(events); if (channel != null) { channel.Write(syncOwner); } else { log.Warn(__Res.GetString(__Res.Channel_NotFound)); } } } //Clear owner events events.Clear(); //Get read-only version of sync events events.AddRange(_syncEvents); //Clear out previous events _syncEvents.Clear(); if (events.Count != 0) { // Synchronize updates with all registered clients of this shared foreach (IEventListener listener in _listeners) { if (listener == _source) { // Don't re-send update to active client continue; } if (!(listener is RtmpConnection)) { log.Warn(__Res.GetString(__Res.SharedObject_SyncConnError)); continue; } // Create a new sync message for every client to avoid // concurrent access through multiple threads // TODO: perhaps we could cache the generated message RtmpConnection connection = listener as RtmpConnection; SharedObjectMessage syncMessage; if (connection.ObjectEncoding == ObjectEncoding.AMF0) { syncMessage = new SharedObjectMessage(null, _name, currentVersion, persist); } else { syncMessage = new FlexSharedObjectMessage(null, _name, currentVersion, persist); } syncMessage.AddEvents(events); RtmpChannel channel = connection.GetChannel((byte)3); log.Debug(__Res.GetString(__Res.SharedObject_Sync, channel)); channel.Write(syncMessage); } } }