/// <summary>
        ///		Creates <see cref="ServerResponseContext"/> which contains specified required states.
        /// </summary>
        /// <param name="transport">The transport to be bound to the context.</param>
        /// <returns><see cref="ServerResponseContext"/> for the unit testing argument.</returns>
        public static ServerResponseContext CreateResponseContext(IContextBoundableTransport transport)
        {
            var result = new ServerResponseContext();

            result.SetTransport(transport);
            return(result);
        }
示例#2
0
		/// <summary>
		///		Performs protocol specific asynchronous 'Send' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected sealed override void SendCore( ServerResponseContext context )
		{
			// Manager stores the socket which is dedicated socket to this transport in the AcceptSocket property.
			if ( !this.BoundSocket.SendToAsync( context.SocketContext ) )
			{
				context.SetCompletedSynchronously();
				this.OnSent( context );
			}
		}
示例#3
0
        private void TestGetServiceInvokerCore <TArg1, TArg2, TResult>(
            EventHandler <ServiceInvokedEventArgs <TResult> > invoked,
            RpcServerConfiguration configuration,
            TArg1 arg1,
            TArg2 arg2,
            Action <ServerResponseContext> assertion
            )
        {
            using (var target = new ServiceInvokerGenerator(true))
                using (var server = new RpcServer())
                    using (var transportManager = new NullServerTransportManager(server))
                        using (var transport = new NullServerTransport(transportManager))
                        {
                            var service = new Service <TArg1, TArg2, TResult>();
                            service.Invoked += invoked;

                            var serviceDescription = new ServiceDescription("Service", () => service);
                            var targetOperation    = service.GetType().GetMethod("Invoke");

                            using (var requestContext = new ServerRequestContext())
                            {
                                requestContext.ArgumentsBufferPacker = Packer.Create(requestContext.ArgumentsBuffer, false);
                                requestContext.ArgumentsBufferPacker.PackArrayHeader(2);
                                requestContext.ArgumentsBufferPacker.Pack(arg1);
                                requestContext.ArgumentsBufferPacker.Pack(arg2);
                                requestContext.ArgumentsBuffer.Position = 0;
                                requestContext.MessageId         = 123;
                                requestContext.ArgumentsUnpacker = Unpacker.Create(requestContext.ArgumentsBuffer, false);

                                var responseContext = new ServerResponseContext();
                                responseContext.SetTransport(transport);
                                try
                                {
                                    var result = target.GetServiceInvoker(RpcServerRuntime.Create(configuration, this._serializationContext), serviceDescription, targetOperation);

                                    result.InvokeAsync(requestContext, responseContext).Wait(TimeSpan.FromSeconds(1));

                                    assertion(responseContext);
                                }
                                finally
                                {
                                    if (this._isDumpEnabled)
                                    {
                                        try
                                        {
                                            target.Dump();
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.Error.WriteLine("Failed to dump: {0}", ex);
                                        }
                                    }
                                }
                            }
                        }
        }
示例#4
0
		/// <summary>
		/// Performs protocol specific asynchronous 'Send' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected override void SendCore( ServerResponseContext context )
		{
			var handler = this.Sent;
			if ( handler != null )
			{
				handler( this, new SentEventArgs( context ) );
			}

			return;
		}
示例#5
0
        /// <summary>
        ///		Sets the return value to the <see cref="ServerResponseContext"/>.
        /// </summary>
        /// <typeparam name="T">The type of the return value.</typeparam>
        /// <param name="context">The <see cref="ServerResponseContext"/> to be set the return value.</param>
        /// <param name="returnValue">The return value to be set.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is <c>null</c>.
        /// </exception>
        protected void SetReturnValue <T>(ServerResponseContext context, T returnValue)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Contract.EndContractBlock();

            context.Serialize(returnValue, RpcErrorMessage.Success, this.SerializationContext.GetSerializer <T>());
        }
		private static void TestCore( Action<ServerResponseContext, ServerTransport> test )
		{
			using ( var server = new RpcServer() )
			using ( var manager = new NullServerTransportManager( server ) )
			using ( var transport = new NullServerTransport( manager ) )
			using ( var target = new ServerResponseContext() )
			{
				target.SetTransport( transport );
				test( target, transport );
			}
		}
示例#7
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>());
        }
示例#8
0
        public void TestInvokeAsync_Success_TaskSetSerializedReturnValue()
        {
            using (var server = new RpcServer())
                using (var transportManager = new NullServerTransportManager(server))
                    using (var transport = new NullServerTransport(transportManager))
                    {
                        ServerRequestContext  requestContext  = DispatchTestHelper.CreateRequestContext();
                        ServerResponseContext responseContext = DispatchTestHelper.CreateResponseContext(transport);
                        using (var result = new Target(null, RpcErrorMessage.Success).InvokeAsync(requestContext, responseContext))
                        {
                            result.Wait();
                        }

                        Assert.That(responseContext.GetReturnValueData(), Is.EqualTo(new byte[] { 123 }));
                        Assert.That(responseContext.GetErrorData(), Is.EqualTo(new byte[] { 0xC0 }));
                    }
        }
示例#9
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);
        }
