diff options
author | Muxi Yan <mxyan@google.com> | 2018-06-18 14:07:40 -0700 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2018-06-18 14:07:40 -0700 |
commit | 965a015b05cf63b12336d9b274da4e2c2db9a36f (patch) | |
tree | d5b53ba987c78af2a7d8d933ceaea1faa3d54b0d /src/objective-c/NetworkTransitionBehavior.md | |
parent | f613be8e822f88b73f8800011043c37b88ca0226 (diff) |
Updated doc
Diffstat (limited to 'src/objective-c/NetworkTransitionBehavior.md')
-rw-r--r-- | src/objective-c/NetworkTransitionBehavior.md | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/objective-c/NetworkTransitionBehavior.md b/src/objective-c/NetworkTransitionBehavior.md new file mode 100644 index 0000000000..a0c2e781c4 --- /dev/null +++ b/src/objective-c/NetworkTransitionBehavior.md @@ -0,0 +1,86 @@ + +# 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 connects 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. + +## 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 is also flawed. + +#### TCP Sockets Issues +The TCP sockets on iOS is flawed in that it does not reflect the viability of +the channel connection. Particularly, we found the following issues related to +TCP sockets: +* When a TCP sockets 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. +* The TCP sockets does not report certain events that happens 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. + +#### gRPC iOS resolutions +We introduced +[`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html) +in gRPC iOS library to alleviate these issues in TCP sockets, which changes the +network transition behaviors a bit. + +We classfy 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 uses Apple's networking API to make +connections. It resolves the issues above that is known to TCP sockets on iOS. +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). + |