2

I’m not talking about Reachability.

What I’m talking about is figuring out how to create a network connection from an iOS device across the cellular interface.

Why? Because I have conditions where the device connects to a WiFi access point so it chooses WiFi… but that access point is not internet connected and goes nowhere. I have data which I must make every effort to deliver and it some cases it’s getting lost in the WiFi gateway to purgatory. In both cases of using Reachability and relying on MPTCP, Apple has already given priority to WiFi in the stack.

I know NSURLSessionConfiguration can set allowsCellularAccess to allow cellular access — I’m looking to require cellular for the routing.

Even at the CFNetwork level I’m looking at kCFStreamPropertyConnectionIsCellular for status, kCFStreamPropertyNoCellular to disable cellular.

I can’t find anyway to give preference to the cellular radio. I realize Apple has gone to great lengths to prefer WiFi and I’m going against that — which is why I’m having such difficulty finding an answer to this.

I'd like to keep this up in the Cocoa level, but not opposed to going into Foundation or deeper levels. I would like to avoid trying to parse an interface table (if it's even accessible) to figure out which is the cellular interface.

Has anyone successfully created a network connection across the cellular link despite WiFi appearing to be present?

Is some configuration of Multipath TCP the answer here?

Thompsonian
  • 407
  • 5
  • 23

2 Answers2

0

To bind to a particular interface, as far as I'm aware, you'd have to drop all the way down to the raw socket level, and there's no way to provide a custom socket for NSURLSession purposes, so you'd basically be rewriting it from scratch. You should file a bug asking for support for binding an NSURLSession to a source IP.

The behavior you're experiencing is a known problem with iOS and disconnected networks. iOS 9 and later do a better job, but even then, they can be highly problematic; the devices sometimes refuse to talk to the Wi-Fi network, and sometimes refuse to talk to the cellular network. Specifically, it seems to fail spectacularly if either signal is weak. Just this morning, I actually had to force my iPhone (iOS 10) to talk to a disconnected Wi-Fi network by putting it in Airplane mode and enabling only Wi-Fi.

I'm told that you can fix this by configuring the network's DHCP server to not provide a router advertisement; that said, every time I've tried that, the iOS device would just keep asking for an offer repeatedly. Maybe that bug got fixed at some point. If so, it might be worth a shot, but don't expect it to work in older versions of iOS.

Failing that, assuming you don't need to support web browsers in iOS 3 and earlier, you might try eliminating the DHCP server on that Wi-Fi network entirely, and just rely on DNS service discovery with zero-conf IPs. That way, the device won't see a router, and it won't try to send data out that interface except to those link-local IPs.

If that isn't possible for some reason, ordinarily I would suggest using a customized copy of libcurl, except that I doubt this will work in your case, because POSIX networking doesn't wake the cellular hardware.

dgatwood
  • 10,129
  • 1
  • 28
  • 49
  • Good information — despite the bad news. In my particular case the WiFi signal is strong and is required to announce SSID. There are also conditions which require blocking the outbound side of the access point creating this bandwidth vacuum — when those conditions are removed, the access point is opened back up to the internet. I have heard that the “WiFi Assist” helps with this. Perhaps a tweaked NSURLSessionConfiguration to lower the timeout thresholds can cause it to roll over to cellular “assist” more quickly. – Thompsonian Jan 23 '17 at 17:42
0

In iOS 12 and later you can use the Network Framework. Sample code is here.

EricS
  • 9,650
  • 2
  • 38
  • 34