예제 #1
0
        /// <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;

            dotFlex.Messaging.Rtmp.SO.SharedObjectMessage message;
            if (connection.ObjectEncoding == ObjectEncoding.AMF0)
            {
                message = new dotFlex.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO);
            }
            else
            {
                message = new dotFlex.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO);
            }
            dotFlex.Messaging.Rtmp.SO.SharedObjectEvent evt = new dotFlex.Messaging.Rtmp.SO.SharedObjectEvent(dotFlex.Messaging.Rtmp.SO.SharedObjectEventType.SERVER_CONNECT, null, null);
            message.AddEvent(evt);
            _connection.NetConnectionClient.Write(message);
        }
예제 #2
0
 /// <summary>
 /// Initializes a new instance of the SharedObject class.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="name"></param>
 /// <param name="path"></param>
 /// <param name="persistent"></param>
 public SharedObject(IDictionary data, string name, string path, bool persistent)
 {
     base.SetAttributes(data);
     _name         = name;
     _path         = path;
     _persistentSO = persistent;
     _ownerMessage = new SharedObjectMessage(null, name, 0, persistent);
     _creationTime = System.Environment.TickCount;
 }
예제 #3
0
        /// <summary>
        /// Closes the connection between a remote shared object and the server.
        /// </summary>
        public void Close()
        {
            if (_initialSyncReceived && _connection != null && _connection.Connected)
            {
                dotFlex.Messaging.Rtmp.SO.SharedObjectMessage message;
                if (_connection.ObjectEncoding == ObjectEncoding.AMF0)
                {
                    message = new dotFlex.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO);
                }
                else
                {
                    message = new dotFlex.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO);
                }
                dotFlex.Messaging.Rtmp.SO.SharedObjectEvent evt = new dotFlex.Messaging.Rtmp.SO.SharedObjectEvent(dotFlex.Messaging.Rtmp.SO.SharedObjectEventType.SERVER_DISCONNECT, null, null);
                message.AddEvent(evt);
                _connection.NetConnectionClient.Write(message);

                // clear collections
                base.RemoveAttributes();
                _ownerMessage.Events.Clear();
            }
            _initialSyncReceived = false;
        }
예제 #4
0
        /// <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);
				}
			}
		}
예제 #5
0
		/// <summary>
		/// Initializes a new instance of the SharedObject class.
		/// </summary>
		/// <param name="data"></param>
		/// <param name="name"></param>
		/// <param name="path"></param>
		/// <param name="persistent"></param>
        public SharedObject(IDictionary data, string name, string path, bool persistent)
		{
			base.SetAttributes(data);
			_name = name;
			_path = path;
			_persistentSO = persistent;
			_ownerMessage = new SharedObjectMessage(null, name, 0, persistent);
            _creationTime = System.Environment.TickCount;
		}
예제 #6
0
		/// <summary>
        /// Initializes a new instance of the SharedObject class. This is used by the persistence framework.
		/// </summary>
		public SharedObject()
		{
			_ownerMessage = new SharedObjectMessage(null, null, -1, false);
            _persistentSO = false;
            _creationTime = System.Environment.TickCount;
		}
예제 #7
0
		static ISharedObjectMessage DecodeSharedObject(ByteBuffer stream)
		{
			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
			//skip(4);
			reader.ReadInt32();

			SharedObjectMessage so = new SharedObjectMessage(null, name, version, persistent);
			DecodeSharedObject(so, stream, reader);
			return so;
		}
