Hi Eskimo,
I am playing around with the new DNSProxyProvider to see how performances are compared to traditional lew-level netwrok / kext programming approaches available in MacOS. My task is relatively simple: intercept all (UDP to start with) requests and relay them to the original destination server (e.g: remote endpoint) they are intended to reach in the first place.
In order to do so I am:
1) Implementing my subclass of DNSProxyProvider to get hold of new flows being opened (handleNewFlow:)
2) For each new flow opened, I create an NSOperation (FlowOperation) to handle that flow. I add it to a concurrent FlowOperationQueue
3) The flow operation reads the datagrams and the intended remotes, and for each of those creates and enques a ResolverOperation whose task is to write to the destination server and relay the response back to the flow / original client.
The upstream flow (DNSProxyProvider / ResolverOperation -> remote endpoint and back) is handled via an NWUDPSession instantiated with the given remote endpoint. Here we come to the core issue. I am not sure whether:
1) We are supposed to have a a single NWUDPSession per DNSProxyProvider at a time. If that is the case (and given that the writeDatagram" method is supposed to wait for the response callback before writing again to the session), I guess we can handle a flow at a time. I have tried to set FlowOperationQueue.maxOperationCount to1, and also serialise the execution of the ResolverOperations writing to the UDPSession.
This approach seems to give the best results, as in it resolves the hosts and I get the pages to load. On the other side, it is not particularly efficient as each DNS request needs to wait for the completion of the previous one before being served, and multiple flows (e.g: Safari's WebViews, Whatsapp, Facebook etc..) are also serialised.
2) Can can create multiple NWUDPSessions at a time? The original idea was to have one per flow concurrently handle (assuming the remote endpoint for each datagram in a flow was invariant), If that is the case, we could increase the number of concurrent flows being resolved at the same time as each one would be using its own udpSession. This doesn't seem to work: when multiple flows are created at once they don't seem to transition to a Ready state where read and write operation can begin.
I might be getting it all wrong entirely, but the lack of documentation and examples in the field make it less trivial to figure out. I have seen usages of NWUDPSession in the context of tunnel providers but they were usually a single session per Provider / custom server to exchange configuration, but here the requirements to serve DNS are obviouslt different.
Thoughts?
P.s: happy to open a DTS with the code if that helps.