Subject: [Taps] New Transport Networking APIs in iOS 12 beta

From: Tommy Pauly <[email-masked]>
Date: Fri, 08 Jun 2018 15:29:09 -0700

Hello TAPS!

This week we released Network.framework, a new set of transport APIs, as part of the beta for iOS 12 and macOS Mojave.

This API provides support for connections and listeners using TCP, UDP, TLS, and DTLS; connecting by name or service, with happy eyeballs support for addresses, interfaces, and protocols (for proxies, etc). This provides our basis for “post-sockets” API work. As we define as a working group more of the full TAPS API vision for protocol agility, we'd like on add that support to this framework. 

Video of the presentation:
https://developer.apple.com/videos/play/wwdc2018/715/ <https://developer.apple.com/videos/play/wwdc2018/715/>

Sample implementation of netcat:
https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework <https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework>

Swift and C API:
https://developer.apple.com/documentation/network <https://developer.apple.com/documentation/network>

If you are an iOS or macOS developer, please try out the APIs! Either way, we’d love for everyone to take a read through the API and give feedback on how we can continue to evolve things towards a post-sockets and fully TAPS model. Note that on iOS and tvOS, this framework is currently using a user-space networking stack instead of sockets when applicable.

Best,
Tommy

---

From: Michael Tuexen <[email-masked]>
Date: Sat, 9 Jun 2018 14:38:03 -0400

> On 8. Jun 2018, at 18:29, Tommy Pauly <[email-masked]> wrote:
> 
> Hello TAPS!
> 
Hi Tommy,

great news!
Is there also a possibility to add new transports to the framework, like
SCTP or QUIC?

Best regards
Michael
> https://developer.apple.com/videos/play/wwdc2018/715/
> 
> https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework
> 
> Swift and C API:
> https://developer.apple.com/documentation/network
> 
> _______________________________________________
> Taps mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/taps

---

From: Tommy Pauly <[email-masked]>
Date: Sat, 09 Jun 2018 13:54:46 -0700

Hello Michael,

The architecture is designed specifically to allow loading different protocols. The parameters object is centered around a “protocol stack” configuration object, which is composed of protocol options for defined protocol implementations. This only exposes a default stack now, but is designed to offer the configuration of alternate stacks as well. In this first version, we’re only letting developers compose stacks with pre-defined protocols, but I want to allow custom protocol definitions and implementations going forward—for both simple framers, as well as full blown transports like SCTP and QUIC! The model of the connection sending and receiving messages is sufficiently generic to support any of the TAPS protocols. 

Best,
Tommy

---

From: Michael Welzl <[email-masked]>
Date: Sun, 10 Jun 2018 10:02:31 +0200

Hi,

This - in particular your answer to Michael - is indeed extremely cool! Thanks to you and your colleagues at Apple for pursuing this direction, and thanks for sharing it with the group!

About this statement in the original email:
***
Either way, we’d love for everyone to take a read through the API and give feedback on how we can continue to evolve things towards a post-sockets and fully TAPS model.
***

I think an obvious answer to this is: the more in line with draft-ietf-taps-interface it is, the better - and where it’s not, it would probably be interesting for the group to know the reasons.

Cheers,
Michael

> On Jun 9, 2018, at 10:54 PM, Tommy Pauly <[email-masked]> wrote:
> 
> Hello Michael,
>

---

From: Jonathan Lennox <[email-masked]>
Date: Mon, 11 Jun 2018 12:47:12 -0400

I’ve read over Apple’s new API.  (One note: the URL that Tommy sent a link to doesn’t have the full documentation of the API yet; many of the types and methods still say “No overview available.” If you’re an Apple developer, the header files supplied with the macOS 10.14 and iOS 12 beta SDKs in the Xcode 10 beta contain much fuller versions of the documentation.)

The main difference I’ve found between TAPS and Network.framework is that Network.framework doesn’t have a Preconnection object.  Instead, Connection objects for outgoing connections are directly created from a constructor, and then must have their .start method called before they act.

This part is a relatively minor semantic difference, but more significant is how incoming connections are handled.  In Network.framework, there is a Listener object with a new_connection handler, and this object can produce unlimited numbers of Connections until stopped.  This is unlike TAPS where a Listen action consumes a Preconnection, and to receive multiple connections on the same port, Listen must be called on multiple cloned Preconnections.

I feel like the Network.framework model is an easier programming model for most use cases, but it has the downside that an API user has no way to pace its handling of incoming connections.

> On Jun 10, 2018, at 4:02 AM, Michael Welzl <[email-masked]> wrote:
> 
> Hi,
>

---

From: Michael Welzl <[email-masked]>
Date: Fri, 15 Jun 2018 10:00:30 +0200

