/// <summary>
		///		Unpack request/notification message array header.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		internal bool UnpackRequestHeader( ServerRequestContext context )
		{
			Contract.Assert( context != null );

			if ( context.RootUnpacker == null )
			{
				context.UnpackingBuffer = new ByteArraySegmentStream( context.ReceivedData );
				context.RootUnpacker = Unpacker.Create( context.UnpackingBuffer, false );
				Interlocked.Increment( ref this._processing );
				context.RenewSessionId();
				if ( this._manager.Server.Configuration.ReceiveTimeout != null )
				{
					context.Timeout += this.OnReceiveTimeout;
					context.StartWatchTimeout( this._manager.Server.Configuration.ReceiveTimeout.Value );
				}

				if ( MsgPackRpcServerProtocolsTrace.ShouldTrace( MsgPackRpcServerProtocolsTrace.NewSession ) )
				{
					MsgPackRpcServerProtocolsTrace.TraceEvent(
						MsgPackRpcServerProtocolsTrace.NewSession,
						"New session is created. {{ \"SessionID\" : {0} }}",
						context.SessionId
					);
				}
			}

			if ( !context.ReadFromRootUnpacker() )
			{
				MsgPackRpcServerProtocolsTrace.TraceEvent( 
					MsgPackRpcServerProtocolsTrace.NeedRequestHeader,
					"Array header is needed. {{ \"SessionID\" : {0} }}", 
					context.SessionId 
				);
				return false;
			}

			if ( !context.RootUnpacker.IsArrayHeader )
			{
				this.HandleDeserializationError( context, "Invalid request/notify message stream. Message must be array.", () => context.UnpackingBuffer.ToArray() );
				return true;
			}

			if ( context.RootUnpacker.ItemsCount != 3 && context.RootUnpacker.ItemsCount != 4 )
			{
				this.HandleDeserializationError(
					context,
					String.Format(
						CultureInfo.CurrentCulture,
						"Invalid request/notify message stream. Message must be valid size array. Actual size is {0}.",
						context.RootUnpacker.ItemsCount
					),
					() => context.UnpackingBuffer.ToArray()
				);
				return true;
			}

			context.HeaderUnpacker = context.RootUnpacker.ReadSubtree();
			context.NextProcess = UnpackMessageType;
			return context.NextProcess( context );
		}
示例#2
0
		private static ServerRequestContext CreateRequestContext( MemoryStream arguments )
		{
			var result = new ServerRequestContext();
			arguments.CopyTo( result.ArgumentsBuffer );
			result.ArgumentsBuffer.Position = 0;
			result.ArgumentsUnpacker = Unpacker.Create( result.ArgumentsBuffer, false );
			return result;
		}
示例#3
0
		private static void TestCore( Action<ServerRequestContext, ServerTransport> test )
		{
			using ( var server = new RpcServer() )
			using ( var manager = new NullServerTransportManager( server ) )
			using ( var transport = new NullServerTransport( manager ) )
			using ( var target = new ServerRequestContext() )
			{
				test( target, transport );
			}
		}
        /// <summary>
        ///		Returns the request context to the pool.
        /// </summary>
        /// <param name="context">The context to the pool.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is  <c>null</c>.
        /// </exception>
        protected internal void ReturnRequestContext(ServerRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Contract.EndContractBlock();

            context.Clear();
            context.UnboundTransport();
            this.RequestContextPool.Return(context);
        }
示例#5
0
        protected override void ReceiveCore(ServerRequestContext context)
        {
            this.OnReceiving();
            try
            {
                InProcPacket.ProcessReceive(this._inboundQueue, this._pendingPackets, context, this._receivingCancellationTokenSource.Token);
            }
            catch (OperationCanceledException)
            {
                context.SocketError = SocketError.OperationAborted;
            }

            this.OnReceived(context);
            this.OnReceived();
        }
示例#6
0
 internal void StartReceive(ServerRequestContext context)
 {
     if (this._receivingTask == null)
     {
         Contract.Assert(context.BoundTransport == this);
         this._receivingTask =
             Task.Factory.StartNew(
                 this.DoReceiveLoop,
                 context,
                 this._receivingCancellationTokenSource.Token,
                 TaskCreationOptions.LongRunning,
                 TaskScheduler.Default
                 );
     }
 }