示例#10
0
        public void TestInvokeAsync_MethodError_TaskSetSerializedError()
        {
            using (var server = new RpcServer())
                using (var transportManager = new NullServerTransportManager(server))
                    using (var transport = new NullServerTransport(transportManager))
                    {
                        ServerRequestContext  requestContext  = DispatchTestHelper.CreateRequestContext();
                        ServerResponseContext responseContext = DispatchTestHelper.CreateResponseContext(transport);
                        using (var result = new Target(null, new RpcErrorMessage(RpcError.ArgumentError, MessagePackObject.Nil)).InvokeAsync(requestContext, responseContext))
                        {
                            result.Wait();
                        }

                        var error       = Unpacking.UnpackObject(responseContext.GetErrorData());
                        var errorDetail = Unpacking.UnpackObject(responseContext.GetReturnValueData());
                        Assert.That(error.Value.Equals(RpcError.ArgumentError.Identifier));
                        Assert.That(errorDetail.Value.IsNil, Is.True);
                    }
        }
示例#11
0
        public void TestInvokeAsync_FatalError_TaskSetSerializedError()
        {
            using (var server = new RpcServer())
                using (var transportManager = new NullServerTransportManager(server))
                    using (var transport = new NullServerTransport(transportManager))
                    {
                        ServerRequestContext  requestContext  = DispatchTestHelper.CreateRequestContext();
                        ServerResponseContext responseContext = DispatchTestHelper.CreateResponseContext(transport);
                        using (var result = new Target(new Exception("FAIL"), RpcErrorMessage.Success).InvokeAsync(requestContext, responseContext))
                        {
                            result.Wait();
                        }

                        var error       = Unpacking.UnpackObject(responseContext.GetErrorData());
                        var errorDetail = Unpacking.UnpackObject(responseContext.GetReturnValueData());
                        Assert.That(error.Value.Equals(RpcError.CallError.Identifier));
                        Assert.That(errorDetail.Value.IsNil, Is.False);
                    }
        }
 /// <summary>
 ///		Invokes target service operation asynchronously.
 /// </summary>
 /// <param name="requestContext">
 ///		The context object to hold request data.
 ///		Note that properties of the context is only valid until this method returns.
 ///		That is, it will be unpredectable state in the asynchronous operation.
 ///	</param>
 /// <param name="responseContext">
 ///		The context object to pack response value or error.
 ///		This is <c>null</c> for the notification messages.
 ///	</param>
 /// <returns>
 ///   <see cref="Task"/> to control entire process including sending response.
 /// </returns>
 public abstract Task InvokeAsync(ServerRequestContext requestContext, ServerResponseContext responseContext);
示例#13
0
		protected override void SendCore( ServerResponseContext context )
		{
			this._manager.SendAsync( context )
				.ContinueWith(
					previous => this.OnSent( context )
				).Wait( this._receivingCancellationTokenSource.Token );
		}
示例#14
0
		protected override void SendCore( ServerResponseContext context )
		{
			Contract.Requires( context != null );
		}
示例#15
0
			internal SentEventArgs( ServerResponseContext context )
			{
				this._context = context;
			}
示例#16
0
 public void InvokeSetReturnValue <T>(ServerResponseContext responseContext, T returnValue)
 {
     this.SetReturnValue(responseContext, returnValue);
 }
示例#17
0
		/// <summary>
		///		Creates <see cref="ServerResponseContext"/> which contains specified required states.
		/// </summary>
		/// <param name="transport">The transport to be bound to the context.</param>
		/// <returns><see cref="ServerResponseContext"/> for the unit testing argument.</returns>
		public static ServerResponseContext CreateResponseContext( IContextBoundableTransport transport )
		{
			var result = new ServerResponseContext();
			result.SetTransport( transport );
			return result;
		}
示例#18
0
 public void InvokeSetException(ServerResponseContext responseContext, string operationId, Exception exception)
 {
     this.SetException(responseContext, operationId, exception);
 }
示例#19
0
		/// <summary>
		///		Invokes target service operation asynchronously.
		/// </summary>
		/// <param name="requestContext">
		///		The context object to hold request data.
		///		Note that properties of the context is only valid until this method returns.
		///		That is, it will be unpredectable state in the asynchronous operation.
		///	</param>
		/// <param name="responseContext">
		///		The context object to pack response value or error.
		///		This is <c>null</c> for the notification messages.
		///	</param>
		/// <returns>
		///   <see cref="Task"/> to control entire process including sending response.
		/// </returns>
		public abstract Task InvokeAsync( ServerRequestContext requestContext, ServerResponseContext responseContext );
示例#20
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
            }
        }
示例#21
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
        }
示例#22
0
		/// <summary>
		///		Returns the response context to the pool.
		/// </summary>
		/// <param name="context">The response to the pool.</param>
		/// <exception cref="ArgumentNullException">
		///		<paramref name="context"/> is  <c>null</c>.
		/// </exception>
		protected internal void ReturnResponseContext( ServerResponseContext context )
		{
			if ( context == null )
			{
				throw new ArgumentNullException( "context" );
			}

			Contract.EndContractBlock();

			context.Clear();
			context.UnboundTransport();
			this.ResponseContextPool.Return( context );
		}
示例#23
0
		/// <summary>
		///		Performs protocol specific asynchronous 'Send' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected sealed override void SendCore( ServerResponseContext context )
		{
			Contract.Assert( this.BoundSocket != null );

			if ( !this.BoundSocket.SendAsync( context.SocketContext ) )
			{
				context.SetCompletedSynchronously();
				this.OnSent( context );
			}
		}