Example #1
0
        private async Task PushNotifyInboxMessageGoogleAsync(InboxEntity inbox)
        {
            if (!string.IsNullOrEmpty(inbox.GoogleCloudMessagingRegistrationId))
            {
                var notifications = new GooglePushNotifications(this.HttpClient, ConfigurationManager.AppSettings["GoogleApiKey"], inbox.GoogleCloudMessagingRegistrationId);

                bool invalidChannel = false;
                try
                {
                    bool successfulPush = await notifications.PushGoogleRawNotificationAsync(CancellationToken.None);

                    invalidChannel |= !successfulPush;
                }
                catch (HttpRequestException)
                {
                    invalidChannel = true;
                }

                if (invalidChannel)
                {
                    inbox.GoogleCloudMessagingRegistrationId = null;
                    this.InboxTable.UpdateObject(inbox);
                }
            }
        }
Example #2
0
        private async Task PushNotifyInboxMessageWinPhoneAsync(InboxEntity inbox)
        {
            if (!string.IsNullOrEmpty(inbox.WinPhone8PushChannelUri))
            {
                var notifications = new WinPhonePushNotifications(this.HttpClient, new Uri(inbox.WinPhone8PushChannelUri));

                int count = await this.RetrieveInboxItemsCountAsync(inbox.RowKey);

                bool invalidChannel = false;
                try
                {
                    var         pushTile  = notifications.PushWinPhoneTileAsync(inbox.WinPhone8TileTemplate, count: count);
                    Task <bool> pushToast = Task.FromResult(false);
                    if (!string.IsNullOrEmpty(inbox.WinPhone8ToastText1) || !string.IsNullOrEmpty(inbox.WinPhone8ToastText2))
                    {
                        var line1 = string.Format(CultureInfo.InvariantCulture, inbox.WinPhone8ToastText1 ?? string.Empty, count);
                        var line2 = string.Format(CultureInfo.InvariantCulture, inbox.WinPhone8ToastText2 ?? string.Empty, count);
                        if (inbox.LastWinPhone8PushNotificationUtc.HasValue && inbox.LastAuthenticatedInteractionUtc.HasValue && inbox.LastWinPhone8PushNotificationUtc.Value > inbox.LastAuthenticatedInteractionUtc.Value)
                        {
                            // We've sent a toast notification more recently than the user has checked messages,
                            // so there's no reason to send another for now.
                            pushToast = Task.FromResult(true);
                        }
                        else
                        {
                            pushToast = notifications.PushWinPhoneToastAsync(line1, line2);
                        }
                    }

                    Task <bool> pushRaw = Task.FromResult(false);
                    if (!string.IsNullOrEmpty(inbox.WinPhone8PushChannelContent))
                    {
                        pushRaw = notifications.PushWinPhoneRawNotificationAsync(inbox.WinPhone8PushChannelContent);
                    }

                    await Task.WhenAll(pushTile, pushToast, pushRaw);

                    invalidChannel |= !(pushTile.Result || pushToast.Result || pushRaw.Result);
                }
                catch (HttpRequestException)
                {
                    invalidChannel = true;
                }

                if (invalidChannel)
                {
                    inbox.WinPhone8PushChannelUri     = null;
                    inbox.WinPhone8PushChannelContent = null;
                    inbox.WinPhone8ToastText1         = null;
                    inbox.WinPhone8ToastText2         = null;
                }
                else
                {
                    inbox.LastWinPhone8PushNotificationUtc = DateTime.UtcNow;
                }

                this.InboxTable.UpdateObject(inbox);
            }
        }
Example #3
0
        private async Task PushNotifyInboxMessageAsync(InboxEntity inbox)
        {
            Requires.NotNull(inbox, "inbox");

            await Task.WhenAll(
                this.PushNotifyInboxMessageWinStoreAsync(inbox),
                this.PushNotifyInboxMessageWinPhoneAsync(inbox));
        }
