Since the Multipeer Connectivity framework no longer supports Bluetooth.
(https://developer.apple.com/forums/thread/749346)
Why does its official documentation still mention "In iOS, the framework uses infrastructure Wi-Fi networks, peer-to-peer Wi-Fi, and Bluetooth personal area networks for the underlying transport." ?(https://developer.apple.com/documentation/multipeerconnectivity)
What is the purpose of using Bluetooth personal area networks for the underlying transport?
Bonjour
RSS for tagBonjour, also known as zero-configuration networking, enables automatic discovery of devices and services on a local network using industry standard.
Posts under Bonjour tag
43 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello, In this inquiry(https://developer.apple.com/forums/thread/747860), I came across this conclusion.
“Apple disabled TCP/IP networking over Bluetooth completely. Apple’s peer-to-peer networking APIs now run exclusively over Wi-Fi."
I have three questions I would like to ask.
The Multipeer Connectivity Framework supports Wi-Fi networks, peer-to-peer Wi-Fi, and Bluetooth personal area networks. Since the framework abstracts away the underlying protocols, we cannot specify which protocol to choose. Can this framework still establish a pure Bluetooth connection now? (Not just using Bluetooth for the discovery phase).
Given that the framework supports Bluetooth protocols, why does it not require Bluetooth permissions but only local network permissions?
Does the Bluetooth protocol supported by the framework have the capability to discover traditional Bluetooth devices and services that the Core Bluetooth framework can discover?
I am currently attempting to resolve the hostname of a device connected to the same Wi-Fi network as mine. However, I've been unable to find sufficient resources or documentation on utilising the NBNS (NetBIOS Name Service) protocol for this purpose. Can someone please provide guidance on how to achieve this?
I compiled the Bonjour source code myself both for Linux and windows.
Then I succeed in publishing and detecting services for two Windows devices.
But I can't use Bonjour between a windows device and a Linux device.
So is this a limitation? If not, any tips on how to solve it?
Using the Bonjour service requires obtaining local network permissions, but the Bonjour service also scans nearby devices through Bluetooth. Why doesn't Bluetooth permission be required?
https://developer.apple.com/library/archive/qa/qa1753/_index.html#apple_ref/doc/uid/DTS40011315/
Did I misunderstand? Is there an issue with the design of iOS here?
Local network permissions are required to use the Bonjour service, But Bonjour service can also detect nearby devices through Bluetooth scanning without Bluetooth permission.
https://developer.apple.com/library/archive/qa/qa1753/_index.html#apple_ref/doc/uid/DTS40011315/
Did I misunderstand? Or is there an issue with Apple's design here?
unresolved external symbol _mdns_malloc@4 referenced in function _syslog dnssd \mDNSResponder-2200.80.16\mDNSWindows\DLL\dnssd_clientstub.obj
unresolved external symbol _mdns_free@4 referenced in function _syslog dnssd \mDNSResponder-2200.80.16\mDNSWindows\DLL\dnssd_clientstub.obj
I am facing this error on my SDK project. Could not identify what's the actual issue. I've added the Firebase crash logs below.
Crashed: com.apple.root.default-qos
0 libdispatch.dylib 0x1a778 dispatch_channel_cancel + 12
1 libdispatch.dylib 0x1a778 dispatch_source_cancel + 12
2 libsystem_dnssd.dylib 0x2084 DNSServiceProcessResult + 860
3 Common 0x2df04 __swift_memcpy5_4 + 25916
4 Common 0x10b00 block_destroy_helper.10 + 188
5 libdispatch.dylib 0x26a8 _dispatch_call_block_and_release + 32
6 libdispatch.dylib 0x4300 _dispatch_client_callout + 20
7 libdispatch.dylib 0x744c _dispatch_queue_override_invoke + 928
8 libdispatch.dylib 0x15be4 _dispatch_root_queue_drain + 392
9 libdispatch.dylib 0x163ec _dispatch_worker_thread2 + 156
10 libsystem_pthread.dylib 0x1928 _pthread_wqthread + 228
11 libsystem_pthread.dylib 0x1a04 start_wqthread + 8
Hello!
I'm working on VLC, that is a multimedia playback app available for any platform.
Among many things, we support discovery of servers on the local network using Bonjour, UPnP and NETBIOS with consecutive connections to those servers for media playback purposes. Additionally, we allow connections to unicast and multicast streams based on any domain name or IP (i.e. "rtsp://207.254.***.***"). Discovery of the mentioned services works very well with the Multicast entitlement along with NSLocalNetworkUsageDescription also on iOS 17.
According to documentation, iOS 17 prohibits any IP based connections by default, which breaks the entire functionality mentioned above that was previously enabled by including the NSAllowsArbitraryLoads key with the value TRUE in Info.plist.
We amended the Info.plist with the following configuration and still fail to connect to hosts in that IP range.
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>192.168.0.0/24</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionAllowsLocalNetworking</key>
<true/>
</dict>
</dict>
Additionally, there does not seem to be a viable, publicly documented solution to connect to any server on the internet based on an IP address. Further, the process for IPv6 seems unclear.
Any help how to solve this so we can transition to the iOS/tvOS 17 SDK in time would be very much appreciated.
How to get full DNS responses from the system resolver? DNSServiceQueryRecord not returning errors..
I would like to get the full DNS responses from the system resolver. I'm using DNSServiceQueryRecord, but I can't get negative responses. How do I get the negative responses?
I need the full response because they have clues about network-level censorship. For instance, mismatched case in the name, bad answer RR type, missing SOA record on no answers response.
On Android I can use android_res_nquery, but I couldn't find anything similar on iOS and macOS. The closest I found was DNSServiceQueryRecord, which at least gives me resource records, so I can inspect TTL and name case.
After some struggle, I was able to make it work. I'm using Go with cgo for that: https://github.com/fortuna/gio-test/blob/fortuna-dns/sysresolver_darwin.go
https://github.com/fortuna/gio-test/blob/fortuna-dns/sysresolver_darwin_export.go
My sequence of calls is:
DNSServiceQueryRecord(sdRef, 0, 0, fullname, rrtype, rrclass, (DNSServiceQueryRecordReply)goCallback, context);
fd := C.DNSServiceRefSockFD(sdRef)
nReady, err := unix.Poll([]unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN | unix.POLLERR | unix.POLLHUP}}, timeout)
serviceErr = C.DNSServiceProcessResult(sdRef)
// Here my callback gets called, multiple times for multiple answers.
C.DNSServiceRefDeallocate(sdRef)
I'm able to get positive answers, even multiple answers. But the Poll doesn't return when there are no answers (like for CNAME www.example.com). I expected the poll to return on negative answers, and my callback to be called with an error when calling DNSServiceProcessResult.
Is that not the expected behavior? How do I get notified that a query has no answers?
Hi,
I have a strange problem. In my local network, I have some apple devices (including mac, iphone, ipad) and a windows computer. The windows pc and any of the apple devices can ping each other, while every two of the apple devices can't ping each other. Whether udp or tcp are in the same situation. As is the situation, the firewall/mask/local ip are not the problems. I can't use wireshark to debug, because there is not any packet between these apple devices.
Does someone know what the problem it may be? Or could someone tell me how to debug this?
Thanks in advance!
After upgrading to iOS 17 (now 17.2.1) on iPhone 11 pro the device does not appear to be discoverable on the local network via Bonjour. This is impeding, e.g., connecting to the device with iMazing etc. I looked at the local network with the Discovery app for Bonjour and while an iPad running iOS 16 is visible, the iPhone with iOS 17 is not. Any ideas ? We need to connect with iMazing via wifi since the mighty lightning port is predictably hosed for USB connection. Any insight appreciated. Thanks!
It worked fine before iOS 17.1. Just checked with iOS 16 on real device. And my teammate from QA department confirmed it works for iOS 17.0.1.
The problem occurs only with device in local network connected via ethernet. The device itself has two options for connection - via Wi-Fi and Ethernet. It works for all iOS versions via Wi-Fi. But it can't resolve host for Ethernet connection.
Error appears in
func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber])
looks like that:
(NSNetServicesErrorDomain: 10,
NSNetServicesErrorCode: -72007)
Could you please explain this error code?
I expect there is a shockingly obvious answer to this, but I've been stuck a couple of days on Problem Obvious and could use a tip / cake-with-file to escape from development jail.
I have used DNSServiceRef / Bonjour to advertise my service, and have used the same to get a list of what is advertised (using the hit on lo0 for the moment since still testing). So, now I have a machine name "mymachine.local." and the right port number to connect to. Yay!
What I can not figure out is how to get that information into a (IPV6) sockaddr so I can use it with connect. The point of confusion for me is that DNSServiceGetAddrInfo() does not take a port argument, and I see no other place to squeeze this information into the sockaddr returned by the DNSServiceGetAddrInfoReply.
If I just use a IPV6 socket with that sockaddr, I get back EADDRNOTAVAIL. Haven't tried IPv4. No error is returned from DNSServiceGetAddrInfo. I'm reading around that this may be because the port is 0, and indeed I can't find any spot in this pathway to squeeze that information in.
I'll attach an obligatory bit of code so that the reader may feel more grounded:
// My DNSServiceGetAddrInfoReply
void ServiceList::Node::AddressInfoCallback( DNSServiceRef __nonnull _sdRef,
DNSServiceFlags _flags,
uint32_t _interfaceIndex,
DNSServiceErrorType _errorCode,
const char * __nullable _hostname,
const struct sockaddr * __nullable _address,
uint32_t UNUSED _ttl, void * __nonnull context)
{
printf( "AddressInfo: \"%s\"\n", _hostname);
AddrInfo * info = (AddrInfo*) context;
if( kDNSServiceErr_NoError != _errorCode || NULL == _hostname || NULL == _address)
{
LOG_ERROR("Failed to get address info on \"%s\"\n", (const char*) info->hostTarget);
delete info;
return;
}
int err = connect(info->socket, _address, _address->sa_len); // returns EADDRNOTAVAIL on IPv6 socket.
What am I really trying to do? I'd like to connect to the address and port that I from my DNSServiceResolveReply.
Hey All,
I'm currently trying to use the BCT v1.5.3 to validate the avahi mdns implementation. This is not so much to validate the avahi implementation but to actually understand how the BCT works.
My setup is the following:
the testing machine, where the BCT runs, is a 13-inch MacBook Pro 2019
the DUT (Device Under test) where avahi runs is a Linux machine (arch) and avahi runs version 0.8
I've tried several connection between the two:
they have been connected point-to-point by a single network cable and the IPs have been set statically
they have been connected via a router (that's not connected to the interned) both by cable and with IPs statically set
connected via a router where the BCT computer is connected via cable and the DUT is connected via WIFI.
My requirement is to run only the MDNS tests so the command I'm issuing on the BCT side is:
sudo ./BounjourConformanceTest -M -I en4 -DD -V -Aip None -Amac None
On the DUT side I start avahi as a daemon:
sudo avahi-daemon
And after that I also publish a service. I've done several tries but one that I think should be working is:
sudo avahi-publish -s "My HAP Service" _hap._tcp 3213 []
I can see the three packets that make up the probing packets spaced out at 250ms each on wireshark both on the DUT and on the BCT device and the BCT prints:
recv_packet 01997: received packet (96 bytes)
recv_packet 01997: received packet (96 bytes)
recv_packet 01997: received packet (96 bytes)
But the tests doesn't seem to finish correctly.
What am I doing wrong? Is my configuration incorrect/incomplete? Do I need to advertise a certain service?
Thanks for the response in advance.
Hello there,
We have an iPad application which uses mDNS to find specific devices on the network then it resolves an IP address so then the application can connect to it through websocket. It has been working for years now. Recently our clients started to update their iPads to iOS 17 and suddenly this functionality stopped working.
When I wanted to test out what's going on I found out that when I run the application on an iPad simulator on my macbook it can resolve the IP address immediately but when I run it on an iPad it cannot. That seemed weird so I decided to look into the code and I saw that the NetServiceBrowser api had been deprecated and I thought that maybe that's the problem so I refactored the code to use NWBrowser which was rather easy it found the service, but then when I wanted to meg an NWConnection to it the same error happened. From macOS it works fine but on the iPad the connection's state never gets ready, it hangs on the preparing state.
I created a new test application just with this functionality to test it on an iPhone too. Well it seems that the issue is appearing on the iOS too.
One other thing to mention, I created a simple node.js application which uses mDNS broadcast to simulate this device which we're trying to connect. The weird part that both the iPad and the iPhone can resolve it's address.
I'm curious if something has changed since iOS 16, I couldn't find anything and I don't know where to go next, or how can somebody reproduce this error without the device. Any help is appreciated.
Here is my discovery code:
import UIKit
import Network
class ViewController: UIViewController {
var browser: NWBrowser!
override func viewDidLoad() {
super.viewDidLoad()
browser = NWBrowser(for: .bonjour(type: "_http._tcp", domain: ""), using: .tcp)
browser.stateUpdateHandler = { newState in
switch newState {
case .failed(let error):
print("NW Browser: now in Error state: \(error)")
self.browser.cancel()
case .ready:
print("NW Browser: new bonjour discovery - ready")
case .setup:
print("NW Browser: ooh, apparently in SETUP state")
default:
break
}
}
browser.browseResultsChangedHandler = { ( results, changes ) in
print("NW Browser: Scan results found:")
for result in results {
switch result.endpoint {
case let .service(name: name, type: _, domain: _, interface: _):
// All of our device has 'justfit' in their name
if name.uppercased().contains("JUSTFIT"){
print(name)
let proto: NWParameters = .tcp
if let opt = proto.defaultProtocolStack.internetProtocol as? NWProtocolIP.Options {
opt.version = .v4
}
let connection = NWConnection(to: result.endpoint, using: proto)
connection.stateUpdateHandler = { state in
if state == .ready {
if let path = connection.currentPath, let endpoint = path.remoteEndpoint {
switch(endpoint) {
case let .hostPort(host: host, port: port):
print("IP: \(host), port: \(port)")
break
default:
break
}
connection.cancel()
}
} else {
print(state)
}
}
connection.start(queue: .main)
}
default:
break
}
}
}
browser.start(queue: .main)
}
}
I'm running a webserver for a specific service on port 8900
I'm using telegraph to run the webserver, so that opens and claims the port.
I also want to advertise the service on bonjour - ideally with the correct port.
This is trivial with NetService - but that's deprecated, so I should probably move to the Network framework.
I can advertise without specifying a port
listener = try NWListener(service: service, using: .tcp)
but, then my service broadcasts addresses with port:61443
I can advertise using
listener = try NWListener(using: .tcp, on: <myport>)
however, that fails in my use case because (unsurprisingly) the Listener isn't able to get the port (my server already has it)
Is this just a gap in the new API, or am I missing something?
We use the OSS release of mDNSresponder fairly extensively and have patched it to fix some issues.
I was curious if Apple accepted such contributions upstream, or provided a way to communicate the changes for potential inclusion in future patches, as maintaining a fork isn't ideal for both parties.
It seems that PRs on the GH repo are not always reviewed, but there is some evidence that they are looked at. We realise that POSIX implementation for mDNSResponder might not be a priority for Apple, but curious if there's a process for contributions from industry?
I'm attempting to create a service that:
Listens on iOS device A using NWListener
Broadcasts the NWService ( using NWListener(service:using:)) ) on Bonjour
Allows a separate device, iOS device B, to receive information about that service via an NWBrowser
Connect to that service using the information contained in NWBrowser.Result 's NWEndpoint
I've been able to successfully do this using a SwiftNIO service, in the following environments:
iOS device A and iOS device B are physical iOS devices on the same WiFi network. This works.
iOS device A and iOS device B are iOS simulators on the same machine. This works.
iOS device A is a physical device, and iOS device B is a simulator. iOS device A is not connected to a WiFi network, iOS device B is connected to a WiFi network. This works.
However, when iOS device A and iOS device B are physical devices that are not connected to a WiFi network, I encounter the following behavior:
The Bonjour service is correctly advertised, and iOS device A and iOS device B are able to observe the advertisement of the service.
In both cases, iOS device A and iOS device B, while able to resolve an NWEndpoint for the Bonjour service, are not able to connect to each other, and the connection attempt hangs.
My setup for the listener side of things looks roughly like:
let opts: NWParameters = .tcp
opts.includePeerToPeer = true
opts.allowLocalEndpointReuse = true
let service = NWListener.Service(name: "aux", type: BONJOUR_SERVICE_TYPE, domain: "")
try bootstrap.withNWListener(NWListener(service: service, using: opts)).wait() // bootstrap is an artifact of using SwiftNIO
Similarly, my setup on the discovery side of things looks like:
let params: NWParameters = .tcp
params.includePeerToPeer = true
let browser = NWBrowser(for: .bonjour(type: BONJOUR_SERVICE_TYPE, domain: BONJOUR_SERVICE_DOMAIN), using: params)
browser.browseResultsChangedHandler = { (searchResults, changed) in
// save the result to pass on its NWEndpoint later
}
and finally, where I have an NWEndpoint, I use SwiftNIO's NIOTSConnectionBootstrap.connect(endpoint:) to initialize a connection to my TCP service ( a web socket server ).
The fact that I am able to get P2P networking (presumably over an awdl interface?) between the simulator and the iOS device suggests to me that I haven't done anything obviously wrong in my setup. Similarly, the fact that it works over the same WiFi network and that, in P2P, I am able to at least observe the Bonjour advertisement, strikes me that I'm somewhere in the right neighborhood of getting this to work. I've also ensured that my Info.plist for the app has a NSLocalNetworkUsageDescription and NSBonjourServices for the Bonjour service type I'm browsing for.
I've even attempted to exercise the "Local Network Permission" dialog by using a hacky attempt that sends data to a local IP in order to trigger a permissions dialog, though the hack does not appear to actually force the dialog to appear.
Is there some trick or other piece of knowledge regarding allowing the use of P2P w/ Network.framework and TCP connections to services?
Hi, I'm new to swift programming and right now writing an app for esp8266-controlled lamp device. My lamp is broadcasting it's own IP through bonjour. So all I want is to discover any lamps in my network (http.tcp) and to read name and value. Is there any example of such implementation? All I found so far is old or a lit bit complicated for such simple question. Thanks in advance!