Hi,

Thanks for sharing this! It’s quite interesting -

> On Jun 11, 2018, at 6:47 PM, Jonathan Lennox <[email-masked]> wrote:
> 

I agree, things are a bit inconsistent in the online docs for now… e.g. somehow this:
https://developer.apple.com/documentation/network?language=objc <https://developer.apple.com/documentation/network?language=objc>
seems to be more complete than
https://developer.apple.com/documentation/network/nwpath <https://developer.apple.com/documentation/network/nwpath>
but then there are also differences that are probably not due to the language choice only. Well, it all clearly says “Beta”, so that’s ok, we’ll just have to wait until this documentation is updated.

> This part is a relatively minor semantic difference, but more significant is how incoming connections are handled.  In Network.framework, there is a Listener object with a new_connection handler, a…

I agree that the first difference is minor (constructor vs. “Preconnection”). I would also say that the latter difference is interesting but not huge… (“under the hood” it’s easy to imagine that these can be two ways to essentially expose the same thing). I’d also agree that the Network.framework method is more convenient though. Tommy - what would you say about moving our API in that direction for Listening?

> I feel like the Network.framework model is an easier programming model for most use cases, but it has the downside that an API user has no way to pace its handling of incoming connections.

I haven’t played with the Network.framework myself, but I would guess that, if I want to slow down the rate at which I handle incoming connections, there isn’t really much difference between not calling Listen (current TAPS) vs. ignoring a newly created incoming Connection (Network.framework). Why wouldn’t that work as a way to pace conn. handling?

Cheers,
Michael

---

From: Tommy Pauly <[email-masked]>
Date: Fri, 15 Jun 2018 09:17:05 -0700

> On Jun 15, 2018, at 1:00 AM, Michael Welzl <[email-masked]> wrote:
> 
> Hi,
> 
>> On Jun 11, 2018, at 6:47 PM, Jonathan Lennox <[email-masked] <mailto:[email-masked]>> wrote:
>> 

One first note: a lot of the ‘preconnection’ properties are encapsulated in our NWParameters object. The main difference, conceptually, is that the parameters object is just a container (which may be reused) but doesn’t imply that any work can happen just by creating a parameters object.

Regarding calling listen multiple times vs providing a single completion handler to be called multiple times: I find the Listen model appropriate to have a single completion that gets invoked multiple times because the code in response to a Listen is generally going to be the same—each new connection cannot be assumed to have any relationship or ordering with regards to prior connections, so the logic you need to write to process an inbound connection will be the same. Thus, providing a single completion is cleaner. Contrast this to a Receive completion, in which receiving on a connection is assumed to have order—I may expect to read a “header” message, followed by a “body” message, etc, thus using multiple Receive calls not only provides back pressure, but allows different handling upon completion.

Adding back pressure to inbound connections is something that we do need to add. The approach Michael suggests, of just ignoring an inbound connection until we’re ready to process it, certainly would work. The downside is that this requires the caller of the API to manage their own array of pending inbound connections. One option we’ve considered is allowing the application to specify a “receive connection window size” on a listener, thus defining how many more inbound connections they’re ready to handle at a given time. What do people think about this approach?

Thanks,
Tommy

---

From: John Grant <[email-masked]>
Date: Fri, 15 Jun 2018 17:37:51 +0100

On 15/06/2018 17:17, Tommy Pauly wrote:

[snip]
>
> Adding back pressure to inbound connections is something that we do 
> need to add. The approach Michael suggests, of just ignoring an 
> inbound connection until we’re ready to process it, certainly would 
> work. The downside is that this requires the caller of the API to 
> manage their own array of pending inbound connections. One option 
> we’ve considered is allowing the application to specify a “receive 
> connection window size” on a listener, thus defining how many more 
> inbound connections they’re ready to handle at a given time. What do 
> people think about this approach?
Yes, that should be effective. One thing that needs to be avoided is the 
possibility of an attacker (or software error) causing huge numbers of 
Connection objects to be created.

-- 
John Grant
Nine Tiles, Cambridge, England
+44 1223 862599 and +44 1223 511455
http://www.ninetiles.com

---

From: Michael Welzl <[email-masked]>
Date: Fri, 15 Jun 2018 20:27:26 +0200

> On Jun 15, 2018, at 6:37 PM, John Grant <[email-masked]> wrote:
> 
> Yes, that should be effective. One thing that needs to be avoided is the possibility of an attacker (or software error) causing huge numbers of Connection objects to be created.

I believe that this could be dealt with in any case, by just allowing a max connection limit to be specified (and having a reasonable upper bound by default).
But I still prefer Tommy’s proposal over what I described, because it seems to me to be simpler to handle for the application developer.

Cheers,
Michael