예제 #8
0
		static void DecodeSharedObject(SharedObjectMessage so, ByteBuffer stream, RtmpReader reader)
		{
			// Parse request body
			while(stream.HasRemaining)
			{
				byte typeCode = reader.ReadByte();
				SharedObjectEventType type = SharedObjectTypeMapping.ToType(typeCode);
				string key = null;
				object value = null;

				int length = stream.GetInt();//reader.ReadInt32();
				switch(type)
				{
					case SharedObjectEventType.CLIENT_STATUS:
						// Status code
						key = reader.ReadString();
						// Status level
						value = reader.ReadString();
						break;
					case SharedObjectEventType.CLIENT_UPDATE_DATA:
					{
                        key = reader.ReadString();
                        value = reader.ReadData();
                        /*
						key = null;
						// Map containing new attribute values
						Hashtable map = new Hashtable();
						int start = (int)stream.Position;
						while((int)stream.Position - start < length) 
						{
							string tmp = reader.ReadString();
							map[tmp] = reader.ReadData();
						}
						value = map;
                        */
					}
						break;
					default:
						if (type != SharedObjectEventType.SERVER_SEND_MESSAGE && type != SharedObjectEventType.CLIENT_SEND_MESSAGE) 
						{
							if (length > 0) 
							{
								key = reader.ReadString();
								if(length > key.Length + 2) 
								{
									value = reader.ReadData();
								}
							}
						} 
						else 
						{
							int start = (int)stream.Position;
							// the "send" event seems to encode the handler name
							// as complete AMF string including the string type byte
							key = reader.ReadData() as string;
							// read parameters
#if !(NET_1_1)
                            List<object> paramList = new List<object>();
#else
							ArrayList paramList = new ArrayList();
#endif
                            while (stream.Position - start < length)
							{
								object tmp = reader.ReadData();
								paramList.Add(tmp);
							}
							value = paramList;
						}
						break;
				}
				so.AddEvent(type, key, value);
			}
		}
예제 #9
0
 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);
 }
예제 #10
0
 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);
 }
예제 #11
0
        protected override void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message) 
		{
			ISharedObject so = null;
			string name = message.Name;
			IScope scope = connection.Scope;
            bool persistent = message.IsPersistent;
			if(scope == null) 
			{
                // The scope already has been deleted.
                SendSOCreationFailed(connection, name, persistent);
				return;
			}
            ISharedObjectService sharedObjectService = ScopeUtils.GetScopeService(scope, typeof(ISharedObjectService)) as ISharedObjectService;
			if (!sharedObjectService.HasSharedObject(scope, name))
			{
                ISharedObjectSecurityService securityService = ScopeUtils.GetScopeService(scope, typeof(ISharedObjectSecurityService)) as ISharedObjectSecurityService;
			    if (securityService != null) 
                {
				    // Check handlers to see if creation is allowed
                    IEnumerator enumerator = securityService.GetSharedObjectSecurity();
                    while(enumerator.MoveNext())
                    {
                        ISharedObjectSecurity handler = enumerator.Current as ISharedObjectSecurity;
                        if (!handler.IsCreationAllowed(scope, name, persistent))
                        {
                            SendSOCreationFailed(connection, name, persistent);
						    return;
					    }
				    }
			    }

                if (!sharedObjectService.CreateSharedObject(scope, name, persistent)) 
				{
                    SendSOCreationFailed(connection, name, persistent);
					return;
				}
			}
			so = sharedObjectService.GetSharedObject(scope, name);
            if (so.IsPersistentObject != persistent)
            {
                log.Debug(string.Format("Shared object '{0}' persistence mismatch", name));
                SendSOPersistenceMismatch(connection, name, persistent);
                return;
            }
			so.DispatchEvent(message);
		}
예제 #12
0
 /// <summary>
 /// This method supports the Fluorine infrastructure and is not intended to be used directly from your code.
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="channel"></param>
 /// <param name="header"></param>
 /// <param name="message"></param>
 protected abstract void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message);
예제 #13
0
        /// <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);
                }
            }
        }
예제 #14
0
 /// <summary>
 /// Initializes a new instance of the SharedObject class. This is used by the persistence framework.
 /// </summary>
 public SharedObject()
 {
     _ownerMessage = new SharedObjectMessage(null, null, -1, false);
     _persistentSO = false;
     _creationTime = System.Environment.TickCount;
 }