jbagg / QtZeroConf

Qt wrapper class for ZeroConf libraries across various platforms.
Other
69 stars 51 forks source link

Stopped working for ios 17 #64

Closed zeroalphagit closed 5 months ago

zeroalphagit commented 7 months ago

I have had this working fine until ios 17 update. I can't get it to find any mdns services from different iphones all running ios 17. Anyone have this working on ios17?

zeroalphagit commented 6 months ago

I connected to the onError signal and it gives me -3

    function onError(error) {
        console.log('zeroConf Error: ', error)
    }
jbagg commented 6 months ago

Do you have

NSLocalNetworkUsageDescription
NSBonjourServices

set in your info.plist?

jbagg commented 6 months ago

error -3 is browser failed (from qzeroconf.h) enum error_t { noError = 0, serviceRegistrationFailed = -1, serviceNameCollision = -2, browserFailed = -3, };

jbagg commented 6 months ago

Is service publishing and browsing broken or only browsing? If your app does not have service publishing, please run the example on your iOS17 device as well as a computer. They should see each other.

jbagg commented 5 months ago

Hi, I just wanted to make sure you got my message...

Do you have

NSLocalNetworkUsageDescription NSBonjourServices

set in your info.plist?

zeroalphagit commented 5 months ago

Hello thanks for replying :)

Yes I have included this in my info.plist

<key>NSLocalNetworkUsageDescription</key>
<string>This app requires network access to send information.</string>  
<key>NSBonjourServices</key>
    <array>
        <string>_test._tcp</string>
    </array>

Last year (2023) The app was working perfectly fine on android and ios 16. This year (2024) phones were updated to ios17 and latest android and now zeroconf stopped working.

It was successfully working on QT 6.4 & 6.5. I have updated to 6.6 but no help. I have tried with several

We are publishing a zerconf service using python which is working.

I think the browserFailed (-3) error confirms something is wrong with my ios/android project. I have been trying to troubleshoot this for a while. Its not possible the SDK or QT has changed something. A lot of app developers reported zeroconf problems after ios 17

zeroalphagit commented 5 months ago

I ran the example and it works fine on ios17 with Qt 6.6.2

I am using QML

I might try going back to c++

jbagg commented 5 months ago

Please apply this patch and run your qml app. There are 4 places that can generate browserFailed. bonjour_debug1.txt (I had to use .txt as github does not allow files with .patch)

zeroalphagit commented 5 months ago

i ran the patch and i think browser is running ok now. Not getting any browser errors.

But im not getting the onServiceAdded / onServiceRemoved signals either

jbagg commented 5 months ago

You should have a new debug message "browser failed .....xyz". Does c++ qDebug() output make it out in a python app?

zeroalphagit commented 5 months ago

startBrowser is working. The -3 error was because I was calling it when it was already active. This turns out to be a red herring.

I have confirmed that bonjour.cpp does find my zeroconf service. I added more qDebug():

Service found: test-service Type: _test._tcp. Domain: local.

void DNSSD_API QZeroConfPrivate::browseCallback(DNSServiceRef, DNSServiceFlags flags,
                                                quint32 interfaceIndex, DNSServiceErrorType err, const char *name,
                                                const char *type, const char *domain, void *userdata)
{
    QString key;
    QZeroConfService zcs;
    QZeroConfPrivate *ref = static_cast<QZeroConfPrivate *>(userdata);

    qDebug() << "Service finder running";

    if (err == kDNSServiceErr_NoError) {
        key = name + QString::number(interfaceIndex);
        if (flags & kDNSServiceFlagsAdd) {
            if (!ref->pub->services.contains(key)) {
                zcs = QZeroConfService::create();
                zcs->m_name = name;
                zcs->m_type = type;
                zcs->m_domain = domain;
                zcs->m_interfaceIndex = interfaceIndex;
                ref->resolve(zcs);
                qDebug() << "Service found: " << name << " Type: " << type << " Domain: " << domain;
            }
        }
        else if (ref->pub->services.contains(key)) {
            zcs = ref->pub->services[key];
            ref->pub->services.remove(key);
            if (ref->resolvers.contains(key))
                ref->resolvers[key]->cleanUp();
            emit ref->pub->serviceRemoved(zcs);
            qDebug() << "Service removed: " << name << " Type: " << type << " Domain: " << domain;
        }
    }
    else {
        ref->cleanUp(ref->browser);
        qDebug() << "Browser failed to find services.";
        emit ref->pub->error(QZeroConf::browserFailed);
    }
}

The problem now is that I am not getting any signals back in QML except for onError

    QZeroConf {
        id: zeroConf
        Component.onCompleted: {
              zeroConf.startBrowser("_test._tcp")
       }

        onServiceAdded: (serviceName)=> {console.log("not working 1")}
        onServicePublished: (serviceName)=> {console.log("not working 2")}
        onServiceUpdated: (serviceName)=> {console.log("not working 3")}
        onError: (error)=> {console.log("This error is working ", error)}
    }

Doesn't matter if i try with QML type connections. Im not getting any of these signals

 Connections {
        target: zeroConf

        onServiceAdded: {
            console.log("Service added:", serviceName)
        }

        onServicePublished: {
            console.log("Service published:", serviceName)
        }

        onServiceUpdated: {
            console.log("Service updated:", serviceName)
        }

        onError: {
            console.log("Error:", error)
        }
    }

QML is just not receiving these signals....

zeroalphagit commented 5 months ago

I found the problem: resolverCallback never gets called.

In bonjour.cpp line 88 is responsible for calling it: err = DNSServiceResolve(&resolver->DNSresolverRef, kDNSServiceFlagsTimeout, zcs->interfaceIndex(), zcs->name().toUtf8(), zcs->type().toUtf8(), zcs->domain().toUtf8(), static_cast(resolverCallback), resolver);

This gets called but function resolverCallback never gets called from the SDK. Which means we never get as far as addressReply and the signal never gets emitted.

My zeroConf service is published via python so i will modify the example code and see if it can connect to python instead of itself.

jbagg commented 5 months ago

After DNSServiceResolve() is called, a QSocketNotifier is used to "wakeup" an run the resolverCallback. Maybe the QSocketNotifier is not working with python? Please try this patch. It forces the resolverCallback to run after 1.5 seconds.

jbagg commented 5 months ago

bypass-socket-notifier.txt

zeroalphagit commented 5 months ago

I FOUND THE SOLUTION!!!

Well these guys found the solution: https://github.com/esp8266/Arduino/issues/9046#issuecomment-1913728940

I did the same thing with my python-zeroconf code by simply adding a TXT record to the published service and now the ios callback is working again.

I am using python-zeroconf to publish my service so I just had to assign a record to the properties parameter: https://python-zeroconf.readthedocs.io/en/latest/api.html