Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bonjour issues on iOS

I'm trying to create a Bonjour service in my iOS application, but can't get it to publish. Only the netServiceWillPublish delegate method is ever called and the service isn't showing up using dns-sd.

Here's my code:

var service: NetService? = nil

func start() {
    createSockets()

    service = NetService(domain: "test", type: "_test._tcp.", name: "Test", port: Int32(port))
    service?.delegate = self
    service?.startMonitoring()
    service?.publish()
    service?.setTXTRecord(NetService.data(fromTXTRecord: [
        "model": "AppleTV3,2,1".data(using: .utf8)!,
        "srcvers": "160.10".data(using: .utf8)!,
        "features": "0x100009FF".data(using: .utf8)!,
        "deviceId": "b8:53:ac:43:f3:15".data(using: .utf8)!,
        "pw": "0".data(using: .utf8)!,
        "rmodel": "MacBookPro10,2".data(using: .utf8)!
        ]))

}

private func createSockets() {
    ipv4Socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAutomaticallyReenableAcceptCallBack, socketCallback, nil)

    var sin = sockaddr_in()

    memset(&sin, 0, MemoryLayout<sockaddr_in>.size)
    sin.sin_len = __uint8_t(MemoryLayout<sockaddr_in>.size)
    sin.sin_family = sa_family_t(AF_INET); /* Address family */
    sin.sin_port = in_port_t(port) /* Or a specific port */
    sin.sin_addr.s_addr = INADDR_ANY

    let sincfd = withUnsafePointer(to: &sin) {
        $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<sockaddr_in>.size) {
            return CFDataCreate(kCFAllocatorDefault, $0, MemoryLayout<sockaddr_in>.size)
        }
    }

    CFSocketSetAddress(ipv4Socket, sincfd)

    let socketsource = CFSocketCreateRunLoopSource(
        kCFAllocatorDefault,
        ipv4Socket,
        0);

    CFRunLoopAddSource(
        CFRunLoopGetCurrent(),
        socketsource,
        CFRunLoopMode.defaultMode);
}

I'm new to this type of networking in iOS, what am I doing wrong here?

like image 560
Jake Avatar asked Dec 08 '16 16:12

Jake


1 Answers

Using service?.publish(options: NetService.Options.listenForConnections) and not creating the socket myself fixed the issue.

It ends up let publishing this way will automatically create a TCP listener for both IPv4 and IPv6 for the NetService.

Apple Documentation:

/* When passed to -publishWithOptions:, in addition to publishing the service, a
 * TCP listener is started for both IPv4 and IPv6 on the port specified by the
 * NSNetService. If the listening port can't be opened, an error is reported using
 * -netService:didNotPublish:. Specify a port number of zero to use a random port.
 * When -netServiceDidPublish: is called, -port will return the actual listening
 * port number. Since the listener only supports TCP, the publish will fail with
 * NSNetServicesBadArgumentError if the NSNetService type does not end with "_tcp".
 * New incoming connections will be delivered in the form of NSStreams via the
 * -netService:didAcceptConnectionWithInputStream:outputStream: delegate method.
 */
 @available(iOS 7.0, *)
 public static var listenForConnections: NetService.Options { get }
like image 167
Jake Avatar answered Sep 29 '22 23:09

Jake