Hi, for a particular application, I need to change the hostname advertised on the NWListener service. Is it possible? Thanks
Change hostname on NWListener
The standard way to have your listener register a service is with this code:
let l = try NWListener(using: .tcp, on: 12345)
let t = "_my-service._tcp"
l.service = NWListener.Service(type: t)
In that case the name
parameter of the NWListener.Service
initialiser defaults to nil
, which means it uses the device name. To override that, pass in a value to that parameter:
let n = "Guy Smiley"
l.service = NWListener.Service(name: n, type: t)
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
thanks for the reply @eskimo but this will not unfortunately change the hostname, but just the name of the service. Let me explain better my issue.
This is how the NWListener service presents itself on the network
and instead how it must be advertised
Let me know if you need more details.
this will not unfortunately change the hostname
Ah, OK, I misunderstood your goal here.
instead how it must be advertised
Why do you care about the local DNS name? That’s not something that anyone should be showing to the user.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
@eskimo unfortunately my app talks with another iOS application that looks for this particular hostname (not developed by me of course). I was able to do this until iOS 16.1 using a custom Bonjour frame, but now it seems that I need to use a multicast entitlement for this goal from one day to another :( I requested the entitlement but the process it's stucked :( Do you have any hints?
unfortunately my app talks with another iOS application that looks for this particular hostname
Have you tried escalating that with the app’s author? Working around their limitations is tricky, and it’s not going to get less tricky over time.
As to how you might work around this, the DNS-SD API (<dns_sd.h>
) has a DNSServiceRegisterRecord
routine that lets you register arbitrary records. I believe that you’ll be able to use this to register A
and AAAA
records for your device.
If you want the service discovery PTR
record to point to an SRV
record that points to your local DNS host name, you’ll need to register those yourself as well. Do that using DNSServiceRegister
, passing in a value to the host
parameter rather than using the more normal NULL
.
For a demo of how to do this, look at the implementation of the -P
option in dns-sd
. See here.
Also, the DNS-SD API can be a bit of a bear to call from high-level languages. For an example of that, see the DNSSDObjects sample code.
I don’t know if any of this requires the multicasts entitlement. It’s pretty obscure stuff.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Have you tried escalating that with the app’s author? Working around their limitations is tricky, and it’s not going to get less tricky over time.
I already tried this approach but it didn't work unfortunately.
As to how you might work around this, the DNS-SD API (<dns_sd.h>) has a DNSServiceRegisterRecord routine that lets you register arbitrary records. I believe that you’ll be able to use this to register A and AAAA records for your device.
Yes it's what I tried 2 days ago but the Domain on iOS never been registered. The API itself returns ok without error. This is the code:
DNSServiceErrorType err;
char txtMac[255];
TXTRecordRef recordMac;
TXTRecordCreate(&recordMac, 255, &txtMac);
err = TXTRecordSetValue(&recordMac, "mac-address", mac.toUtf8().length(), mac.toUtf8());
err = TXTRecordSetValue(&recordMac, "serial-number", serialN.toUtf8().length(), serialN.toUtf8());
err = TXTRecordSetValue(&recordMac, "ble-service-uuids", ble_uuids.toUtf8().length(), ble_uuids.toUtf8());
DNSRecordRef recordRef;
const char *hostname = "WAHOO KICKR 0000H"
DNSServiceErrorType error;
DNSServiceRef dnsRef;
struct in_addr *addr = atoaddr("192.168.0.46");
error = DNSServiceCreateConnection(&dnsRef);
error = DNSServiceRegisterRecord(dnsRef, &recordRef, kDNSServiceFlagsUnique | kDNSServiceFlagsShareConnection, 0, hostname, kDNSServiceType_A, kDNSServiceClass_IN, sizeof(struct in_addr), addr, 240, TXTRegisterCallback, NULL);
err = DNSServiceRegister(&ref1, 0, 0, serverName.toUtf8().constData(), "_wahoo-fitness-tnp._tcp", "local", serverName.toUtf8().constData(), htons(serverPort), strlen(txtMac) /* txtLen */, txtMac /* txtRecord */, register_reply_callback, NULL);
DNSServiceProcessResult(ref1);
I can see everything correct using the Discovery app, for example, but the domain is not registered. Is this API requires some special entitlement or something on iOS?
I don’t know if any of this requires the multicasts entitlement. It’s pretty obscure stuff.
Yes it's my fear too. Also if I can access to the entitlement, I can directly use the code that was working since iOS 16.1
Is this API requires some special entitlement or something on iOS?
I don’t know for sure.
My advice is that you try it on the Mac, just for testing purposes. macOS does not implement local network privacy, so there’s no potential for that to get in the way. And you can do your initial prototype with the dns-sd
tool.
If your code works on the Mac but fails on iOS, it’s quite possible that local network privacy is getting in your way.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
My advice is that you try it on the Mac, just for testing purposes. macOS does not implement local network privacy, so there’s no potential for that to get in the way. And you can do your initial prototype with the dns-sd tool.
Are you sure about this? All this problem started when iOS 16.1 and Ventura released in the same day. So I guess there is the same limitation. The issue is not present in iOS < 16.1 and on MacOS < Ventura.
Are you sure about this?
Am I sure that macOS does not implement local network privacy? Yes, absolutely. The fact that your previous code fails on both iOS and macOS suggests that something else is afoot. It might be changes to common code that’s related to LNP, but it’s not LNP per se.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thanks @eskimo Apple gave me finally the entitlment so now everything works again as expected! Thanks for your support :)
so now everything works again as expected!
With your previous code? Or new code that uses the DNS-SD API?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
The previous one, without modifying. Now with the entitlement everything is working again. This sounds to me like a confirmation that something has changed in the 16.1 version
The previous one, without modifying.
OK.
To be clear, this isn’t an approach I recommend. It’s akin to building your own mDNS responder, which is hard to do right and not something we support.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"