private static void DeserializeCore( RequestMessageDeserializationContext context ) { using ( var unpacker = new Unpacker( context.ReadBytes() ) ) { var request = unpacker.UnpackObject(); if ( request == null ) { if ( context.SerializationError.IsSuccess ) { // Since entire stream was readed and its length was in quota, the stream may be coruppted. context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Cannot deserialize message stream." ) ); } return; } if ( !request.Value.IsTypeOf<IList<MessagePackObject>>().GetValueOrDefault() ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Request message is not array." ) ); return; } var requestFields = request.Value.AsList(); if ( requestFields.Count > 4 || requestFields.Count < 3 ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Request message is not 3 nor 4 element array." ) ); return; } if ( !requestFields[ 0 ].IsTypeOf<int>().GetValueOrDefault() ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message type of request message is not int 32." ) ); return; } int nextPosition = 1; switch ( ( MessageType )requestFields[ 0 ].AsInt32() ) { case MessageType.Request: { if ( !requestFields[ nextPosition ].IsTypeOf<uint>().GetValueOrDefault() ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message ID of request message is not uint32." ) ); return; } // For CLS compliance store uint32 value as int32. unchecked { context.MessageId = ( int )requestFields[ nextPosition ].AsUInt32(); } nextPosition++; break; } case MessageType.Notification: { break; } default: { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message type of request message is not Request(0) nor Notification(2)." ) ); return; } } if ( !requestFields[ nextPosition ].IsTypeOf<string>().GetValueOrDefault() ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", String.Format( CultureInfo.CurrentCulture, "Method of request message (ID:{0}) is not raw. ", context.MessageId ) ) ); return; } try { context.MethodName = MessagePackConvert.DecodeStringStrict( requestFields[ nextPosition ].AsBinary() ); } catch ( InvalidOperationException ex ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", String.Format( CultureInfo.CurrentCulture, "Message ID:{0}: {1}", context.MessageId, ex.Message ) ) ); return; } nextPosition++; if ( !requestFields[ nextPosition ].IsTypeOf<IList<MessagePackObject>>().GetValueOrDefault() ) { context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", String.Format( CultureInfo.CurrentCulture, "Arguments of request message (ID:{0}) is not array.", context.MessageId ) ) ); return; } context.Arguments = requestFields[ nextPosition ].AsList(); } }
/// <summary> /// Deserialize from specified buffer. /// </summary> /// <param name="input">Buffer which stores serialized request/notification stream.</param> /// <param name="result">Deserialied packed message will be stored.</param> /// <returns>Error information.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="input"/> is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Some filters violate contract. /// </exception> public RpcErrorMessage Deserialize( IEnumerable<byte> input, out RequestMessage result ) { if ( input == null ) { throw new ArgumentNullException( "input" ); } Contract.EndContractBlock(); var context = new RequestMessageDeserializationContext( input, this._maxRequestLength ); var sequence = context.ReadBytes(); foreach ( var preDeserializationFilter in this._preDeserializationFilters ) { sequence = preDeserializationFilter.GetFilter().Process( sequence, context ); if ( !context.SerializationError.IsSuccess ) { result = default( RequestMessage ); return context.SerializationError; } } DeserializeCore( context ); if ( !context.SerializationError.IsSuccess ) { result = default( RequestMessage ); return context.SerializationError; } Contract.Assert( !String.IsNullOrWhiteSpace( context.MethodName ) ); Contract.Assert( context.Arguments != null ); foreach ( var postDeserializationFilter in this._postDeserializationFilters ) { postDeserializationFilter.GetFilter().Process( context ); if ( !context.SerializationError.IsSuccess ) { result = default( RequestMessage ); return context.SerializationError; } } if ( String.IsNullOrWhiteSpace( context.MethodName ) ) { throw new InvalidOperationException( "Filter became method null or empty." ); } if ( context.Arguments == null ) { throw new InvalidOperationException( "Filter became arguments null." ); } result = new RequestMessage( context.MessageId, context.MethodName, context.Arguments ); return RpcErrorMessage.Success; }