/// <summary>
        /// Called to process message
        /// </summary>
        /// <param name="rawMessage">The message from the queue</param>
        /// <param name="message">The refined message data. All information should now be present</param>
        protected override void NotifyMessageProcessingReady(IMessagingMessage rawMessage, IncomingMessage message)
        {
            var reply = MessagingNotification.NotifySynchronousMessageReceived(message);

            if (reply == null)
            {
                throw new InvalidOperationException($"Message handler for function {message.MessageFunction} returned null");
            }

            var outgoingMessage = new OutgoingMessage()
            {
                ToHerId         = message.FromHerId,
                Payload         = reply,
                MessageFunction = message.MessageFunction,
                MessageId       = Guid.NewGuid().ToString()
            };

            Task.WaitAll(Core.Send(Logger, outgoingMessage, QueueType.SynchronousReply, rawMessage.ReplyTo, rawMessage.CorrelationId));
        }
Beispiel #2
0
        /// <summary>
        /// Called to process message
        /// </summary>
        /// <param name="rawMessage">The message from the queue</param>
        /// <param name="message">The refined message data. All information should now be present</param>
        protected override void NotifyMessageProcessingReady(IMessagingMessage rawMessage, IncomingMessage message)
        {
            if (rawMessage == null)
            {
                throw new ArgumentNullException(nameof(rawMessage));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var stringBuilder = new StringBuilder();

            stringBuilder.Append($"Label: {message.MessageFunction} ");

            // we have received a soap fault
            if (message.MessageFunction.Equals(ServiceBusCore.SoapFaultLabel, StringComparison.OrdinalIgnoreCase) &&
                (message.Payload != null))
            {
                XNamespace soapNs   = "http://www.w3.org/2003/05/soap-envelope";
                XNamespace dialogNs = "http://www.kith.no/xmlstds/digitaldialog/2013-10-08";

                if (message.Payload.Root != null)
                {
                    var bodyNode  = message.Payload.Root.Element(soapNs + "Body");
                    var faultNode = bodyNode?.Element(soapNs + "Fault");
                    if (faultNode != null)
                    {
                        var valueNode = faultNode.Descendants(soapNs + "Value").FirstOrDefault();
                        if (valueNode != null)
                        {
                            stringBuilder.Append($"FaultCode: {valueNode.Value} ");
                        }
                        var reasonNode = faultNode.Descendants(soapNs + "Text").FirstOrDefault();
                        if (reasonNode != null)
                        {
                            stringBuilder.Append($"FaultReason: \"{reasonNode.Value}\" ");
                        }
                        var messageIdNode = faultNode.Descendants(dialogNs + "messageId").FirstOrDefault();
                        if (messageIdNode != null)
                        {
                            stringBuilder.Append($"MessageId: {messageIdNode.Value} ");
                        }
                        var timestampNode = faultNode.Descendants(dialogNs + "applicationTimeStamp").FirstOrDefault();
                        if (timestampNode != null)
                        {
                            stringBuilder.Append($"ApplicationTimeStamp: {timestampNode.Value} ");
                        }
                    }
                }
            }
            else // we received a message where error codes are stored in properties
            {
                foreach (var property in rawMessage.Properties)
                {
                    stringBuilder.Append($"{property.Key}: {property.Value} ");
                }
            }

            Logger.LogExternalReportedError(stringBuilder.ToString());

            Logger.LogBeforeNotificationHandler(nameof(MessagingNotification.NotifyErrorMessageReceived), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
            MessagingNotification.NotifyErrorMessageReceived(rawMessage);
            Logger.LogAfterNotificationHandler(nameof(MessagingNotification.NotifyErrorMessageReceived), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
        }
Beispiel #3
0
 /// <summary>
 /// Called prior to message processing
 /// </summary>
 /// <param name="message">Reference to the incoming message. Some fields may not have values since they get populated later in the processing pipeline.</param>
 protected override void NotifyMessageProcessingStarted(IncomingMessage message)
 {
     Logger.LogBeforeNotificationHandler(nameof(MessagingNotification.NotifyErrorMessageReceivedStarting), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
     MessagingNotification.NotifyErrorMessageReceivedStarting(message);
     Logger.LogAfterNotificationHandler(nameof(MessagingNotification.NotifyErrorMessageReceivedStarting), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
 }
 /// <summary>
 /// Called to process message
 /// </summary>
 /// <param name="rawMessage">The message from the queue</param>
 /// <param name="message">The refined message data. All information should now be present</param>
 protected override void NotifyMessageProcessingReady(IMessagingMessage rawMessage, IncomingMessage message)
 {
     Logger.LogDebug("NotifyMessageProcessingReady");
     MessagingNotification.NotifySynchronousMessageReceived(message);
 }
 /// <summary>
 /// Called when message processing is complete
 /// </summary>
 /// <param name="message">Reference to the incoming message</param>
 protected override void NotifyMessageProcessingCompleted(IncomingMessage message)
 {
     MessagingNotification.NotifySynchronousMessageReceivedCompleted(message);
 }
        private async Task <IncomingMessage> HandleRawMessage(IMessagingMessage message, bool alwaysRemoveMessage)
        {
            if (message == null)
            {
                return(null);
            }
            Stream bodyStream = null;

            try
            {
                var incomingMessage = new IncomingMessage()
                {
                    MessageFunction = message.MessageFunction,
                    FromHerId       = message.FromHerId,
                    ToHerId         = message.ToHerId,
                    MessageId       = message.MessageId,
                    CorrelationId   = message.CorrelationId,
                    EnqueuedTimeUtc = message.EnqueuedTimeUtc,
                    RenewLock       = message.RenewLock,
                    DeliveryCount   = message.DeliveryCount
                };
                NotifyMessageProcessingStarted(incomingMessage);
                Logger.LogStartReceive(QueueType, incomingMessage);

                // we cannot dispose of the stream before we have potentially cloned the message for error use
                bodyStream = message.GetBody();

                ValidateMessageHeader(message);
                // we need the certificates for decryption and certificate use
                incomingMessage.CollaborationAgreement = await ResolveProfile(message).ConfigureAwait(false);

                var payload = HandlePayload(message, bodyStream, message.ContentType, incomingMessage, out bool contentWasSigned);
                incomingMessage.ContentWasSigned = contentWasSigned;
                if (payload != null)
                {
                    if (Core.LogPayload)
                    {
                        Logger.LogDebug(payload.ToString());
                    }
                    incomingMessage.Payload = payload;
                }
                NotifyMessageProcessingReady(message, incomingMessage);
                ServiceBusCore.RemoveProcessedMessageFromQueue(message);
                Logger.LogRemoveMessageFromQueueNormal(message, QueueName);
                NotifyMessageProcessingCompleted(incomingMessage);
                Logger.LogEndReceive(QueueType, incomingMessage);
                return(incomingMessage);
            }
            catch (SecurityException ex)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.RemoteCertificate, message, "transport:invalid-certificate", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (HeaderValidationException ex)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.MissingField, message, "transport:invalid-field-value", ex.Message, ex.Fields);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (XmlSchemaValidationException ex) // reportable error from message handler (application)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.NotXml, message, "transport:not-well-formed-xml", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (ReceivedDataMismatchException ex) // reportable error from message handler (application)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.DataMismatch, message, "transport:invalid-field-value", ex.Message, new[] { ex.ExpectedValue, ex.ReceivedValue }, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (NotifySenderException ex) // reportable error from message handler (application)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.ApplicationReported, message, "transport:internal-error", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (SenderHerIdMismatchException ex) // reportable error from message handler (application)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.DataMismatch, message, "abuse:spoofing-attack", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (PayloadDeserializationException ex) // from parsing to XML, reportable exception
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.ApplicationReported, message, "transport:not-well-formed-xml", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (AggregateException ex) when(ex.InnerException is MessagingException && ((MessagingException)ex.InnerException).EventId.Id == EventIds.Send.Id)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.ApplicationReported, message, "transport:invalid-field-value", "Invalid value in field: 'ReplyTo'", null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (UnsupportedMessageException ex)  // reportable error from message handler (application)
            {
                Core.ReportErrorToExternalSender(Logger, EventIds.ApplicationReported, message, "transport:unsupported-message", ex.Message, null, ex);
                MessagingNotification.NotifyHandledException(message, ex);
            }
            catch (Exception ex) // unknown error
            {
                message.AddDetailsToException(ex);
                Logger.LogError(EventIds.UnknownError, null, $"Message processing failed. Keeping lock until it times out and we can try again. Message expires at UTC {message.ExpiresAtUtc}");
                Logger.LogException("Unknown error", ex);
                // if something unknown goes wrong, we want to retry the message after a delay
                // we don't call Complete() or Abandon() since that will cause the message to be availble again
                // chances are that the failure may still be around
                // the Defer() method requires us to store the sequence id, but we don't have a place to store it
                // the option then is to let the lock time-out. This will happen after a couple of minutes and the
                // message becomes available again. 10 retries = 10 timeouts before it gets added to DLQ

                if (alwaysRemoveMessage)
                {
                    ServiceBusCore.RemoveMessageFromQueueAfterError(Logger, message);
                }
                MessagingNotification.NotifyUnhandledException(message, ex);
            }
            finally
            {
                bodyStream?.Dispose();
                message.Dispose();
            }
            return(null);
        }
 /// <summary>
 /// Called to process message
 /// </summary>
 /// <param name="rawMessage">The message from the queue</param>
 /// <param name="message">The refined message data. All information should now be present</param>
 protected override void NotifyMessageProcessingReady(IMessagingMessage rawMessage, IncomingMessage message)
 {
     MessagingNotification.NotifyAsynchronousMessageReceived(message);
 }
 /// <summary>
 /// Called prior to message processing
 /// </summary>
 /// <param name="message">Reference to the incoming message. Some fields may not have values since they get populated later in the processing pipeline.</param>
 protected override void NotifyMessageProcessingStarted(IncomingMessage message)
 {
     MessagingNotification.NotifyAsynchronousMessageReceivedStarting(message);
 }
Beispiel #9
0
 /// <summary>
 /// Called to process message
 /// </summary>
 /// <param name="rawMessage">The message from the queue</param>
 /// <param name="message">The refined message data. All information should now be present</param>
 protected override void NotifyMessageProcessingReady(IMessagingMessage rawMessage, IncomingMessage message)
 {
     Logger.LogBeforeNotificationHandler(nameof(MessagingNotification.NotifySynchronousMessageReceived), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
     MessagingNotification.NotifySynchronousMessageReceived(message);
     Logger.LogAfterNotificationHandler(nameof(MessagingNotification.NotifySynchronousMessageReceived), message.MessageFunction, message.FromHerId, message.ToHerId, message.MessageId);
 }