I've encountered a very strange issue since iOS 10.1 in a custom App I wrote for a company. This App needs to access the internal network via VPN, and this internal company network uses NTLM athorization. The VPN connection is established by a third-party App (PulseSecure) and is working fine in general, so I think this is not the issue here.
The App uses UIWebView to access the internal company sites and also NSURLProtocol for certain important features which can not be implemented with WKWebView (like content filtering of the network traffic). The problem is not related to UIWebView, I can also reproduce it if I simply request all the resources of the site directly using NSURLSession. So for my test case I can simply use Apple's own "CustomHTTPProtocol" reference implementation for HTTP/HTTPS protocol handlers via NSURLProtocol and then send the HTTP request sequencially with a certain delay between all requests using the NSURLSession framework.
What happens is that if I send all the requests, with a delay of about 1-2 seconds between the requests, then after the 10th request, all network traffic shuts down for about 1 minute (some kind of timeout or so), then the network requests will continue to be processed and eventually shutting down after a while again.
The delay of 1-2 seconds between the request is more than enough to get the response from the server and finishing the requests successfully. So basically I send a request, get the response, wait the remaining time, send the next request, get the reponse etc. So at the time when the iOS stops processing network requests there are no unfinished network requests left. Which means for this 1 minute where the network layer is frozen, all the requests are queued up within NSURLSession but are not processed at all. After this minute they are processed again.
If I reduce the delay between the requests for example to only a small fraction of a second, then there will be multiple requests that needs to processed at the same time. But nevertheless the iOS will stop all network after processing the 10th request. Which means it does not matter how many requests are processed at the same time, and how many are waiting to be processed.
Only if I increase the delay between the requests to about 4-5 seconds, there's no more freezing network layer.
This problem seems to be related to NTLM authentication, all connections without NTLM do not cause this issue.
It looks like the problem is that the network layer only has a limited number of resources available for NTLM authorization which also seems to be busy for a while even after the request is already finished. And the network layer blocks if a certain number of NTLM authorization requests needs to be processed within a certain time (which seems to be about 4-5 seconds)
I do have found an ugly workaround for this iOS problem: Instead of using one single NSURLSession for all the network requests, I do create 15(!) sessions and distribute all requests to all these sessions equally. This way, when loading a web site (which can easily create about 90 requests), each session would only have to deal with a small number of the requests (in my example, each session only gets 6 requests), which is less than the 10 which have been found to be the limit which can be handled without a freezing network layer. And this does indeed avoid the freezing network traffic in my App.
While I can use this workaround for now, I wonder if there's a smarter workaround available for this problem? Are there any side effects when using so many NSURLSessions? Is there a better way to deal with this problem?
BTW: Bug ID #29383085