Reproducible failures with UWP HttpClient, HTTP/2 and client certificates

3

The problem

We have built a Windows 10 app which sends push notifications to iOS devices. While load testing, we discovered a pretty severe bug with UWP's HttpClient classes that is seemingly-impossible to diagnose.

Our UWP app sends push notifications to Apple's APN servers. We can send HTTP/2 TLS requests and everything works fine as long as we send a message every few seconds.

But if we wait a minute or so between HTTP/2 requests, HttpClient completely breaks down, returning a COMException with error code 0x80072efd and the COM error text "A connection with the server could not be established".

We have tested this scenario against our own web-based HTTP/2 servers (ASP.NET Core HTTPS behind Nginx) using the same payload and appropriate client certificates. Everything works fine there--so this problem seems to be isolated to HttpClient interoperability with either the Apple APN client certificates or Apple's HTTP/2 frontend.

Attempts to diagnose

To diagnose the issue, we installed mitmproxy (with HTTP/2 and client certificate support) but the HTTP/2 implementation that mitmproxy uses behaves perfectly and does not exhibit the same issues as UWP's HttpClient classes so we were unable to debug the issue there.

We also tried using Fiddler, but Fiddler (and Fiddler Core which Microsoft's message analyzer uses) only has early HTTP/2 support and corrupts HTTP/2 streams.

And of course we looked at diagnostics with SSLSPLIT and similar solutions but could not find any diagnostic tool that could handle HTTP/2 and client certificates.

Code, for reference

/* code called during app startup */
Certificate clientCertificate = [apns certificate omitted for security];
string deviceToken = "[omitted for security]";
string appBundleId = "[omitted for security]";
//
Windows.Web.Http.Filters.HttpBaseProtocolFilter filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
filter.ClientCertificate = clientCertificate;
var client = new Windows.Web.Http.HttpClient(filter);


/* code called every time a push notification needs to be sent */
string messageUuid = Guid.NewGuid().ToString("D");
//
var request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, new Uri("https://api.development.push.apple.com:443/3/device/" + deviceToken));
//
request.Headers.Add("apns-id", messageUuid);
request.Headers.Add("apns-expiration", "0");
request.Headers.Add("apns-priority", "10");
request.Headers.Add("apns-topic", appBundleId);
// sample notification content for testing purposes only 
request.Content = new Windows.Web.Http.HttpStringContent("{ \"aps\" : { \"alert\" : \" -- test message " + messageUuid + " -- \" } }");
//
try
{
    // this next line of code works fine if called a few seconds after the last message--but throws a COMException if a minute has passed
    var response = await client.SendRequestAsync(request);
}
catch (Exception ex)
{
    System.Diagnostics.Debug.Write(ex.Message);
}

Questions

  1. What if any options are available to diagnose WinInet/HttpClient failures on Windows 10? With HTTP/2, TLS and Client Certificates in the mix?

  2. Is there anything special about Apple's selected HTTP/2 implementation which is known to cause issues with UWP's HttpClient--with a known workaround?

c#
networking
apple-push-notifications
win-universal-app
desktop-application
asked on Stack Overflow Apr 13, 2016 by Flint

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0