/// <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> /// 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)); }
/// <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)); }
/// <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)); }
/// <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 ); }
/// <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 ); }
/// <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> /// 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 ); }