private void ProcessPublishResponse(
ResponseHeader responseHeader,
uint subscriptionId,
UInt32Collection availableSequenceNumbers,
bool moreNotifications,
NotificationMessage notificationMessage)
{
Subscription subscription = null;
// send notification that the server is alive.
OnKeepAlive(m_serverState, responseHeader.Timestamp);
// collect the current set if acknowledgements.
lock (SyncRoot)
{
// clear out acknowledgements for messages that the server does not have any more.
SubscriptionAcknowledgementCollection acknowledgementsToSend = new SubscriptionAcknowledgementCollection();
for (int ii = 0; ii < m_acknowledgementsToSend.Count; ii++)
{
SubscriptionAcknowledgement acknowledgement = m_acknowledgementsToSend[ii];
if (acknowledgement.SubscriptionId != subscriptionId)
{
acknowledgementsToSend.Add(acknowledgement);
}
else
{
if (availableSequenceNumbers == null || availableSequenceNumbers.Contains(acknowledgement.SequenceNumber))
{
acknowledgementsToSend.Add(acknowledgement);
}
}
}
// create an acknowledgement to be sent back to the server.
if (notificationMessage.NotificationData.Count > 0)
{
SubscriptionAcknowledgement acknowledgement = new SubscriptionAcknowledgement();
acknowledgement.SubscriptionId = subscriptionId;
acknowledgement.SequenceNumber = notificationMessage.SequenceNumber;
acknowledgementsToSend.Add(acknowledgement);
}
uint lastSentSequenceNumber = 0;
if (availableSequenceNumbers != null)
{
foreach (uint availableSequenceNumber in availableSequenceNumbers)
{
if (m_latestAcknowledgementsSent.ContainsKey(subscriptionId))
{
lastSentSequenceNumber = m_latestAcknowledgementsSent[subscriptionId];
// If the last sent sequence number is uint.Max do not display the warning; the counter rolled over
// If the last sent sequence number is greater or equal to the available sequence number (returned by the publish), a warning must be logged.
if (((lastSentSequenceNumber >= availableSequenceNumber) && (lastSentSequenceNumber != uint.MaxValue)) || (lastSentSequenceNumber == availableSequenceNumber) && (lastSentSequenceNumber == uint.MaxValue))
{
Utils.Trace("Received sequence number which was already acknowledged={0}", availableSequenceNumber);
}
}
}
}
if (m_latestAcknowledgementsSent.ContainsKey(subscriptionId))
{
lastSentSequenceNumber = m_latestAcknowledgementsSent[subscriptionId];
// If the last sent sequence number is uint.Max do not display the warning; the counter rolled over
// If the last sent sequence number is greater or equal to the notificationMessage's sequence number (returned by the publish), a warning must be logged.
if (((lastSentSequenceNumber >= notificationMessage.SequenceNumber) && (lastSentSequenceNumber != uint.MaxValue)) || (lastSentSequenceNumber == notificationMessage.SequenceNumber) && (lastSentSequenceNumber == uint.MaxValue))
{
Utils.Trace("Received sequence number which was already acknowledged={0}", notificationMessage.SequenceNumber);
}
}
if (availableSequenceNumbers != null)
{
foreach (var acknowledgement in acknowledgementsToSend)
{
if (acknowledgement.SubscriptionId == subscriptionId && !availableSequenceNumbers.Contains(acknowledgement.SequenceNumber))
{
Utils.Trace("Sequence number={0} was not received in the available sequence numbers.", acknowledgement.SequenceNumber);
}
}
}
m_acknowledgementsToSend = acknowledgementsToSend;
if (notificationMessage.IsEmpty)
{
Utils.Trace("Empty notification message received for SessionId {0} with PublishTime {1}", SessionId, notificationMessage.PublishTime.ToLocalTime());
}
// find the subscription.
foreach (Subscription current in m_subscriptions)
{
if (current.Id == subscriptionId)
{
subscription = current;
break;
}
}
}
// ignore messages with a subscription that has been deleted.
if (subscription != null)
{
// Validate publish time and reject old values.
if (notificationMessage.PublishTime.AddMilliseconds(subscription.CurrentPublishingInterval * subscription.CurrentLifetimeCount) < DateTime.UtcNow)
{
Utils.Trace("PublishTime {0} in publish response is too old for SubscriptionId {1}.", notificationMessage.PublishTime.ToLocalTime(), subscription.Id);
}
// Validate publish time and reject old values.
if (notificationMessage.PublishTime > DateTime.UtcNow.AddMilliseconds(subscription.CurrentPublishingInterval * subscription.CurrentLifetimeCount))
{
Utils.Trace("PublishTime {0} in publish response is newer than actual time for SubscriptionId {1}.", notificationMessage.PublishTime.ToLocalTime(), subscription.Id);
}
// update subscription cache.
subscription.SaveMessageInCache(
availableSequenceNumbers,
notificationMessage,
responseHeader.StringTable);
// raise the notification.
lock (m_eventLock)
{
NotificationEventArgs args = new NotificationEventArgs(subscription, notificationMessage, responseHeader.StringTable);
if (m_Publish != null)
{
ThreadPool.QueueUserWorkItem(OnRaisePublishNotification, args);
}
}
}
else
{
Utils.Trace("Received Publish Response for Unknown SubscriptionId={0}", subscriptionId);
}
}