Example #4
0
        private async Task PushNotifyInboxMessageWinStoreAsync(InboxEntity inbox, int failedAttempts = 0)
        {
            if (string.IsNullOrEmpty(inbox.ClientPackageSecurityIdentifier) || string.IsNullOrEmpty(inbox.PushChannelUri))
            {
                return;
            }

            var client = await this.ClientTable.GetAsync(inbox.ClientPackageSecurityIdentifier);

            string bearerToken       = client.AccessToken;
            var    pushNotifyRequest = new HttpRequestMessage(HttpMethod.Post, inbox.PushChannelUri);

            pushNotifyRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
            pushNotifyRequest.Headers.Add("X-WNS-Type", "wns/raw");
            pushNotifyRequest.Content = new StringContent(inbox.PushChannelContent ?? string.Empty);

            // yes, it's a string, but we must claim it's an octet-stream
            pushNotifyRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            var response = await this.HttpClient.SendAsync(pushNotifyRequest);

            if (response.IsSuccessStatusCode)
            {
                inbox.LastWindows8PushNotificationUtc = DateTime.UtcNow;
                this.InboxTable.UpdateObject(inbox);
            }
            else
            {
                if (failedAttempts == 0)
                {
                    var authHeader = response.Headers.WwwAuthenticate.FirstOrDefault();
                    if (authHeader != null)
                    {
                        if (authHeader.Parameter.Contains("Token expired"))
                        {
                            await client.AcquireWnsPushBearerTokenAsync(this.HttpClient);

                            this.ClientTable.UpdateObject(client);
                            await this.ClientTable.SaveChangesAsync();

                            await this.PushNotifyInboxMessageWinStoreAsync(inbox, failedAttempts + 1);

                            return;
                        }
                    }
                }

                // Log a failure.
                // TODO: code here.
            }
        }
Example #5
0
        private async Task PushNotifyInboxMessageAppleAsync(InboxEntity inbox)
        {
            if (MvcApplication.IsApplePushRegistered)
            {
                if (!string.IsNullOrEmpty(inbox.ApplePushNotificationGatewayDeviceToken))
                {
                    int count = await this.RetrieveInboxItemsCountAsync(inbox.RowKey);

                    MvcApplication.PushBroker.QueueNotification(new AppleNotification()
                                                                .ForDeviceToken(inbox.ApplePushNotificationGatewayDeviceToken)
                                                                .WithBadge(count));
                }
            }
        }
Example #6
0
        public async Task <ActionResult> PostNotificationAsync(string id, int lifetime)
        {
            Requires.NotNullOrEmpty(id, "id");
            Requires.Range(lifetime > 0, "lifetime");

            if (this.Request.ContentLength > MaxNotificationSize)
            {
                throw new ArgumentException("Maximum message notification size exceeded.");
            }

            InboxEntity inbox = await this.GetInboxAsync(id);

            if (inbox == null)
            {
                return(new HttpNotFoundResult());
            }

            var directory = this.InboxContainer.GetDirectoryReference(id);
            var blob      = directory.GetBlockBlobReference(Utilities.CreateRandomWebSafeName(24));

            Debug.WriteLine("Defining blob: {0} ({1})", blob.Name, blob.Uri);

            var requestedLifeSpan = TimeSpan.FromMinutes(lifetime);
            var actualLifespan    = requestedLifeSpan > MaxLifetimeCeiling ? MaxLifetimeCeiling : requestedLifeSpan;
            var expirationDate    = DateTime.UtcNow + actualLifespan;

            blob.Metadata[ExpirationDateMetadataKey] = expirationDate.ToString(CultureInfo.InvariantCulture);

            await blob.UploadFromStreamAsync(this.Request.InputStream);

            // One more last ditch check that the max size was not exceeded, in case
            // the client is lying in the HTTP headers.
            if (blob.Properties.Length > MaxNotificationSize)
            {
                await blob.DeleteAsync();

                throw new ArgumentException("Maximum message notification size exceeded.");
            }

            // Notifying the receiver isn't something the sender needs to wait for.
            var nowait = Task.Run(async delegate
            {
                await this.AlertLongPollWaiterAsync(inbox);
                await this.InboxTable.SaveChangesWithMergeAsync(inbox);
            });

            return(new HttpStatusCodeResult(HttpStatusCode.Created));
        }
Example #7
0
        public async Task <JsonResult> CreateAsync()
        {
            var inbox = InboxEntity.Create();

            this.InboxTable.AddObject(inbox);
            await this.InboxTable.SaveChangesWithMergeAsync(inbox);

            string messageReceivingEndpoint = this.GetAbsoluteUrlForAction("Slot", new { id = inbox.RowKey }).AbsoluteUri;
            var    result = new InboxCreationResponse {
                MessageReceivingEndpoint = messageReceivingEndpoint,
                InboxOwnerCode           = inbox.InboxOwnerCode,
            };

            return(new JsonResult {
                Data = result
            });
        }
Example #8
0
        private async Task AlertLongPollWaiterAsync(InboxEntity inbox)
        {
            Requires.NotNull(inbox, "inbox");

            await this.PushNotifyInboxMessageAsync(inbox);

            var id = inbox.RowKey;
            TaskCompletionSource <object> tcs;

            lock (LongPollWaiters) {
                if (LongPollWaiters.TryGetValue(id, out tcs))
                {
                    LongPollWaiters.Remove(id);
                }
            }

            if (tcs != null)
            {
                tcs.TrySetResult(null);
            }
        }