Exemplo n.º 1
0
 private static void SendSOPersistenceMismatch(RtmpConnection connection, string name, bool persistent)
 {
     SharedObjectMessage msg;
     if (connection.ObjectEncoding == ObjectEncoding.AMF0)
         msg = new SharedObjectMessage(name, 0, persistent);
     else
         msg = new FlexSharedObjectMessage(name, 0, persistent);
     msg.AddEvent(new SharedObjectEvent(SharedObjectEventType.CLIENT_STATUS, StatusASO.SO_PERSISTENCE_MISMATCH, "error"));
     connection.GetChannel((byte)3).Write(msg);
 }
Exemplo n.º 2
0
 private static void SendSOCreationFailed(RtmpConnection connection, string name, bool persistent)
 {
     SharedObjectMessage msg;
     if (connection.ObjectEncoding == ObjectEncoding.AMF0)
         msg = new SharedObjectMessage(name, 0, persistent);
     else
         msg = new FlexSharedObjectMessage(name, 0, persistent);
     msg.AddEvent(new SharedObjectEvent(SharedObjectEventType.CLIENT_STATUS, StatusASO.SO_CREATION_FAILED, "error"));
     connection.GetChannel((byte)3).Write(msg);
 }
Exemplo n.º 3
0
        internal static void Push(RtmpConnection connection, IMessage message, IMessageClient messageClient)
        {
            if (connection != null)
            {
                object response = message;
                if (message is BinaryMessage)
                {
                    BinaryMessage binaryMessage = message as BinaryMessage;
                    binaryMessage.Update(messageClient);
                    byte[] binaryContent = binaryMessage.body as byte[];
                    //byte[] destClientBinaryId = messageClient.GetBinaryId();
                    //Array.Copy(destClientBinaryId, 0, binaryContent, binaryMessage.PatternPosition, destClientBinaryId.Length);

                    RawBinary result = new RawBinary(binaryContent);
                    response = result;
                }
                else
                {
                    //This should be a clone of the original message
                    message.SetHeader(MessageBase.DestinationClientIdHeader, messageClient.ClientId);
                    message.clientId = messageClient.ClientId;
                }

                RtmpChannel channel = connection.GetChannel(3);
                FlexInvoke reply = new FlexInvoke();
                Call call = new Call("receive", new object[] { response });
                reply.ServiceCall = call;
                //reply.Cmd = "receive";
                //reply.Response = response;
                reply.InvokeId = connection.InvokeId;
                channel.Write(reply);
            }
        }
Exemplo n.º 4
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;
            }
		}
Exemplo n.º 5
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
            }
        }