Home | History | Annotate | Download | only in objective-c
      1 
      2 # gRPC iOS Network Transition Behaviors
      3 Network connectivity on an iOS device may transition between cellular, WIFI, or
      4 no network connectivity. This document describes how these network changes
      5 should be handled by gRPC and current known issues.
      6 
      7 ## Expected Network Transition Behaviors
      8 The 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     * Conncetion 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
     37 gRPC's default implementation is to use TCP sockets for networking. It turns
     38 out that although Apple supports this type of usage, it is [not recommended by
     39 Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
     40 and has some issues described below.
     41 
     42 #### Issues with TCP Sockets
     43 The TCP sockets on iOS is flawed in that it does not reflect the viability of
     44 the channel connection. Particularly, we observed the following issues when
     45 using 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.
     53 In both situations, the user will see the call hang for an extended period of
     54 time before the TCP socket times out.
     55 
     56 #### gRPC iOS library's resolution to TCP socket issues
     57 We introduced
     58 [`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
     59 in gRPC iOS library v0.14.0 to alleviate these issues in TCP sockets,
     60 which changes the network transition behaviors a bit.
     61 
     62 We classify network connectivity state of the device into three categories
     63 based 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 
     72 Whenever there is a transition of network between two of these categories, all
     73 previously existing channels are assumed to be broken and are actively
     74 destroyed. If there is an unfinished call, the call should return with status
     75 code `UNAVAILABLE`.
     76 
     77 `ConnectivityMonitor` is able to detect the scenario of the first issue above
     78 and actively destroy the channels. However, the second issue is not resolvable.
     79 To solve that issue the best solution is to switch to CFStream implementation
     80 which eliminates all of them.
     81 
     82 ### gRPC iOS with CFStream
     83 gRPC iOS with CFStream implementation (introduced in v1.13.0) uses Apple's
     84 networking API to make connections. It resolves the issues with TCP sockets
     85 mentioned above. Users are recommended to use this implementation rather than
     86 TCP socket implementation. The detailed behavior of streams in CFStream is not
     87 documented by Apple, but our experiments show that it accords to the expected
     88 behaviors.  With CFStream implementation, an event is always received when the
     89 underlying connection is no longer viable. For more detailed information and
     90 usages of CFStream implementation, refer to the
     91 [user guide](https://github.com/grpc/grpc/blob/master/src/objective-c/README-CFSTREAM.md).
     92 
     93