diff options
Diffstat (limited to 'src/objective-c/NetworkTransitionBehavior.md')
-rw-r--r-- | src/objective-c/NetworkTransitionBehavior.md | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/objective-c/NetworkTransitionBehavior.md b/src/objective-c/NetworkTransitionBehavior.md new file mode 100644 index 0000000000..51b1e472ed --- /dev/null +++ b/src/objective-c/NetworkTransitionBehavior.md @@ -0,0 +1,92 @@ + +# gRPC iOS Network Transition Behaviors +Network connectivity on an iOS device may transition between cellular, WIFI, or +no network connectivity. This document describes how these network changes +should be handled by gRPC and current known issues. + +## Expected Network Transition Behaviors +The expected gRPC iOS channel and network transition behaviors are: +* Channel connection to a particular host is established at the time of + starting the first call to the channel and remains connected for future calls + to the same host. +* If the underlying connection to the remote host is broken, the channel is + disconnected and enters TRANSIENT\_FAILURE state. +* A channel is broken if the channel connection is no longer viable. This + happens when + * The network interface is no longer available, e.g. WiFi or cellular + interface is turned off or goes offline, airplane mode turned on, etc; + * The underlying TCP connection is no longer valid, e.g. WiFi connects to + another hotspot, cellular data switched from LTE to 4G, etc; + * A network interface more preferable by the OS is valid, e.g. WiFi gets + connected when the channel is already connected via cellular. +* A channel in TRANSIENT\_FAILURE state attempts reconnection on start of the + next call to the same host, but only after a certain backoff period (see + corresponding + [doc](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)). + During the backoff period, any call to the same host will wait until the + first of the following events occur: + * Connection succeeded; calls will be made using this channel; + * Conncetion failed; calls will be failed and return UNAVAILABLE status code; + * The call's deadline is reached; the call will fail and return + DEADLINE\_EXCEEDED status code. + The length of backoff period of a channel is reset whenever a connection + attempt is successful. + +## Implementations +### gRPC iOS with TCP Sockets +gRPC's default implementation is to use TCP sockets for networking. It turns +out that although Apple supports this type of usage, it is [not recommended by +Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html) +and has some issues described below. + +#### Issues with TCP Sockets +The TCP sockets on iOS is flawed in that it does not reflect the viability of +the channel connection. Particularly, we observed the following issues when +using TCP sockets: +* When a TCP socket connection is established on cellular data and WiFi + becomes available, the TCP socket neither return an error event nor continue + sending/receiving data on it, but still accepts write on it. +* A TCP socket does not report certain events that happen in the + background. When a TCP connection breaks in the background for the reason + like WiFi connects to another hotspot, the socket neither return an error nor + continue sending/receiving data on it, but still accepts write on it. +In both situations, the user will see the call hang for an extended period of +time before the TCP socket times out. + +#### gRPC iOS library's resolution to TCP socket issues +We introduced +[`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html) +in gRPC iOS library v0.14.0 to alleviate these issues in TCP sockets, +which changes the network transition behaviors a bit. + +We classify network connectivity state of the device into three categories +based on flags obtained from `SCNetworkReachability` API: + +| Reachable | ConnectionRequired | IsWWAN | **Category** | +|:---------:|:------------------:|:------:|:------------:| +| 0 | X | X | None | +| X | 1 | X | None | +| 1 | 0 | 0 | WiFi | +| 1 | 0 | 1 | Cellular | + +Whenever there is a transition of network between two of these categories, all +previously existing channels are assumed to be broken and are actively +destroyed. If there is an unfinished call, the call should return with status +code `UNAVAILABLE`. + +`ConnectivityMonitor` is able to detect the scenario of the first issue above +and actively destroy the channels. However, the second issue is not resolvable. +To solve that issue the best solution is to switch to CFStream implementation +which eliminates all of them. + +### gRPC iOS with CFStream +gRPC iOS with CFStream implementation (introduced in v1.13.0) uses Apple's +networking API to make connections. It resolves the issues with TCP sockets +mentioned above. Users are recommended to use this implementation rather than +TCP socket implementation. The detailed behavior of streams in CFStream is not +documented by Apple, but our experiments show that it accords to the expected +behaviors. With CFStream implementation, an event is always received when the +underlying connection is no longer viable. For more detailed information and +usages of CFStream implementation, refer to the +[user guide](https://github.com/grpc/grpc/blob/master/src/objective-c/README-CFSTREAM.md). + |