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