1 2# gRPC iOS Network Transition Behaviors 3Network connectivity on an iOS device may transition between cellular, WIFI, or 4no network connectivity. This document describes how these network changes 5should be handled by gRPC and current known issues. 6 7## Expected Network Transition Behaviors 8The expected gRPC iOS channel and network transition behaviors are: 9* Channel connection to a particular host is established at the time of 10 starting the first call to the channel and remains connected for future calls 11 to the same host. 12* If the underlying connection to the remote host is broken, the channel is 13 disconnected and enters TRANSIENT\_FAILURE state. 14* A channel is broken if the channel connection is no longer viable. This 15 happens when 16 * The network interface is no longer available, e.g. WiFi or cellular 17 interface is turned off or goes offline, airplane mode turned on, etc; 18 * The underlying TCP connection is no longer valid, e.g. WiFi connects to 19 another hotspot, cellular data switched from LTE to 4G, etc; 20 * A network interface more preferable by the OS is valid, e.g. WiFi gets 21 connected when the channel is already connected via cellular. 22* A channel in TRANSIENT\_FAILURE state attempts reconnection on start of the 23 next call to the same host, but only after a certain backoff period (see 24 corresponding 25 [doc](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)). 26 During the backoff period, any call to the same host will wait until the 27 first of the following events occur: 28 * Connection succeeded; calls will be made using this channel; 29 * Connection failed; calls will be failed and return UNAVAILABLE status code; 30 * The call's deadline is reached; the call will fail and return 31 DEADLINE\_EXCEEDED status code. 32 The length of backoff period of a channel is reset whenever a connection 33 attempt is successful. 34 35## Implementations 36### gRPC iOS with TCP Sockets 37gRPC's default implementation is to use TCP sockets for networking. It turns 38out that although Apple supports this type of usage, it is [not recommended by 39Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html) 40and has some issues described below. 41 42#### Issues with TCP Sockets 43The TCP sockets on iOS is flawed in that it does not reflect the viability of 44the channel connection. Particularly, we observed the following issues when 45using TCP sockets: 46* When a TCP socket connection is established on cellular data and WiFi 47 becomes available, the TCP socket neither return an error event nor continue 48 sending/receiving data on it, but still accepts write on it. 49* A TCP socket does not report certain events that happen in the 50 background. When a TCP connection breaks in the background for the reason 51 like WiFi connects to another hotspot, the socket neither return an error nor 52 continue sending/receiving data on it, but still accepts write on it. 53In both situations, the user will see the call hang for an extended period of 54time before the TCP socket times out. 55 56#### gRPC iOS library's resolution to TCP socket issues 57We introduced 58[`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html) 59in gRPC iOS library v0.14.0 to alleviate these issues in TCP sockets, 60which changes the network transition behaviors a bit. 61 62We classify network connectivity state of the device into three categories 63based on flags obtained from `SCNetworkReachability` API: 64 65| Reachable | ConnectionRequired | IsWWAN | **Category** | 66|:---------:|:------------------:|:------:|:------------:| 67| 0 | X | X | None | 68| X | 1 | X | None | 69| 1 | 0 | 0 | WiFi | 70| 1 | 0 | 1 | Cellular | 71 72Whenever there is a transition of network between two of these categories, all 73previously existing channels are assumed to be broken and are actively 74destroyed. If there is an unfinished call, the call should return with status 75code `UNAVAILABLE`. 76 77`ConnectivityMonitor` is able to detect the scenario of the first issue above 78and actively destroy the channels. However, the second issue is not resolvable. 79To solve that issue the best solution is to switch to CFStream implementation 80which eliminates all of them. 81 82### gRPC iOS with CFStream 83gRPC iOS with CFStream implementation (introduced in v1.13.0) uses Apple's 84networking API to make connections. It resolves the issues with TCP sockets 85mentioned above. Users are recommended to use this implementation rather than 86TCP socket implementation. The detailed behavior of streams in CFStream is not 87documented by Apple, but our experiments show that it accords to the expected 88behaviors. With CFStream implementation, an event is always received when the 89underlying connection is no longer viable. For more detailed information and 90usages of CFStream implementation, refer to the 91[user guide](https://github.com/grpc/grpc/blob/master/src/objective-c/README-CFSTREAM.md). 92 93