示例#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;

            GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectMessage message;
            if (connection.ObjectEncoding == ObjectEncoding.AMF0)
            {
                message = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO);
            }
            else
            {
                message = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO);
            }
            GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectEvent evt = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectEvent(GodLesZ.Library.Amf.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)
            {
                GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectMessage message;
                if (_connection.ObjectEncoding == ObjectEncoding.AMF0)
                {
                    message = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectMessage(_name, _version, _persistentSO);
                }
                else
                {
                    message = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.FlexSharedObjectMessage(_name, _version, _persistentSO);
                }
                GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectEvent evt = new GodLesZ.Library.Amf.Messaging.Rtmp.SO.SharedObjectEvent(GodLesZ.Library.Amf.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. This is used by the persistence framework.
 /// </summary>
 public SharedObject()
 {
     _ownerMessage = new SharedObjectMessage(null, null, -1, false);
     _persistentSO = false;
     _creationTime = System.Environment.TickCount;
 }
示例#6
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);
				}
			}
		}
示例#7
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;
		}
示例#8
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;
		}
示例#9
0
		/// <summary>
		/// This method supports the 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);
示例#10
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;
		}
示例#11
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);
			}
		}
示例#12
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);
		}
示例#13
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);
		}
示例#14
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);
		}