예제 #1
0
        public static ByteBuffer EncodeMessage(RtmpContext context, RtmpHeader header, IRtmpEvent message)
        {
            switch (header.DataType)
            {
            case Constants.TypeChunkSize:
                return(EncodeChunkSize(context, message as ChunkSize));

            case Constants.TypeInvoke:
                return(EncodeInvoke(context, message as Invoke));

            case Constants.TypeFlexInvoke:
                return(EncodeFlexInvoke(context, message as FlexInvoke));

            case Constants.TypeSharedObject:
                return(EncodeSharedObject(context, message as ISharedObjectMessage));

            case Constants.TypeFlexSharedObject:
                return(EncodeFlexSharedObject(context, message as ISharedObjectMessage));

            case Constants.TypeNotify:
                if ((message as Notify).ServiceCall == null)
                {
                    return(EncodeStreamMetadata(context, message as Notify));
                }
                else
                {
                    return(EncodeNotify(context, message as Notify));
                }

            case Constants.TypePing:
                return(EncodePing(context, message as Ping));

            case Constants.TypeBytesRead:
                return(EncodeBytesRead(context, message as BytesRead));

            case Constants.TypeAudioData:
                return(EncodeAudioData(context, message as AudioData));

            case Constants.TypeVideoData:
                return(EncodeVideoData(context, message as VideoData));

            case Constants.TypeServerBandwidth:
                return(EncodeServerBW(context, message as ServerBW));

            case Constants.TypeClientBandwidth:
                return(EncodeClientBW(context, message as ClientBW));

            case Constants.TypeFlexStreamEnd:
                return(EncodeFlexStreamSend(context, message as FlexStreamSend));

            default:
#if !SILVERLIGHT
                if (_log.IsErrorEnabled)
                {
                    _log.Error("Unknown object type: " + header.DataType);
                }
#endif
                return(null);
            }
        }
예제 #2
0
        /// <summary>
        /// Determine type of header to use.
        /// </summary>
        /// <param name="header">RTMP message header.</param>
        /// <param name="lastHeader">Previous header.</param>
        /// <returns>Header type to use.</returns>
        private static HeaderType GetHeaderType(RtmpHeader header, RtmpHeader lastHeader)
        {
            HeaderType headerType;

            if (lastHeader == null ||
                header.StreamId != lastHeader.StreamId ||
                !header.IsTimerRelative)
            {
                // New header mark if header for another stream
                headerType = HeaderType.HeaderNew;
            }
            else if (header.Size != lastHeader.Size ||
                     header.DataType != lastHeader.DataType)
            {
                // Same source header if last header data type or size differ
                headerType = HeaderType.HeaderSameSource;
            }
            else if (header.Timer != lastHeader.Timer)
            {
                // Timer change marker if there's time gap between headers timestamps
                headerType = HeaderType.HeaderTimerChange;
            }
            else
            {
                // Continue encoding
                headerType = HeaderType.HeaderContinue;
            }
            return(headerType);
        }
예제 #3
0
        /// <summary>
        /// Encode RTMP header into given ByteBuffer
        /// </summary>
        /// <param name="header">RTMP message header</param>
        /// <param name="lastHeader">Previous header</param>
        /// <param name="buffer">Buffer to write encoded header to</param>
        /// <returns>Encoded header data</returns>
        public static ByteBuffer EncodeHeader(RtmpHeader header, RtmpHeader lastHeader, ByteBuffer buffer)
        {
            HeaderType headerType = GetHeaderType(header, lastHeader);

            EncodeHeaderByte(buffer, (byte)headerType, header.ChannelId);
            switch (headerType)
            {
            case HeaderType.HeaderNew:
                if (header.Timer < 0xffffff)
                {
                    buffer.WriteMediumInt(header.Timer);
                }
                else
                {
                    buffer.WriteMediumInt(0xffffff);
                }
                buffer.WriteMediumInt(header.Size);
                buffer.Put((byte)header.DataType);
                buffer.WriteReverseInt(header.StreamId);
                break;

            case HeaderType.HeaderSameSource:
                if (header.Timer < 0xffffff)
                {
                    buffer.WriteMediumInt(header.Timer);
                }
                else
                {
                    buffer.WriteMediumInt(0xffffff);
                }
                buffer.WriteMediumInt(header.Size);
                buffer.Put((byte)header.DataType);
                break;

            case HeaderType.HeaderTimerChange:
                if (header.Timer < 0xffffff)
                {
                    buffer.WriteMediumInt(header.Timer);
                }
                else
                {
                    buffer.WriteMediumInt(0xffffff);
                }
                break;

            case HeaderType.HeaderContinue:
                break;
            }

            if (header.Timer >= 0xffffff)
            {
                buffer.PutInt(header.Timer);
            }

            return(buffer);
        }
예제 #4
0
 internal void SetLastWriteHeader(int channelId, RtmpHeader header)
 {
     try {
         ReaderWriterLock.AcquireWriterLock();
         _lastWriteChannel        = channelId;
         _writeHeaders[channelId] = header;
     } finally {
         ReaderWriterLock.ReleaseWriterLock();
     }
 }
예제 #5
0
		/// <summary>
		/// Calculate number of bytes necessary to encode the header.
		/// </summary>
		/// <param name="header">RTMP message header</param>
		/// <param name="lastHeader">Previous header</param>
		/// <returns>Calculated size</returns>
		private static int CalculateHeaderSize(RtmpHeader header, RtmpHeader lastHeader) {
			HeaderType headerType = GetHeaderType(header, lastHeader);
			int channelIdAdd;
			if (header.ChannelId > 320)
				channelIdAdd = 2;
			else if (header.ChannelId > 63)
				channelIdAdd = 1;
			else
				channelIdAdd = 0;

			return RtmpHeader.GetHeaderLength(headerType) + channelIdAdd;
		}
예제 #6
0
		/// <summary>
		/// Writes packet from event data to the RTMP connection using the specified stream id.
		/// </summary>
		/// <param name="message">Event data.</param>
		/// <param name="streamId">Stream id.</param>
		private void Write(IRtmpEvent message, int streamId) {
			RtmpHeader header = new RtmpHeader();
			RtmpPacket packet = new RtmpPacket(header, message);

			header.ChannelId = _channelId;
			header.Timer = message.Timestamp;
			header.StreamId = streamId;
			header.DataType = message.DataType;
			if (message.Header != null)
				header.IsTimerRelative = message.Header.IsTimerRelative;
			_connection.Write(packet);
		}
예제 #7
0
        /// <summary>
        /// Writes packet from event data to the RTMP connection using the specified stream id.
        /// </summary>
        /// <param name="message">Event data.</param>
        /// <param name="streamId">Stream id.</param>
        private void Write(IRtmpEvent message, int streamId)
        {
            RtmpHeader header = new RtmpHeader();
            RtmpPacket packet = new RtmpPacket(header, message);

            header.ChannelId = _channelId;
            header.Timer     = message.Timestamp;
            header.StreamId  = streamId;
            header.DataType  = message.DataType;
            if (message.Header != null)
            {
                header.IsTimerRelative = message.Header.IsTimerRelative;
            }
            _connection.Write(packet);
        }
예제 #8
0
		/// <summary>
		/// Determine type of header to use.
		/// </summary>
		/// <param name="header">RTMP message header.</param>
		/// <param name="lastHeader">Previous header.</param>
		/// <returns>Header type to use.</returns>
		private static HeaderType GetHeaderType(RtmpHeader header, RtmpHeader lastHeader) {
			HeaderType headerType;
			if (lastHeader == null
				|| header.StreamId != lastHeader.StreamId
				|| !header.IsTimerRelative) {
				// New header mark if header for another stream
				headerType = HeaderType.HeaderNew;
			} else if (header.Size != lastHeader.Size
				  || header.DataType != lastHeader.DataType) {
				// Same source header if last header data type or size differ
				headerType = HeaderType.HeaderSameSource;
			} else if (header.Timer != lastHeader.Timer) {
				// Timer change marker if there's time gap between headers timestamps
				headerType = HeaderType.HeaderTimerChange;
			} else {
				// Continue encoding
				headerType = HeaderType.HeaderContinue;
			}
			return headerType;
		}
예제 #9
0
        /// <summary>
        /// Calculate number of bytes necessary to encode the header.
        /// </summary>
        /// <param name="header">RTMP message header</param>
        /// <param name="lastHeader">Previous header</param>
        /// <returns>Calculated size</returns>
        private static int CalculateHeaderSize(RtmpHeader header, RtmpHeader lastHeader)
        {
            HeaderType headerType = GetHeaderType(header, lastHeader);
            int        channelIdAdd;

            if (header.ChannelId > 320)
            {
                channelIdAdd = 2;
            }
            else if (header.ChannelId > 63)
            {
                channelIdAdd = 1;
            }
            else
            {
                channelIdAdd = 0;
            }

            return(RtmpHeader.GetHeaderLength(headerType) + channelIdAdd);
        }
예제 #10
0
		/*
		FlexInvoke flexInvoke = new FlexInvoke();
		flexInvoke.Cmd = "onstatus";
		flexInvoke.DataType = DataType.TypeUnknown;
		StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_CLOSED, connection.ObjectEncoding);
		flexInvoke.Parameters = new object[]{ statusASO };
		RtmpChannel channel = connection.GetChannel(3);
		channel.Write(flexInvoke);
		*/


		protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize) {
			if (connection is IStreamCapableConnection) {
				IStreamCapableConnection streamCapableConnection = connection as IStreamCapableConnection;
				{
					foreach (IClientStream stream in streamCapableConnection.GetStreams()) {
						if (stream is IClientBroadcastStream) {
							IClientBroadcastStream bs = stream as IClientBroadcastStream;
							IBroadcastScope scope = bs.Scope.GetBasicScope(Constants.BroadcastScopeType, bs.PublishedName) as IBroadcastScope;
							if (scope == null)
								continue;

							OOBControlMessage setChunkSize = new OOBControlMessage();
							setChunkSize.Target = "ClientBroadcastStream";
							setChunkSize.ServiceName = "chunkSize";
							setChunkSize.ServiceParameterMap.Add("chunkSize", chunkSize.Size);
							scope.SendOOBControlMessage((IConsumer)null, setChunkSize);
							if (log.IsDebugEnabled) {
								log.Debug("Sending chunksize " + chunkSize + " to " + bs.Provider);
							}
						}
					}
				}
			}
		}
예제 #11
0
 static Notify DecodeNotify(ByteBuffer stream, RtmpHeader header)
 {
     return(DecodeNotifyOrInvoke(new Notify(), stream, header));
 }
예제 #12
0
		/// <summary>
		/// Encode RTMP header into given ByteBuffer
		/// </summary>
		/// <param name="header">RTMP message header</param>
		/// <param name="lastHeader">Previous header</param>
		/// <param name="buffer">Buffer to write encoded header to</param>
		/// <returns>Encoded header data</returns>
		public static ByteBuffer EncodeHeader(RtmpHeader header, RtmpHeader lastHeader, ByteBuffer buffer) {
			HeaderType headerType = GetHeaderType(header, lastHeader);
			EncodeHeaderByte(buffer, (byte)headerType, header.ChannelId);
			switch (headerType) {
				case HeaderType.HeaderNew:
					if (header.Timer < 0xffffff)
						buffer.WriteMediumInt(header.Timer);
					else
						buffer.WriteMediumInt(0xffffff);
					buffer.WriteMediumInt(header.Size);
					buffer.Put((byte)header.DataType);
					buffer.WriteReverseInt(header.StreamId);
					break;
				case HeaderType.HeaderSameSource:
					if (header.Timer < 0xffffff)
						buffer.WriteMediumInt(header.Timer);
					else
						buffer.WriteMediumInt(0xffffff);
					buffer.WriteMediumInt(header.Size);
					buffer.Put((byte)header.DataType);
					break;
				case HeaderType.HeaderTimerChange:
					if (header.Timer < 0xffffff)
						buffer.WriteMediumInt(header.Timer);
					else
						buffer.WriteMediumInt(0xffffff);
					break;
				case HeaderType.HeaderContinue:
					break;
			}

			if (header.Timer >= 0xffffff)
				buffer.PutInt(header.Timer);

			return buffer;
		}
예제 #13
0
        /*
         * FlexInvoke flexInvoke = new FlexInvoke();
         * flexInvoke.Cmd = "onstatus";
         * flexInvoke.DataType = DataType.TypeUnknown;
         * StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_CLOSED, connection.ObjectEncoding);
         * flexInvoke.Parameters = new object[]{ statusASO };
         * RtmpChannel channel = connection.GetChannel(3);
         * channel.Write(flexInvoke);
         */


        protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize)
        {
            if (connection is IStreamCapableConnection)
            {
                IStreamCapableConnection streamCapableConnection = connection as IStreamCapableConnection;
                {
                    foreach (IClientStream stream in streamCapableConnection.GetStreams())
                    {
                        if (stream is IClientBroadcastStream)
                        {
                            IClientBroadcastStream bs    = stream as IClientBroadcastStream;
                            IBroadcastScope        scope = bs.Scope.GetBasicScope(Constants.BroadcastScopeType, bs.PublishedName) as IBroadcastScope;
                            if (scope == null)
                            {
                                continue;
                            }

                            OOBControlMessage setChunkSize = new OOBControlMessage();
                            setChunkSize.Target      = "ClientBroadcastStream";
                            setChunkSize.ServiceName = "chunkSize";
                            setChunkSize.ServiceParameterMap.Add("chunkSize", chunkSize.Size);
                            scope.SendOOBControlMessage((IConsumer)null, setChunkSize);
                            if (log.IsDebugEnabled)
                            {
                                log.Debug("Sending chunksize " + chunkSize + " to " + bs.Provider);
                            }
                        }
                    }
                }
            }
        }
예제 #14
0
		static Notify DecodeNotifyOrInvoke(Notify notify, ByteBuffer stream, RtmpHeader header) {
			long start = stream.Position;
			RtmpReader reader = new RtmpReader(stream);
			string action = reader.ReadData() as string;

			if (!(notify is Invoke)) {
				//Don't decode "NetStream.send" requests
				stream.Position = start;
				notify.Data = ByteBuffer.Allocate(stream.Remaining);
				notify.Data.Put(stream);
				//notify.setData(in.asReadOnlyBuffer());
				return notify;
			}

			if (header == null || header.StreamId == 0) {
				double invokeId = (double)reader.ReadData();
				notify.InvokeId = (int)invokeId;
			}

			object[] parameters = Call.EmptyArguments;
			if (stream.HasRemaining) {
#if !(NET_1_1)
				List<object> paramList = new List<object>();
#else
                ArrayList paramList = new ArrayList();
#endif
				object obj = reader.ReadData();

				if (obj is IDictionary) {
					// for connect we get a map
					notify.ConnectionParameters = obj as IDictionary;
				} else if (obj != null) {
					paramList.Add(obj);
				}

				while (stream.HasRemaining) {
					paramList.Add(reader.ReadData());
				}
				parameters = paramList.ToArray();
			}

			int dotIndex = action.LastIndexOf(".");
			string serviceName = (dotIndex == -1) ? null : action.Substring(0, dotIndex);
			string serviceMethod = (dotIndex == -1) ? action : action.Substring(dotIndex + 1, action.Length - dotIndex - 1);

			if (notify is Invoke) {
				PendingCall call = new PendingCall(serviceName, serviceMethod, parameters);
				notify.ServiceCall = call;
			} else {
				Call call = new Call(serviceName, serviceMethod, parameters);
				notify.ServiceCall = call;
			}
			return notify;
		}
예제 #15
0
 protected override void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBW)
 {
 }
예제 #16
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);
        }
예제 #17
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="source"></param>
		/// <param name="streamBytesRead"></param>
		protected void OnStreamBytesRead(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, BytesRead streamBytesRead) {
			connection.ReceivedBytesRead(streamBytesRead.Bytes);
		}
예제 #18
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="source"></param>
 /// <param name="clientBW"></param>
 protected abstract void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBW);
예제 #19
0
		protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke) {
			IServiceCall serviceCall = invoke.ServiceCall;

			// If it's a callback for server remote call then pass it over to callbacks handler
			// and return
			if (serviceCall.ServiceMethodName.Equals("_result") || serviceCall.ServiceMethodName.Equals("_error")) {
				HandlePendingCallResult(connection, invoke);
				return;
			}

			bool disconnectOnReturn = false;
			string action = null;
			if (serviceCall.ServiceName == null) {
				action = serviceCall.ServiceMethodName;
				switch (action) {
					case ACTION_CONNECT: {
							if (!connection.IsConnected) {
								IDictionary parameters = invoke.ConnectionParameters;
								string host = null;
								if (parameters.Contains("tcUrl"))
									host = GetHostname(parameters["tcUrl"] as string);
								if (host != null && host.IndexOf(":") != -1) {
									// Remove default port from connection string
									host = host.Substring(0, host.IndexOf(":"));
								}
								string app = parameters["app"] as string;
								string path = parameters["app"] as string;
								// App name as path, but without query string if there is one
								if (path != null && path.IndexOf("?") != -1) {
									int idx = path.IndexOf("?");
									parameters["queryString"] = path.Substring(idx);
									path = path.Substring(0, idx);
								}
								parameters["path"] = path;

								connection.Setup(host, path, parameters);
								try {
									//IGlobalScope global = this.Endpoint.LookupGlobal(host, path);
									IGlobalScope global = this.Endpoint.GetMessageBroker().GlobalScope;
									if (global == null) {
										serviceCall.Status = Call.STATUS_SERVICE_NOT_FOUND;
										if (serviceCall is IPendingServiceCall) {
											StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_INVALID_APPLICATION, connection.ObjectEncoding);
											status.description = "No global scope on this server.";
											(serviceCall as IPendingServiceCall).Result = status;
										}
										log.Info(string.Format("No application scope found for {0} on host {1}. Misspelled or missing application folder?", path, host));
										disconnectOnReturn = true;
									} else {
										IScopeContext context = global.Context;
										IScope scope = null;
										try {
											scope = context.ResolveScope(global, path);
										} catch (ScopeNotFoundException /*exception*/) {
											if (log.IsErrorEnabled)
												log.Error(__Res.GetString(__Res.Scope_NotFound, path));

											serviceCall.Status = Call.STATUS_SERVICE_NOT_FOUND;
											if (serviceCall is IPendingServiceCall) {
												StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
												status.description = "No scope \"" + path + "\" on this server.";
												(serviceCall as IPendingServiceCall).Result = status;
											}
											disconnectOnReturn = true;
										} catch (ScopeShuttingDownException) {
											serviceCall.Status = Call.STATUS_APP_SHUTTING_DOWN;
											if (serviceCall is IPendingServiceCall) {
												StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_APPSHUTDOWN, connection.ObjectEncoding);
												status.description = "Application at \"" + path + "\" is currently shutting down.";
												(serviceCall as IPendingServiceCall).Result = status;
											}
											log.Info(string.Format("Application at {0} currently shutting down on {1}", path, host));
											disconnectOnReturn = true;
										}
										if (scope != null) {
											if (log.IsInfoEnabled)
												log.Info(__Res.GetString(__Res.Scope_Connect, scope.Name));
											bool okayToConnect;
											try {
												//The only way to differentiate NetConnection.connect() and Consumer.subscribe() seems to be the app name
												if (app == string.Empty) {
													connection.SetIsFlexClient(true);
													okayToConnect = connection.Connect(scope, serviceCall.Arguments);
													if (okayToConnect) {
														if (serviceCall.Arguments != null && serviceCall.Arguments.Length >= 3) {
															string credentials = serviceCall.Arguments[2] as string;
															if (credentials != null && credentials != string.Empty) {
																MessageBroker messageBroker = this.Endpoint.GetMessageBroker();
																AuthenticationService authenticationService = messageBroker.GetService(AuthenticationService.ServiceId) as AuthenticationService;
																authenticationService.Authenticate(credentials);
															}
														}
														//FDS 2.0.1 fds.swc
														if (serviceCall.Arguments != null && serviceCall.Arguments.Length == 1) {
															string credentials = serviceCall.Arguments[0] as string;
															if (credentials != null && credentials != string.Empty) {
																MessageBroker messageBroker = this.Endpoint.GetMessageBroker();
																AuthenticationService authenticationService = messageBroker.GetService(AuthenticationService.ServiceId) as AuthenticationService;
																authenticationService.Authenticate(credentials);
															}
														}
													}
												} else {
													connection.SetIsFlexClient(false);
													okayToConnect = connection.Connect(scope, serviceCall.Arguments);
												}
												if (okayToConnect) {
													if (log.IsDebugEnabled)
														log.Debug("Connected RtmpClient: " + connection.Client.Id);
													serviceCall.Status = Call.STATUS_SUCCESS_RESULT;
													if (serviceCall is IPendingServiceCall) {
														StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_SUCCESS, connection.ObjectEncoding);
														statusASO.Add("id", connection.Client.Id);
														(serviceCall as IPendingServiceCall).Result = statusASO;
													}
													// Measure initial roundtrip time after connecting
													connection.GetChannel((byte)2).Write(new Ping(Ping.StreamBegin, 0, -1));
													connection.StartRoundTripMeasurement();
												} else {
													if (log.IsDebugEnabled)
														log.Debug("Connect failed");
													serviceCall.Status = Call.STATUS_ACCESS_DENIED;
													if (serviceCall is IPendingServiceCall)
														(serviceCall as IPendingServiceCall).Result = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
													disconnectOnReturn = true;
												}
											} catch (ClientRejectedException rejected) {
												if (log.IsDebugEnabled)
													log.Debug("Connect rejected");
												serviceCall.Status = Call.STATUS_ACCESS_DENIED;
												if (serviceCall is IPendingServiceCall) {
													StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
													statusASO.Application = rejected.Reason;
													(serviceCall as IPendingServiceCall).Result = statusASO;
												}
												disconnectOnReturn = true;
											}
										}
									}
								} catch (Exception ex) {
									if (log.IsErrorEnabled)
										log.Error("Error connecting", ex);

									serviceCall.Status = Call.STATUS_GENERAL_EXCEPTION;
									if (serviceCall is IPendingServiceCall)
										(serviceCall as IPendingServiceCall).Result = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_FAILED, connection.ObjectEncoding);
									disconnectOnReturn = true;
								}
							} else {
								// Service calls, must be connected.
								InvokeCall(connection, serviceCall);
							}
						}
						break;
					case ACTION_DISCONNECT:
						connection.Close();
						break;
					case ACTION_CREATE_STREAM:
					case ACTION_DELETE_STREAM:
					case ACTION_RELEASE_STREAM:
					case ACTION_PUBLISH:
					case ACTION_PLAY:
					case ACTION_SEEK:
					case ACTION_PAUSE:
					case ACTION_CLOSE_STREAM:
					case ACTION_RECEIVE_VIDEO:
					case ACTION_RECEIVE_AUDIO: {
							IStreamService streamService = ScopeUtils.GetScopeService(connection.Scope, typeof(IStreamService)) as IStreamService;
							StatusASO status = null;
							try {
								if (!InvokeCall(connection, serviceCall, streamService)) {
									status = StatusASO.GetStatusObject(StatusASO.NS_INVALID_ARGUMENT, connection.ObjectEncoding);
									status.description = "Failed to " + action + " (stream ID: " + header.StreamId + ")";
								}
							} catch (Exception ex) {
								log.Error("Error while invoking " + action + " on stream service.", ex);
								status = StatusASO.GetStatusObject(StatusASO.NS_FAILED, connection.ObjectEncoding);
								status.description = "Error while invoking " + action + " (stream ID: " + header.StreamId + ")";
								status.details = ex.Message;
							}
							if (status != null)
								channel.SendStatus(status);
						}
						break;
					default:
						if (connection.IsConnected)
							InvokeCall(connection, serviceCall);
						else {
							// Warn user attemps to call service without being connected
							if (log.IsWarnEnabled)
								log.Warn("Not connected, closing connection");
							connection.Close();
						}
						break;
				}
			}
			/*
			if(invoke is FlexInvoke) 
			{
				FlexInvoke reply = new FlexInvoke();
				reply.InvokeId = invoke.InvokeId;
				reply.SetResponseSuccess();
				//TODO
				if( serviceCall is IPendingServiceCall )
				{
					IPendingServiceCall pendingCall = (IPendingServiceCall)serviceCall;
					reply.Response = pendingCall.Result;
				}
				channel.Write(reply);
			}
			else if(invoke is Invoke) 
			*/
			if (invoke is Invoke) {
				if ((header.StreamId != 0)
					&& (serviceCall.Status == Call.STATUS_SUCCESS_VOID || serviceCall.Status == Call.STATUS_SUCCESS_NULL)) {
					if (log.IsDebugEnabled)
						log.Debug("Method does not have return value, do not reply");
					return;
				}

				// The client expects a result for the method call.
				Invoke reply = new Invoke();
				reply.ServiceCall = serviceCall;
				reply.InvokeId = invoke.InvokeId;
				//sending reply
				channel.Write(reply);
			}
			if (disconnectOnReturn) {
				connection.Close();
			}
			if (action == ACTION_CONNECT) {
				connection.Context.ObjectEncoding = connection.ObjectEncoding;
			}
		}
예제 #20
0
		/// <summary>
		/// Decodes RTMP message event.
		/// </summary>
		/// <param name="context">RTMP protocol state.</param>
		/// <param name="header">RTMP header.</param>
		/// <param name="stream">Buffer to be decoded.</param>
		/// <returns>Decoded RTMP event.</returns>
		public static IRtmpEvent DecodeMessage(RtmpContext context, RtmpHeader header, ByteBuffer stream) {
			IRtmpEvent message = null;
			/*
			if(header.Timer == 0xffffff) 
			{
				// Skip first four bytes
				byte[] extendedTimestamp = new byte[4];
				stream.Read(extendedTimestamp, 0, 4);
				log.Warn("Discarding extended timestamp");
				//int unknown = stream.ReadInt32();
			}
			*/
			switch (header.DataType) {
				case Constants.TypeChunkSize:
					message = DecodeChunkSize(stream);
					break;
				case Constants.TypeInvoke:
					message = DecodeInvoke(stream);
					break;
				case Constants.TypeFlexInvoke:
					message = DecodeFlexInvoke(stream);
					break;
				case Constants.TypeNotify:
					if (header.StreamId == 0)
						message = DecodeNotify(stream, header);
					else
						message = DecodeStreamMetadata(stream);
					break;
				case Constants.TypePing:
					message = DecodePing(stream);
					break;
				case Constants.TypeBytesRead:
					message = DecodeBytesRead(stream);
					break;
				case Constants.TypeAudioData:
					message = DecodeAudioData(stream);
					break;
				case Constants.TypeVideoData:
					message = DecodeVideoData(stream);
					break;
				case Constants.TypeSharedObject:
					message = DecodeSharedObject(stream);
					break;
				case Constants.TypeFlexSharedObject:
					message = DecodeFlexSharedObject(stream);
					break;
				case Constants.TypeServerBandwidth:
					message = DecodeServerBW(stream);
					break;
				case Constants.TypeClientBandwidth:
					message = DecodeClientBW(stream);
					break;
				default:
#if !SILVERLIGHT
					log.Warn("Unknown object type: " + header.DataType);
#endif
					message = DecodeUnknown(stream);
					break;
			}
			message.Header = header;
			message.Timestamp = header.Timer;
			return message;
		}
예제 #21
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);
		}
예제 #22
0
		protected override void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke) {
			IMessage message = null;
			if (invoke.ServiceCall.Arguments != null && invoke.ServiceCall.Arguments.Length > 0)
				message = invoke.ServiceCall.Arguments[0] as IMessage;
			if (message != null) {
				MessageBroker messageBroker = this.Endpoint.GetMessageBroker();
				if (message.clientId == null) {
					message.clientId = Guid.NewGuid().ToString("D");
					/*
					if( !(message is CommandMessage) )
					{
						//producer may send messages without subscribing
						CommandMessage commandMessageSubscribe = new CommandMessage(CommandMessage.SubscribeOperation);
						commandMessageSubscribe.messageId = Guid.NewGuid().ToString("D");
						commandMessageSubscribe.headers = message.headers.Clone() as Hashtable;
						commandMessageSubscribe.messageRefType = message.GetType().FullName;//"flex.messaging.messages.AsyncMessage"
						commandMessageSubscribe.destination = message.destination;

						IMessage subscribeResponse = messageBroker.RouteMessage(commandMessageSubscribe, _endpoint, connection);
						message.clientId = subscribeResponse.clientId;
					}
					}
					*/
				}
				IMessage response = messageBroker.RouteMessage(message, this.Endpoint);
				invoke.ServiceCall.Status = response is ErrorMessage ? Call.STATUS_INVOCATION_EXCEPTION : Call.STATUS_SUCCESS_RESULT;
				if (invoke.ServiceCall is IPendingServiceCall)
					(invoke.ServiceCall as IPendingServiceCall).Result = response;

				FlexInvoke reply = new FlexInvoke();
				reply.InvokeId = invoke.InvokeId;
				reply.ServiceCall = invoke.ServiceCall;
				/*
				if( response is ErrorMessage )
					reply.SetResponseFailure();
				else
					reply.SetResponseSuccess();
				reply.Response = response;
				*/
				channel.Write(reply);
			} else {
				// If it's a callback for server remote call then pass it over to callbacks handler and return
				OnInvoke(connection, channel, header, invoke);
			}
		}
예제 #23
0
        public static ByteBuffer EncodePacket(RtmpContext context, RtmpPacket packet)
        {
            RtmpHeader header    = packet.Header;
            int        channelId = header.ChannelId;
            IRtmpEvent message   = packet.Message;
            ByteBuffer data;

            if (message is ChunkSize)
            {
                ChunkSize chunkSizeMsg = (ChunkSize)message;
                context.SetWriteChunkSize(chunkSizeMsg.Size);
            }

            data = EncodeMessage(context, header, message);

            if (data.Position != 0)
            {
                data.Flip();
            }
            else
            {
                data.Rewind();
            }
            header.Size = (int)data.Limit;

            RtmpHeader lastHeader = context.GetLastWriteHeader(channelId);
            int        headerSize = CalculateHeaderSize(header, lastHeader);

            context.SetLastWriteHeader(channelId, header);
            context.SetLastWritePacket(channelId, packet);

            int chunkSize       = context.GetWriteChunkSize();
            int chunkHeaderSize = 1;

            if (header.ChannelId > 320)
            {
                chunkHeaderSize = 3;
            }
            else if (header.ChannelId > 63)
            {
                chunkHeaderSize = 2;
            }
            int        numChunks = (int)Math.Ceiling(header.Size / (float)chunkSize);
            int        bufSize   = (int)header.Size + headerSize + (numChunks > 0 ? (numChunks - 1) * chunkHeaderSize : 0);
            ByteBuffer output    = ByteBuffer.Allocate(bufSize);

            EncodeHeader(header, lastHeader, output);

            if (numChunks == 1)
            {
                // we can do it with a single copy
                ByteBuffer.Put(output, data, output.Remaining);
            }
            else
            {
                for (int i = 0; i < numChunks - 1; i++)
                {
                    ByteBuffer.Put(output, data, chunkSize);
                    EncodeHeaderByte(output, (byte)HeaderType.HeaderContinue, header.ChannelId);
                }
                ByteBuffer.Put(output, data, output.Remaining);
            }
            //data.Close();
            output.Flip();
            return(output);
        }
예제 #24
0
		internal void SetLastWriteHeader(int channelId, RtmpHeader header) {
			try {
				ReaderWriterLock.AcquireWriterLock();
				_lastWriteChannel = channelId;
				_writeHeaders[channelId] = header;
			} finally {
				ReaderWriterLock.ReleaseWriterLock();
			}
		}
예제 #25
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="source"></param>
		/// <param name="chunkSize"></param>
		protected abstract void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize);
예제 #26
0
		protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) {
			switch (ping.PingType) {
				case Ping.ClientBuffer:
					IClientStream stream = null;
					// Get the stream id
					int streamId = ping.Value2;
					// Get requested buffer size in milliseconds
					int buffer = ping.Value3;
					if (streamId != 0) {
						// The client wants to set the buffer time
						stream = connection.GetStreamById(streamId);
						if (stream != null) {
							stream.SetClientBufferDuration(buffer);
							if (log.IsDebugEnabled)
								log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId));
						}
					}
					// Catch-all to make sure buffer size is set
					if (stream == null) {
						// Remember buffer time until stream is created
						connection.RememberStreamBufferDuration(streamId, buffer);
						if (log.IsDebugEnabled)
							log.Debug(string.Format("Remembering client buffer size: {0} on stream id: {1} ", buffer, streamId));
					}
					break;
				case Ping.PongServer:
					// This is the response to an IConnection.Ping request
					connection.PingReceived(ping);
					break;
				default:
					log.Warn("Unhandled ping: " + ping);
					break;
			}
		}
예제 #27
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="source"></param>
		/// <param name="ping"></param>
		protected abstract void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping);
예제 #28
0
		protected override void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBW) {

		}
예제 #29
0
		/// <summary>
		/// Decodes RTMP packet header.
		/// </summary>
		/// <param name="context">RTMP protocol state.</param>
		/// <param name="lastHeader">Previous header.</param>
		/// <param name="stream">Buffer to be decoded.</param>
		/// <returns>Decoded RTMP header.</returns>
		public static RtmpHeader DecodeHeader(RtmpContext context, RtmpHeader lastHeader, ByteBuffer stream) {
			byte headerByte = stream.Get();
			int headerValue;
			int byteCount = 1;
			if ((headerByte & 0x3f) == 0) {
				// Two byte header
				headerValue = ((int)headerByte & 0xff) << 8 | ((int)stream.Get() & 0xff);
				byteCount = 2;
			} else if ((headerByte & 0x3f) == 1) {
				// Three byte header
				headerValue = ((int)headerByte & 0xff) << 16 | ((int)stream.Get() & 0xff) << 8 | ((int)stream.Get() & 0xff);
				byteCount = 3;
			} else {
				// Single byte header
				headerValue = (int)headerByte & 0xff;
				byteCount = 1;
			}
			byte channelId = DecodeChannelId(headerValue, byteCount);
			byte headerSize = DecodeHeaderSize(headerValue, byteCount);
			RtmpHeader header = new RtmpHeader();
			header.ChannelId = channelId;
			header.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;

			if ((HeaderType)headerSize != HeaderType.HeaderNew && lastHeader == null) {
#if !SILVERLIGHT
				if (log.IsErrorEnabled)
					log.Error(string.Format("Last header null not new, headerSize: {0}, channelId {1}", headerSize, channelId));
#endif
				lastHeader = new RtmpHeader();
				lastHeader.ChannelId = channelId;
				lastHeader.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;
			}


#if !SILVERLIGHT
			if (log.IsDebugEnabled)
				log.Debug(__Res.GetString(__Res.Rtmp_DecodeHeader, Enum.GetName(typeof(HeaderType), (HeaderType)headerSize)));
#endif

			switch ((HeaderType)headerSize) {
				case HeaderType.HeaderNew:
					header.Timer = stream.ReadUInt24();// ReadUnsignedMediumInt();
					header.Size = stream.ReadUInt24();// ReadMediumInt();
					header.DataType = stream.Get();
					header.StreamId = stream.ReadReverseInt();
					break;
				case HeaderType.HeaderSameSource:
					header.Timer = stream.ReadUInt24();// ReadUnsignedMediumInt();
					header.Size = stream.ReadUInt24();// ReadMediumInt();
					header.DataType = stream.Get();
					header.StreamId = lastHeader.StreamId;
					break;
				case HeaderType.HeaderTimerChange:
					header.Timer = stream.ReadUInt24();//ReadUnsignedMediumInt();
					header.Size = lastHeader.Size;
					header.DataType = lastHeader.DataType;
					header.StreamId = lastHeader.StreamId;
					break;
				case HeaderType.HeaderContinue:
					header.Timer = lastHeader.Timer;
					header.Size = lastHeader.Size;
					header.DataType = lastHeader.DataType;
					header.StreamId = lastHeader.StreamId;
					header.IsTimerRelative = lastHeader.IsTimerRelative;
					break;
				default:
#if !SILVERLIGHT
					log.Error("Unexpected header size: " + headerSize);
#endif
					return null;
			}
			if (header.Timer >= 0xffffff) {
				//Extended timestamp
				header.Timer = stream.GetInt();
			}

			return header;
		}
예제 #30
0
        protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke)
        {
            IServiceCall serviceCall = invoke.ServiceCall;

            // If it's a callback for server remote call then pass it over to callbacks handler
            // and return
            if (serviceCall.ServiceMethodName.Equals("_result") || serviceCall.ServiceMethodName.Equals("_error"))
            {
                HandlePendingCallResult(connection, invoke);
                return;
            }

            bool   disconnectOnReturn = false;
            string action             = null;

            if (serviceCall.ServiceName == null)
            {
                action = serviceCall.ServiceMethodName;
                switch (action)
                {
                case ACTION_CONNECT: {
                    if (!connection.IsConnected)
                    {
                        IDictionary parameters = invoke.ConnectionParameters;
                        string      host       = null;
                        if (parameters.Contains("tcUrl"))
                        {
                            host = GetHostname(parameters["tcUrl"] as string);
                        }
                        if (host != null && host.IndexOf(":") != -1)
                        {
                            // Remove default port from connection string
                            host = host.Substring(0, host.IndexOf(":"));
                        }
                        string app  = parameters["app"] as string;
                        string path = parameters["app"] as string;
                        // App name as path, but without query string if there is one
                        if (path != null && path.IndexOf("?") != -1)
                        {
                            int idx = path.IndexOf("?");
                            parameters["queryString"] = path.Substring(idx);
                            path = path.Substring(0, idx);
                        }
                        parameters["path"] = path;

                        connection.Setup(host, path, parameters);
                        try {
                            //IGlobalScope global = this.Endpoint.LookupGlobal(host, path);
                            IGlobalScope global = this.Endpoint.GetMessageBroker().GlobalScope;
                            if (global == null)
                            {
                                serviceCall.Status = Call.STATUS_SERVICE_NOT_FOUND;
                                if (serviceCall is IPendingServiceCall)
                                {
                                    StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_INVALID_APPLICATION, connection.ObjectEncoding);
                                    status.description = "No global scope on this server.";
                                    (serviceCall as IPendingServiceCall).Result = status;
                                }
                                log.Info(string.Format("No application scope found for {0} on host {1}. Misspelled or missing application folder?", path, host));
                                disconnectOnReturn = true;
                            }
                            else
                            {
                                IScopeContext context = global.Context;
                                IScope        scope   = null;
                                try {
                                    scope = context.ResolveScope(global, path);
                                } catch (ScopeNotFoundException /*exception*/) {
                                    if (log.IsErrorEnabled)
                                    {
                                        log.Error(__Res.GetString(__Res.Scope_NotFound, path));
                                    }

                                    serviceCall.Status = Call.STATUS_SERVICE_NOT_FOUND;
                                    if (serviceCall is IPendingServiceCall)
                                    {
                                        StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
                                        status.description = "No scope \"" + path + "\" on this server.";
                                        (serviceCall as IPendingServiceCall).Result = status;
                                    }
                                    disconnectOnReturn = true;
                                } catch (ScopeShuttingDownException) {
                                    serviceCall.Status = Call.STATUS_APP_SHUTTING_DOWN;
                                    if (serviceCall is IPendingServiceCall)
                                    {
                                        StatusASO status = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_APPSHUTDOWN, connection.ObjectEncoding);
                                        status.description = "Application at \"" + path + "\" is currently shutting down.";
                                        (serviceCall as IPendingServiceCall).Result = status;
                                    }
                                    log.Info(string.Format("Application at {0} currently shutting down on {1}", path, host));
                                    disconnectOnReturn = true;
                                }
                                if (scope != null)
                                {
                                    if (log.IsInfoEnabled)
                                    {
                                        log.Info(__Res.GetString(__Res.Scope_Connect, scope.Name));
                                    }
                                    bool okayToConnect;
                                    try {
                                        //The only way to differentiate NetConnection.connect() and Consumer.subscribe() seems to be the app name
                                        if (app == string.Empty)
                                        {
                                            connection.SetIsFlexClient(true);
                                            okayToConnect = connection.Connect(scope, serviceCall.Arguments);
                                            if (okayToConnect)
                                            {
                                                if (serviceCall.Arguments != null && serviceCall.Arguments.Length >= 3)
                                                {
                                                    string credentials = serviceCall.Arguments[2] as string;
                                                    if (credentials != null && credentials != string.Empty)
                                                    {
                                                        MessageBroker         messageBroker         = this.Endpoint.GetMessageBroker();
                                                        AuthenticationService authenticationService = messageBroker.GetService(AuthenticationService.ServiceId) as AuthenticationService;
                                                        authenticationService.Authenticate(credentials);
                                                    }
                                                }
                                                //FDS 2.0.1 fds.swc
                                                if (serviceCall.Arguments != null && serviceCall.Arguments.Length == 1)
                                                {
                                                    string credentials = serviceCall.Arguments[0] as string;
                                                    if (credentials != null && credentials != string.Empty)
                                                    {
                                                        MessageBroker         messageBroker         = this.Endpoint.GetMessageBroker();
                                                        AuthenticationService authenticationService = messageBroker.GetService(AuthenticationService.ServiceId) as AuthenticationService;
                                                        authenticationService.Authenticate(credentials);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            connection.SetIsFlexClient(false);
                                            okayToConnect = connection.Connect(scope, serviceCall.Arguments);
                                        }
                                        if (okayToConnect)
                                        {
                                            if (log.IsDebugEnabled)
                                            {
                                                log.Debug("Connected RtmpClient: " + connection.Client.Id);
                                            }
                                            serviceCall.Status = Call.STATUS_SUCCESS_RESULT;
                                            if (serviceCall is IPendingServiceCall)
                                            {
                                                StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_SUCCESS, connection.ObjectEncoding);
                                                statusASO.Add("id", connection.Client.Id);
                                                (serviceCall as IPendingServiceCall).Result = statusASO;
                                            }
                                            // Measure initial roundtrip time after connecting
                                            connection.GetChannel((byte)2).Write(new Ping(Ping.StreamBegin, 0, -1));
                                            connection.StartRoundTripMeasurement();
                                        }
                                        else
                                        {
                                            if (log.IsDebugEnabled)
                                            {
                                                log.Debug("Connect failed");
                                            }
                                            serviceCall.Status = Call.STATUS_ACCESS_DENIED;
                                            if (serviceCall is IPendingServiceCall)
                                            {
                                                (serviceCall as IPendingServiceCall).Result = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
                                            }
                                            disconnectOnReturn = true;
                                        }
                                    } catch (ClientRejectedException rejected) {
                                        if (log.IsDebugEnabled)
                                        {
                                            log.Debug("Connect rejected");
                                        }
                                        serviceCall.Status = Call.STATUS_ACCESS_DENIED;
                                        if (serviceCall is IPendingServiceCall)
                                        {
                                            StatusASO statusASO = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_REJECTED, connection.ObjectEncoding);
                                            statusASO.Application = rejected.Reason;
                                            (serviceCall as IPendingServiceCall).Result = statusASO;
                                        }
                                        disconnectOnReturn = true;
                                    }
                                }
                            }
                        } catch (Exception ex) {
                            if (log.IsErrorEnabled)
                            {
                                log.Error("Error connecting", ex);
                            }

                            serviceCall.Status = Call.STATUS_GENERAL_EXCEPTION;
                            if (serviceCall is IPendingServiceCall)
                            {
                                (serviceCall as IPendingServiceCall).Result = StatusASO.GetStatusObject(StatusASO.NC_CONNECT_FAILED, connection.ObjectEncoding);
                            }
                            disconnectOnReturn = true;
                        }
                    }
                    else
                    {
                        // Service calls, must be connected.
                        InvokeCall(connection, serviceCall);
                    }
                }
                break;

                case ACTION_DISCONNECT:
                    connection.Close();
                    break;

                case ACTION_CREATE_STREAM:
                case ACTION_DELETE_STREAM:
                case ACTION_RELEASE_STREAM:
                case ACTION_PUBLISH:
                case ACTION_PLAY:
                case ACTION_SEEK:
                case ACTION_PAUSE:
                case ACTION_CLOSE_STREAM:
                case ACTION_RECEIVE_VIDEO:
                case ACTION_RECEIVE_AUDIO: {
                    IStreamService streamService = ScopeUtils.GetScopeService(connection.Scope, typeof(IStreamService)) as IStreamService;
                    StatusASO      status        = null;
                    try {
                        if (!InvokeCall(connection, serviceCall, streamService))
                        {
                            status             = StatusASO.GetStatusObject(StatusASO.NS_INVALID_ARGUMENT, connection.ObjectEncoding);
                            status.description = "Failed to " + action + " (stream ID: " + header.StreamId + ")";
                        }
                    } catch (Exception ex) {
                        log.Error("Error while invoking " + action + " on stream service.", ex);
                        status             = StatusASO.GetStatusObject(StatusASO.NS_FAILED, connection.ObjectEncoding);
                        status.description = "Error while invoking " + action + " (stream ID: " + header.StreamId + ")";
                        status.details     = ex.Message;
                    }
                    if (status != null)
                    {
                        channel.SendStatus(status);
                    }
                }
                break;

                default:
                    if (connection.IsConnected)
                    {
                        InvokeCall(connection, serviceCall);
                    }
                    else
                    {
                        // Warn user attemps to call service without being connected
                        if (log.IsWarnEnabled)
                        {
                            log.Warn("Not connected, closing connection");
                        }
                        connection.Close();
                    }
                    break;
                }
            }

            /*
             * if(invoke is FlexInvoke)
             * {
             *      FlexInvoke reply = new FlexInvoke();
             *      reply.InvokeId = invoke.InvokeId;
             *      reply.SetResponseSuccess();
             *      //TODO
             *      if( serviceCall is IPendingServiceCall )
             *      {
             *              IPendingServiceCall pendingCall = (IPendingServiceCall)serviceCall;
             *              reply.Response = pendingCall.Result;
             *      }
             *      channel.Write(reply);
             * }
             * else if(invoke is Invoke)
             */
            if (invoke is Invoke)
            {
                if ((header.StreamId != 0) &&
                    (serviceCall.Status == Call.STATUS_SUCCESS_VOID || serviceCall.Status == Call.STATUS_SUCCESS_NULL))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Method does not have return value, do not reply");
                    }
                    return;
                }

                // The client expects a result for the method call.
                Invoke reply = new Invoke();
                reply.ServiceCall = serviceCall;
                reply.InvokeId    = invoke.InvokeId;
                //sending reply
                channel.Write(reply);
            }
            if (disconnectOnReturn)
            {
                connection.Close();
            }
            if (action == ACTION_CONNECT)
            {
                connection.Context.ObjectEncoding = connection.ObjectEncoding;
            }
        }
예제 #31
0
 internal RtmpPacket(RtmpHeader header, IRtmpEvent message)
 {
     _header  = header;
     _message = message;
 }
예제 #32
0
        protected override void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke)
        {
            IMessage message = null;

            if (invoke.ServiceCall.Arguments != null && invoke.ServiceCall.Arguments.Length > 0)
            {
                message = invoke.ServiceCall.Arguments[0] as IMessage;
            }
            if (message != null)
            {
                MessageBroker messageBroker = this.Endpoint.GetMessageBroker();
                if (message.clientId == null)
                {
                    message.clientId = Guid.NewGuid().ToString("D");

                    /*
                     * if( !(message is CommandMessage) )
                     * {
                     *      //producer may send messages without subscribing
                     *      CommandMessage commandMessageSubscribe = new CommandMessage(CommandMessage.SubscribeOperation);
                     *      commandMessageSubscribe.messageId = Guid.NewGuid().ToString("D");
                     *      commandMessageSubscribe.headers = message.headers.Clone() as Hashtable;
                     *      commandMessageSubscribe.messageRefType = message.GetType().FullName;//"flex.messaging.messages.AsyncMessage"
                     *      commandMessageSubscribe.destination = message.destination;
                     *
                     *      IMessage subscribeResponse = messageBroker.RouteMessage(commandMessageSubscribe, _endpoint, connection);
                     *      message.clientId = subscribeResponse.clientId;
                     * }
                     * }
                     */
                }
                IMessage response = messageBroker.RouteMessage(message, this.Endpoint);
                invoke.ServiceCall.Status = response is ErrorMessage ? Call.STATUS_INVOCATION_EXCEPTION : Call.STATUS_SUCCESS_RESULT;
                if (invoke.ServiceCall is IPendingServiceCall)
                {
                    (invoke.ServiceCall as IPendingServiceCall).Result = response;
                }

                FlexInvoke reply = new FlexInvoke();
                reply.InvokeId    = invoke.InvokeId;
                reply.ServiceCall = invoke.ServiceCall;

                /*
                 * if( response is ErrorMessage )
                 *      reply.SetResponseFailure();
                 * else
                 *      reply.SetResponseSuccess();
                 * reply.Response = response;
                 */
                channel.Write(reply);
            }
            else
            {
                // If it's a callback for server remote call then pass it over to callbacks handler and return
                OnInvoke(connection, channel, header, invoke);
            }
        }
예제 #33
0
        /// <summary>
        /// Decodes RTMP packet header.
        /// </summary>
        /// <param name="context">RTMP protocol state.</param>
        /// <param name="lastHeader">Previous header.</param>
        /// <param name="stream">Buffer to be decoded.</param>
        /// <returns>Decoded RTMP header.</returns>
        public static RtmpHeader DecodeHeader(RtmpContext context, RtmpHeader lastHeader, ByteBuffer stream)
        {
            byte headerByte = stream.Get();
            int  headerValue;
            int  byteCount = 1;

            if ((headerByte & 0x3f) == 0)
            {
                // Two byte header
                headerValue = ((int)headerByte & 0xff) << 8 | ((int)stream.Get() & 0xff);
                byteCount   = 2;
            }
            else if ((headerByte & 0x3f) == 1)
            {
                // Three byte header
                headerValue = ((int)headerByte & 0xff) << 16 | ((int)stream.Get() & 0xff) << 8 | ((int)stream.Get() & 0xff);
                byteCount   = 3;
            }
            else
            {
                // Single byte header
                headerValue = (int)headerByte & 0xff;
                byteCount   = 1;
            }
            byte       channelId  = DecodeChannelId(headerValue, byteCount);
            byte       headerSize = DecodeHeaderSize(headerValue, byteCount);
            RtmpHeader header     = new RtmpHeader();

            header.ChannelId       = channelId;
            header.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;

            if ((HeaderType)headerSize != HeaderType.HeaderNew && lastHeader == null)
            {
#if !SILVERLIGHT
                if (log.IsErrorEnabled)
                {
                    log.Error(string.Format("Last header null not new, headerSize: {0}, channelId {1}", headerSize, channelId));
                }
#endif
                lastHeader                 = new RtmpHeader();
                lastHeader.ChannelId       = channelId;
                lastHeader.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;
            }


#if !SILVERLIGHT
            if (log.IsDebugEnabled)
            {
                log.Debug(__Res.GetString(__Res.Rtmp_DecodeHeader, Enum.GetName(typeof(HeaderType), (HeaderType)headerSize)));
            }
#endif

            switch ((HeaderType)headerSize)
            {
            case HeaderType.HeaderNew:
                header.Timer    = stream.ReadUInt24();                    // ReadUnsignedMediumInt();
                header.Size     = stream.ReadUInt24();                    // ReadMediumInt();
                header.DataType = stream.Get();
                header.StreamId = stream.ReadReverseInt();
                break;

            case HeaderType.HeaderSameSource:
                header.Timer    = stream.ReadUInt24();                    // ReadUnsignedMediumInt();
                header.Size     = stream.ReadUInt24();                    // ReadMediumInt();
                header.DataType = stream.Get();
                header.StreamId = lastHeader.StreamId;
                break;

            case HeaderType.HeaderTimerChange:
                header.Timer    = stream.ReadUInt24();                     //ReadUnsignedMediumInt();
                header.Size     = lastHeader.Size;
                header.DataType = lastHeader.DataType;
                header.StreamId = lastHeader.StreamId;
                break;

            case HeaderType.HeaderContinue:
                header.Timer           = lastHeader.Timer;
                header.Size            = lastHeader.Size;
                header.DataType        = lastHeader.DataType;
                header.StreamId        = lastHeader.StreamId;
                header.IsTimerRelative = lastHeader.IsTimerRelative;
                break;

            default:
#if !SILVERLIGHT
                log.Error("Unexpected header size: " + headerSize);
#endif
                return(null);
            }
            if (header.Timer >= 0xffffff)
            {
                //Extended timestamp
                header.Timer = stream.GetInt();
            }

            return(header);
        }
예제 #34
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="invoke"></param>
		protected abstract void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke);
예제 #35
0
		static Notify DecodeNotify(ByteBuffer stream, RtmpHeader header) {
			return DecodeNotifyOrInvoke(new Notify(), stream, header);
		}
예제 #36
0
 internal RtmpPacket(RtmpHeader header)
 {
     _header = header;
     _data   = ByteBuffer.Allocate(header.Size + (header.Timer == 0xffffff ? 4 : 0));
 }
