Network.framework: fall through endpoints?

In Network.framework the documentation for nw_connection_force_cancel() suggests that it's possible to provide fall through endpoints?


/// Cancel the currently connected endpoint, causing the connection to fall through to the next endpoint if
/// available, or to go to the waiting state if no more endpoints are available.


However I can't seem find a way to provide multiple endpoints to an NWConnection. The ability to fall through to a different endpoint in the case of failure on a primary one, or indeed simply being able to cancel the current one and move to the next, would be pretty nice. Is this functionality available currently or am I misunderstanding the docu in this case?


Thanks!

Answered by ElenaS in 319513022

Short:

I've made a test and it seem it's true.


Long:

I've created hostname that points to multiple ip addresses

test.tridigy.com. 86400 IN A 212.122.90.147
test.tridigy.com. 86400 IN A 212.122.90.146
test.tridigy.com. 86400 IN A 89.117.128.41

And only one IP responds to HTTPS - 89.117.128.41


I've captured packet dump and see that it tries to connect to second one, first one and then establishes connection to third one:

23:57:09.337331 IP 192.168.62.132.49353 > 212.122.90.147.443: Flags [SEW], seq 2091855968, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923258 ecr 0,sackOK,eol], length 0
23:57:09.485493 IP 192.168.62.132.49354 > 212.122.90.146.443: Flags [SEW], seq 996630428, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923405 ecr 0,sackOK,eol], length 0
23:57:09.629142 IP 192.168.62.132.49355 > 89.117.128.41.443: Flags [SEW], seq 1320591488, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923548 ecr 0,sackOK,eol], length 0
23:57:09.675129 IP 89.117.128.41.443 > 192.168.62.132.49355: Flags [S.], seq 436958124, ack 1320591489, win 64240, options [mss 1460], length 0
23:57:09.675237 IP 192.168.62.132.49355 > 89.117.128.41.443: Flags [.], ack 1, win 65535, length 0


Here's the sample code for command line project main.swift:

import Foundation
import Network
let queue = DispatchQueue(label: "test")
let tcpParameters = NWProtocolTCP.Options()
let connectionParameters = NWParameters(tls: nil, tcp: tcpParameters)

let connection = NWConnection(host: "test.tridigy.com", port: 443, using: connectionParameters)
print("")
connection.stateUpdateHandler = { (newState) in
  print("connection state changed \(newState)")

}
if(connection.state == .setup) {
  connection.start(queue: queue)
}

RunLoop.main.run()

I remember at one WWDC talk they said URLConnection tries connecting to fall through different IP address based on DNS response,

maybe here is the same. Of course this means that reponse should include more than one ip address:

$dig icloud.com a

; <<>> DiG 9.10.6 <<>> icloud.com a
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61585
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;icloud.com. IN A

;; ANSWER SECTION:
icloud.com. 3600 IN A 17.167.146.43
icloud.com. 3600 IN A 17.178.106.77
icloud.com. 3600 IN A 17.110.240.82
icloud.com. 3600 IN A 17.167.144.39

;; Query time: 62 msec
;; SERVER: 192.168.8.1#53(192.168.8.1)
;; WHEN: Fri Jun 29 17:18:01 EEST 2018
;; MSG SIZE  rcvd: 103

Ah! Interesting. Thank you. If that's the case it has nothing to do with additional NWEndpoints and everything to do with alternate resolutions for said endpoint. If Eskimo can validate this (or the documentation in the future corroborates it) I will be happy to mark your reply as the correct answer!


Thanks again.

Accepted Answer

Short:

I've made a test and it seem it's true.


Long:

I've created hostname that points to multiple ip addresses

test.tridigy.com. 86400 IN A 212.122.90.147
test.tridigy.com. 86400 IN A 212.122.90.146
test.tridigy.com. 86400 IN A 89.117.128.41

And only one IP responds to HTTPS - 89.117.128.41


I've captured packet dump and see that it tries to connect to second one, first one and then establishes connection to third one:

23:57:09.337331 IP 192.168.62.132.49353 > 212.122.90.147.443: Flags [SEW], seq 2091855968, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923258 ecr 0,sackOK,eol], length 0
23:57:09.485493 IP 192.168.62.132.49354 > 212.122.90.146.443: Flags [SEW], seq 996630428, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923405 ecr 0,sackOK,eol], length 0
23:57:09.629142 IP 192.168.62.132.49355 > 89.117.128.41.443: Flags [SEW], seq 1320591488, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 377923548 ecr 0,sackOK,eol], length 0
23:57:09.675129 IP 89.117.128.41.443 > 192.168.62.132.49355: Flags [S.], seq 436958124, ack 1320591489, win 64240, options [mss 1460], length 0
23:57:09.675237 IP 192.168.62.132.49355 > 89.117.128.41.443: Flags [.], ack 1, win 65535, length 0


Here's the sample code for command line project main.swift:

import Foundation
import Network
let queue = DispatchQueue(label: "test")
let tcpParameters = NWProtocolTCP.Options()
let connectionParameters = NWParameters(tls: nil, tcp: tcpParameters)

let connection = NWConnection(host: "test.tridigy.com", port: 443, using: connectionParameters)
print("")
connection.stateUpdateHandler = { (newState) in
  print("connection state changed \(newState)")

}
if(connection.state == .setup) {
  connection.start(queue: queue)
}

RunLoop.main.run()

Can't beat that for a thorough answer / confirmation!

FYI, the example shown by ElenaS only tests the TCP ‘Happy Eyeballs’ support, which doesn’t require any developer intervention (because the system can tell whether a TCP connection is working on not). The purpose of

nw_connection_cancel_current_endpoint
is to allow apps using UDP to get similar support by explicitly telling the system that the connection it returned isn’t working.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Network.framework: fall through endpoints?
 
 
Q