Beispiel #1
0
		public ConnectionConsumer(RtmpConnection connection, int videoChannel, int audioChannel, int dataChannel) {
#if !SILVERLIGHT
			if (log.IsDebugEnabled)
				log.Debug(string.Format("Channel ids - video: {0} audio: {1} data: {2}", videoChannel, audioChannel, dataChannel));
#endif
			_connection = connection;
			_video = connection.GetChannel(videoChannel);
			_audio = connection.GetChannel(audioChannel);
			_data = connection.GetChannel(dataChannel);
			_timeStamper = new TimeStamper();
		}
Beispiel #2
0
 /// <summary>
 /// Creates output stream from channels.
 /// </summary>
 /// <param name="video">Video channel.</param>
 /// <param name="audio">Audio channel.</param>
 /// <param name="data">Data channel.</param>
 internal OutputStream(RtmpChannel video, RtmpChannel audio, RtmpChannel data)
 {
     _video = video;
     _audio = audio;
     _data = data;
 }
Beispiel #3
0
 internal void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message)
 {
     RemoteSharedObject.Dispatch(message);
 }
Beispiel #4
0
        public void publish(string name, string mode)
        {
            IConnection connection = FluorineContext.Current.Connection;

            if (!(connection is IStreamCapableConnection))
            {
                return;
            }
            IStreamCapableConnection streamConnection = connection as IStreamCapableConnection;
            IScope scope    = connection.Scope;
            int    streamId = GetCurrentStreamId();

            if (name == null || string.Empty.Equals(name))
            {
                SendNSFailed(streamConnection as RtmpConnection, "The stream name may not be empty.", name, streamId);
                return;
            }

            IStreamSecurityService security = ScopeUtils.GetScopeService(scope, typeof(IStreamSecurityService)) as IStreamSecurityService;

            if (security != null)
            {
                IEnumerator handlers = security.GetStreamPublishSecurity();
                while (handlers.MoveNext())
                {
                    IStreamPublishSecurity handler = handlers.Current as IStreamPublishSecurity;
                    if (!handler.IsPublishAllowed(scope, name, mode))
                    {
                        SendNSFailed(streamConnection as RtmpConnection, "You are not allowed to publish the stream.", name, streamId);
                        return;
                    }
                }
            }
            IBroadcastScope bsScope = GetBroadcastScope(scope, name);

            if (bsScope != null && bsScope.GetProviders().Count > 0)
            {
                // Another stream with that name is already published.
                StatusASO badName = new StatusASO(StatusASO.NS_PUBLISH_BADNAME);
                badName.clientid = streamId;
                badName.details  = name;
                badName.level    = "error";
                // FIXME: there should be a direct way to send the status
                RtmpChannel channel = (streamConnection as RtmpConnection).GetChannel((byte)(4 + ((streamId - 1) * 5)));
                channel.SendStatus(badName);
                return;
            }
            IClientStream stream = streamConnection.GetStreamById(streamId);

            if (stream != null && !(stream is IClientBroadcastStream))
            {
                return;
            }
            bool created = false;

            if (stream == null)
            {
                stream  = streamConnection.NewBroadcastStream(streamId);
                created = true;
            }
            IClientBroadcastStream bs = stream as IClientBroadcastStream;

            try
            {
                bs.PublishedName = name;
                IScopeContext context = connection.Scope.Context;
                //IProviderService providerService = (IProviderService)context.getBean(IProviderService.BEAN_NAME);
                IProviderService providerService = ScopeUtils.GetScopeService(connection.Scope, typeof(IProviderService)) as IProviderService;
                // TODO handle registration failure
                if (providerService.RegisterBroadcastStream(connection.Scope, name, bs))
                {
                    bsScope = GetBroadcastScope(connection.Scope, name);
                    bsScope.SetAttribute(Constants.BroadcastScopeStreamAttribute, bs);
                    if (connection is BaseConnection)
                    {
                        (connection as BaseConnection).RegisterBasicScope(bsScope);
                    }
                }
                if (Constants.ClientStreamModeRecord.Equals(mode))
                {
                    bs.Start();
                    bs.SaveAs(name, false);
                }
                else if (Constants.ClientStreamModeAppend.Equals(mode))
                {
                    bs.Start();
                    bs.SaveAs(name, true);
                }
                else if (Constants.ClientStreamModeLive.Equals(mode))
                {
                    bs.Start();
                }
                bs.StartPublishing();
            }
            catch (System.IO.IOException ex)
            {
                StatusASO accessDenied = new StatusASO(StatusASO.NS_RECORD_NOACCESS);
                accessDenied.clientid    = streamId;
                accessDenied.description = "The file could not be created/written to." + ex.Message;
                accessDenied.details     = name;
                accessDenied.level       = "error";
                // FIXME: there should be a direct way to send the status
                RtmpChannel channel = (streamConnection as RtmpConnection).GetChannel((byte)(4 + ((streamId - 1) * 5)));
                channel.SendStatus(accessDenied);
                bs.Close();
                if (created)
                {
                    streamConnection.DeleteStreamById(streamId);
                }
            }
            catch (Exception ex)
            {
                log.Warn("Publish caught exception", ex);
            }
        }
