Why isn't networking working for my user?

Discussion in 'Mac Programming' started by ArtOfWarfare, Oct 22, 2013.

  1. ArtOfWarfare, Oct 22, 2013
    Last edited: Oct 22, 2013

    ArtOfWarfare macrumors G3


    Nov 26, 2007
    I received this email from a customer:

    It's been over a year since I last touched the networking part of Battery Status, and I believe I copied most of it out of a sample project. I've been trying to track down a spot where a port is chosen... it appears to be done in the function that I've reproduced (in a condensed fashion - I took out a lot of error checking code) below:

    socklen_t           namelen;
    int fdForListening = socket(AF_INET6, SOCK_STREAM, 0);
    struct sockaddr_in6 serverAddress6;
    memset(&serverAddress6, 0, sizeof(serverAddress6));
    serverAddress6.sin6_family = AF_INET6;
    serverAddress6.sin6_len    = sizeof(serverAddress6);
    bind(fdForListening, (const struct sockaddr *) &serverAddress6, sizeof(serverAddress6));
    namelen = sizeof(serverAddress6);
    getsockname(fdForListening, (struct sockaddr *) &serverAddress6, &namelen);
    chosenPort = ntohs(serverAddress6.sin6_port);
    // checks an error code, repeats using IPv4 instead of IPv6 if the error is equal to EAFNOSUPPORT... omitting that because it's nearly identical code...
    // Listen for connections on our socket, then create a CFSocket to route any connections to a run loop based callback.
    listen(fdForListening, 5);
    // Register our service with Bonjour.
    CFSocketContext     context = {0, self, NULL, NULL, NULL};
    CFRunLoopSourceRef  rls;
    self->_listeningSocket = CFSocketCreateWithNative(NULL, fdForListening, kCFSocketAcceptCallBack, ListeningSocketCallback, &context);
    fdForListening = -1;        // so that the clean up code doesn't close it
    rls = CFSocketCreateRunLoopSource(NULL, self->_listeningSocket, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
    [[NSNetService alloc] initWithDomain:@"" type:kServiceTypeBatteryStatus name:self.serviceName port:chosenPort]
    Checking the documentation on all these functions, it seems that the port is automagically chosen (by Bonjour?) Which brings me to my question: what does my end user have to do to enable this code to work on their Mac?

    I searched through System Preferences but nothing jumped out at me as relevant.
  2. mfram macrumors 65816

    Jan 23, 2010
    San Diego, CA USA
    The code doesn't appear to be specifying a specific port. Since a port isn't specified before calling bind(), the operating system is assigning you a free one. The getsockname() call is pulling out the port number that the operating system assigned.

    I don't know what your app is doing with the network, so it's hard to me to tell what the issue is. Is your app accepting connections from other computers to query information?

    If so, the problem is that you're going to get blocked if a firewall is enabled. The comments imply maybe you're communicating with Bonjour. Honestly, I don't know if doing that will somehow open a firewall port on your Mac, but I doubt it. The comment about "corporate environment" also implies using a firewall which is pretty standard practice.

    That would be why the user is asking about specific ports and protocols. If the port is hard-coded into your app then a firewall hole could be opened to allow external connections to your app. Or if your app used HTML or some other well-known protocol, the firewall could be programmed to allow it.

    But if you're using a custom protocol and you aren't hard-coding a port to use then that's not going to be compatible if a firewall is enabled on the Mac or on some other part of the network where the Mac is connected.

    I would read the Bonjour document about if or how it handles opening holes in the firewall on the Mac to allow connections. I haven't studied Bonjour enough to know about those details.
  3. ghellquist macrumors regular

    Aug 21, 2011
    Stockholm Sweden

Share This Page