I'm not the only one … having a hard time finding documentation on the Network.framework. Shall I open a rdar asking for more examples?
Absolutely. Please post the bug number, just for the record.
Do you know by any chance if there's a documentation on what conditions make a connection to go into
.waiting
state?
There is not. Documenting that would be hard because it’s all about implementation details. Lurking underneath the Network framework API is a complex chunk of code that attempts to open connections [1]. The
.waiting
state means that this connection engine has got to a point where it’s exhausted all available options. It’s now waiting for some
visible change to the network environment in order to retry.
Remember that visible means visible to the local device. Thus, it’s relatively easy to get into a position where a connection is in the
.waiting
state but doing an immediate retry will succeed. For example:
Set up a server located across the wider Internet.
Unplug its Ethernet cable.
Start a connection on the client; it can’t connect to the server and thus enters the
.waiting
state.Plug the server’s Ethernet cable back in.
The client will stay in the
.waiting
state because the change in step 4 is not visible to it.
The way I approach problems like this depends on the nature of the connection:
For a solicited network connection, it’s best to include a UI that indicates progress and allows the user to cancel and retry. This has two key advantages. First, it puts the user in control, which users really like. Second, it avoids you having to make any policy decisions, which is good because it’s hard to come up with a policy that works in all scenarios.
For example, consider the scenario described above. The best way to get the connection through is for the user to cancel and retry. OTOH, if the connection failed to go through because the user has stepped out of Wi-Fi range, the best fix is for them to step back into range.
For unsolicited connections, assistance from the user is not an option and thus you have to come up with a retry policy. Personally I’m a big fan of leaning on the built-in policy from the Network framework, but there’s nothing stopping you from building on top of that.
The funny thing is that after that it immediately goes to ready.
In situations like this it’s worth evaluating whether the connection engine should have retried. If the problem that prevented the first connection going through was local — that is, visible to the client device as I’ve discussed above — and the problem cleared but the connection is still waiting, that’s definitely bugworthy.
If you file a bug about this:
Make sure to include a sysdiagnose log, as described on our Bug Reporting > Profiles and Logs page.
Make sure to note, with some degree of precision, the time that you started the first connection and the time that you started the second.
The best way to do this is to add your own entry to the system log when you start a connection. Using
NSLog
with an easily identifiable log string should be sufficient.Again, please post your bug number, just for the record.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
[1] For an inkling of how complex this is, consider RFC 8305 and then realise that the Apple implementation is much more complex (-:
[2] Here I’m using terms from Technote 1145 Living in a Dynamic TCP/IP Environment, one of my oldest technotes that I regularly reference!