Example #1
0
        public async Task <string> ServerPush(string message)
        {
            var response    = new StringBuilder();
            var pushMessage = new WP.PushMessage(message)
            {
                Topic   = "Debug",
                Urgency = WP.PushMessageUrgency.Normal
            };
            await _subscriptionStore.ForEachSubscriptionAsync(_applicationUser.Id, (subscription) => {
                _notificationService.SendNotificationAsync(subscription, pushMessage, "http://fergl.ie");
                response.Append($"Sent: {subscription.Endpoint}");
            });

            return(response.ToString());
        }
        public async Task <IActionResult> SendNotification([FromBody] PushMessageViewModel message)
        {
            _logger.LogInformation($"Sending targeted push for: {message.Target} - {message.Notification}");
            var pushMessage = new WP.PushMessage(message.Notification)
            {
                Topic   = message.Topic,
                Urgency = message.Urgency
            };

            // TODO: This should be scheduled in background
            await _subscriptionStore.ForEachSubscriptionAsync(message.Target, (WP.PushSubscription subscription) => {
                _logger.LogInformation($"Found subscription: {subscription}");
                _notificationService.SendNotificationAsync(subscription, pushMessage, message.Target);
            });

            return(NoContent());
        }
        private static HttpRequestMessage SetContent(HttpRequestMessage pushMessageDeliveryRequest, PushSubscription subscription, PushMessage message)
        {
            HttpContent httpContent = message.HttpContent;

            if (httpContent is null)
            {
                pushMessageDeliveryRequest.Content = null;
            }
            else
            {
                AsymmetricCipherKeyPair applicationServerKeys = ECKeyHelper.GenerateAsymmetricCipherKeyPair();
                byte[] applicationServerPublicKey             = ((ECPublicKeyParameters)applicationServerKeys.Public).Q.GetEncoded(false);

                pushMessageDeliveryRequest.Content = new Aes128GcmEncodedContent(
                    httpContent,
                    GetKeyingMaterial(subscription, applicationServerKeys.Private, applicationServerPublicKey),
                    applicationServerPublicKey,
                    CONTENT_RECORD_SIZE
                    );
            }

            return(pushMessageDeliveryRequest);
        }
        private static HttpRequestMessage SetUrgency(HttpRequestMessage pushMessageDeliveryRequest, PushMessage message)
        {
            switch (message.Urgency)
            {
            case PushMessageUrgency.Normal:
                break;

            case PushMessageUrgency.VeryLow:
            case PushMessageUrgency.Low:
            case PushMessageUrgency.High:
                pushMessageDeliveryRequest.Headers.Add(URGENCY_HEADER_NAME, _urgencyHeaderValues[message.Urgency]);
                break;

            default:
                throw new NotSupportedException($"Not supported value has been provided for {nameof(PushMessageUrgency)}.");
            }

            return(pushMessageDeliveryRequest);
        }
        private static HttpRequestMessage SetTopic(HttpRequestMessage pushMessageDeliveryRequest, PushMessage message)
        {
            if (!String.IsNullOrWhiteSpace(message.Topic))
            {
                pushMessageDeliveryRequest.Headers.Add(TOPIC_HEADER_NAME, message.Topic);
            }

            return(pushMessageDeliveryRequest);
        }
        private HttpRequestMessage PreparePushMessageDeliveryRequest(PushSubscription subscription, PushMessage message, VapidAuthentication authentication, VapidAuthenticationScheme authenticationScheme)
        {
            authentication = authentication ?? DefaultAuthentication;
            if (authentication == null)
            {
                throw new InvalidOperationException("The VAPID authentication information is not available");
            }

            HttpRequestMessage pushMessageDeliveryRequest = new HttpRequestMessage(HttpMethod.Post, subscription.Endpoint)
            {
                Headers =
                {
                    { TTL_HEADER_NAME, (message.TimeToLive ?? DefaultTimeToLive).ToString(CultureInfo.InvariantCulture) }
                }
            };

            pushMessageDeliveryRequest = SetAuthentication(pushMessageDeliveryRequest, subscription, authentication, authenticationScheme);
            pushMessageDeliveryRequest = SetUrgency(pushMessageDeliveryRequest, message);
            pushMessageDeliveryRequest = SetTopic(pushMessageDeliveryRequest, message);
            pushMessageDeliveryRequest = SetContent(pushMessageDeliveryRequest, subscription, message);

            return(pushMessageDeliveryRequest);
        }
        /// <summary>
        /// Requests delivery of push message by push service as an asynchronous operation.
        /// </summary>
        /// <param name="subscription">The push service subscription.</param>
        /// <param name="message">The push message.</param>
        /// <param name="authentication">The authentication details.</param>
        /// <param name="authenticationScheme">The <see cref="VapidAuthenticationScheme"/> to use.</param>
        /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public async Task RequestPushMessageDeliveryAsync(PushSubscription subscription, PushMessage message, VapidAuthentication authentication, VapidAuthenticationScheme authenticationScheme, CancellationToken cancellationToken)
        {
            HttpRequestMessage  pushMessageDeliveryRequest         = PreparePushMessageDeliveryRequest(subscription, message, authentication, authenticationScheme);
            HttpResponseMessage pushMessageDeliveryRequestResponse = null;

            try
            {
                pushMessageDeliveryRequestResponse = await _httpClient.SendAsync(pushMessageDeliveryRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

                int retriesAfterCount = 0;
                while (ShouldRetryAfter(pushMessageDeliveryRequestResponse, retriesAfterCount, out TimeSpan delay))
                {
                    pushMessageDeliveryRequest.Dispose();
                    pushMessageDeliveryRequestResponse.Dispose();

                    await Task.Delay(delay, cancellationToken);

                    pushMessageDeliveryRequest         = PreparePushMessageDeliveryRequest(subscription, message, authentication, authenticationScheme);
                    pushMessageDeliveryRequestResponse = await _httpClient.SendAsync(pushMessageDeliveryRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken);

                    retriesAfterCount++;
                }

                await HandlePushMessageDeliveryRequestResponse(pushMessageDeliveryRequestResponse, subscription);
            }
            finally
            {
                pushMessageDeliveryRequest.Dispose();
                pushMessageDeliveryRequestResponse?.Dispose();
            }
        }
 /// <summary>
 /// Requests delivery of push message by push service as an asynchronous operation.
 /// </summary>
 /// <param name="subscription">The push service subscription.</param>
 /// <param name="message">The push message.</param>
 /// <param name="authentication">The authentication details.</param>
 /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
 /// <returns>The task object representing the asynchronous operation.</returns>
 public Task RequestPushMessageDeliveryAsync(PushSubscription subscription, PushMessage message, VapidAuthentication authentication, CancellationToken cancellationToken)
 {
     return(RequestPushMessageDeliveryAsync(subscription, message, authentication, DefaultAuthenticationScheme, cancellationToken));
 }
 /// <summary>
 /// Requests delivery of push message by push service as an asynchronous operation.
 /// </summary>
 /// <param name="subscription">The push service subscription.</param>
 /// <param name="message">The push message.</param>
 /// <param name="authentication">The authentication details.</param>
 /// <param name="authenticationScheme">The <see cref="VapidAuthenticationScheme"/> to use.</param>
 /// <returns>The task object representing the asynchronous operation.</returns>
 public Task RequestPushMessageDeliveryAsync(PushSubscription subscription, PushMessage message, VapidAuthentication authentication, VapidAuthenticationScheme authenticationScheme)
 {
     return(RequestPushMessageDeliveryAsync(subscription, message, authentication, authenticationScheme, CancellationToken.None));
 }
 /// <summary>
 /// Requests delivery of push message by push service as an asynchronous operation.
 /// </summary>
 /// <param name="subscription">The push service subscription.</param>
 /// <param name="message">The push message.</param>
 /// <returns>The task object representing the asynchronous operation.</returns>
 public Task RequestPushMessageDeliveryAsync(PushSubscription subscription, PushMessage message)
 {
     return(RequestPushMessageDeliveryAsync(subscription, message, null, DefaultAuthenticationScheme, CancellationToken.None));
 }