Beispiel #5
0
        protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping)
        {
            switch (ping.PingType)
            {
            case Ping.PingClient:
            case Ping.StreamBegin:
            case Ping.RecordedStream:
            case Ping.StreamPlayBufferClear:
                // The server wants to measure the RTT
                Ping pong = new Ping();
                pong.PingType = Ping.PongServer;
                // The event data is a 4-byte timestamp, which was received with the in the Ping request
                pong.Value2 = ping.Value2;
                connection.Ping(pong);
                break;

            case Ping.StreamDry:
#if !SILVERLIGHT
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("Stream indicates there is no data available");
                }
#endif
                break;

            case Ping.ClientBuffer:
                //Set the client buffer
                IClientStream stream = null;
                //Get the stream id
                int streamId = ping.Value2;
                //Get requested buffer size in milliseconds
                int buffer = ping.Value3;
#if !SILVERLIGHT
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId));
                }
#endif
                if (streamId != 0)
                {
                    // The client wants to set the buffer time
                    stream = connection.GetStreamById(streamId);
                    if (stream != null)
                    {
                        stream.SetClientBufferDuration(buffer);
#if !SILVERLIGHT
                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug(string.Format("Setting client buffer on stream: {0}", streamId));
                        }
#endif
                    }
                }
                //Catch-all to make sure buffer size is set
                if (stream == null)
                {
                    // Remember buffer time until stream is created
                    connection.RememberStreamBufferDuration(streamId, buffer);
#if !SILVERLIGHT
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug(string.Format("Remembering client buffer on stream: {0}", streamId));
                    }
#endif
                }
                break;

            default:
#if !SILVERLIGHT
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(string.Format("Unhandled ping: {0}", ping));
                }
#endif
                break;
            }
        }
Beispiel #6
0
 protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize)
 {
     //ChunkSize is not implemented yet
 }
Beispiel #7
0
 protected override void OnFlexInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, FlexInvoke invoke)
 {
     OnInvoke(connection, channel, header, invoke);
 }
Beispiel #8
0
 protected override void OnSharedObject(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, SharedObjectMessage message)
 {
     _netConnection.OnSharedObject(connection, channel, header, message);
 }
Beispiel #9
0
        protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke)
        {
            IServiceCall call = invoke.ServiceCall;

            if (invoke.EventType == EventType.STREAM_DATA)
            {
#if !SILVERLIGHT
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(string.Format("Ignoring stream data notify with header {0}", header));
                }
#endif
                return;
            }

            if (call.ServiceMethodName == "_result" || call.ServiceMethodName == "_error")
            {
                if (call.ServiceMethodName == "_error")
                {
                    call.Status = Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION;
                }
                if (call.ServiceMethodName == "_result")
                {
                    call.Status = Messaging.Rtmp.Service.Call.STATUS_SUCCESS_RESULT;
                }
                //Get the panding call, if any, as HandlePendingCallResult will remove it
                IPendingServiceCall pendingCall = connection.GetPendingCall(invoke.InvokeId);
                HandlePendingCallResult(connection, invoke);

                if (call.IsSuccess && invoke.InvokeId == 1)
                {
                    // Should keep this as an Object to stay compatible with FMS3 etc
                    IDictionary aso = call.Arguments[0] as IDictionary;
                    if (aso != null)
                    {
                        object clientId = null;
                        if (aso.Contains("clientid"))
                        {
                            clientId = aso["clientid"];
                        }
#if !SILVERLIGHT
                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug(string.Format("Client id: {0}", clientId));
                        }
#endif
                        _netConnection.SetClientId(clientId != null ? clientId.ToString() : null);
                    }
                }

                //Notify via NetConnection if no IPendingServiceCallback was defined but the call failed
                if (call.ServiceMethodName == "_error")
                {
                    object[] args      = call.Arguments;
                    ASObject statusAso = null;
                    if ((args != null) && (args.Length > 0))
                    {
                        statusAso = args[0] as ASObject;
                    }
                    bool raiseError = false;
                    if (pendingCall != null)
                    {
                        IPendingServiceCallback[] callbacks = pendingCall.GetCallbacks();
                        if (callbacks == null || callbacks.Length == 0)
                        {
                            raiseError = true;
                        }
                    }
                    else
                    {
                        raiseError = true;
                    }
                    if (raiseError)
                    {
                        if (statusAso != null)
                        {
                            _netConnection.RaiseNetStatus(statusAso);
                        }
                        else
                        {
                            string msg = __Res.GetString(__Res.Invocation_Failed, pendingCall != null ? pendingCall.ServiceMethodName : string.Empty, "Invocation failed");
                            _netConnection.RaiseNetStatus(msg);
                        }
                    }
                }
                return;
            }

            bool onStatus = call.ServiceMethodName.Equals("onStatus") || call.ServiceMethodName.Equals("onMetaData") ||
                            call.ServiceMethodName.Equals("onPlayStatus");
            if (onStatus)
            {
                /*
                 * IDictionary aso = call.Arguments[0] as IDictionary;
                 * // Should keep this as an Object to stay compatible with FMS3 etc
                 * object clientId = null;
                 * if( aso.Contains("clientid") )
                 *      clientId = aso["clientid"];
                 * if (clientId == null)
                 *      clientId = header.StreamId;
                 #if !SILVERLIGHT
                 * if (log.IsDebugEnabled)
                 *      log.Debug(string.Format("Client id: {0}", clientId));
                 #endif
                 * if (clientId != null)
                 * {
                 *      NetStream stream = _connection.GetStreamById((int)clientId) as NetStream;
                 *      if (stream != null)
                 *      {
                 *              stream.OnStreamEvent(invoke);
                 *      }
                 * }
                 */
                NetStream stream = _connection.GetStreamById(header.StreamId) as NetStream;
                if (stream != null)
                {
                    stream.OnStreamEvent(invoke);
                }
                return;
            }

            if (call is IPendingServiceCall)
            {
                IPendingServiceCall psc = call as IPendingServiceCall;

                /*
                 * object result = psc.Result;
                 * object result = psc.Result;
                 * if (result is DeferredResult)
                 * {
                 *      DeferredResult dr = result as DeferredResult;
                 *      dr.InvokeId = invoke.InvokeId;
                 *      dr.ServiceCall = psc;
                 *      dr.Channel = channel;
                 *      connection.RegisterDeferredResult(dr);
                 * }
                 * else
                 * {
                 *      Invoke reply = new Invoke();
                 *      reply.ServiceCall = call;
                 *      reply.InvokeId = invoke.InvokeId;
                 *      channel.Write(reply);
                 * }
                 */
                MethodInfo mi = MethodHandler.GetMethod(_netConnection.Client.GetType(), call.ServiceMethodName, call.Arguments, false, false);
                if (mi != null)
                {
                    ParameterInfo[] parameterInfos = mi.GetParameters();
                    object[]        args           = new object[parameterInfos.Length];
                    call.Arguments.CopyTo(args, 0);
                    TypeHelper.NarrowValues(args, parameterInfos);
                    try {
                        InvocationHandler invocationHandler = new InvocationHandler(mi);
                        object            result            = invocationHandler.Invoke(_netConnection.Client, args);
                        if (mi.ReturnType == typeof(void))
                        {
                            call.Status = Messaging.Rtmp.Service.Call.STATUS_SUCCESS_VOID;
                        }
                        else
                        {
                            call.Status = result == null ? Messaging.Rtmp.Service.Call.STATUS_SUCCESS_NULL : Messaging.Rtmp.Service.Call.STATUS_SUCCESS_RESULT;
                            psc.Result  = result;
                        }
                    } catch (Exception exception) {
                        call.Exception = exception;
                        call.Status    = Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION;
                        //log.Error("Error while invoking method " + call.ServiceMethodName + " on client", exception);
                    }
                }
                else                  // if (!onStatus)
                {
                    string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, call.ServiceMethodName);
                    call.Status    = Messaging.Rtmp.Service.Call.STATUS_METHOD_NOT_FOUND;
                    call.Exception = new FluorineException(msg);
                    _netConnection.RaiseNetStatus(call.Exception);

                    //log.Error(msg, call.Exception);
                }
                if (call.Status == Messaging.Rtmp.Service.Call.STATUS_SUCCESS_VOID || call.Status == Messaging.Rtmp.Service.Call.STATUS_SUCCESS_NULL)
                {
#if !SILVERLIGHT
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Method does not have return value, do not reply");
                    }
#endif
                    return;
                }
                Invoke reply = new Invoke();
                reply.ServiceCall = call;
                reply.InvokeId    = invoke.InvokeId;
                channel.Write(reply);
            }
            else
            {
                IPendingServiceCall pendingCall = connection.RetrievePendingCall(invoke.InvokeId);
                Unreferenced.Parameter(pendingCall);
            }
        }
Beispiel #10
0
 protected override void OnClientBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ClientBW clientBw)
 {
     channel.Write(new ServerBW(clientBw.Bandwidth));
 }
Beispiel #11
0
 protected override void OnServerBW(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ServerBW serverBw)
 {
 }
Beispiel #12
0
 /// <summary>
 /// Creates output stream from channels.
 /// </summary>
 /// <param name="video">Video channel.</param>
 /// <param name="audio">Audio channel.</param>
 /// <param name="data">Data channel.</param>
 internal OutputStream(RtmpChannel video, RtmpChannel audio, RtmpChannel data)
 {
     _video = video;
     _audio = audio;
     _data  = data;
 }
Beispiel #13
0
        protected override void OnInvoke(RtmpConnection connection, RtmpChannel channel, RtmpHeader header, Notify invoke)
        {
            IServiceCall serviceCall = invoke.ServiceCall;

            if ((serviceCall.ServiceMethodName == "_result") || (serviceCall.ServiceMethodName == "_error"))
            {
                if (serviceCall.ServiceMethodName == "_error")
                {
                    serviceCall.Status = 0x13;
                }
                if (serviceCall.ServiceMethodName == "_result")
                {
                    serviceCall.Status = 2;
                }
                base.HandlePendingCallResult(connection, invoke);
            }
            else if (serviceCall is IPendingServiceCall)
            {
                IPendingServiceCall call2      = serviceCall as IPendingServiceCall;
                MethodInfo          methodInfo = MethodHandler.GetMethod(this._netConnection.Client.GetType(), serviceCall.ServiceMethodName, serviceCall.Arguments, false, false);
                if (methodInfo != null)
                {
                    ParameterInfo[] parameters = methodInfo.GetParameters();
                    object[]        array      = new object[parameters.Length];
                    serviceCall.Arguments.CopyTo(array, 0);
                    TypeHelper.NarrowValues(array, parameters);
                    try
                    {
                        object obj2 = new InvocationHandler(methodInfo).Invoke(this._netConnection.Client, array);
                        if (methodInfo.ReturnType == typeof(void))
                        {
                            serviceCall.Status = 4;
                        }
                        else
                        {
                            serviceCall.Status = (obj2 == null) ? ((byte)3) : ((byte)2);
                            call2.Result       = obj2;
                        }
                    }
                    catch (Exception exception)
                    {
                        serviceCall.Exception = exception;
                        serviceCall.Status    = 0x13;
                    }
                }
                else
                {
                    string message = __Res.GetString("Invocation_NoSuitableMethod", new object[] { serviceCall.ServiceMethodName });
                    serviceCall.Status    = 0x11;
                    serviceCall.Exception = new FluorineException(message);
                }
                if ((serviceCall.Status == 4) || (serviceCall.Status == 3))
                {
                    if (log.get_IsDebugEnabled())
                    {
                        log.Debug("Method does not have return value, do not reply");
                    }
                }
                else
                {
                    FluorineFx.Messaging.Rtmp.Event.Invoke invoke2 = new FluorineFx.Messaging.Rtmp.Event.Invoke {
                        ServiceCall = serviceCall,
                        InvokeId    = invoke.InvokeId
                    };
                    channel.Write(invoke2);
                }
            }
        }
