xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/NetworkTransitionBehavior.md (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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