示例#7
0
        /// <summary>
        ///		Unpack array header of Arguments part on request/notification message.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool UnpackArgumentsHeader(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            if (!context.ReadFromHeaderUnpacker())
            {
                MsgPackRpcServerProtocolsTrace.TraceEvent(
                    MsgPackRpcServerProtocolsTrace.NeedArgumentsArrayHeader,
                    "Arguments array header is needed. {{ \"SessionID\" : {0} }}",
                    context.SessionId
                    );
                return(false);
            }

            if (!context.HeaderUnpacker.IsArrayHeader)
            {
                this.HandleDeserializationError(
                    context,
                    "Invalid request/notify message stream. Arguments must be array.",
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            // TODO: Avoid actual unpacking to improve performance.
            context.ArgumentsBufferUnpacker = context.HeaderUnpacker.ReadSubtree();

            if (Int32.MaxValue < context.ArgumentsBufferUnpacker.ItemsCount)
            {
                this.HandleDeserializationError(
                    context,
                    RpcError.MessageTooLargeError,
                    "Too many arguments.",
                    context.ArgumentsBufferUnpacker.ItemsCount.ToString("#,0", CultureInfo.CurrentCulture),
                    () => context.UnpackingBuffer.ToArray()
                    );
                return(true);
            }

            context.ArgumentsCount        = unchecked (( int )(context.ArgumentsBufferUnpacker.ItemsCount));
            context.ArgumentsBufferPacker = Packer.Create(context.ArgumentsBuffer, false);
            context.ArgumentsBufferPacker.PackArrayHeader(context.ArgumentsCount);
            context.UnpackedArgumentsCount = 0;
            context.NextProcess            = this.UnpackArguments;
            return(context.NextProcess(context));
        }
示例#8
0
 private static void InitializeBuffers(ServerRequestContext target)
 {
     target.ArgumentsBuffer.WriteByte(1);
     target.ArgumentsBufferPacker   = Packer.Create(target.ArgumentsBuffer, false);
     target.ArgumentsBufferUnpacker = Unpacker.Create(target.ArgumentsBuffer, false);
     target.ArgumentsCount          = 2;
     target.UnpackingBuffer         = new ByteArraySegmentStream(target.ReceivedData);
     target.UnpackedArgumentsCount  = 3;
     target.RootUnpacker            = Unpacker.Create(target.UnpackingBuffer, false);
     target.HeaderUnpacker          = Unpacker.Create(target.UnpackingBuffer, false);
     target.ArgumentsUnpacker       = Unpacker.Create(target.UnpackingBuffer, false);
     target.SetCompletedSynchronously();
     target.MessageId   = 123;
     target.MessageType = MessageType.Request;
     target.MethodName  = "Method";
     target.NextProcess = _ => true;
 }
示例#9
0
		private static void InitializeBuffers( ServerRequestContext target )
		{
			target.ArgumentsBuffer.WriteByte( 1 );
			target.ArgumentsBufferPacker = Packer.Create( target.ArgumentsBuffer, false );
			target.ArgumentsBufferUnpacker = Unpacker.Create( target.ArgumentsBuffer, false );
			target.ArgumentsCount = 2;
			target.UnpackingBuffer = new ByteArraySegmentStream( target.ReceivedData );
			target.UnpackedArgumentsCount = 3;
			target.RootUnpacker = Unpacker.Create( target.UnpackingBuffer, false );
			target.HeaderUnpacker = Unpacker.Create( target.UnpackingBuffer, false );
			target.ArgumentsUnpacker = Unpacker.Create( target.UnpackingBuffer, false );
			target.SetCompletedSynchronously();
			target.MessageId = 123;
			target.MessageType = MessageType.Request;
			target.MethodName = "Method";
			target.NextProcess = _ => true;
		}
示例#10
0
		public void TestRaiseServerError_RpcServerServerErrorEventOccurredWithSpeicifiedValues()
		{
			bool occurred = false;
			using ( var server = new RpcServer() )
			using ( var context = new ServerRequestContext() )
			{
				var exception = new InvalidOperationException();
				server.ServerError +=
					( sender, e ) =>
					{
						Assert.That( e.Exception, Is.EqualTo( exception ) );
						occurred = true;
					};
				using ( var target = new Target( server ) )
				{
					target.RaiseServerError( exception );
					Assert.That( occurred );
				}
			}
		}
示例#11
0
        /// <summary>
        ///		Performs protocol specific asynchronous 'Receive' operation.
        /// </summary>
        /// <param name="context">Context information.</param>
        protected sealed override void ReceiveCore(ServerRequestContext context)
        {
            bool isAsyncOperationStarted;

            try
            {
                isAsyncOperationStarted = this.BoundSocket.ReceiveAsync(context.SocketContext);
            }
            catch (ObjectDisposedException)
            {
                // Canceled.
                return;
            }

            if (!isAsyncOperationStarted)
            {
                context.SetCompletedSynchronously();
                this.OnReceived(context);
            }
        }
示例#12
0
        /// <summary>
        ///		Dispatch request/notification message via the <see cref="MsgPack.Rpc.Server.Dispatch.Dispatcher"/>.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the pipeline is finished;
        ///		<c>false</c>, the pipeline is interruppted because extra data is needed.
        /// </returns>
        private bool Dispatch(ServerRequestContext context)
        {
            Contract.Assert(context != null);

            context.StopWatchTimeout();
            context.Timeout -= this.OnReceiveTimeout;

            context.ClearBuffers();

            var isNotification = context.MessageType == MessageType.Notification;

            try
            {
                this._dispatcher.Dispatch(
                    this,
                    context
                    );
            }
            finally
            {
                context.ClearDispatchContext();

                if (isNotification)
                {
                    this.OnSessionFinished();
                }
            }

            context.NextProcess = this.UnpackRequestHeader;

            if (context.UnpackingBuffer.Length > 0)
            {
                // Subsequent request is already arrived.
                return(context.NextProcess(context));
            }
            else
            {
                // Try receive subsequent.
                return(true);
            }
        }
示例#13
0
        public void TestRaiseServerError_RpcServerServerErrorEventOccurredWithSpeicifiedValues()
        {
            bool occurred = false;

            using (var server = new RpcServer())
                using (var context = new ServerRequestContext())
                {
                    var exception = new InvalidOperationException();
                    server.ServerError +=
                        (sender, e) =>
                    {
                        Assert.That(e.Exception, Is.EqualTo(exception));
                        occurred = true;
                    };
                    using (var target = new Target(server))
                    {
                        target.RaiseServerError(exception);
                        Assert.That(occurred);
                    }
                }
        }
示例#14
0
        /// <summary>
        ///		Performs protocol specific asynchronous 'Receive' operation.
        /// </summary>
        /// <param name="context">Context information.</param>
        protected sealed override void ReceiveCore(ServerRequestContext context)
        {
            // Manager stores the socket which is dedicated socket to this transport in the AcceptSocket property.
            bool isAsyncOperationStarted;

            try
            {
                isAsyncOperationStarted = this.BoundSocket.ReceiveFromAsync(context.SocketContext);
            }
            catch (ObjectDisposedException)
            {
                // Canceled.
                return;
            }

            if (!isAsyncOperationStarted)
            {
                context.SetCompletedSynchronously();
                this.OnReceived(context);
            }
        }
示例#15
0
		public void TestRaiseClientError_RpcServerClientErrorEventOccurredWithSpeicifiedValues()
		{
			bool occurred = false;
			using ( var server = new RpcServer() )
			using ( var context = new ServerRequestContext() )
			{
				var error = RpcError.ArgumentError;
				server.ClientError +=
					( sender, e ) =>
					{
						Assert.That( e.MessageId, Is.EqualTo( context.MessageId ) );
						Assert.That( e.RemoteEndPoint, Is.EqualTo( context.RemoteEndPoint ) );
						Assert.That( e.RpcError.Error, Is.EqualTo( error ) );
						Assert.That( e.SessionId, Is.EqualTo( context.SessionId ) );
						occurred = true;
					};
				using ( var target = new Target( server ) )
				{
					target.RaiseClientError( context, new RpcErrorMessage( error, "Test" ) );
					Assert.That( occurred );
				}
			}
		}
示例#16
0
        public void TestRaiseClientError_RpcServerClientErrorEventOccurredWithSpeicifiedValues()
        {
            bool occurred = false;

            using (var server = new RpcServer())
                using (var context = new ServerRequestContext())
                {
                    var error = RpcError.ArgumentError;
                    server.ClientError +=
                        (sender, e) =>
                    {
                        Assert.That(e.MessageId, Is.EqualTo(context.MessageId));
                        Assert.That(e.RemoteEndPoint, Is.EqualTo(context.RemoteEndPoint));
                        Assert.That(e.RpcError.Error, Is.EqualTo(error));
                        Assert.That(e.SessionId, Is.EqualTo(context.SessionId));
                        occurred = true;
                    };
                    using (var target = new Target(server))
                    {
                        target.RaiseClientError(context, new RpcErrorMessage(error, "Test"));
                        Assert.That(occurred);
                    }
                }
        }
		/// <summary>
		///		Unpack array header of Arguments part on request/notification message.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool UnpackArgumentsHeader( ServerRequestContext context )
		{
			Contract.Assert( context != null );

			if ( !context.ReadFromHeaderUnpacker() )
			{
				MsgPackRpcServerProtocolsTrace.TraceEvent( 
					MsgPackRpcServerProtocolsTrace.NeedArgumentsArrayHeader,
					"Arguments array header is needed. {{ \"SessionID\" : {0} }}",
					context.SessionId 
				);
				return false;
			}

			if ( !context.HeaderUnpacker.IsArrayHeader )
			{
				this.HandleDeserializationError(
					context,
					"Invalid request/notify message stream. Arguments must be array.",
					() => context.UnpackingBuffer.ToArray()
				);
				return true;
			}

			// TODO: Avoid actual unpacking to improve performance.
			context.ArgumentsBufferUnpacker = context.HeaderUnpacker.ReadSubtree();

			if ( Int32.MaxValue < context.ArgumentsBufferUnpacker.ItemsCount )
			{
				this.HandleDeserializationError(
					context,
					RpcError.MessageTooLargeError,
					"Too many arguments.",
					context.ArgumentsBufferUnpacker.ItemsCount.ToString( "#,0", CultureInfo.CurrentCulture ),
					() => context.UnpackingBuffer.ToArray()
				);
				return true;
			}

			context.ArgumentsCount = unchecked( ( int )( context.ArgumentsBufferUnpacker.ItemsCount ) );
			context.ArgumentsBufferPacker = Packer.Create( context.ArgumentsBuffer, false );
			context.ArgumentsBufferPacker.PackArrayHeader( context.ArgumentsCount );
			context.UnpackedArgumentsCount = 0;
			context.NextProcess = this.UnpackArguments;
			return context.NextProcess( context );
		}
示例#18
0
		protected override void ReceiveCore( ServerRequestContext context )
		{
			Contract.Requires( context != null );
		}
示例#19
0
		/// <summary>
		/// Performs protocol specific asynchronous 'Receive' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected override void ReceiveCore( ServerRequestContext context )
		{
			return;
		}
 private static bool InvalidFlow(ServerRequestContext context)
 {
     throw new InvalidOperationException("Invalid state transition.");
 }
示例#21
0
		protected override void ReceiveCore( ServerRequestContext context )
		{
			this.OnReceiving();
			try
			{
				InProcPacket.ProcessReceive( this._inboundQueue, this._pendingPackets, context, this._receivingCancellationTokenSource.Token );
			}
			catch ( OperationCanceledException )
			{
				context.SocketError = SocketError.OperationAborted;
			}

			this.OnReceived( context );
			this.OnReceived();
		}
		/// <summary>
		///		Unpack Method Name part on request/notification message.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool UnpackMethodName( ServerRequestContext context )
		{
			Contract.Assert( context != null );

			if ( !context.ReadFromHeaderUnpacker() )
			{
				MsgPackRpcServerProtocolsTrace.TraceEvent( 
					MsgPackRpcServerProtocolsTrace.NeedMethodName,
					"Method Name is needed. {{ \"SessionID\" : {0} }}",
					context.SessionId 
				);
				return false;
			}

			try
			{
				context.MethodName = context.HeaderUnpacker.LastReadData.AsString();
			}
			catch ( InvalidOperationException )
			{
				this.HandleDeserializationError(
					context,
					"Invalid request/notify message stream. Method name must be UTF-8 string.",
					() => context.UnpackingBuffer.ToArray()
				);
				return true;
			}

			context.NextProcess = this.UnpackArgumentsHeader;
			return context.NextProcess( context );
		}
示例#23
0
		/// <summary>
		///		Returns the request context to the pool.
		/// </summary>
		/// <param name="context">The context to the pool.</param>
		/// <exception cref="ArgumentNullException">
		///		<paramref name="context"/> is  <c>null</c>.
		/// </exception>
		protected internal void ReturnRequestContext( ServerRequestContext context )
		{
			if ( context == null )
			{
				throw new ArgumentNullException( "context" ); 
			}

			Contract.EndContractBlock();

			context.Clear();
			context.UnboundTransport();
			this.RequestContextPool.Return( context );
		}
		/// <summary>
		///		Unpack array elements of Arguments part on request/notification message.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool UnpackArguments( ServerRequestContext context )
		{
			Contract.Assert( context != null );
			
			while ( context.UnpackedArgumentsCount < context.ArgumentsCount )
			{
				if ( !context.ReadFromArgumentsBufferUnpacker() )
				{
					MsgPackRpcServerProtocolsTrace.TraceEvent( 
						MsgPackRpcServerProtocolsTrace.NeedArgumentsElement,
						"Arguments array element is needed. {0}/{1}  {{ \"SessionID\" : {2} }}",
						context.UnpackedArgumentsCount, 
						context.ArgumentsCount, 
						context.SessionId 
					);
					return false;
				}

				context.ArgumentsBufferPacker.Pack( context.ArgumentsBufferUnpacker.LastReadData );
				context.UnpackedArgumentsCount++;
			}

			context.ArgumentsBuffer.Position = 0;
			context.ArgumentsUnpacker = Unpacker.Create( context.ArgumentsBuffer, false );
			context.NextProcess = this.Dispatch;
			return context.NextProcess( context );
		}
示例#25
0
		/// <summary>
		///		Performs protocol specific asynchronous 'Receive' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected sealed override void ReceiveCore( ServerRequestContext context )
		{
			// Manager stores the socket which is dedicated socket to this transport in the AcceptSocket property.
			bool isAsyncOperationStarted;
			try
			{
				isAsyncOperationStarted = this.BoundSocket.ReceiveFromAsync( context.SocketContext );
			}
			catch( ObjectDisposedException )
			{
				// Canceled.
				return;
			}

			if ( !isAsyncOperationStarted )
			{
				context.SetCompletedSynchronously();
				this.OnReceived( context );
			}
		}
		/// <summary>
		///		Unpack Message ID part on request message.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool UnpackMessageId( ServerRequestContext context )
		{
			Contract.Assert( context != null );

			if ( !context.ReadFromHeaderUnpacker() )
			{
				MsgPackRpcServerProtocolsTrace.TraceEvent( 
					MsgPackRpcServerProtocolsTrace.NeedMessageId,
					"Message ID is needed. {{ \"SessionID\" : {0} }}", 
					context.SessionId 
				);
				return false;
			}

			try
			{
				context.MessageId = unchecked( ( int )context.HeaderUnpacker.LastReadData.AsUInt32() );
			}
			catch ( InvalidOperationException )
			{
				this.HandleDeserializationError(
					context,
					"Invalid request message stream. ID must be UInt32 compatible integer.",
					() => context.UnpackingBuffer.ToArray()
				);
				return true;
			}

			context.NextProcess = this.UnpackMethodName;
			return context.NextProcess( context );
		}
 /// <summary>
 /// Performs protocol specific asynchronous 'Receive' operation.
 /// </summary>
 /// <param name="context">Context information.</param>
 protected override void ReceiveCore(ServerRequestContext context)
 {
     return;
 }
示例#28
0
		private static bool InvalidFlow( ServerRequestContext context )
		{
			throw new InvalidOperationException( "Invalid state transition." );
		}
示例#29
0
		/// <summary>
		///		Raises <see cref="E:RpcServer.ClientError"/> event on the hosting <see cref="RpcServer"/>.
		/// </summary>
		/// <param name="context">The <see cref="ServerRequestContext"/> which holds client information.</param>
		/// <param name="rpcError">The <see cref="RpcErrorMessage"/> representing the error.</param>
		internal void RaiseClientError( ServerRequestContext context, RpcErrorMessage rpcError )
		{
			Contract.Requires( context != null );
			Contract.Requires( !rpcError.IsSuccess );

			this.Server.RaiseClientError( context, rpcError );
		}
示例#30
0
		/// <summary>
		///		Called when asynchronous 'Receive' operation is completed.
		/// </summary>
		/// <param name="context">Context information.</param>
		///	<exception cref="InvalidOperationException">
		///		This instance is not in 'Idle' nor 'Receiving' state.
		///	</exception>
		///	<exception cref="ObjectDisposedException">
		///		This instance is disposed.
		///	</exception>
		protected override void OnReceived( ServerRequestContext context )
		{
			Task.Factory.StartNew(
				state => base.OnReceived( state as ServerRequestContext ),
				context
			);
		}
示例#31
0
		internal ServerResponseContext GetResponseContext( ServerRequestContext requestContext )
		{
			Contract.Requires( requestContext != null );
			Contract.Requires( requestContext.MessageId != null );
			Contract.Requires( requestContext.BoundTransport != null );
			Contract.Ensures( Contract.Result<ServerResponseContext>() != null );

			return this.GetResponseContext( requestContext.BoundTransport, requestContext.RemoteEndPoint, requestContext.SessionId, requestContext.MessageId.Value );
		}
示例#32
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 );
示例#33
0
		/// <summary>
		///		Performs protocol specific asynchronous 'Receive' operation.
		/// </summary>
		/// <param name="context">Context information.</param>
		protected sealed override void ReceiveCore( ServerRequestContext context )
		{
			bool isAsyncOperationStarted;
			try
			{
				isAsyncOperationStarted = this.BoundSocket.ReceiveAsync( context.SocketContext );
			}
			catch( ObjectDisposedException )
			{
				// Canceled.
				return;
			}

			if ( !isAsyncOperationStarted )
			{
				context.SetCompletedSynchronously();
				this.OnReceived( context );
			}
		}
