Exemple #1
0
        /// <summary>
        /// Parses an message received through the messaging client
        /// </summary>
        /// <param name="message"></param>
        private void parseMessage(string message)
        {
            //check if the message's format is valid
            if (!verifyMessageFormat(message))
            {
                logger.Error("Received invalid message, aborting message processing");
                sendresult(Result.InvalidFormat);
                return;
            }

            //get the messages metadata and payload
            IEnumerable <string> parts = message.Split(';').Where(x => !x.IsNullOrEmpty());
            string payload_str         = message.EndsWith(";") ?  null : parts.Last();

            parts = (payload_str == null) ? parts : parts.Take(parts.Count() - 1);


            //parse metadata keys
            var metadata = parts.Select(x => new Tuple <Key, string>((Key)Enum.Parse(typeof(Key), x.Split(':').First(), true), x.Split(':').Last()));


            //check for message id
            var messageIdQuery = metadata.Where(x => x.Item1 == Key.Message_id);
            int messageId      = -1;

            if (!messageIdQuery.Any() || !int.TryParse(messageIdQuery.First().Item2, out messageId))
            {
                logger.Warn("Invalid message. MessageId not found or invalid");
                sendresult(Result.InvalidFormat);
                return;
            }

            //check if message is a delivery notification
            var resultQuery = metadata.Where(x => x.Item1 == Key.Result);

            if (metadata.Count() == 2 && messageId > 0 && resultQuery.Any())
            {
                //handle delivery confirmation

                Result deliveryResult;
                if (!Enum.TryParse(resultQuery.First().Item2, true, out deliveryResult))
                {
                    deliveryResult = Result.UnknownError;
                }

                logger.Info("Received delivery confirmation for message {0} from {1}, Result: {2}", messageId, this.Recipient, deliveryResult);


                lock (this)
                {
                    //store result in result cache and unblock waiting threads
                    if (waitingThreads.ContainsKey(messageId))
                    {
                        if (!messageResults.ContainsKey(messageId))
                        {
                            messageResults.Add(messageId, deliveryResult);
                        }
                        else
                        {
                            messageResults[messageId] = deliveryResult;
                        }

                        //relese threads waiting for the result
                        waitingThreads[messageId].Release();
                    }
                }

                return;
            }


            //check for splitted messages
            var fragmentIndexQuery = metadata.Where(x => x.Item1 == Key.Fragment_Index);
            var fragmentCountQuery = metadata.Where(x => x.Item1 == Key.Fragment_Count);

            if (fragmentCountQuery.Any() || fragmentIndexQuery.Any())
            {
                logger.Info("Received splitted message");

                if (!(fragmentIndexQuery.Any() && fragmentIndexQuery.Any()))
                {
                    logger.Error("Missing metadata information for splitted message");
                    return;
                }

                int fragmentIndex = int.Parse(fragmentIndexQuery.First().Item2);
                int fragmentCount = int.Parse(fragmentCountQuery.First().Item2);

                if (fragmentCount <= 0 || fragmentIndex < 0)
                {
                    logger.Warn("Fragment Index or Count out of range");
                    sendresult(Result.SplittingError, messageId);
                    return;
                }

                if (!messageFragments.ContainsKey(messageId))
                {
                    messageFragments.Add(messageId, new string[fragmentCount]);
                }

                //check if fragment index is valid
                if (fragmentIndex >= messageFragments[messageId].Length)
                {
                    logger.Warn("Fragment index out of range");
                    sendresult(Result.SplittingError, messageId);
                    return;
                }

                //check if fragment count is consistent with previous messages
                if (fragmentCount != messageFragments[messageId].Length)
                {
                    logger.Error("Inconsistent fragment count");
                    sendresult(Result.SplittingError, messageId);
                }

                messageFragments[messageId][fragmentIndex] = payload_str;

                //check if all fragments have been received
                if (messageFragments[messageId].Any(x => x == null))
                {
                    logger.Info("Missing fragments of message {0}, waiting for next piece", messageId);
                    return;
                }
                else
                {
                    logger.Info("Received all fragments of message {0}", messageId);
                    payload_str = messageFragments[messageId].Aggregate((str1, str2) => str1 + str2);

                    messageFragments.Remove(messageId);
                }
            }


            ParsingResult result = new ParsingResult();

            byte[] payload = payload_str.GetBytesBase64();

            //check if message is encrypted
            var encryptedMetadate = metadata.Any(x => x.Item1 == Key.Encryption) ? metadata.First(x => x.Item1 == Key.Encryption) : null;

            if (encryptedMetadate != null)
            {
                //check if encryption algorith is supported
                if (encryptedMetadate.Item2.ToLower() != "aes")
                {
                    logger.Warn("Encryption algorithm not supported");
                    sendresult(Result.EncryptionError);
                    return;
                }

                payload = payload.DecryptAES(this.EncryptionKey, this.EncryptionIV);

                result.WasEncrypted = true;
            }


            //check if message is compressed
            var compressedMetadate = metadata.Any(x => x.Item1 == Key.Gzip) ? metadata.First(x => x.Item1 == Key.Gzip) : null;

            if (compressedMetadate != null)
            {
                int length;
                if (!int.TryParse(compressedMetadate.Item2, out length))
                {
                    logger.Error("Could not parse length from GZip metadate");
                    sendresult(Result.InvalidFormat, messageId);
                }

                result.WasCompressed = true;
                payload = payload.Take(length).ToArray <byte>().Decompress();
            }


            result.Payload = payload;

            //everything went okay => send delivery notifiaction
            sendresult(Result.Success, messageId);

            onMessageReceived(result);
        }
