Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Howto: query meta service _services._dns-sd._udp.local #20

Open
chinenual opened this issue Sep 19, 2020 · 6 comments
Open

Howto: query meta service _services._dns-sd._udp.local #20

chinenual opened this issue Sep 19, 2020 · 6 comments

Comments

@chinenual
Copy link

chinenual commented Sep 19, 2020

I'm trying to send out a unicast QU for service discovery at startup of my application. I can't find a way to use the library to do that. LookupType() does not expose a way to set the unicast bit and unconditionally sends out a QM query.

I tried to copy and paste the browse.go functions into my app and adapt them, but got stuck since I can't create a Query struct (all fields are unexported) and I can't find a public constructor function.

Ideas?

(if you agree that this is a reasonable use case and adding a call to setQuestionUnicast() in lookupType is the fix, I could create a pull request. Perhaps create a new func LookupTypeUnicast() that passes in a boolean to tell lookupType() to set the bit?)

@chinenual
Copy link
Author

chinenual commented Sep 19, 2020

To recap: I'm trying to fix behavior in the current library that causes a LookupType() to not see some services that have already registered themselves with mDNS prior to my application startup. I've observed another application that appears to solve this by sending out a _services._dns-sd._udp query at startup - and gets answers for everything on the network.

.... actually I think my proposed solution may not be sufficient (see below for how it behaves):

I am using wireshark to try to understand how a general bonjour browser works (Discovery on macos). I see it send out a QU query for _services._dns-sd._udp.local and gets Answers for everything on the network.

I've made a local copy of the dnssd module with the proposed fix:

func LookupTypeUnicast(ctx context.Context, service string, add AddServiceFunc, rmv RmvServiceFunc) (err error) {
	conn, err := newMDNSConn()
	if err != nil {
		return err
	}
	defer conn.close()

	return lookupType(ctx, service, conn, add, rmv, true)
}

func lookupType(ctx context.Context, service string, conn MDNSConn, add AddServiceFunc, rmv RmvServiceFunc, unicast bool) (err error) {
...
	if unicast {
		setQuestionUnicast(&m.Question[0])
	}

and call it like this from my application:

                serviceType := "_services._dns-sd._udp.local."
		logger.Infof("ZEROCONF: serviceDiscovery %s\n", serviceType)
		if err = dnssd.LookupTypeUnicast(ctx, serviceType, addFn, rmvFn); err != nil {
			if strings.Contains(err.Error(), "context deadline exceeded") {
				logger.Debugf("ZEROCONF: ListenFor %s %v\n", serviceType, err)
			} else {
				logger.Errorf("ZEROCONF: ListenFor %s %v\n", serviceType, err)
			}
			return
		}

I can see the query via wireshark and it looks identical to the one I see from Discovery -- however mine has no answers. Is there something else I need to do ?

@chinenual
Copy link
Author

chinenual commented Sep 20, 2020

I have created a pull request that implements unicast queries. It solves my "missing answer at app startup" bug. (despite my previous comment suggesting that it was not sufficient, I've been testing since and it does appear to solve the problem).

#21

@brutella
Copy link
Owner

Thanks for your effort. I've made some significant changes to the library in the refactoring branch. Your issue might already be fixed in that branch.

@chinenual
Copy link
Author

chinenual commented Sep 29, 2020

I peeked at the refactoring branch and don't see anything similar.

FWIW: I've had to change my forked library to be based on the released v1.1.1 tag rather than master. When I run with master, my application chews up 100% CPU continuously while browsing. I've not been able to profile the library to determine why. v1.1.1 does not have this problem.

After testing this for several days, I am no longer sure that this Unicast browse really solves my problem. Even with the unicast query, I am seeing frequent cases where a service started before my application is not seen by the query until that service is restarted.

@brutella
Copy link
Owner

I've experienced that unicast responses are never received #15. That's why the library do not use them – see probe.go

I was not able to figure out why this happens. Any ideas?

@chinenual
Copy link
Author

chinenual commented Oct 26, 2020

I just tried commenting out the SetQuestionUnicast() in my fork -- unfortunately it doesn't seem to improve things.

I spent a considerable time staring at Wireshark logs trying to understand what makes my app using dnssd different than, for example, the Discovery bonjour browser application in the mac store. Other than the unicast difference I could not spot a difference. I really don't know how to diagnose this any further.

What's weird is that for my application, I browse for two different service types. One always works. The other rarely works. Both work 100% reliably in the Discovery app.

_osc._udp.local. reliably responds immediately (the app is touchosc running on two different ios devices).
The other is a JUCE-based VST (_synergia._tcp.local.) running on the localhost which rarely responds unless I restart it after I've started my browse. I've reviewed the library that app is using (https://github.com/Anthony-Nicholls/jucey_bonjour); it seems to be directly using Apple's SDK so I have no reason to suspect it's doing something wrong...

I'm open to any and all ideas of how to debug/diagnose this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants