Ejemplo n.º 1
0
		static ByteBuffer EncodeNotifyOrInvoke(RtmpContext context, Notify invoke)
		{
			//MemoryStreamEx output = new MemoryStreamEx();
			ByteBuffer output = ByteBuffer.Allocate(1024);
			output.AutoExpand = true;
			RtmpWriter writer = new RtmpWriter(output);
            //Set legacy collection flag from context
            writer.UseLegacyCollection = context.UseLegacyCollection;
            writer.UseLegacyThrowable = context.UseLegacyThrowable;

			IServiceCall serviceCall = invoke.ServiceCall;
			bool isPending = serviceCall.Status == Call.STATUS_PENDING;
			if (!isPending) 
			{
				//log.debug("Call has been executed, send result");
                writer.WriteData(context.ObjectEncoding, serviceCall.IsSuccess ? "_result" : "_error");
			}
			else
			{
				//log.debug("This is a pending call, send request");
				string action = (serviceCall.ServiceName == null) ? serviceCall.ServiceMethodName : serviceCall.ServiceName + "." + serviceCall.ServiceMethodName;
				writer.WriteData(context.ObjectEncoding, action);
			}
			if(invoke is Invoke)
			{
				writer.WriteData(context.ObjectEncoding, invoke.InvokeId);
				writer.WriteData(context.ObjectEncoding, invoke.ConnectionParameters);
			}
			if(!isPending && (invoke is Invoke)) 
			{
				IPendingServiceCall pendingCall = (IPendingServiceCall)serviceCall;
                if (!serviceCall.IsSuccess && !(pendingCall.Result is StatusASO))
                {
                    StatusASO status = GenerateErrorResult(StatusASO.NC_CALL_FAILED, serviceCall.Exception);
                    pendingCall.Result = status;
                }
				writer.WriteData(context.ObjectEncoding, pendingCall.Result);
			}
			else
			{
				//log.debug("Writing params");
				object[] args = invoke.ServiceCall.Arguments;
				if (args != null) 
				{
					foreach(object element in args)
					{
						writer.WriteData(context.ObjectEncoding, element);
					}
				}
			}
			return output;
		}
Ejemplo n.º 2
0
        public void PushMessage(IPipe pipe, IMessage message)
        {
		    if (message is ResetMessage) 
            {
			    _timeStamper.Reset();
            } 
            else if (message is StatusMessage) 
            {
			    StatusMessage statusMsg = message as StatusMessage;
			    _data.SendStatus(statusMsg.body as StatusASO);
		    }
            else if (message is RtmpMessage)
            {
                // Make sure chunk size has been sent
                if (!_chunkSizeSent)
                    SendChunkSize();

                RtmpMessage rtmpMsg = message as RtmpMessage;
                IRtmpEvent msg = rtmpMsg.body;

                int eventTime = msg.Timestamp;
#if !SILVERLIGHT
                if(log.IsDebugEnabled)
                    log.Debug(string.Format("Message timestamp: {0}", eventTime));
#endif
                if (eventTime < 0)
                {
#if !SILVERLIGHT
                    if (log.IsDebugEnabled)
                        log.Debug(string.Format("Message has negative timestamp: {0}", eventTime));
#endif
                    return;
                }
                byte dataType = msg.DataType;
                // Create a new header for the consumer
                RtmpHeader header = _timeStamper.GetTimeStamp(dataType, eventTime);

                switch (msg.DataType)
                {
                    case Constants.TypeStreamMetadata:
                        Notify notify = new Notify((msg as Notify).Data);
                        notify.Header = header;
                        notify.Timestamp = header.Timer;
                        _data.Write(notify);
                        break;
                    case Constants.TypeFlexStreamEnd:
                        // TODO: okay to send this also to AMF0 clients?
                        FlexStreamSend send = new FlexStreamSend((msg as Notify).Data);
                        send.Header = header;
                        send.Timestamp = header.Timer;
                        _data.Write(send);
                        break;
                    case Constants.TypeVideoData:
                        VideoData videoData = new VideoData((msg as VideoData).Data);
                        videoData.Header = header;
                        videoData.Timestamp = header.Timer;
                        _video.Write(videoData);
                        break;
                    case Constants.TypeAudioData:
                        AudioData audioData = new AudioData((msg as AudioData).Data);
                        audioData.Header = header;
                        audioData.Timestamp = header.Timer;
                        _audio.Write(audioData);
                        break;
                    case Constants.TypePing:
                        Ping ping = new Ping((msg as Ping).PingType, (msg as Ping).Value2, (msg as Ping).Value3, (msg as Ping).Value4);
                        ping.Header = header;
                        _connection.Ping(ping);
                        break;
                    case Constants.TypeBytesRead:
                        BytesRead bytesRead = new BytesRead((msg as BytesRead).Bytes);
                        bytesRead.Header = header;
                        bytesRead.Timestamp = header.Timer;
                        _connection.GetChannel((byte)2).Write(bytesRead);
                        break;
                    default:
                        _data.Write(msg);
                        break;
                }
            }
        }
Ejemplo n.º 3
0
 static ByteBuffer EncodeStreamMetadata(RtmpContext context, Notify metaData)
 {
     ByteBuffer output = metaData.Data;
     return output;
 }
Ejemplo n.º 4
0
 static ByteBuffer EncodeNotify(RtmpContext context,  Notify notify)
 {
     return EncodeNotifyOrInvoke(context, notify);
 }
Ejemplo n.º 5
0
        public void OnStreamEvent(Notify notify)
        {
            bool onStatus = notify.ServiceCall.ServiceMethodName.Equals("onStatus");
            if (!onStatus)
            {
                if (notify.ServiceCall.ServiceMethodName.Equals("onMetaData"))
                    RaiseOnMetaData(notify.ServiceCall.Arguments[0] as IDictionary);
                if (notify.ServiceCall.ServiceMethodName.Equals("onPlayStatus"))
                    RaiseOnPlayStatus(notify.ServiceCall.Arguments[0] as IDictionary);

                MethodInfo mi = MethodHandler.GetMethod(_client.GetType(), notify.ServiceCall.ServiceMethodName, notify.ServiceCall.Arguments, false, false);
                if (mi != null)
                {
                    ParameterInfo[] parameterInfos = mi.GetParameters();
                    object[] args = new object[parameterInfos.Length];
                    notify.ServiceCall.Arguments.CopyTo(args, 0);
                    TypeHelper.NarrowValues(args, parameterInfos);
                    try
                    {
                        InvocationHandler invocationHandler = new InvocationHandler(mi);
                        object result = invocationHandler.Invoke(_client, args);
                    }
                    catch (Exception exception)
                    {
                        notify.ServiceCall.Exception = exception;
                        notify.ServiceCall.Status = dotFlex.Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION;
                        //log.Error("Error while invoking method " + call.ServiceMethodName + " on client", exception);
                    }
                }
                else
                {
                    string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, notify.ServiceCall.ServiceMethodName);
                    this.RaiseNetStatus(new FluorineException(msg));
                }
            }
            else
            {
                object[] args = notify.ServiceCall.Arguments;
                ASObject statusASO = null;
                if ((args != null) && (args.Length > 0))
                    statusASO = args[0] as ASObject;
                this.RaiseNetStatus(statusASO);
            }
        }
Ejemplo n.º 6
0
 private void SendOnPlayStatus(String code, int duration, long bytes)
 {
     MemoryStream ms = new MemoryStream();
     AMFWriter writer = new AMFWriter(ms);
     writer.WriteString("onPlayStatus");
     Hashtable props = new Hashtable();
     props.Add("code", code);
     props.Add("level", "status");
     props.Add("duration", duration);
     props.Add("bytes", bytes);
     writer.WriteAssociativeArray(ObjectEncoding.AMF0, props);
     ByteBuffer buffer = new ByteBuffer(ms);
     IRtmpEvent evt = new Notify(buffer);
     if (_lastMessage != null)
     {
         int timestamp = _lastMessage.Timestamp;
         evt.Timestamp = timestamp;
     }
     else
     {
         evt.Timestamp = 0;
     }
     RtmpMessage msg = new RtmpMessage();
     msg.body = evt;
     DoPushMessage(msg);
 }
Ejemplo n.º 7
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;
		}
Ejemplo n.º 8
0
 public IMessage PullMessage(IPipe pipe)
 {
     lock (_syncLock)
     {
         if (_pipe != pipe)
             return null;
         if (_reader == null)
             Init();
         if (!_reader.HasMoreTags())
         {
             // TODO send OOBCM to notify EOF
             // Do not unsubscribe as this kills VOD seek while in buffer
             // this.pipe.unsubscribe(this);
             return null;
         }
         ITag tag = _reader.ReadTag();
         IRtmpEvent msg = null;
         int timestamp = tag.Timestamp;
         switch (tag.DataType)
         {
             case Constants.TypeAudioData:
                 msg = new AudioData(tag.Body);
                 break;
             case Constants.TypeVideoData:
                 msg = new VideoData(tag.Body);
                 break;
             case Constants.TypeInvoke:
                 msg = new Invoke(tag.Body);
                 break;
             case Constants.TypeNotify:
                 msg = new Notify(tag.Body);
                 break;
             case Constants.TypeFlexStreamEnd:
                 msg = new FlexStreamSend(tag.Body);
                 break;
             default:
                 log.Warn("Unexpected type " + tag.DataType);
                 msg = new Unknown(tag.DataType, tag.Body);
                 break;
         }
         msg.Timestamp = timestamp;
         RtmpMessage rtmpMsg = new RtmpMessage();
         rtmpMsg.body = msg;
         return rtmpMsg;
     }
 }
Ejemplo n.º 9
0
		static Notify DecodeStreamMetadata(ByteBuffer stream) 
		{
            RtmpReader reader = new RtmpReader(stream);
            string action = reader.ReadData() as string;
            object obj = reader.ReadData();
            Notify notify = new Notify();
			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);
            object[] parameters = new object[1]{obj};
			Call call = new Call(serviceName, serviceMethod, parameters);
			notify.ServiceCall = call;
            return notify;
		}
Ejemplo n.º 10
0
        /// <summary>
        /// Notifies service using service call object and channel.
        /// </summary>
        /// <param name="serviceCall">Service call object.</param>
        /// <param name="channel">Channel to use.</param>
		public void Notify(IServiceCall serviceCall, byte channel)
		{
			Notify notify = new Notify();
			notify.ServiceCall = serviceCall;
			GetChannel(channel).Write(notify);
		}
Ejemplo n.º 11
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;
            }
		}
Ejemplo n.º 12
0
        /// <summary>
        /// Handler for pending call result. Dispatches results to all pending call handlers.
        /// </summary>
        /// <param name="connection">Connection.</param>
        /// <param name="invoke">Pending call result event context.</param>
        protected void HandlePendingCallResult(RtmpConnection connection, Notify invoke)
        {
            IServiceCall call = invoke.ServiceCall;
            IPendingServiceCall pendingCall = connection.RetrievePendingCall(invoke.InvokeId);
            if (pendingCall != null)
            {
                pendingCall.Status = call.Status;
                // The client sent a response to a previously made call.
                object[] args = call.Arguments;
                if ((args != null) && (args.Length > 0))
                {
                    pendingCall.Result = args[0];
                }

                IPendingServiceCallback[] callbacks = pendingCall.GetCallbacks();
                if (callbacks != null && callbacks.Length > 0)
                {
                    foreach (IPendingServiceCallback callback in callbacks)
                    {
                        try
                        {
                            callback.ResultReceived(pendingCall);
                        }
                        catch (Exception ex)
                        {
#if !SILVERLIGHT
                            log.Error("Error while executing callback " + callback, ex);
#endif
                        }
                    }
                }
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// This method supports the Fluorine infrastructure and is not intended to be used directly from your code.
 /// </summary>
 /// <param name="connection"></param>
 /// <param name="channel"></param>
 /// <param name="header"></param>
 /// <param name="invoke"></param>
 protected abstract void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke);