Application
I have very complex application which uses multiple network services. Some of them are bandwidth demanding and time critical (for example SIP service) and some are more tolerant for poor internet connection (for example power point presentation).
Problem
Now there is starvation problem (one service can dominate the whole bandwidth).
Receiving data has been solved easily. Data rate is calculated for each service and application sends desired data rate to a server and server controls speed of incoming data.
The hard problem is to control speed of data when sending data.
For raw socket connection this is quite easy. The sockets output stream is simply wrapped by subclass of NSOutputStream
which delays stream events HasSpaceAvailable
, depending on how many bytes has been written to the socket in some time unit.
Question
The question is how do this properly for NSURLSession
? I could do the same trick for input stream of HTTP body which is delivered in delegate method:
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
but this approach will not take into account HTTP frame (headers). For some service, which will do intensive polling, HTTP frame can be significant part of sent data. So to control data rate properly HTTP frame should be taken into account. Problem is that there is no API which could help to control data rate for the whole HTTP protocol. I can see API which allows to control data rete of the HTTP request body only.
Update
I've tried to use API needNewBodyStream and it doesn't work. NSURLSession uses delivered stream synchronously. Any attempts to split data into chunks which could be delayed for sending leads to some strange errors and request is not sent at all.
So I'm looking for any alternative. Solution proposed in answer: own implementation of NSURLProtocol have lots of drawbacks:
- lots of complex code which not relay related to my instance of NSURLSession
- problems to distinguish what services is is so to which bandwidth bucket assign a request
- this has impact on whole application and I'm providing a framework
So I'm still looking for better solution