示例#34
0
文件: RpcServer.cs 项目: Indifer/Test
		/// <summary>
		///		Raises the <see cref="E:ClientError"/> event.
		/// </summary>
		/// <param name="context">The context information.</param>
		/// <param name="rpcError">The RPC error.</param>
		internal void RaiseClientError( ServerRequestContext context, RpcErrorMessage rpcError )
		{
			this.OnClientError(
				new RpcClientErrorEventArgs( rpcError )
				{
					RemoteEndPoint = context.RemoteEndPoint,
					SessionId = context.SessionId,
					MessageId = context.MessageId
				}
			);
		}
		/// <summary>
		///		Dispatch request/notification message via the <see cref="MsgPack.Rpc.Server.Dispatch.Dispatcher"/>.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool Dispatch( ServerRequestContext context )
		{
			Contract.Assert( context != null );

			context.StopWatchTimeout();
			context.Timeout -= this.OnReceiveTimeout;

			context.ClearBuffers();

			var isNotification = context.MessageType == MessageType.Notification;
			try
			{
				this._dispatcher.Dispatch(
					this,
					context
				);
			}
			finally
			{
				context.ClearDispatchContext();

				if ( isNotification )
				{
					this.OnSessionFinished();
				}
			}

			context.NextProcess = this.UnpackRequestHeader;

			if ( context.UnpackingBuffer.Length > 0 )
			{
				// Subsequent request is already arrived.
				return context.NextProcess( context );
			}
			else
			{
				// Try receive subsequent.
				return true;
			}
		}
示例#36
0
		internal void StartReceive( ServerRequestContext context )
		{
			if ( this._receivingTask == null )
			{
				Contract.Assert( context.BoundTransport == this );
				this._receivingTask =
					Task.Factory.StartNew(
						this.DoReceiveLoop,
						context,
						this._receivingCancellationTokenSource.Token,
						TaskCreationOptions.LongRunning,
						TaskScheduler.Default
					);
			}
		}
示例#37
0
 protected override void ReceiveCore(ServerRequestContext context)
 {
     Contract.Requires(context != null);
 }
		/// <summary>
		///		Unpack Message Type part on request/notification message.
		/// </summary>
		/// <param name="context">Context information.</param>
		/// <returns>
		///		<c>true</c>, if the pipeline is finished;
		///		<c>false</c>, the pipeline is interruppted because extra data is needed.
		/// </returns>
		private bool UnpackMessageType( ServerRequestContext context )
		{
			Contract.Assert( context != null );
			
			if ( !context.ReadFromHeaderUnpacker() )
			{
				MsgPackRpcServerProtocolsTrace.TraceEvent( 
					MsgPackRpcServerProtocolsTrace.NeedMessageType,
					"Message Type is needed. {{ \"SessionID\" : {0} }}",
					context.SessionId 
				);
				return false;
			}

			int numericType;
			try
			{
				numericType = context.HeaderUnpacker.LastReadData.AsInt32();
			}
			catch ( InvalidOperationException )
			{
				this.HandleDeserializationError( context, "Invalid request/notify message stream. Message Type must be Int32 compatible integer.", () => context.UnpackingBuffer.ToArray() );
				return true;
			}

			MessageType type = ( MessageType )numericType;
			context.MessageType = type;

			switch ( type )
			{
				case MessageType.Request:
				{
					context.NextProcess = this.UnpackMessageId;
					break;
				}
				case MessageType.Notification:
				{
					context.NextProcess = this.UnpackMethodName;
					break;
				}
				default:
				{
					this.HandleDeserializationError(
						context,
						String.Format( CultureInfo.CurrentCulture, "Unknown message type '{0:x8}'", numericType ),
						() => context.UnpackingBuffer.ToArray()
					);
					return true;
				}
			}

			return context.NextProcess( context );
		}