Beispiel #14
0
 protected override void OnChunkSize(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, ChunkSize chunkSize)
 {
 }
Beispiel #15
0
        /// <summary>
        /// Send update notification over data channel of RTMP connection
        /// </summary>
        private void SendUpdates()
        {
            int  currentVersion = _version.Value;
            bool persist        = this.IsPersistentObject;
            //Get read-only version of events
            ConcurrentLinkedQueue <ISharedObjectEvent> events = new ConcurrentLinkedQueue <ISharedObjectEvent>(_ownerMessage.Events);

            //clear out previous events
            _ownerMessage.Events.Clear();

            if (events.Count != 0)
            {
                //Send update to "owner" of this update request
                if (_source != null)
                {
                    RtmpConnection connection = _source as RtmpConnection;
                    // Only send updates when issued through RTMP request
                    RtmpChannel channel = connection.GetChannel((byte)3);

                    // Send update to "owner" of this update request
                    SharedObjectMessage syncOwner;
                    if (connection.ObjectEncoding == ObjectEncoding.AMF0)
                    {
                        syncOwner = new SharedObjectMessage(null, _name, currentVersion, persist);
                    }
                    else
                    {
                        syncOwner = new FlexSharedObjectMessage(null, _name, currentVersion, persist);
                    }
                    syncOwner.AddEvents(events);

                    if (channel != null)
                    {
                        channel.Write(syncOwner);
                    }
                    else
                    {
                        log.Warn(__Res.GetString(__Res.Channel_NotFound));
                    }
                }
            }
            //Clear owner events
            events.Clear();
            //Get read-only version of sync events
            events.AddRange(_syncEvents);
            //Clear out previous events
            _syncEvents.Clear();
            if (events.Count != 0)
            {
                // Synchronize updates with all registered clients of this shared
                foreach (IEventListener listener in _listeners)
                {
                    if (listener == _source)
                    {
                        // Don't re-send update to active client
                        continue;
                    }
                    if (!(listener is RtmpConnection))
                    {
                        log.Warn(__Res.GetString(__Res.SharedObject_SyncConnError));
                        continue;
                    }
                    // Create a new sync message for every client to avoid
                    // concurrent access through multiple threads
                    // TODO: perhaps we could cache the generated message
                    RtmpConnection      connection = listener as RtmpConnection;
                    SharedObjectMessage syncMessage;
                    if (connection.ObjectEncoding == ObjectEncoding.AMF0)
                    {
                        syncMessage = new SharedObjectMessage(null, _name, currentVersion, persist);
                    }
                    else
                    {
                        syncMessage = new FlexSharedObjectMessage(null, _name, currentVersion, persist);
                    }
                    syncMessage.AddEvents(events);

                    RtmpChannel channel = connection.GetChannel((byte)3);
                    log.Debug(__Res.GetString(__Res.SharedObject_Sync, channel));
                    channel.Write(syncMessage);
                }
            }
        }