public void TestHandleInvocationException_Null_IsNotDebugMode_AsRemoteRuntimeError()
        {
            var result = InvocationHelper.HandleInvocationException(null, "Method", false);

            Assert.That(result.Error, Is.EqualTo(RpcError.CallError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.Not.Null.And.Not.Empty);
            Assert.That(result.Detail.AsDictionary().ContainsKey(RpcException.DebugInformationKeyUtf8), Is.False);
        }
        public void TestHandleArgumentDeserializationException_Null_IsNotDebugMode_DefaultString()
        {
            var result = InvocationHelper.HandleArgumentDeserializationException(null, null, false);

            Assert.That(result.IsSuccess, Is.False);
            Assert.That(result.Error, Is.EqualTo(RpcError.ArgumentError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.Not.Null.And.Not.Empty);
            Assert.That(result.Detail.AsDictionary().ContainsKey(RpcException.DebugInformationKeyUtf8), Is.False);
        }
示例#3
0
        protected sealed override Func <ServerRequestContext, ServerResponseContext, Task> Dispatch(string methodName)
        {
            // Ignore methodName
            return
                ((requestContext, responseContext) =>
            {
                var argumentsUnpacker = requestContext.ArgumentsUnpacker;
                argumentsUnpacker.Read();
                MessagePackObject[] args = MessagePackSerializer.Create <MessagePackObject[]>(_serializationContext).UnpackFrom(argumentsUnpacker);
                var messageId = requestContext.MessageId;

                return
                Task.Factory.StartNew(
                    () =>
                {
                    MessagePackObject returnValue;

                    try
                    {
                        this.BeginOperation();
                        try
                        {
                            returnValue = this._dispatch(methodName, messageId, args);
                        }
                        catch (ThreadAbortException ex)
                        {
                            this.HandleThreadAbortException(ex);
                            returnValue = MessagePackObject.Nil;
                        }
                        finally
                        {
                            this.EndOperation();
                        }
                    }
                    catch (Exception exception)
                    {
                        if (responseContext != null)
                        {
                            base.SetException(responseContext, methodName, exception);
                        }
                        else
                        {
                            // notification
                            InvocationHelper.HandleInvocationException(requestContext.SessionId, MessageType.Notification, requestContext.MessageId, requestContext.MethodName, exception, this.IsDebugMode);
                        }
                        return;
                    }

                    if (responseContext != null)
                    {
                        base.SetReturnValue(responseContext, returnValue);
                    }
                }
                    );
            });
        }
        public void TestHandleInvocationException_NotNull_OtherException_IsDebugMode_AsRemoteRuntimeError()
        {
            var exception = new Exception(Guid.NewGuid().ToString());

            var result = InvocationHelper.HandleInvocationException(exception, "Method", true);

            Assert.That(result.Error, Is.EqualTo(RpcError.CallError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.Not.Null.And.Not.Empty.And.StringContaining(exception.Message));
            Assert.That(result.Detail.AsDictionary()[RpcException.DebugInformationKeyUtf8].AsString(), Is.StringContaining(exception.Message));
        }
        public void TestHandleInvocationException_NotNull_RpcException_IsDebugMode_AsCorrespondingErrorWithoutDebugInformation()
        {
            var exception = new RpcException(RpcError.MessageTooLargeError, Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            var result = InvocationHelper.HandleInvocationException(exception, "Method", false);

            Assert.That(result.Error, Is.EqualTo(exception.RpcError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.Not.Null.And.No.Empty.And.Not.StringContaining(exception.Message).And.Not.StringContaining(exception.DebugInformation));
            Assert.That(result.Detail.AsDictionary().ContainsKey(RpcException.DebugInformationKeyUtf8), Is.False);
        }
        public void TestHandleInvocationException_NotNull_ArgumentException_IsNotDebugMode_AsArgumentErrorWithoutDebugInformation()
        {
            var exception = new ArgumentException(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());

            var result = InvocationHelper.HandleInvocationException(exception, "Method", false);

            Assert.That(result.Error, Is.EqualTo(RpcError.ArgumentError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.StringContaining(exception.ParamName));
            Assert.That(result.Detail.AsDictionary().ContainsKey(RpcException.DebugInformationKeyUtf8), Is.False);
        }
        public void TestHandleArgumentDeserializationException_NotNull_IsNotDebugMode_DoesNotIncludeFullExceptionInfo()
        {
            var    exception     = new Exception(Guid.NewGuid().ToString());
            string parameterName = Guid.NewGuid().ToString();

            var result = InvocationHelper.HandleArgumentDeserializationException(exception, parameterName, false);

            Assert.That(result.IsSuccess, Is.False);
            Assert.That(result.Error, Is.EqualTo(RpcError.ArgumentError));
            Assert.That(result.Detail.AsDictionary()[RpcException.MessageKeyUtf8].AsString(), Is.StringContaining(parameterName));
            Assert.That(result.Detail.AsDictionary().ContainsKey(RpcException.DebugInformationKeyUtf8), Is.False);
        }
示例#8
0
        private static void HandleInvocationResult(Task previous, Tuple <AsyncServiceInvoker <T>, long, int, string, ServerResponseContext, RpcErrorMessage> closureState)
        {
            var @this           = closureState.Item1;
            var sessionId       = closureState.Item2;
            var messageId       = closureState.Item3;
            var operationId     = closureState.Item4;
            var responseContext = closureState.Item5;
            var error           = closureState.Item6;

            T result = default(T);

            try
            {
                if (previous != null)
                {
                    if (error.IsSuccess)
                    {
                        if (previous.Exception != null)
                        {
                            error =
                                InvocationHelper.HandleInvocationException(
                                    sessionId,
                                    responseContext == null ? MessageType.Notification : MessageType.Request,
                                    responseContext == null ? default(int?) : messageId,
                                    operationId,
                                    previous.Exception.InnerException,
                                    @this.IsDebugMode
                                    );
                        }
                        else if (@this._returnValueSerializer != null)
                        {
                            result = (previous as Task <T>).Result;
                        }
                    }

                    previous.Dispose();
                }

                InvocationHelper.TraceInvocationResult(sessionId, responseContext == null ? MessageType.Notification : MessageType.Request, messageId, @this.OperationId, error, result);
            }
            finally
            {
                SafeStopLogicalOperation();
            }

            if (responseContext != null)
            {
                responseContext.Serialize(result, error, @this._returnValueSerializer);
            }
        }
        public void TestTrace_SuccessAtLeast()
        {
            var oldLevel = MsgPackRpcServerDispatchTrace.Source.Switch.Level;

            try
            {
                MsgPackRpcServerDispatchTrace.Source.Switch.Level = System.Diagnostics.SourceLevels.All;
                InvocationHelper.TraceInvocationResult <object>(1, Rpc.Protocols.MessageType.Request, 1, "TracingTest", RpcErrorMessage.Success, null);
                InvocationHelper.TraceInvocationResult <object>(1, Rpc.Protocols.MessageType.Request, 1, "TracingTest", new RpcErrorMessage(RpcError.RemoteRuntimeError, "Description", "DebugInformation"), null);
            }
            finally
            {
                MsgPackRpcServerDispatchTrace.Source.Switch.Level = oldLevel;
            }
        }
示例#10
0
        /// <summary>
        ///		Sets the exception to the <see cref="ServerResponseContext"/> as called method failure.
        /// </summary>
        /// <param name="context">The <see cref="ServerResponseContext"/> to be set the error.</param>
        /// <param name="operationId">The ID of operation which causes <paramref name="exception"/>.</param>
        /// <param name="exception">The exception to be set as the RPC error.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is <c>null</c>.
        ///		Or, <paramref name="exception"/> is <c>null</c>.
        /// </exception>
        /// <remarks>
        ///		You should use <see cref="RpcException"/> derived class to represent application error.
        ///		The runtime does not interpret other exception types except <see cref="ArgumentException"/> derviced class,
        ///		so they are represented as <see cref="RpcError.CallError"/> in the lump.
        ///		(<see cref="ArgumentException"/> derviced class is transformed to <see cref="P:RpcError.ArgumentError"/>.
        /// </remarks>
        protected void SetException(ServerResponseContext context, string operationId, Exception exception)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            Contract.EndContractBlock();

            context.Serialize <MessagePackObject>(MessagePackObject.Nil, InvocationHelper.HandleInvocationException(exception, operationId, this.IsDebugMode), this.SerializationContext.GetSerializer <MessagePackObject>());
        }
示例#11
0
        private static void SendResponse(Task previous, ServerTransport transport, ServerResponseContext context, Tuple <RpcServer, long, int?, string> sessionState)
        {
            if (context == null)
            {
                if (previous.IsFaulted)
                {
                    try
                    {
                        previous.Exception.Handle(inner => inner is OperationCanceledException);
                    }
                    catch (AggregateException exception)
                    {
                        InvocationHelper.HandleInvocationException(
                            sessionState.Item2,
                            MessageType.Notification,
                            null,
                            sessionState.Item4,
                            exception,
                            sessionState.Item1.Configuration.IsDebugMode
                            );
                    }
                }

                previous.Dispose();
                return;
            }

            switch (previous.Status)
            {
            case TaskStatus.Canceled:
            {
                context.Serialize <object>(null, new RpcErrorMessage(RpcError.TimeoutError, "Server task exceeds execution timeout.", null), null);
                break;
            }

            case TaskStatus.Faulted:
            {
                context.Serialize <object>(null, new RpcErrorMessage(RpcError.RemoteRuntimeError, "Dispatcher throws exception.", previous.Exception.ToString()), null);
                break;
            }
            }

            previous.Dispose();
            transport.Send(context);
        }
示例#12
0
        public sealed override Task InvokeAsync(ServerRequestContext requestContext, ServerResponseContext responseContext)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }

            Contract.Ensures(Contract.Result <Task>() != null);

            var messageId = requestContext.MessageId;
            var arguments = requestContext.ArgumentsUnpacker;

            bool readMustSuccess = arguments.Read();

            Contract.Assert(readMustSuccess, "Arguments is not an array.");
            Contract.Assert(arguments.IsArrayHeader);

            SafeStartLogicalOperation();
            if (MsgPackRpcServerDispatchTrace.ShouldTrace(MsgPackRpcServerDispatchTrace.OperationStart))
            {
                MsgPackRpcServerDispatchTrace.TraceData(
                    MsgPackRpcServerDispatchTrace.OperationStart,
                    "Operation starting.",
                    responseContext == null ? MessageType.Notification : MessageType.Request,
                    messageId,
                    this.OperationId
                    );
            }

            AsyncInvocationResult result;

            try
            {
                result = this.InvokeCore(arguments);
            }
            catch (Exception ex)
            {
                result = new AsyncInvocationResult(InvocationHelper.HandleInvocationException(requestContext.SessionId, requestContext.MessageType, requestContext.MessageId, this.OperationId, ex, this.IsDebugMode));
            }

            var tuple = Tuple.Create(this, requestContext.SessionId, messageId.GetValueOrDefault(), this.OperationId, responseContext, result.InvocationError);

            if (result.AsyncTask == null)
            {
                return(Task.Factory.StartNew(state => HandleInvocationResult(null, state as Tuple <AsyncServiceInvoker <T>, long, int, string, ServerResponseContext, RpcErrorMessage>), tuple));
            }
            else
            {
#if NET_4_5
                return
                    (result.AsyncTask.ContinueWith(
                         (previous, state) => HandleInvocationResult(
                             previous,
                             state as Tuple <AsyncServiceInvoker <T>, long, int, string, ServerResponseContext, RpcErrorMessage>
                             ),
                         tuple
                         ));
#else
                return
                    (result.AsyncTask.ContinueWith(
                         previous => HandleInvocationResult(
                             previous,
                             tuple
                             )
                         ));
#endif
            }
        }
示例#13
0
        /// <summary>
        ///		Dispatches the specified request, and dispatches the response to the specified transport.
        /// </summary>
        /// <param name="serverTransport">The server transport the response to be dispatched.</param>
        /// <param name="requestContext">The request context.</param>
        internal void Dispatch(ServerTransport serverTransport, ServerRequestContext requestContext)
        {
            Contract.Requires(serverTransport != null);
            Contract.Requires(requestContext != null);

            ServerResponseContext responseContext = null;

            if (requestContext.MessageType == MessageType.Request)
            {
                responseContext = serverTransport.Manager.GetResponseContext(requestContext);
            }

            Task task;
            var  operation = this.Dispatch(requestContext.MethodName);

            if (operation == null)
            {
                var error = new RpcErrorMessage(RpcError.NoMethodError, "Operation does not exist.", null);
                InvocationHelper.TraceInvocationResult <object>(
                    requestContext.SessionId,
                    requestContext.MessageType,
                    requestContext.MessageId.GetValueOrDefault(),
                    requestContext.MethodName,
                    error,
                    null
                    );

                if (responseContext != null)
                {
                    task = Task.Factory.StartNew(() => responseContext.Serialize <object>(null, error, null));
                }
                else
                {
                    return;
                }
            }
            else
            {
                task = operation(requestContext, responseContext);
            }

            var sessionState = Tuple.Create(this._server, requestContext.SessionId, requestContext.MessageType == MessageType.Request ? requestContext.MessageId : default(int?), requestContext.MethodName);

#if NET_4_5
            task.ContinueWith((previous, state) =>
            {
                var tuple = state as Tuple < ServerTransport, ServerResponseContext, Tuple <RpcServer, long, int?, string>;
                SendResponse(previous, tuple.Item1, tuple.Item2, tuple.Item3)
            },
                              Tuple.Create(serverTransport, responseContext, sessionState)
                              ).ContinueWith((previous, state) =>
            {
                HandleSendFailure(previous, state as Tuple <RpcServer, long, int?, string>);
            },
                                             TaskContinuationOptions.OnlyOnFaulted,
                                             sessionState
                                             );
#else
            task.ContinueWith(previous =>
            {
                SendResponse(previous, serverTransport, responseContext, sessionState);
            }
                              ).ContinueWith(previous =>
            {
                HandleSendFailure(previous, sessionState);
            },
                                             TaskContinuationOptions.OnlyOnFaulted
                                             );
#endif
        }