Beispiel #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);
        }
Beispiel #2
0
        /// <summary>
        /// Generate error object to return for given exception.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        static StatusASO GenerateErrorResult(string code, Exception exception)
        {
            string message = "";

            if (exception != null && exception.Message != null)
            {
                message = exception.Message;
            }
            StatusASO status = new StatusASO(code, "error", message);

            return(status);
        }
Beispiel #3
0
		/// <summary>
		/// Sends status notification.
		/// </summary>
		/// <param name="status">Status object.</param>
		public void SendStatus(StatusASO status) {
			bool andReturn = !status.code.Equals(StatusASO.NS_DATA_START);
			Invoke invoke;
			if (andReturn) {
				PendingCall call = new PendingCall(null, "onStatus", new object[] { status });
				invoke = new Invoke();
				invoke.InvokeId = 1;
				invoke.ServiceCall = call;
			} else {
				Call call = new Call(null, "onStatus", new object[] { status });
				invoke = (Invoke)new Notify();
				invoke.InvokeId = 1;
				invoke.ServiceCall = call;
			}
			// We send directly to the corresponding stream as for
			// some status codes, no stream has been created and thus
			// "getStreamByChannelId" will fail.
			Write(invoke, _connection.GetStreamIdForChannel(_channelId));
		}
Beispiel #4
0
        /// <summary>
        /// Sends status notification.
        /// </summary>
        /// <param name="status">Status object.</param>
        public void SendStatus(StatusASO status)
        {
            bool   andReturn = !status.code.Equals(StatusASO.NS_DATA_START);
            Invoke invoke;

            if (andReturn)
            {
                PendingCall call = new PendingCall(null, "onStatus", new object[] { status });
                invoke             = new Invoke();
                invoke.InvokeId    = 1;
                invoke.ServiceCall = call;
            }
            else
            {
                Call call = new Call(null, "onStatus", new object[] { status });
                invoke             = (Invoke) new Notify();
                invoke.InvokeId    = 1;
                invoke.ServiceCall = call;
            }
            // We send directly to the corresponding stream as for
            // some status codes, no stream has been created and thus
            // "getStreamByChannelId" will fail.
            Write(invoke, _connection.GetStreamIdForChannel(_channelId));
        }
Beispiel #5
0
		/// <summary>
		/// This method supports the infrastructure and is not intended to be used directly from your code.
		/// </summary>
		public override void Timeout() {
			if (!IsClosed) {
				if (this.IsFlexClient) {
					FlexInvoke flexInvoke = new FlexInvoke();
					StatusASO statusASO = new StatusASO(StatusASO.NC_CONNECT_CLOSED, StatusASO.STATUS, "Connection Timed Out", null, this.ObjectEncoding);
					Call call = new Call("onstatus", new object[] { statusASO });
					flexInvoke.ServiceCall = call;
					//flexInvoke.Cmd = "onstatus";
					//flexInvoke.Parameters = new object[] { statusASO };
					RtmpChannel channel = this.GetChannel(3);
					channel.Write(flexInvoke);
				} else {
					StatusASO statusASO = new StatusASO(StatusASO.NC_CONNECT_CLOSED, StatusASO.ERROR, "Connection Timed Out", null, this.ObjectEncoding);
					RtmpChannel channel = this.GetChannel(3);
					channel.SendStatus(statusASO);
				}
			}
		}
		/// <summary>
		/// Generate error object to return for given exception.
		/// </summary>
		/// <param name="code"></param>
		/// <param name="exception"></param>
		/// <returns></returns>
		static StatusASO GenerateErrorResult(string code, Exception exception) {
			string message = "";
			if (exception != null && exception.Message != null)
				message = exception.Message;
			StatusASO status = new StatusASO(code, "error", message);
			return status;
		}
Beispiel #7
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;
            }
        }