Exemple #2
0
        /// <summary>
        /// Processes an incoming message (using the MessageProcessor for deserialization)
        /// </summary>
        /// <param name="message">The message to be processed</param>
        private void processMessage(ParsingResult message)
        {
            //parse the message
            XElement   xmlMessage;
            RpcMessage msg  = null;
            var        body = message.Payload.ToStringUTF8();

            try
            {
                //try to parse it as XML
                xmlMessage = XElement.Parse(body);

                switch (xmlMessage.Name.LocalName.ToLower())
                {
                case "remotemethodcall":
                    msg = new RemoteMethodCall();
                    break;

                case "remotemethodresponse":
                    msg = new RemoteMethodResponse();
                    break;

                case "remoteerror":
                    msg = new RemoteError();
                    break;
                }

                if (!msg.Validate(xmlMessage))
                {
                    logger.Error("Message from {0} could not be validated", this.Target);
                    var error = new RemoteError(RemoteErrorCode.InvalidXmlError);
                    sendMessage(error);
                    return;
                }

                msg.Deserialize(xmlMessage);
            }
            //Catch XmlException and wrap it into a format exception (makes catching errors in the caller easier)
            catch (XmlException)
            {
                logger.Error("Could not parse message received from {0}", this.Target);
                RemoteError error = new RemoteError(RemoteErrorCode.InvalidXmlError);
                sendMessage(error);
                return;
            }



            //encryption is mandatory if TrustLevel is 2 or higher
            //if message was not encrypted it will result in a RemoteError and the connection will be reset
            if (this.TrustLevel >= 2 && !message.WasEncrypted && !(msg is RemoteMethodCall && (msg as RemoteMethodCall).MethodName == CoreMethods.SendResetNotice))
            {
                RemoteError error = new RemoteError(RemoteErrorCode.EncryptionError);
                if (msg.CallId != Guid.Empty)
                {
                    error.CallId = msg.CallId;
                }
                error.ComponentName = "Authentication";

                //The RemoteError will not be encrypted
                WtlpClient.EncryptMessages = false;
                sendMessage(error);
                ResetConnection();
                return;
            }



            if (msg is RemoteMethodCall)
            {
                //get the component responsible for handling the message
                string componentName = (msg as RpcMessage).ComponentName;
                var    component     = GetServerComponent(componentName);

                if (component == null)
                {
                    //no component to handle the request was found => send a RemoteError as response and return
                    RemoteError error = new RemoteError(RemoteErrorCode.ComponentNotFoundError);
                    error.CallId = (msg as RemoteMethodCall).CallId;
                    sendMessage(error);
                    return;
                }

                var processingTask = new Task(delegate
                {
                    processRemoteMethodCall(msg as RemoteMethodCall, component);
                });

                processingTask.Start();

                var heartBeatTask = new Task(delegate
                {
                    var coreComponent = new CoreClientComponent();
                    coreComponent.ClientConnection = this;
                    while (!processingTask.IsCompleted)
                    {
                        Thread.Sleep(25000);
                        if (!processingTask.IsCompleted)
                        {
                            coreComponent.HeartbeatAsync();
                        }
                    }
                });

                heartBeatTask.Start();
            }
            else if (msg is RemoteMethodResponse)
            {
                processRemoteMethodResponse(msg as RemoteMethodResponse);
            }
            else if (msg is RemoteError)
            {
                processRemoteError(msg as RemoteError);
            }
            else
            {
                logger.Error("ProcessMessage() encoutered an unknown type of Message");
                sendMessage(new RemoteError(RemoteErrorCode.UnknownMessage));
            }
        }
        /// <summary>
        /// Parses an message received through the messaging client
        /// </summary>
        /// <param name="message"></param>
        private void parseMessage(string message)
        {
            //check if the message's format is valid
            if (!verifyMessageFormat(message))
            {
                logger.Error("Received invalid message, aborting message processing");
                sendresult(Result.InvalidFormat);
                return;
            }

            //get the messages metadata and payload
            IEnumerable<string> parts = message.Split(';').Where(x => !x.IsNullOrEmpty());
            string payload_str =  message.EndsWith(";") ?  null : parts.Last();
            parts = (payload_str == null) ? parts : parts.Take(parts.Count() - 1);

            //parse metadata keys
            var metadata = parts.Select(x => new Tuple<Key, string>((Key)Enum.Parse(typeof(Key), x.Split(':').First(), true), x.Split(':').Last()));

            //check for message id
            var messageIdQuery = metadata.Where(x => x.Item1 == Key.Message_id);
            int messageId = -1;
            if (!messageIdQuery.Any() || !int.TryParse(messageIdQuery.First().Item2, out messageId))
            {
                logger.Warn("Invalid message. MessageId not found or invalid");
                sendresult(Result.InvalidFormat);
                return;
            }

            //check if message is a delivery notification
            var resultQuery = metadata.Where(x => x.Item1 == Key.Result);
            if (metadata.Count() == 2 && messageId > 0 && resultQuery.Any())
            {
                //handle delivery confirmation

                Result deliveryResult;
                if (!Enum.TryParse(resultQuery.First().Item2, true, out deliveryResult))
                    deliveryResult = Result.UnknownError;

                logger.Info("Received delivery confirmation for message {0} from {1}, Result: {2}", messageId, this.Recipient,  deliveryResult);

                lock (this)
                {
                    //store result in result cache and unblock waiting threads
                    if (waitingThreads.ContainsKey(messageId))
                    {
                        if (!messageResults.ContainsKey(messageId))
                            messageResults.Add(messageId, deliveryResult);
                        else
                            messageResults[messageId] = deliveryResult;

                        //relese threads waiting for the result
                        waitingThreads[messageId].Release();
                    }
                }

                return;
            }

            //check for splitted messages
            var fragmentIndexQuery = metadata.Where(x => x.Item1 == Key.Fragment_Index);
            var fragmentCountQuery = metadata.Where(x => x.Item1 == Key.Fragment_Count);

            if (fragmentCountQuery.Any() || fragmentIndexQuery.Any())
            {
                logger.Info("Received splitted message");

                if (!(fragmentIndexQuery.Any() && fragmentIndexQuery.Any()))
                {
                    logger.Error("Missing metadata information for splitted message");
                    return;
                }

                int fragmentIndex = int.Parse(fragmentIndexQuery.First().Item2);
                int fragmentCount = int.Parse(fragmentCountQuery.First().Item2);

                if (fragmentCount <= 0 || fragmentIndex < 0)
                {
                    logger.Warn("Fragment Index or Count out of range");
                    sendresult(Result.SplittingError, messageId);
                    return;
                }

                if (!messageFragments.ContainsKey(messageId))
                    messageFragments.Add(messageId, new string[fragmentCount]);

                //check if fragment index is valid
                if (fragmentIndex >= messageFragments[messageId].Length)
                {
                    logger.Warn("Fragment index out of range");
                    sendresult(Result.SplittingError, messageId);
                    return;
                }

                //check if fragment count is consistent with previous messages
                if (fragmentCount != messageFragments[messageId].Length)
                {
                    logger.Error("Inconsistent fragment count");
                    sendresult(Result.SplittingError, messageId);
                }

                messageFragments[messageId][fragmentIndex] = payload_str;

                //check if all fragments have been received
                if (messageFragments[messageId].Any(x => x == null))
                {
                    logger.Info("Missing fragments of message {0}, waiting for next piece", messageId);
                    return;
                }
                else
                {
                    logger.Info("Received all fragments of message {0}", messageId);
                    payload_str = messageFragments[messageId].Aggregate((str1, str2) => str1 + str2);

                    messageFragments.Remove(messageId);
                }
            }

            ParsingResult result = new ParsingResult();
            byte[] payload = payload_str.GetBytesBase64();

            //check if message is encrypted
            var encryptedMetadate = metadata.Any(x => x.Item1 == Key.Encryption) ? metadata.First(x => x.Item1 == Key.Encryption) : null;

            if (encryptedMetadate != null)
            {
                //check if encryption algorith is supported
                if (encryptedMetadate.Item2.ToLower() != "aes")
                {
                    logger.Warn("Encryption algorithm not supported");
                    sendresult(Result.EncryptionError);
                    return;
                }

                payload = payload.DecryptAES(this.EncryptionKey, this.EncryptionIV);

                result.WasEncrypted = true;
            }

            //check if message is compressed
            var compressedMetadate = metadata.Any(x => x.Item1 == Key.Gzip) ? metadata.First(x => x.Item1 == Key.Gzip) : null;
            if (compressedMetadate != null)
            {
                int length;
                if (!int.TryParse(compressedMetadate.Item2, out length))
                {
                    logger.Error("Could not parse length from GZip metadate");
                    sendresult(Result.InvalidFormat, messageId);
                }

                result.WasCompressed = true;
                payload = payload.Take(length).ToArray<byte>().Decompress();
            }

            result.Payload = payload;

            //everything went okay => send delivery notifiaction
            sendresult(Result.Success, messageId);

            onMessageReceived(result);
        }
        /// <summary>
        /// Processes an incoming message (using the MessageProcessor for deserialization)
        /// </summary>
        /// <param name="message">The message to be processed</param>
        private void processMessage(ParsingResult message)
        {
            //parse the message
            XElement xmlMessage;
            RpcMessage msg = null;
            var body = message.Payload.ToStringUTF8();
            try
            {
                //try to parse it as XML
                xmlMessage = XElement.Parse(body);

                switch (xmlMessage.Name.LocalName.ToLower())
                {
                    case "remotemethodcall":
                        msg = new RemoteMethodCall();
                        break;
                    case "remotemethodresponse":
                        msg = new RemoteMethodResponse();
                        break;
                    case "remoteerror":
                        msg = new RemoteError();
                        break;
                }

                if (!msg.Validate(xmlMessage))
                {
                    logger.Error("Message from {0} could not be validated", this.Target);
                    var error = new RemoteError(RemoteErrorCode.InvalidXmlError);
                    sendMessage(error);
                    return;
                }

                msg.Deserialize(xmlMessage);

            }
            //Catch XmlException and wrap it into a format exception (makes catching errors in the caller easier)
            catch (XmlException)
            {
                logger.Error("Could not parse message received from {0}", this.Target);
                RemoteError error = new RemoteError(RemoteErrorCode.InvalidXmlError);
                sendMessage(error);
                return;
            }

            //encryption is mandatory if TrustLevel is 2 or higher
            //if message was not encrypted it will result in a RemoteError and the connection will be reset
            if (this.TrustLevel >= 2 && !message.WasEncrypted && !(msg is RemoteMethodCall && (msg as RemoteMethodCall).MethodName == CoreMethods.SendResetNotice))
            {
                RemoteError error = new RemoteError(RemoteErrorCode.EncryptionError);
                if (msg.CallId != Guid.Empty)
                    error.CallId = msg.CallId;
                error.ComponentName = "Authentication";

                //The RemoteError will not be encrypted
                WtlpClient.EncryptMessages = false;
                sendMessage(error);
                ResetConnection();
                return;
            }

            if (msg is RemoteMethodCall)
            {
                //get the component responsible for handling the message
                string componentName = (msg as RpcMessage).ComponentName;
                var component = GetServerComponent(componentName);

                if (component == null)
                {
                    //no component to handle the request was found => send a RemoteError as response and return
                    RemoteError error = new RemoteError(RemoteErrorCode.ComponentNotFoundError);
                    error.CallId = (msg as RemoteMethodCall).CallId;
                    sendMessage(error);
                    return;
                }

                var processingTask = new Task(delegate
                    {
                        processRemoteMethodCall(msg as RemoteMethodCall, component);
                    });

                processingTask.Start();

                var heartBeatTask = new Task(delegate
                    {
                        var coreComponent = new CoreClientComponent();
                        coreComponent.ClientConnection = this;
                        while (!processingTask.IsCompleted)
                        {
                            Thread.Sleep(25000);
                            if (!processingTask.IsCompleted)
                                coreComponent.HeartbeatAsync();
                        }
                    });

                heartBeatTask.Start();
            }
            else if (msg is RemoteMethodResponse)
            {
                processRemoteMethodResponse(msg as RemoteMethodResponse);
            }
            else if (msg is RemoteError)
            {
                processRemoteError(msg as RemoteError);
            }
            else
            {
                logger.Error("ProcessMessage() encoutered an unknown type of Message");
                sendMessage(new RemoteError(RemoteErrorCode.UnknownMessage));
            }
        }
 /// <summary>
 /// Raises the MessageReceived event
 /// </summary>
 /// <param name="message">The message that has been received</param>
 private void onMessageReceived(ParsingResult message)
 {
     if (this.MessageReceived != null)
         this.MessageReceived(this, message);
 }