private void HandleFailedNotification(int identifier, byte status) { int failedNotificationIndex = -1; SentNotification failedNotification = null; //Try and find the failed notification in our sent list for (int i = 0; i < sentNotifications.Count; i++) { var n = sentNotifications[i]; if (n.Identifier.Equals(identifier)) { failedNotificationIndex = i; failedNotification = n; break; } } //Don't bother doing anything unless we know what failed if (failedNotification != null && failedNotificationIndex > -1) { Interlocked.Decrement(ref PendingNotificationsResult); //Anything before the failed message must have sent OK // so let's expedite the success status Success for all those before the failed one if (failedNotificationIndex > 0) { for (int i = 0; i < failedNotificationIndex; i++) { this.Events.RaiseNotificationSent(sentNotifications[i].Notification); } } //The notification that failed needs to have a failure event raised // we don't requeue it because apple told us it failed for real this.Events.RaiseNotificationSendFailure(failedNotification.Notification, new NotificationFailureException(status, failedNotification.Notification)); // finally, raise failure for anything after the index of this failed one // in the sent list, since we may have sent them but apple will have disregarded // anything after the failed one and not told us about it if (failedNotificationIndex < sentNotifications.Count - 1) { //Requeue the failed notification since we're not sure it's a bad // notification, just that it was sent after a bad one was for (int i = failedNotificationIndex + 1; i <= sentNotifications.Count - 1; i++) { Interlocked.Decrement(ref PendingNotificationsResult); this.QueueNotification(sentNotifications[i].Notification, false); } } //Now clear out the sent list since we processed them all manually above sentNotifications.Clear(); } }
private void HandleFailedNotification(int identifier, byte status) { int index = this.sentNotifications.FindIndex((Predicate <SentNotification>)(n => n.Identifier == identifier)); if (index < 0) { return; } Log.Info("Failed Notification: {0}", (object)identifier); if (index > 0) { this.sentNotifications.GetRange(0, index).ForEach((Action <SentNotification>)(n => { Interlocked.Decrement(ref this.trackedNotificationCount); if (n.Callback == null) { return; } n.Callback((object)this, new SendNotificationResult((INotification)n.Notification, false, (Exception)null)); })); this.sentNotifications.RemoveRange(0, index); } SentNotification failedNotification = this.sentNotifications[0]; Interlocked.Decrement(ref this.trackedNotificationCount); if (failedNotification.Callback != null) { failedNotification.Callback((object)this, new SendNotificationResult((INotification)failedNotification.Notification, false, (Exception) new NotificationFailureException((int)status, failedNotification.Notification))); } this.sentNotifications.RemoveAt(0); this.sentNotifications.Reverse(); this.sentNotifications.ForEach((Action <SentNotification>)(n => { Interlocked.Decrement(ref this.trackedNotificationCount); if (failedNotification.Callback == null) { return; } failedNotification.Callback((object)this, new SendNotificationResult((INotification)n.Notification, true, new Exception("Sent after previously failed Notification.")) { CountsAsRequeue = false }); })); this.sentNotifications.Clear(); }
void Reader() { try { var result = networkStream.BeginRead(readBuffer, 0, 6, new AsyncCallback((asyncResult) => { lock (sentLock) { try { var bytesRead = networkStream.EndRead(asyncResult); if (bytesRead > 0) { //We now expect apple to close the connection on us anyway, so let's try and close things // up here as well to get a head start //Hopefully this way we have less messages written to the stream that we have to requeue try { stream.Close(); stream.Dispose(); } catch { } try { client.Close(); stream.Dispose(); } catch { } //Get the enhanced format response // byte 0 is always '1', byte 1 is the status, bytes 2,3,4,5 are the identifier of the notification var status = readBuffer[1]; var identifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(readBuffer, 2)); int failedNotificationIndex = -1; SentNotification failedNotification = null; //Try and find the failed notification in our sent list for (int i = 0; i < sentNotifications.Count; i++) { var n = sentNotifications[i]; if (n.Identifier.Equals(identifier)) { failedNotificationIndex = i; failedNotification = n; break; } } //Don't bother doing anything unless we know what failed if (failedNotification != null && failedNotificationIndex > -1) { //Anything before the failed message must have sent OK // so let's expedite the success status Success for all those before the failed one if (failedNotificationIndex > 0) { for (int i = 0; i < failedNotificationIndex; i++) { this.Events.RaiseNotificationSent(sentNotifications[i].Notification); } } //The notification that failed needs to have a failure event raised // we don't requeue it because apple told us it failed for real this.Events.RaiseNotificationSendFailure(failedNotification.Notification, new NotificationFailureException(status, failedNotification.Notification)); // finally, raise failure for anything after the index of this failed one // in the sent list, since we may have sent them but apple will have disregarded // anything after the failed one and not told us about it if (failedNotificationIndex < sentNotifications.Count - 1) { //Requeue the failed notification since we're not sure it's a bad // notification, just that it was sent after a bad one was for (int i = failedNotificationIndex + 1; i <= sentNotifications.Count - 1; i++) { this.QueueNotification(sentNotifications[i].Notification, false); } } //Now clear out the sent list since we processed them all manually above sentNotifications.Clear(); } //Start reading again Reader(); } else { connected = false; } } catch { connected = false; } } // End Lock }), null); } catch { connected = false; } }
private void Cleanup() { int num = -1; try { num = Interlocked.CompareExchange(ref this.cleanupSync, 1, 0); if (num != 0) { return; } bool flag; do { lock (this.connectLock) { try { this.Connect(); } catch (Exception ex) { PushChannelExceptionDelegate onException = this.OnException; if (onException != null) { onException((object)this, ex); } } } flag = false; lock (this.sentLock) { if (this.sentNotifications.Count > 0) { if (this.connected) { SentNotification sentNotification = this.sentNotifications[0]; if (sentNotification.SentAt < DateTime.UtcNow.AddMilliseconds((double)(-1 * this.appleSettings.MillisecondsToWaitBeforeMessageDeclaredSuccess))) { flag = true; Interlocked.Decrement(ref this.trackedNotificationCount); if (sentNotification.Callback != null) { sentNotification.Callback((object)this, new SendNotificationResult((INotification)sentNotification.Notification, false, (Exception)null)); } this.sentNotifications.RemoveAt(0); Interlocked.Increment(ref this.cleanedUp); } else { flag = false; } } else { try { this.sentNotifications[0].SentAt = DateTime.UtcNow; } catch { } } } } }while (flag); } finally { if (num == 0) { this.cleanupSync = 0; } } }
public AbortedQueueContents(IEnumerable<SentNotification> completedItems, SentNotification failedNotification, IEnumerable<SentNotification> itemsIgnoredByApple) { this.ItemsIgnoredByApple = itemsIgnoredByApple; this.FailedNotification = failedNotification; this.CompletedItems = completedItems; }