Issue with Multicast on iOS 14

Hi Team,

We seem to be having issues with the multicast in our app from the time we upgraded ourselves to iOS 14. So since the privacy aspects have changed as part of the iOS 14, we included the key "Privacy - Local Network Usage Description" in the info.plist. Also, as part of our development profile I added the capability of network extensions to create an entitlement. Since we do not add Bonjour and use a 3rd party library called commoncpp for socket connections I didn't add an array key to info.plist for Bonjour.

So even after doing this, our app seems to intermittently get the packets but it is not consistent. Mostly, we do not see the data coming through but when it starts to work it will keep on working on multiple relaunches until we delete the app and reinstall it.

Also, one weird thing that I saw was that i tested with iOS 14 on these devices: iPad Pro 12.5, iPad Pro 9.7, iPhone XR and iPhone 8 Plus. So my understanding is since I have added the key in info.plist for the it should shoot that permission request pop-up for the first time the app looks for local network. But, I just saw the pop-up appearing for the iPhone 8 Plus and not on other devices. (These testing I have done is all done using the developer certificates and I have not tested using the TestFlight.)

Let me know if you need some more info regarding this and thanks in advance for your support.
Have you applied for, and been granted, the com.apple.developer.networking.multicast entitlement? If not, I recommend that you start there.

Also, what API are you using for multicast? Given that your app used to work on iOS 13, I presume you’re using BSD Sockets? Is that correct?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
We seem to be in a similar situation. Our apps use to receive broadcast UDP and they work intermittently with iOS 14 (worked fine with iOS 13). We do use BSD sockets in a form of boost::asio. Do we also need com.apple.developer.networking.multicast for broadcast receive to start working?

Do we also need com.apple.developer.networking.multicast for
broadcast receive to start working?

Currently the system is not requiring the multicast entitlement for BSD Sockets clients (although we expect that to change in the iOS 14.x lifecycle).

As to why your BSD Sockets code is not working, it’s hard to say for sure. Have you tried boiling this down to a small test project?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"

Currently the system is not requiring the multicast entitlement for BSD Sockets clients (although we expect that to change in the iOS 14.x lifecycle).

Thank you, we are requesting the multicast entitlement then.

As to why your BSD Sockets code is not working, it’s hard to say for sure. Have you tried boiling this down to a small test
project?

I have 2 apps, one uses boost::asio, another one uses Qt and QUdpSocket. Both are suffering. The case with Qt is already quite trivial:
Code Block
mUdpSocket = new QUdpSocket(this);
connect(mUdpSocket, SIGNAL(readyRead()), this, SLOT(ProcessMessages()));
connect(mUdpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(OnError(QAbstractSocket::SocketError)));
QHostAddress host = QHostAddress::Any;
mUdpSocket->bind(host, App::cDiscoveryPort, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);

... and on some of devices I neither get an error nor a message callbacks. External side is sending UDP broadcast messages every 2 seconds. The same code worked on the same devices in iOS 13.
What's notable is that it's a TestFlight build that fails, but dev build with development signing works fine. Are there any signing related differences?

What's notable is that it's a TestFlight build that fails, but dev
build with development signing works fine. Are there any signing
related differences?

It’s very unlikely that the way that your app is signed is the distinguishing factor here. My experience is that most problems like this are caused by folks mixing up Debug and Release builds with Development and Distribution code signing.

If you take the Xcode archive that you use to submit to TestFlight and use the Organizer to export a Development signed build — this will give you a Release build that’s Development signed — what do you see?

The case with Qt is already quite trivial:

I’m sorry but I’m not familiar with Qt’s networking code. You’ll have to dig down a layer to uncover what it’s doing at the BSD Sockets layer.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
eskimo,

Thank you for your response.

We got an entitlement and now use it to no luck.
Here's what I have now on all my devices:
  1. Wipe iOS device, install app via TestFlight: doesn't work.

  2. Then use TestFlight to roll back to a previous build that used the same codebase and didn't work as well: suddenly it will start working.

  3. Update to the latest build: doesn't work again.

Next case:
4. Install development build via XCode - works.
5. After that, all TestFlight builds that didn't work start working. Until you wipe the device again.


If you take the Xcode archive that you use to submit to TestFlight and use the Organizer to export a Development signed build — this will give you a Release build that’s Development signed — what do you see?

I got an .ipa that didn't work.


I changed code to use raw BSD sockets in the following way:

Creation code:
Code Block
mSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (mSocket < 0)
{
// Handle error
...
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(OnStageApp::cDiscoveryPort);
addr.sin_addr.s_addr = INADDR_ANY;
int result = bind(mSocket.load(), (const struct sockaddr *)&addr, sizeof(addr));
if (result < 0)
{
// Handle error
...
}


Receive loop code:
Code Block
ssize_t len = recv(socket, (char *)buffer, cBufSize, 0);
if (len == -1)
{
// Handle error
...
}
std::string msg(buffer, len);


What I see is that creation passes without errors and recv is executed. But neither actual messages nor errors are received. Unless you run from XCode with development signing.

Then use TestFlight to roll back to a previous build that used the
same codebase and didn't work as well: suddenly it will start working.

I’m helping another developer who is seeing results very similar to this. I’m still investigating the cause (r. 70530611). At this point I don’t have any concrete advice to share.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
We also have had hundreds of customer complaints about total loss of networking while on our VPN - only for iOS 14. We use BSD Sockets in the packet tunnel provider for UDP - as a DNS proxy of sorts. Prior to iOS 14, everything works fine. As soon as users updated to 14, many have no networking whatsoever. We're finding that recv is never called.

I've tried adding the local privacy permission to no avail.

Do we need the multicast entitlement?
An update to those reading this post: our problem was solved by updating to iOS 14.2.
I'll bet a case of beer that the above comments, especially the VPN one, are related to connect() failing in network extensions on ios 14.4. See https://developer.apple.com/forums/thread/678959.
Issue with Multicast on iOS 14
 
 
Q