iOS 10.2 socket issue

The same code works fine with iOS10.1, but when I update it to 10.2, this problem arises.

I used the bsd socket to send a UDP message to other devices.

The 'sendto' function always fails with error code "operation not permitted" while it never happens with a 10.1 device.

Any ideas why? Thank you very much.

Replies

“operation not permitted” is

EPERM
. I’m not aware of any general problem with UDP sends generating this error on iOS 10.2. You should use the debugger to look at the exact parameters you’re passing to
sendto
, paying specific attention to the address you’re passing in.

If you can’t figure it out from that, post the relevant snippets of code and I can take a look.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

If I bind a socket to a certain port and start listen to it, everything goes fine and I can receive the data. But I couldnt use the same socket to send data to others, it will tell me that operation is not permitted.

If I create a new socket, I can just send data without any problem. So it seems to me that I cannot use the same socket to send and receive UDP data??

It never occurred in 10.1, so I took it for granted that you guys blocked this function. But I still need to use one socket to send and recv, so would you please check on it??

So it seems to me that I cannot use the same socket to send and receive UDP data?

It’s not that simple. Below you’ll find pasted in some simple UDP test code which will happily send and receive from the same socket. In this example:

  • The view controller manages a table view with two items, one to send and another to receive.

  • I ran it on my iPhone, running 10.2, which was on my office Wi-Fi.

  • 192.168.1.189 is the IP address of my Mac on the same Wi-Fi.

  • 192.168.1.184 is the IP address of my iPhone.

  • I tested the send and receive by running

    nc
    on my Mac, as shown below.
$ nc -u -l 12345
Hello Cruel World! 2016-12-21 10:09:34 +0000
Hello Cruel World! 2016-12-21 10:10:45 +0000
…
$ nc -u 192.168.1.184 12345
Hello iPhone 1!
Hello again iPhone!   
…

I recommend that you repeat my test and see if you get the same results. If you do, you can then try to modify the test to reproduce the problem you’re seeing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
#import "MainViewController.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

@interface MainViewController ()

@property (nonatomic, assign, readwrite) int sock;

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.sock = -1;
}

- (void)sendTest {
    struct sockaddr_in addr = {
        .sin_len = sizeof(struct sockaddr),
        .sin_family = AF_INET,
        .sin_port = htons(12345),
        .sin_addr.s_addr = inet_addr("192.168.1.189")
    };

    NSString * message = [NSString stringWithFormat:@"Hello Cruel World! %@\r\n", [NSDate date]];
    NSData * messageData = [message dataUsingEncoding:NSUTF8StringEncoding];
    ssize_t bytesSent = sendto(
        self.sock,
        messageData.bytes,
        messageData.length,
        0,
        (const struct sockaddr *) &addr,
        sizeof(addr)
    );
    if (bytesSent < 0) {
        NSLog(@"send failed: %d", errno);
    } else {
        NSLog(@"sent %zd bytes", bytesSent);
    }
}

- (void)receiveTest {
    struct sockaddr_storage addr;
    socklen_t addrLen = sizeof(addr);
    NSMutableData * bufferData = [[NSMutableData alloc] initWithLength:2048];
    ssize_t bytesReceived = recvfrom(
        self.sock,
        bufferData.mutableBytes,
        bufferData.length, 0,
        (struct sockaddr *)
        &addr,
        &addrLen
    );
    if (bytesReceived < 0) {
        if (errno == EAGAIN) {
            NSLog(@"nothing to receive");
        } else {
            NSLog(@"received failed: %d", errno);
        }
    } else {
        char host[NI_MAXHOST];
        bufferData.length = (NSUInteger) bytesReceived;
        BOOL success = getnameinfo(
            (const struct sockaddr *) &addr,
            addrLen,
            host,
            sizeof(host),
            NULL,
            0,
            NI_NUMERICHOST | NI_NUMERICSERV
        ) == 0;
        assert(success);
        NSLog(@"received %@ from %s", bufferData, host);
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    #pragma unused(tableView)
    #pragma unused(indexPath)

    if (self.sock == -1) {
        self.sock = socket(AF_INET, SOCK_DGRAM, 0);
        assert(self.sock >= 0);

        BOOL success = fcntl(self.sock, F_SETFL, O_NONBLOCK) == 0;
        assert(success);

        struct sockaddr_in addr = {
            .sin_len = sizeof(struct sockaddr),
            .sin_family = AF_INET,
            .sin_port = htons(12345)
        };
        success = bind(self.sock, (const struct sockaddr *) &addr, sizeof(addr)) == 0;
        assert(success);
    }

    switch (indexPath.row) {
        case 0: {
            [self sendTest];
        } break;
        case 1: {
            [self receiveTest];
        } break;
        default: {
            abort();
        } break;
    }

    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}

@end

We're seeing the same thing with our app but reading & writing via GCDAsyncSocket. It works fine in 10.1 but as soon as we upgrade a device to 10.2 our app is only able to communicate in one direction.

We are seeing an issue as well with 10.2. With out changing anything other than upgrading a device to 10.2 we are no longer able to communicate on a socket. Any device that we have tested with 10.1 or below is fine, but the moment we upgrade to 10.2 it no longer works. One thing of note is we are using only using ipv6, and we are seeing this with TCP sockets.

ShaunMurphy wrote:

We're seeing the same thing with our app …

PGMichael wrote:

We are seeing an issue as well with 10.2.

I recommend you both repeat the test I described in my 21 Dec post and see what you get.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi, I use your code for test. The result is :

On my office Wi-Fi, iPad send to Simulator, both send and recv success, the iPad not link to iMac with cable.

On my office Wi-Fi, iPad send to iPad, both send and recv failure.

Use my phone hotspot, iPad send to Simulator, both send and recv success, the iPad not link to iMac with cable.

Use my phone hotspot, iPad send to iPad, both send and recv success.


Why iPad send to iPad failure when use Wi-Fi?

Can you give me some help?

Thank you very much!

On my office Wi-Fi, iPad send to iPad, both send and recv failure.

There’s a variety of possibilities here, the most obvious being that your office Wi-Fi is blocking STA-to-STA traffic for iOS devices (be aware I’m using Wi-Fi specific terminology here; read Wi-Fi Fundamentals for the background to this). However, that’s just one of many different possibilities and to get to the bottom of this you need to start dividing up the problem space. To that end I recommend that you take a look at my Investigating Network Latency Problems post. While the focus of that post is something different entirely, it describes how you can tap into the networking stack at each hop, and you can use that to track down where things are going wrong.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"