Praveen Sharma
Praveen Sharma

Reputation: 181

Cannot Connect to IPv6 with CocoaAsyncSocket

Having issues connecting to iPv6 hosts with the CocoaAsyncSocket library

I successfully had GCDUDPAsyncSocket working but realized TCP was more appropriate for my use case.

Unfortunately - I can never successfully connect with a bonjour published and discovered NSNetService. The service is discovered and the address is discovered as well. A connection attempt without failure happens but the connection is never secured.

I can connect using "connectWithHost" and passing in the IP address assigned to my mac but this the only way i can get that ip is by hard coding it. Is there a way to obtain this IP through NSNetService?

I'm using swift, Xcode 7.1.1 and iOS 9.1. I am connecting between an iPhone and a Mac running an Apple TV Simulator. This works fine with UDP.

No matter what - the connection attempt times out even though an appropriate address is supplied!

Socket is Disconnecting - Error Domain=NSPOSIXErrorDomain Code=60 "Operation timed out" UserInfo={NSLocalizedDescription=Operation timed out, NSLocalizedFailureReason=Error in connect() function}

Anyone run into this before? Here is my connection code:

func connectToAddress(sender: NSNetService) {
if let addresses = sender.addresses {
    for address in addresses {
        print(address)
    }

    self.serverAddresses = addresses
    var done = false

    while !done && (self.serverAddresses.count > 0) {
        let address = self.serverAddresses[0]
        self.socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
        do {
            try self.socket.connectToAddress(address)
            done = true
        } catch {
            print("Unable to Connect")
        }
    }

    if !done {
        print("Could Not Connect To Address")
    }
}

}

Upvotes: 1

Views: 1431

Answers (2)

Raymond Liao
Raymond Liao

Reputation: 1795

You can setting

socket.IPv4PreferredOverIPv6 = NO;

as @Kumar C mentioned, it will works well in IPv6, but if you still need work with IP address(use IP address as Host), you can update the code as below in GCDAsyncSocket.m(IPv4PreferredOverIPv6 should be set to NO first):

+ (NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr
{
   ......

   for (res = res0; res; res = res->ai_next)
        {
            if (res->ai_family == AF_INET)
            {
                // Found IPv4 address.
                // Wrap the native address structure, and add to results.

                if (((struct sockaddr_in *)res->ai_addr)->sin_port == 0)
                    ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(port);

                NSData *address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
                [addresses addObject:address4];
            }
            else if (res->ai_family == AF_INET6)
            {
                // Found IPv6 address.
                // Wrap the native address structure, and add to results.

                if (((struct sockaddr_in6 *)res->ai_addr)->sin6_port == 0)
                    ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = htons(port);

                NSData *address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
                [addresses addObject:address6];
            }
        }

   .......

}

This will allows you app work well in IPv4/IPv6 whatever the HOST is IP address or domain.

Upvotes: 0

Kumar C
Kumar C

Reputation: 553

Please update your CocoaAsyncSocket library. The issue was fixed in May 2nd commit. So this should work with the following flag set to false

socket.IPv4PreferredOverIPv6 = NO;

This will allow your app / game to connect in both IPv4 and IPv6. As of June 1 Apple is rejecting the apps which are not compliant with IPv6 networks. You app should work without any problems in an IPv6 network.

Upvotes: 1

Related Questions