예제 #37
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);
예제 #38
0
        /// <summary>
        /// Decodes a RTMP packet.
        /// </summary>
        /// <param name="context">RTMP protocol state.</param>
        /// <param name="stream">Buffer to be decoded.</param>
        /// <returns>The decoded RTMP packet.</returns>
        public static RtmpPacket DecodePacket(RtmpContext context, ByteBuffer stream)
        {
            int remaining = stream.Remaining;

            // We need at least one byte
            if (remaining < 1)
            {
#if !SILVERLIGHT
                if (log.IsDebugEnabled)
                {
                    log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 1));
                }
#endif
                context.SetBufferDecoding(1);
                return(null);
            }
            int  position   = (int)stream.Position;
            byte headerByte = stream.Get();
            int  headerValue;
            int  byteCount;
            if ((headerByte & 0x3f) == 0)
            {
                // Two byte header
                if (remaining < 2)
                {
                    stream.Position = position;
#if !SILVERLIGHT
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 2));
                    }
#endif
                    context.SetBufferDecoding(2);
                    return(null);
                }
                headerValue = ((int)headerByte & 0xff) << 8 | ((int)stream.Get() & 0xff);
                byteCount   = 2;
            }
            else if ((headerByte & 0x3f) == 1)
            {
                // Three byte header
                if (remaining < 3)
                {
                    stream.Position = position;
#if !SILVERLIGHT
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 3));
                    }
#endif
                    context.SetBufferDecoding(3);
                    return(null);
                }
                headerValue = ((int)headerByte & 0xff) << 16 | ((int)stream.Get() & 0xff) << 8 | ((int)stream.Get() & 0xff);
                byteCount   = 3;
            }
            else
            {
                // Single byte header
                headerValue = (int)headerByte & 0xff;
                byteCount   = 1;
            }
            byte channelId = DecodeChannelId(headerValue, byteCount);
            if (channelId < 0)
            {
                throw new ProtocolException("Bad channel id: " + channelId);
            }
            byte headerSize   = DecodeHeaderSize(headerValue, byteCount);
            int  headerLength = GetHeaderLength(headerSize);
            headerLength += byteCount - 1;

            //if(headerLength > remaining)
            if (headerLength + byteCount - 1 > remaining)
            {
#if !SILVERLIGHT
                if (log.IsDebugEnabled)
                {
                    log.Debug(__Res.GetString(__Res.Rtmp_HeaderBuffering, remaining));
                }
#endif
                stream.Position = position;
                //context.SetBufferDecoding(headerLength);
                context.SetBufferDecoding(headerLength + byteCount - 1);
                return(null);
            }
            // Move the position back to the start
            stream.Position = position;

            RtmpHeader header = DecodeHeader(context, context.GetLastReadHeader(channelId), stream);
#if !SILVERLIGHT
            log.Debug("Decoded " + header);
#endif

            if (header == null)
            {
                throw new ProtocolException("Header is null, check for error");
            }

            // Save the header
            context.SetLastReadHeader(channelId, header);
            // Check to see if this is a new packet or continue decoding an existing one.
            RtmpPacket packet = context.GetLastReadPacket(channelId);
            if (packet == null)
            {
                packet = new RtmpPacket(header);
                context.SetLastReadPacket(channelId, packet);
            }

            ByteBuffer buf     = packet.Data;
            int        addSize = (header.Timer == 0xffffff ? 4 : 0);
            //int addSize = 0;
            int readRemaining = header.Size + addSize - (int)buf.Position;
            int chunkSize     = context.GetReadChunkSize();
            int readAmount    = (readRemaining > chunkSize) ? chunkSize : readRemaining;
            if (stream.Remaining < readAmount)
            {
#if !SILVERLIGHT
                if (log.IsDebugEnabled)
                {
                    log.Debug(__Res.GetString(__Res.Rtmp_ChunkSmall, stream.Remaining, readAmount));
                }
#endif
                //Skip the position back to the start
                stream.Position = position;
                context.SetBufferDecoding(headerLength + readAmount);

                //string path = GodLesZ.Library.Amf.Context.FluorineContext.Current.GetFullPath(@"log\chunk.bin");
                //stream.Dump(path);
                return(null);
            }

            //http://osflash.org/pipermail/free_osflash.org/2005-September/000261.html
            //http://www.acmewebworks.com/Downloads/openCS/091305-initialMeeting.txt
            ByteBuffer.Put(buf, stream, readAmount);
            if (buf.Position < header.Size + addSize)
            {
                context.ContinueDecoding();
                return(null);
            }
            if (buf.Position > header.Size + addSize)
            {
#if !SILVERLIGHT
                log.Warn(string.Format("Packet size expanded from {0} to {1} ({2})", header.Size + addSize, buf.Position, header));
#endif
            }

            buf.Flip();

            try {
                IRtmpEvent message = DecodeMessage(context, packet.Header, buf);
                packet.Message = message;

                if (message is ChunkSize)
                {
                    ChunkSize chunkSizeMsg = message as ChunkSize;
                    context.SetReadChunkSize(chunkSizeMsg.Size);
                }
            } finally {
                context.SetLastReadPacket(channelId, null);
            }
#if !SILVERLIGHT
            if (log.IsDebugEnabled)
            {
                log.Debug("Decoded " + packet.ToString());
            }
#endif
            return(packet);
        }
예제 #39
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="invoke"></param>
		protected abstract void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke);
예제 #40
0
        /// <summary>
        /// Decodes RTMP message event.
        /// </summary>
        /// <param name="context">RTMP protocol state.</param>
        /// <param name="header">RTMP header.</param>
        /// <param name="stream">Buffer to be decoded.</param>
        /// <returns>Decoded RTMP event.</returns>
        public static IRtmpEvent DecodeMessage(RtmpContext context, RtmpHeader header, ByteBuffer stream)
        {
            IRtmpEvent message = null;

            /*
             * if(header.Timer == 0xffffff)
             * {
             *      // Skip first four bytes
             *      byte[] extendedTimestamp = new byte[4];
             *      stream.Read(extendedTimestamp, 0, 4);
             *      log.Warn("Discarding extended timestamp");
             *      //int unknown = stream.ReadInt32();
             * }
             */
            switch (header.DataType)
            {
            case Constants.TypeChunkSize:
                message = DecodeChunkSize(stream);
                break;

            case Constants.TypeInvoke:
                message = DecodeInvoke(stream);
                break;

            case Constants.TypeFlexInvoke:
                message = DecodeFlexInvoke(stream);
                break;

            case Constants.TypeNotify:
                if (header.StreamId == 0)
                {
                    message = DecodeNotify(stream, header);
                }
                else
                {
                    message = DecodeStreamMetadata(stream);
                }
                break;

            case Constants.TypePing:
                message = DecodePing(stream);
                break;

            case Constants.TypeBytesRead:
                message = DecodeBytesRead(stream);
                break;

            case Constants.TypeAudioData:
                message = DecodeAudioData(stream);
                break;

            case Constants.TypeVideoData:
                message = DecodeVideoData(stream);
                break;

            case Constants.TypeSharedObject:
                message = DecodeSharedObject(stream);
                break;

            case Constants.TypeFlexSharedObject:
                message = DecodeFlexSharedObject(stream);
                break;

            case Constants.TypeServerBandwidth:
                message = DecodeServerBW(stream);
                break;

            case Constants.TypeClientBandwidth:
                message = DecodeClientBW(stream);
                break;

            default:
#if !SILVERLIGHT
                log.Warn("Unknown object type: " + header.DataType);
#endif
                message = DecodeUnknown(stream);
                break;
            }
            message.Header    = header;
            message.Timestamp = header.Timer;
            return(message);
        }
