void HandleStatus(WindowsNotificationStatus status) { if (MessageResponseReceived == null) { return; } //RESPONSE HEADERS // X-WNS-Debug-Trace string // X-WNS-DeviceConnectionStatus connected | disconnected | tempdisconnected (if RequestForStatus was set to true) // X-WNS-Error-Description string // X-WNS-Msg-ID string (max 16 char) // X-WNS-NotificationStatus received | dropped | channelthrottled // // 200 OK // 400 One or more headers were specified incorrectly or conflict with another header. // 401 The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. // 403 The cloud service is not authorized to send a notification to this URI even though they are authenticated. // 404 The channel URI is not valid or is not recognized by WNS. - Raise Expiry // 405 Invalid Method - never will get // 406 The cloud service exceeded its throttle limit. // 410 The channel expired. - Raise Expiry // 413 The notification payload exceeds the 5000 byte size limit. // 500 An internal failure caused notification delivery to fail. // 503 The server is currently unavailable. MessageResponseReceived(status); }
WindowsNotificationStatus ParseStatus(HttpWebResponse resp, WindowsNotification notification) { var result = new WindowsNotificationStatus() { HttpStatus = HttpStatusCode.OK }; try { if (resp != null) { result.Notification = notification; result.HttpStatus = resp.StatusCode; var wnsDebugTrace = resp.Headers["X-WNS-Debug-Trace"]; var wnsDeviceConnectionStatus = resp.Headers["X-WNS-DeviceConnectionStatus"] ?? "connected"; var wnsErrorDescription = resp.Headers["X-WNS-Error-Description"]; var wnsMsgId = resp.Headers["X-WNS-Msg-ID"]; var wnsNotificationStatus = resp.Headers["X-WNS-NotificationStatus"] ?? ""; result.DebugTrace = wnsDebugTrace; result.ErrorDescription = wnsErrorDescription; result.MessageID = wnsMsgId; if (wnsNotificationStatus.Equals("received", StringComparison.InvariantCultureIgnoreCase)) { result.NotificationStatus = WindowsNotificationSendStatus.Received; } else if (wnsNotificationStatus.Equals("dropped", StringComparison.InvariantCultureIgnoreCase)) { result.NotificationStatus = WindowsNotificationSendStatus.Dropped; } else { result.NotificationStatus = WindowsNotificationSendStatus.ChannelThrottled; } if (wnsDeviceConnectionStatus.Equals("connected", StringComparison.InvariantCultureIgnoreCase)) { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Connected; } else if (wnsDeviceConnectionStatus.Equals("tempdisconnected", StringComparison.InvariantCultureIgnoreCase)) { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.TempDisconnected; } else { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Disconnected; } } } catch (Exception ex) { Log.Error("Error parsing notification status: {0}", ex.ToString()); } return(result); }
void HandleStatus(WindowsNotificationStatus status, SendNotificationCallbackDelegate callback) { Boolean shouldRequeue = false; if (callback == null) { return; } //RESPONSE HEADERS // X-WNS-Debug-Trace string // X-WNS-DeviceConnectionStatus connected | disconnected | tempdisconnected (if RequestForStatus was set to true) // X-WNS-Error-Description string // X-WNS-Msg-ID string (max 16 char) // X-WNS-NotificationStatus received | dropped | channelthrottled // // 200 OK // 400 One or more headers were specified incorrectly or conflict with another header. // 401 The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. // 403 The cloud service is not authorized to send a notification to this URI even though they are authenticated. // 404 The channel URI is not valid or is not recognized by WNS. - Raise Expiry // 405 Invalid Method - never will get // 406 The cloud service exceeded its throttle limit. // 410 The channel expired. - Raise Expiry // 413 The notification payload exceeds the 5000 byte size limit. // 500 An internal failure caused notification delivery to fail. // 503 The server is currently unavailable. if (status.HttpStatus == HttpStatusCode.OK && status.NotificationStatus == WindowsNotificationSendStatus.Received) { callback(this, new SendNotificationResult(status.Notification)); return; } if (status.HttpStatus == HttpStatusCode.Unauthorized) { Trace.WriteLine("Status no autorizado, reencolando"); shouldRequeue = true; } if (status.HttpStatus == HttpStatusCode.NotFound || status.HttpStatus == HttpStatusCode.Gone) //404 or 410 { callback(this, new SendNotificationResult(status.Notification, false, new Exception("Device Subscription Expired")) { IsSubscriptionExpired = true, OldSubscriptionId = status.Notification.ChannelUri, SubscriptionExpiryUtc = DateTime.UtcNow }); return; } callback(this, new SendNotificationResult(status.Notification, shouldRequeue, new WindowsNotificationSendFailureException(status))); }
WindowsNotificationStatus ParseStatus(HttpWebResponse resp, WindowsNotification notification) { var result = new WindowsNotificationStatus(); result.Notification = notification; result.HttpStatus = resp.StatusCode; var wnsDebugTrace = resp.Headers["X-WNS-Debug-Trace"]; var wnsDeviceConnectionStatus = resp.Headers["X-WNS-DeviceConnectionStatus"] ?? "connected"; var wnsErrorDescription = resp.Headers["X-WNS-Error-Description"]; var wnsMsgId = resp.Headers["X-WNS-Msg-ID"]; var wnsNotificationStatus = resp.Headers["X-WNS-NotificationStatus"] ?? ""; var wnsAuthenticate = resp.Headers["WWW-Authenticate"]; result.DebugTrace = wnsDebugTrace; result.ErrorDescription = wnsErrorDescription; result.MessageID = wnsMsgId; if (wnsNotificationStatus.Equals("received", StringComparison.InvariantCultureIgnoreCase)) { result.NotificationStatus = WindowsNotificationSendStatus.Received; } else if (wnsNotificationStatus.Equals("dropped", StringComparison.InvariantCultureIgnoreCase)) { result.NotificationStatus = WindowsNotificationSendStatus.Dropped; } else if (wnsAuthenticate != null && wnsAuthenticate.Contains("Token expired")) { result.NotificationStatus = WindowsNotificationSendStatus.TokenExpired; } else { result.NotificationStatus = WindowsNotificationSendStatus.ChannelThrottled; } if (wnsDeviceConnectionStatus.Equals("connected", StringComparison.InvariantCultureIgnoreCase)) { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Connected; } else if (wnsDeviceConnectionStatus.Equals("tempdisconnected", StringComparison.InvariantCultureIgnoreCase)) { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.TempDisconnected; } else { result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Disconnected; } return(result); }
void transport_MessageResponseReceived(WindowsNotificationStatus status) { if (status.HttpStatus == HttpStatusCode.OK && status.NotificationStatus == WindowsNotificationSendStatus.Received) { //It worked! Raise success this.Events.RaiseNotificationSent(status.Notification); } else if (status.NotificationStatus == WindowsNotificationSendStatus.TokenExpired) { // If token expired sendind a notification, requeue it again this.QueueNotification(status.Notification); } else { // Something happened this.Events.RaiseNotificationSendFailure(status.Notification, new Exception(status.ErrorDescription)); } Interlocked.Decrement(ref PendingNotificationsResult); Interlocked.Decrement(ref waitCounter); }
void HandleStatus(WindowsNotificationStatus status) { //RESPONSE HEADERS // X-WNS-Debug-Trace string // X-WNS-DeviceConnectionStatus connected | disconnected | tempdisconnected (if RequestForStatus was set to true) // X-WNS-Error-Description string // X-WNS-Msg-ID string (max 16 char) // X-WNS-NotificationStatus received | dropped | channelthrottled // // 200 OK // 400 One or more headers were specified incorrectly or conflict with another header. // 401 The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. // 403 The cloud service is not authorized to send a notification to this URI even though they are authenticated. // 404 The channel URI is not valid or is not recognized by WNS. - Raise Expiry // 405 Invalid Method - never will get // 406 The cloud service exceeded its throttle limit. // 410 The channel expired. - Raise Expiry // 413 The notification payload exceeds the 5000 byte size limit. // 500 An internal failure caused notification delivery to fail. // 503 The server is currently unavailable. if (status.HttpStatus == HttpStatusCode.OK && status.NotificationStatus == WindowsNotificationSendStatus.Received) { this.Events.RaiseNotificationSent(status.Notification); return; } else if (status.HttpStatus == HttpStatusCode.NotFound) //404 { this.Events.RaiseDeviceSubscriptionExpired(PlatformType.Windows, status.Notification.ChannelUri, status.Notification); } else if (status.HttpStatus == HttpStatusCode.Gone) //410 { this.Events.RaiseDeviceSubscriptionExpired(PlatformType.Windows, status.Notification.ChannelUri, status.Notification); } this.Events.RaiseNotificationSendFailure(status.Notification, new WindowsNotificationSendFailureException(status)); }
WindowsNotificationStatus ParseStatus(HttpWebResponse resp, WindowsNotification notification) { var result = new WindowsNotificationStatus(); result.Notification = notification; result.HttpStatus = resp.StatusCode; var wnsDebugTrace = resp.Headers["X-WNS-Debug-Trace"]; var wnsDeviceConnectionStatus = resp.Headers["X-WNS-DeviceConnectionStatus"] ?? "connected"; var wnsErrorDescription = resp.Headers["X-WNS-Error-Description"]; var wnsMsgId = resp.Headers["X-WNS-Msg-ID"]; var wnsNotificationStatus = resp.Headers["X-WNS-NotificationStatus"] ?? ""; result.DebugTrace = wnsDebugTrace; result.ErrorDescription = wnsErrorDescription; result.MessageID = wnsMsgId; if (wnsNotificationStatus.Equals("received", StringComparison.InvariantCultureIgnoreCase)) result.NotificationStatus = WindowsNotificationSendStatus.Received; else if (wnsNotificationStatus.Equals("dropped", StringComparison.InvariantCultureIgnoreCase)) result.NotificationStatus = WindowsNotificationSendStatus.Dropped; else result.NotificationStatus = WindowsNotificationSendStatus.ChannelThrottled; if (wnsDeviceConnectionStatus.Equals("connected", StringComparison.InvariantCultureIgnoreCase)) result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Connected; else if (wnsDeviceConnectionStatus.Equals("tempdisconnected", StringComparison.InvariantCultureIgnoreCase)) result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.TempDisconnected; else result.DeviceConnectionStatus = WindowsDeviceConnectionStatus.Disconnected; return result; }
public WindowsNotificationSendFailureException(WindowsNotificationStatus status) : base() { this.NotificationStatus = status; }
public void SendNotification(INotification notification, SendNotificationCallbackDelegate callback) { //See if we need an access token if (string.IsNullOrEmpty(AccessToken)) { Trace.WriteLine("AccessToken nulo, renovando"); RenewAccessToken(); } if (DateTime.Now > ExpiresIn) { Trace.WriteLine("AccessToken expirado, renovando"); RenewAccessToken(); } var winNotification = notification as WindowsNotification; //https://cloud.notify.windows.com/?token=..... //Authorization: Bearer {AccessToken} // var wnsType = string.Empty; switch (winNotification.Type) { case WindowsNotificationType.Tile: wnsType = "wns/tile"; break; case WindowsNotificationType.Badge: wnsType = "wns/badge"; break; case WindowsNotificationType.DeleteNotification: case WindowsNotificationType.Toast: wnsType = "wns/toast"; break; default: wnsType = "wns/raw"; break; } var request = (HttpWebRequest)HttpWebRequest.Create(winNotification.ChannelUri); // "https://notify.windows.com"); if (winNotification.Type == WindowsNotificationType.DeleteNotification) { request.Method = "DELETE"; } else { request.Method = "POST"; } request.Headers.Add("X-WNS-Type", wnsType); request.Headers.Add("Authorization", string.Format("Bearer {0}", this.AccessToken)); request.ContentType = "text/xml"; if (winNotification.Type == WindowsNotificationType.Raw) { request.ContentType = "application/octet-stream"; } if (winNotification.Type == WindowsNotificationType.Tile) { var winTileNot = winNotification as WindowsTileNotification; if (winTileNot != null && winTileNot.CachePolicy.HasValue) { request.Headers.Add("X-WNS-Cache-Policy", winTileNot.CachePolicy == WindowsNotificationCachePolicyType.Cache ? "cache" : "no-cache"); } } else if (winNotification.Type == WindowsNotificationType.Badge) { if (winNotification is WindowsBadgeNumericNotification) { var winTileBadge = winNotification as WindowsBadgeNumericNotification; if (winTileBadge != null && winTileBadge.CachePolicy.HasValue) { request.Headers.Add("X-WNS-Cache-Policy", winTileBadge.CachePolicy == WindowsNotificationCachePolicyType.Cache ? "cache" : "no-cache"); } } else if (winNotification is WindowsBadgeGlyphNotification) { var winTileBadge = winNotification as WindowsBadgeGlyphNotification; if (winTileBadge != null && winTileBadge.CachePolicy.HasValue) { request.Headers.Add("X-WNS-Cache-Policy", winTileBadge.CachePolicy == WindowsNotificationCachePolicyType.Cache ? "cache" : "no-cache"); } } } else if (winNotification.Type == WindowsNotificationType.Toast) { var winToastPopup = winNotification as WindowsToastNotification;; if (winToastPopup != null && winToastPopup.SuppressPopup) { request.Headers.Add("X-WNS-SuppressPopup", "true"); } } else if (winNotification.Type == WindowsNotificationType.DeleteNotification) { var deleteArgs = "type=wns/toast"; if (!string.IsNullOrEmpty(winNotification.NotificationTag)) { deleteArgs += string.Format(";tag={0}", winNotification.NotificationTag); } if (!string.IsNullOrEmpty(winNotification.NotificationGroup)) { deleteArgs += string.Format(";group={0}", winNotification.NotificationGroup); } request.Headers.Add("X-WNS-Match", deleteArgs); } if (winNotification.RequestForStatus.HasValue) { request.Headers.Add("X-WNS-RequestForStatus", winNotification.RequestForStatus.Value.ToString().ToLower()); } if (!string.IsNullOrEmpty(winNotification.NotificationTag)) { request.Headers.Add("X-WNS-Tag", winNotification.NotificationTag); } if (!string.IsNullOrEmpty(winNotification.NotificationGroup)) { request.Headers.Add("X-WNS-Group", winNotification.NotificationGroup); } if (winNotification.TimeToLive.HasValue) { request.Headers.Add("X-WNS-TTL", winNotification.TimeToLive.Value.ToString()); //Time to live in seconds } //Microsoft recommends we disable expect-100 to improve latency request.ServicePoint.Expect100Continue = false; var payload = winNotification.PayloadToString(); var data = Encoding.UTF8.GetBytes(payload); request.ContentLength = data.Length; using (var rs = request.GetRequestStream()) rs.Write(data, 0, data.Length); try { request.BeginGetResponse(new AsyncCallback(getResponseCallback), new object[] { request, winNotification, callback }); } catch (WebException wex) { WindowsNotificationStatus status = null; try { //Handle different httpstatuses status = ParseStatus(wex.Response as HttpWebResponse, winNotification); HandleStatus(status, callback); } catch (Exception ex) { Log.Error(ex.Message, ex); HandleStatus(new WindowsNotificationStatus() { HttpStatus = HttpStatusCode.RequestTimeout, DeviceConnectionStatus = WindowsDeviceConnectionStatus.Connected, MessageID = "", Notification = winNotification, NotificationStatus = WindowsNotificationSendStatus.Dropped, }, callback); } } }
void HandleStatus(WindowsNotificationStatus status, SendNotificationCallbackDelegate callback) { if (callback == null) return; //RESPONSE HEADERS // X-WNS-Debug-Trace string // X-WNS-DeviceConnectionStatus connected | disconnected | tempdisconnected (if RequestForStatus was set to true) // X-WNS-Error-Description string // X-WNS-Msg-ID string (max 16 char) // X-WNS-NotificationStatus received | dropped | channelthrottled // // 200 OK // 400 One or more headers were specified incorrectly or conflict with another header. // 401 The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. // 403 The cloud service is not authorized to send a notification to this URI even though they are authenticated. // 404 The channel URI is not valid or is not recognized by WNS. - Raise Expiry // 405 Invalid Method - never will get // 406 The cloud service exceeded its throttle limit. // 410 The channel expired. - Raise Expiry // 413 The notification payload exceeds the 5000 byte size limit. // 500 An internal failure caused notification delivery to fail. // 503 The server is currently unavailable. if (status.HttpStatus == HttpStatusCode.OK && status.NotificationStatus == WindowsNotificationSendStatus.Received) { callback(this, new SendNotificationResult(status.Notification)); return; } if (status.HttpStatus == HttpStatusCode.NotFound || status.HttpStatus == HttpStatusCode.Gone) //404 or 410 { callback(this, new SendNotificationResult(status.Notification, false, new Exception("Device Subscription Expired")) { IsSubscriptionExpired = true, OldSubscriptionId = status.Notification.ChannelUri, SubscriptionExpiryUtc = DateTime.UtcNow }); return; } callback(this, new SendNotificationResult(status.Notification, false, new WindowsNotificationSendFailureException(status))); }