I have the following snippet of code for receiving incoming data on a NWConnection:
self.Connection.receive(minimumIncompleteLength: 1, maximumLength: self.MAX_INTAKE) {
(data, context, isComplete, error) in
if let err = error {
// receive <error> returned non-nil
self.Connection.cancel()
return // exit completion handler
}
...
}
This generally works and rarely receives an error. But seemingly at random, <error> will return 89. When this happens I've been sending a .cancel before returning from the completion handler.
It will work great for tens of thousands of connections, then suddenly return 89 error codes.
My question is: Should I be canceling the connection here or simply let NWFramwwork do as it will? Canceling the connection seems to throw my NGINX reverse proxy into fits, from which it never recovers without a restart.
In short what is the best practice for handling errors when receiving bytes in NWFramework?
I’m presuming that this is TCP. There are important differences when dealing with message-oriented protocols, like UDP or QUIC.
Error 89 is ECANCELED
. That’s the error I’d expect to see delivered by my receive handler when I call cancel()
on a connection. As to why you’re seeing it in your situation, it’s hard to say.
It’s generally fine to redundantly cancel a connection. You may get a snarky log message, but it shouldn’t do anything bad.
what is the best practice for handling errors when receiving bytes in NWFramework?
The pattern I’ve settled on is:
func startReceive() {
self.connection.receive(minimumIncompleteLength: 1, maximumLength: 2048) { content, _, isComplete, error in
if let content {
… process content …
}
if isComplete {
… process EOF …
return
}
if let error {
… process error …
return
}
self.startReceive()
}
}
This design means that I process any incoming content or EOF before I check the error. And exactly what I do in the face of an error varies depending on the nature of my program. But, in general:
-
Errors coming from my side — so, my code calling
cancel()
— will trigger theECANCELED
, which I ignore. -
Errors coming from the network will be returned here but also cause the connection to transition to the
.failed(…)
state, so I don’t need to do anything about them here.
Canceling the connection seems to throw my NGINX reverse proxy into fits, from which it never recovers without a restart.
Clearly that’s something you need to debug. The first step would be to see what’s happening on the ‘wire’. That is, what on-the-wire behaviour is causing your apoplexy in your proxy (apo-proxy, perhaps? :-).
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"