예제 #41
0
        /// <summary>
        /// Message recieved.
        /// </summary>
        /// <param name="connection">Connection object.</param>
        /// <param name="obj">Message object.</param>
        public void MessageReceived(RtmpConnection connection, object obj)
        {
            IRtmpEvent    message = null;
            RtmpPacket    packet  = null;
            RtmpHeader    header  = null;
            RtmpChannel   channel = null;
            IClientStream stream  = null;

            try {
                packet  = obj as RtmpPacket;
                message = packet.Message;
                header  = packet.Header;
                channel = connection.GetChannel(header.ChannelId);
                if (connection is IStreamCapableConnection)
                {
                    stream = (connection as IStreamCapableConnection).GetStreamById(header.StreamId);
                }

                // Support stream ids
#if !SILVERLIGHT
                FluorineContext.ValidateContext();
                FluorineContext.Current.Connection.SetAttribute(FluorineContext.FluorineStreamIdKey, header.StreamId);
#endif
                // Increase number of received messages
                connection.MessageReceived();

#if !SILVERLIGHT
                if (log != null && log.IsDebugEnabled)
                {
                    log.Debug("RtmpConnection message received, type = " + header.DataType);
                }
#endif

                if (message != null)
                {
                    message.Source = connection;
                }

                switch (header.DataType)
                {
                case Constants.TypeInvoke:
                    OnInvoke(connection, channel, header, message as Invoke);
                    if (message.Header.StreamId != 0 &&
                        (message as Invoke).ServiceCall.ServiceName == null &&
                        (message as Invoke).ServiceCall.ServiceMethodName == BaseRtmpHandler.ACTION_PUBLISH)
                    {
                        if (stream != null)                                 //Dispatch if stream was created
                        {
                            (stream as IEventDispatcher).DispatchEvent(message);
                        }
                    }
                    break;

                case Constants.TypeFlexInvoke:
                    OnFlexInvoke(connection, channel, header, message as FlexInvoke);
                    if (message.Header.StreamId != 0 &&
                        (message as Invoke).ServiceCall.ServiceName == null &&
                        (message as Invoke).ServiceCall.ServiceMethodName == BaseRtmpHandler.ACTION_PUBLISH)
                    {
                        if (stream != null)                                 //Dispatch if stream was created
                        {
                            (stream as IEventDispatcher).DispatchEvent(message);
                        }
                    }
                    break;

                case Constants.TypeNotify:                        // just like invoke, but does not return
                    if ((message as Notify).Data != null && stream != null)
                    {
                        // Stream metadata
                        (stream as IEventDispatcher).DispatchEvent(message);
                    }
                    else
                    {
                        OnInvoke(connection, channel, header, message as Notify);
                    }
                    break;

                case Constants.TypePing:
                    OnPing(connection, channel, header, message as Ping);
                    break;

                case Constants.TypeBytesRead:
                    OnStreamBytesRead(connection, channel, header, message as BytesRead);
                    break;

                case Constants.TypeSharedObject:
                case Constants.TypeFlexSharedObject:
                    OnSharedObject(connection, channel, header, message as SharedObjectMessage);
                    break;

                case Constants.TypeFlexStreamEnd:
                    if (stream != null)
                    {
                        (stream as IEventDispatcher).DispatchEvent(message);
                    }
                    break;

                case Constants.TypeChunkSize:
                    OnChunkSize(connection, channel, header, message as ChunkSize);
                    break;

                case Constants.TypeAudioData:
                case Constants.TypeVideoData:
                    // NOTE: If we respond to "publish" with "NetStream.Publish.BadName",
                    // the client sends a few stream packets before stopping. We need to
                    // ignore them.
                    if (stream != null)
                    {
                        ((IEventDispatcher)stream).DispatchEvent(message);
                    }
                    break;

                case Constants.TypeServerBandwidth:
                    OnServerBW(connection, channel, header, message as ServerBW);
                    break;

                case Constants.TypeClientBandwidth:
                    OnClientBW(connection, channel, header, message as ClientBW);
                    break;

                default:
#if !SILVERLIGHT
                    if (log != null && log.IsDebugEnabled)
                    {
                        log.Debug("RtmpService event not handled: " + header.DataType);
                    }
#endif
                    break;
                }
            } catch (Exception ex) {
#if !SILVERLIGHT
                if (log.IsErrorEnabled)
                {
                    log.Error(__Res.GetString(__Res.Rtmp_HandlerError), ex);
                    log.Error(__Res.GetString(__Res.Error_ContextDump));
                    //log.Error(Environment.NewLine);
                    log.Error(packet);
                }
#endif
            }
        }
예제 #42
0
        static Notify DecodeNotifyOrInvoke(Notify notify, ByteBuffer stream, RtmpHeader header)
        {
            long       start  = stream.Position;
            RtmpReader reader = new RtmpReader(stream);
            string     action = reader.ReadData() as string;

            if (!(notify is Invoke))
            {
                //Don't decode "NetStream.send" requests
                stream.Position = start;
                notify.Data     = ByteBuffer.Allocate(stream.Remaining);
                notify.Data.Put(stream);
                //notify.setData(in.asReadOnlyBuffer());
                return(notify);
            }

            if (header == null || header.StreamId == 0)
            {
                double invokeId = (double)reader.ReadData();
                notify.InvokeId = (int)invokeId;
            }

            object[] parameters = Call.EmptyArguments;
            if (stream.HasRemaining)
            {
#if !(NET_1_1)
                List <object> paramList = new List <object>();
#else
                ArrayList paramList = new ArrayList();
#endif
                object obj = reader.ReadData();

                if (obj is IDictionary)
                {
                    // for connect we get a map
                    notify.ConnectionParameters = obj as IDictionary;
                }
                else if (obj != null)
                {
                    paramList.Add(obj);
                }

                while (stream.HasRemaining)
                {
                    paramList.Add(reader.ReadData());
                }
                parameters = paramList.ToArray();
            }

            int    dotIndex      = action.LastIndexOf(".");
            string serviceName   = (dotIndex == -1) ? null : action.Substring(0, dotIndex);
            string serviceMethod = (dotIndex == -1) ? action : action.Substring(dotIndex + 1, action.Length - dotIndex - 1);

            if (notify is Invoke)
            {
                PendingCall call = new PendingCall(serviceName, serviceMethod, parameters);
                notify.ServiceCall = call;
            }
            else
            {
                Call call = new Call(serviceName, serviceMethod, parameters);
                notify.ServiceCall = call;
            }
            return(notify);
        }
예제 #43
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="source"></param>
 /// <param name="chunkSize"></param>
 protected abstract void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize);
예제 #44
0
		public static ByteBuffer EncodeMessage(RtmpContext context, RtmpHeader header, IRtmpEvent message) {
			switch (header.DataType) {
				case Constants.TypeChunkSize:
					return EncodeChunkSize(context, message as ChunkSize);
				case Constants.TypeInvoke:
					return EncodeInvoke(context, message as Invoke);
				case Constants.TypeFlexInvoke:
					return EncodeFlexInvoke(context, message as FlexInvoke);
				case Constants.TypeSharedObject:
					return EncodeSharedObject(context, message as ISharedObjectMessage);
				case Constants.TypeFlexSharedObject:
					return EncodeFlexSharedObject(context, message as ISharedObjectMessage);
				case Constants.TypeNotify:
					if ((message as Notify).ServiceCall == null) {
						return EncodeStreamMetadata(context, message as Notify);
					} else {
						return EncodeNotify(context, message as Notify);
					}
				case Constants.TypePing:
					return EncodePing(context, message as Ping);
				case Constants.TypeBytesRead:
					return EncodeBytesRead(context, message as BytesRead);
				case Constants.TypeAudioData:
					return EncodeAudioData(context, message as AudioData);
				case Constants.TypeVideoData:
					return EncodeVideoData(context, message as VideoData);
				case Constants.TypeServerBandwidth:
					return EncodeServerBW(context, message as ServerBW);
				case Constants.TypeClientBandwidth:
					return EncodeClientBW(context, message as ClientBW);
				case Constants.TypeFlexStreamEnd:
					return EncodeFlexStreamSend(context, message as FlexStreamSend);
				default:
#if !SILVERLIGHT
					if (_log.IsErrorEnabled)
						_log.Error("Unknown object type: " + header.DataType);
#endif
					return null;
			}
		}
예제 #45
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="invoke"></param>
 protected abstract void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke);
예제 #46
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="source"></param>
		/// <param name="serverBW"></param>
		protected abstract void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBW);
예제 #47
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="invoke"></param>
 protected abstract void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke);
예제 #48
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="source"></param>
 /// <param name="streamBytesRead"></param>
 protected void OnStreamBytesRead(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, BytesRead streamBytesRead)
 {
     connection.ReceivedBytesRead(streamBytesRead.Bytes);
 }
예제 #49
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="source"></param>
		/// <param name="clientBW"></param>
		protected abstract void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBW);
예제 #50
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="source"></param>
 /// <param name="ping"></param>
 protected abstract void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping);
예제 #51
0
		internal RtmpPacket(RtmpHeader header) {
			_header = header;
			_data = ByteBuffer.Allocate(header.Size + (header.Timer == 0xffffff ? 4 : 0));
		}
예제 #52
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);
예제 #53
0
		internal RtmpPacket(RtmpHeader header, IRtmpEvent message) {
			_header = header;
			_message = message;
		}
예제 #54
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="source"></param>
 /// <param name="serverBW"></param>
 protected abstract void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBW);
예제 #55
0
        protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping)
        {
            switch (ping.PingType)
            {
            case Ping.ClientBuffer:
                IClientStream stream = null;
                // Get the stream id
                int streamId = ping.Value2;
                // Get requested buffer size in milliseconds
                int buffer = ping.Value3;
                if (streamId != 0)
                {
                    // The client wants to set the buffer time
                    stream = connection.GetStreamById(streamId);
                    if (stream != null)
                    {
                        stream.SetClientBufferDuration(buffer);
                        if (log.IsDebugEnabled)
                        {
                            log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId));
                        }
                    }
                }
                // Catch-all to make sure buffer size is set
                if (stream == null)
                {
                    // Remember buffer time until stream is created
                    connection.RememberStreamBufferDuration(streamId, buffer);
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(string.Format("Remembering client buffer size: {0} on stream id: {1} ", buffer, streamId));
                    }
                }
                break;

            case Ping.PongServer:
                // This is the response to an IConnection.Ping request
                connection.PingReceived(ping);
                break;

            default:
                log.Warn("Unhandled ping: " + ping);
                break;
            }
        }
예제 #56
0
 protected override void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBW)
 {
 }
예제 #57
0
		protected override void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBW) {
		}