Generic AMF message.
상속: AmfMessageBase
예제 #1
0
        /// <summary>
        /// Handle command message: a clinet ping.
        /// </summary>
        private AmfGenericMessage HandleClientPing(AmfGenericMessage request, CommandMessage message)
        {
            var acknowledge = AmfOperationUtil.BuildAcknowledgeMessage(message);
            acknowledge.Headers = new Dictionary<string, object>
                                      {
                                          {CommandMessageHeader.MessagingVersion, Capabilities.MessagingVersion}
                                      };

            return AmfOperationUtil.BuildMessageReply(request, acknowledge);
        }
예제 #2
0
        /// <summary>
        /// Build a message reply.
        /// </summary>
        /// <param name="request">Request message.</param>
        /// <param name="body">Reply message's body.</param>
        public static AmfGenericMessage BuildMessageReply(AmfGenericMessage request, object body)
        {
            var replyHeaders = new Dictionary<string, AmfHeader>();
            var replyMessage = new AmfMessage
            {
                Target = CreateResultReplyTarget(request.AmfMessage),
                Response = string.Empty,
                Data = body
            };

            return new AmfGenericMessage(replyHeaders, replyMessage);
        }
예제 #3
0
        /// <summary>
        /// Process an AMF command request.
        /// </summary>
        /// <param name="request">Request message to process.</param>
        /// <returns>Service reply message.</returns>
        protected AmfGenericMessage ProcessCommand(AmfGenericMessage request)
        {
            var command = (CommandMessage)request.AmfMessage.Data;
            Func<AmfGenericMessage, CommandMessage, AmfGenericMessage> handler;

            switch (command.Operation)
            {
                case CommandMessageOperation.ClientPing:
                    handler = HandleClientPing;
                    break;

                default:
                    throw new NotSupportedException(string.Format(Errors.AmfCommandInvoker_ProcessCommand_OperationNotSupported, command.Operation));
            }

            return handler.Invoke(request, command);
        }
예제 #4
0
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            //An internal server error occured
            if (OperationContext.Current == null) return;

            //An AMF operation
            if (OperationContext.Current.IncomingMessageProperties.ContainsKey(MessagingHeaders.InvokerMessageBody))
            {
                var replyHeaders = new Dictionary<string, AmfHeader>();
                var replyMessage = new AmfMessage { Response = string.Empty };

                var requestMessage = (AmfMessage)OperationContext.Current.IncomingMessageProperties[MessagingHeaders.InvokerMessageBody];

                //An RPC operation
                if (OperationContext.Current.IncomingMessageProperties.ContainsKey(MessagingHeaders.RemotingMessage))
                {
                    var rpcMessage = (RemotingMessage)OperationContext.Current.IncomingMessageProperties[MessagingHeaders.RemotingMessage];
                    var acknowledge = AmfOperationUtil.BuildErrorMessage(rpcMessage);
                    if (acknowledge.Headers == null) acknowledge.Headers = new Dictionary<string, object>();

                    if (error is AmfOperationNotFoundException)
                        acknowledge.Headers[AmfMessageHeader.StatusCode] = (int)HttpStatusCode.NotFound;
                    else
                        acknowledge.Headers[AmfMessageHeader.StatusCode] = (int)HttpStatusCode.BadRequest;

                    acknowledge.FaultCode = ErrorMessageFaultCode.DeliveryInDoubt;

                    acknowledge.FaultString = error.Message;

                    if (_capabilities.ExceptionDetailInFaults)
                    {
                        acknowledge.FaultDetail = error.StackTrace;
                    }

                    //Get FaultException's detail object, if any
                    if(error is FaultException)
                    {
                        var type = error.GetType();

                        if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(FaultException<>)))
                        {
                            acknowledge.ExtendedData = type.GetProperty("Detail").GetValue(error, null);
                        }
                    }

                    replyMessage.Target = AmfOperationUtil.CreateStatusReplyTarget(requestMessage);
                    replyMessage.Data = acknowledge;
                }

                fault = new AmfGenericMessage(replyHeaders, replyMessage);
            }
        }
예제 #5
0
 /// <summary>
 /// Deserializes a message into an array of parameters.
 /// </summary>
 /// <param name="message">The incoming message.</param>
 /// <param name="parameters">The objects that are passed to the operation as parameters.</param>
 public virtual void DeserializeRequest(Message message, object[] parameters)
 {
     var request = (AmfGenericMessage)message;
     parameters[0] = new AmfGenericMessage(request.AmfHeaders, request.AmfMessage); //Use space allocated for one AmfGenericMessage
 }
예제 #6
0
        /// <summary>
        /// Selects the service operation to call.
        /// </summary>
        /// <param name="message">The <c>Message</c> object sent to invoke a service operation.</param>
        /// <returns>The name of the service operation to call.</returns>
        public string SelectOperation(ref Message message)
        {
            AmfPacket packet;

            //Read AMF packet from the message
            try
            {
                packet = message.GetBody<AmfPacket>(_context.AmfSerializer);
            }
            finally
            {
                message.Close();
            }

            //Batch request
            if (packet.Messages.Count > 1)
            {
                message = new AmfBatchMessage(packet.Headers, packet.Messages);
                return AmfOperationKind.Batch;
            }

            //Regular request
            var amfMessage = new AmfGenericMessage(packet.Headers, packet.Messages[0]);
            message = amfMessage;

            //Check if it is a Flex message.
            //Due to the nature of NetConnection.call(), RPC arguments
            //are sent in an array. But in case of AMFX, an array is not used
            //if there is only one argument.
            var arraybody = amfMessage.AmfMessage.Data as object[];
            AbstractMessage flexmessage;

            if (arraybody != null && arraybody.Length > 0)
                flexmessage = arraybody[0] as AbstractMessage;
            else
                flexmessage = amfMessage.AmfMessage.Data as AbstractMessage;

            //It is a Flex message after all
            if (flexmessage != null)
            {
                amfMessage.AmfMessage.Data = flexmessage;

                var type = flexmessage.GetType();

                //An RPC operation
                if (type == typeof(RemotingMessage))
                {
                    var operation = ((RemotingMessage)flexmessage).Operation;
                    return EndpointHasOperation(_context.ServiceEndpoint, operation)
                        ? operation
                        : AmfOperationKind.Fault;
                }

                //A Flex command message
                if (type == typeof(CommandMessage))
                {
                    return AmfOperationKind.Command;
                }
            }

            //If it's not a Flex message, then do it the old way
            return EndpointHasOperation(_context.ServiceEndpoint, amfMessage.AmfMessage.Target)
                ? amfMessage.AmfMessage.Target
                : AmfOperationKind.Fault;
        }