Post

Replies

Boosts

Views

Activity

Reply to NWBrowser + NWListener + NWConnection
@DTS Engineer I have searched here on the forums for "WiFi Aware" and have read through just about every post. In a lot of them the person says they were able to get the example app (https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps) working with their iOS devices. I, for some reason, am not able to get the example app to fully work. I am able to build the app and load the app onto two physical iPhone 12 minis. I follow the steps shown here https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps but I get stuck because I can't get past the "enter this pin code to connect" step. I make one device be a host of a simulation and the other to view a simulation. On each device I tap the "+" button. On the viewer device I tap the discovered device. On the host device I then see the pin. I then enter the pin on the viewer device. After this step nothing happens. My only choice on the viewer device is to tap "cancel" and exit the "enter the pin step". If I go into the actual device settings I see that the devices are "paired" but the app doesn't seem to think so. Are there some special settings I need to turn on for the app to work properly? I have a second question that pertains to the new iOS 26 Networking stuff (NetworkBrowser, NetworkListener, NetworkConnection). So as you know I'm currently using NWBrowser, NWListener, NWConnection with Bonjour and QUIC. All it is working as expected. I wanted to try and migrate all my code to use the the new APIs (still use bonjour and NOT use wifi aware) but hit some issues. I was following how the example app was receiving messages like this for try await messageData in connection.messages { but got these errors Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Copyable' Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Escapable' Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Copyable' Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Escapable' When I ask Cursor about this its response was as follows: "The connection.messages stream changed in the new Network APIs: it now yields typed (content, metadata) tuples. Iterating with for try await incoming in connection.messages asks the compiler to conform that tuple to Copyable/Escapable; for QUIC the tuple isn’t copyable, so you hit the conditional-conformance error." I am curious if you've been able to use the new iOS 26 network APIs with QUIC?
Nov ’25
Reply to NWBrowser + NWListener + NWConnection
Note that both iPhone 12 minis are on iOS 26.0.1, both have the wifi toggle ON. I took the example app and paired it down to just send back simple messages based on user button taps. These are my logs from when i start up the app and start on device as the hoster and one as the viewer. Selected Mode: Hoster Start NetworkListener [L1 ready, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: waiting(POSIXErrorCode(rawValue: 50): Network is down) [L1 ready, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: ready [L1 failed, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: failed(-11992: Wi-Fi Aware) nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel Networking failed: -11992: Wi-Fi Aware Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Could not find attribute name in domain plist" UserInfo={NSLocalizedFailureReason=Could not find attribute name in domain plist}> <0x105e35400> Gesture: System gesture gate timed out. Selected Mode: Viewer Start NetworkBrowser [B1 <nw_browse_descriptor application_service _sat-simulation._udp bundle_id=com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J device_types=7f device_scope=ff custom:109>, generic, interface: nan0, attribution: developer]: ready nw_browser_update_path_browser_locked Received browser Wi-Fi Aware nw_browser_cancel [B1] The browser has already been cancelled, ignoring nw_browser_cancel(). [B1 <nw_browse_descriptor application_service _sat-simulation._udp bundle_id=com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J device_types=7f device_scope=ff custom:109>, generic, interface: nan0, attribution: developer]: failed(-11992: Wi-Fi Aware) nw_browser_cancel [B1] The browser has already been cancelled, ignoring nw_browser_cancel(). Networking failed: -11992: Wi-Fi Aware Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Could not find attribute name in domain plist" UserInfo={NSLocalizedFailureReason=Could not find attribute name in domain plist}> This guy stands out to me Networking failed: -11992: Wi-Fi Aware but I cant find any info on what it means.
Nov ’25
Reply to iOS 26 Network Framework AWDL not working
[quote='867952022, DTS Engineer, /thread/808917?answerId=867952022#867952022'] Did you opt in to peer-to-peer on both the listener and the browser? [/quote] I did do that. Please see my code snippets below. private func startBrowser() async throws { let parameters = NWParameters() parameters.includePeerToPeer = true // parameters.requiredInterfaceType = .wifi // parameters.prohibitedInterfaceTypes = [.cellular] try await NetworkBrowser( for: .bonjour(serviceName, domain: nil, includeTxtRecord: false), using: parameters ) .onStateUpdate { _, state in switch state { case let .failed(error): logger.error("[startBrowser]:browser failed: -> \(error)") case .ready: logger.info("[startBrowser]: browser is ready") case .cancelled: logger.error("[startBrowser]: browser cancelled") case .setup: logger.info("[startBrowser]: browser in setup") case let .waiting(error): logger.error("[startBrowser]: browser is waiting: \(error)") @unknown default: break } } .run { endpoints in self.handleBrowserEndpoints(endpoints) } } private func startListener() async throws { guard let identity = Utils.importIdentityFromPKCS12() else { logger.error("could not get identity") return } guard let certificateData = Utils.getCertificateData(from: identity) else { logger.error("could not read certificate data") return } let builder = try makeQUICParametersBuilder(identity: identity, certificateData: certificateData) @SharedReader(.thisDeviceID) var thisDeviceID let listener = try NetworkListener(for: .bonjour(name: nil, type: serviceName), using: builder) listener.service = NWListener.Service(name: thisDeviceID, type: serviceName) try await listener.onServiceRegistrationUpdate { _, change in switch change { case let .add(endpoint): logger.info("onServiceRegistrationUpdate: added \(endpoint.debugDescription)") case let .remove(endpoint): logger.info("onServiceRegistrationUpdate: removed \(endpoint.debugDescription)") @unknown default: return } } .onStateUpdate { lst, state in logger.info("\(String(describing: lst)): \(String(describing: state))") switch state { case let .failed(error): logger.error("Listener failed: \(error)") case .ready: logger.info("Listener ready") case .cancelled: logger.info("listener cancelled") case let .waiting(error): logger.error("listener is waiting: \(error)") case .setup: logger.info("listener setup") @unknown default: break } } .run { connection in logger.info("listener run callback received connection") await self.handleInboundConnection(connection) } } private func makeQUICParametersBuilder(identity: SecIdentity, certificateData: Data) throws -> NWParametersBuilder<QUIC> { guard let nwIdentity = sec_identity_create(identity) else { throw NetworkingError.failedToCreateIdentity } var quic = QUIC(alpn: ["captadoh"]) quic = quic.idleTimeout(0) quic = quic.tls.localIdentity(nwIdentity) quic = quic.tls.certificateValidator { _, secTrust async -> Bool in let trust = sec_trust_copy_ref(secTrust).takeRetainedValue() guard let certificates = SecTrustCopyCertificateChain(trust) as? [SecCertificate], let peerCertificate = certificates.first else { logger.error("Failed to get peer certificate") return false } let peerCertificateData = SecCertificateCopyData(peerCertificate) as Data logger.info("Peer cert SHA256: \(SHA256.hash(data: peerCertificateData).map { String(format: "%02x", $0) }.joined())") logger.info("Local cert SHA256: \(SHA256.hash(data: certificateData).map { String(format: "%02x", $0) }.joined())") return peerCertificateData == certificateData } quic = quic.tls.peerAuthentication(.required) var builder = NWParametersBuilder<QUIC>.parameters { quic } builder = builder.peerToPeerIncluded(true) // builder = builder.requiredInterfaceType(.wifi) // builder = builder.prohibitedInterfaceTypes([.cellular]) return builder }
2w
Reply to iOS 26 Network Framework AWDL not working
To add more info to this I tried the following. I have this going in my app: let m = NWPathMonitor() m.pathUpdateHandler = { [weak self] path in print("pathUpdateHandler: \(path)") print("path.debugDescription: \(path.debugDescription)") print("path.unsatisfiedReason: \(path.unsatisfiedReason)") print("path.status: \(path.status)") print("path.isExpensive: \(path.isExpensive)") print("path.isConstrained: \(path.isConstrained)") print("path.isUltraConstrained: \(path.isUltraConstrained)") print("path.availableInterfaces: \(path.availableInterfaces)") print("path.availableInterfaces.count: \(path.availableInterfaces.count)") path.availableInterfaces.forEach { print("interface: \($0)") } Task { await self?.broadcast(path) } } On the iPhone with NO cellular (device A) - while on the wifi network - I see [en0, en0] for availableInterfaces On the iPhone with cellular (device B) - while on the wifi network - I see [en0, en0, pdp_ip0, pdp_ip0] for availableInterfaces When i cut off the wifi network device A shows [] for availableInterfaces When i cut off the wifi network device B shows [pdp_ip0, pdp_ip0] for availableInterfaces When i then toggle on airplane mode on device B but toggle on wifi I see [] for availableInterfaces So at this point device A and device B are showing the same availableInterfaces - but they still can't connect. They can discovery each other but the connection never makes it to the TLS stage. Below are my logs from having no wifi network, device A has its Device Discovery running (ie NetworkBrowser up and running and NetworkListener up and running) - device A has its wifi toggle on device B has its Device Discovery running (ie NetworkBrowser up and running and NetworkListener up and running) - device B has its wifi toggle on [MessageService] new subscriber added local network service -> browser state update handler: ready unsubscribe voice control commands here in on termination of voice control local network service -> browser state update handler: cancelled [startBrowser]: browser is ready [L1 ready, local endpoint: <NULL>, parameters: quic, local: ::.0, definite, attribution: developer, server, port: 61566, path satisfied (Path is satisfied), viable, interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive, uses cell, LQM: good, service: 8FB0D9E1-303A-47E2-B15A-6826279577D7._captadoh._udp.<NULL> txtLength:0]: ready Listener ready onServiceRegistrationUpdate: added 8FB0D9E1-303A-47E2-B15A-6826279577D7._captadoh._udp.local. [NetworkingService] handleBrowserEndpoints skipping self endpoint: 8FB0D9E1-303A-47E2-B15A-6826279577D7 handleOutboundConnection: connection added here in setupConnectionReceiveTask nw_resolver_start_query_timer_block_invoke [C2.1.1] Query fired: did not receive all answers in time for b4f40bc0-c586-4946-a2f3-950fb21fddeb.local.:64458 [NetworkingService] handleBrowserEndpoints skipping self endpoint: 8FB0D9E1-303A-47E2-B15A-6826279577D7 [NetworkingService] handleEndpointRemoved removed endpoint for 354C4D39-2CA4-4A06-9F41-8A9B755C025B nw_connection_copy_protocol_metadata_internal_block_invoke [C3] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection nw_connection_copy_protocol_metadata_internal_block_invoke [C3] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection nw_connection_copy_connected_local_endpoint_block_invoke [C3] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection nw_connection_copy_connected_remote_endpoint_block_invoke [C3] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection nw_endpoint_flow_failed_with_error [C2.1.1.1 fe80::7cc9:daff:fea6:9151%awdl0.64458 in_progress channel-flow (satisfied (Path is satisfied), viable, interface: awdl0[802.11], scoped, uses wifi, LQM: good)] already failing, returning [NetworkingService] handleBrowserEndpoints skipping self endpoint: 8FB0D9E1-303A-47E2-B15A-6826279577D7 handleOutboundConnection: connection added here in setupConnectionReceiveTask nw_resolver_start_query_timer_block_invoke [C4.1.1] Query fired: did not receive all answers in time for b4f40bc0-c586-4946-a2f3-950fb21fddeb.local.:64458 [NetworkingService] handleBrowserEndpoints skipping self endpoint: 8FB0D9E1-303A-47E2-B15A-6826279577D7 [NetworkingService] handleEndpointRemoved removed endpoint for 354C4D39-2CA4-4A06-9F41-8A9B755C025B nw_connection_copy_protocol_metadata_internal_block_invoke [C5] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection nw_connection_copy_protocol_metadata_internal_block_invoke [C5] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection nw_connection_copy_connected_local_endpoint_block_invoke [C5] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection nw_connection_copy_connected_remote_endpoint_block_invoke [C5] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection nw_endpoint_flow_failed_with_error [C4.1.1.1 fe80::7cc9:daff:fea6:9151%awdl0.64458 in_progress channel-flow (satisfied (Path is satisfied), viable, interface: awdl0[802.11], scoped, uses wifi, LQM: good)] already failing, returning Note that device A has the device ID 354C4D39-2CA4-4A06-9F41-8A9B755C025B - device B has the device ID 8FB0D9E1-303A-47E2-B15A-6826279577D7
2w
Reply to iOS 26 Network Framework AWDL not working
@DTS Engineer - Here is how I build an outbound connection: private func handleOutboundConnection(to endpoint: NWEndpoint, deviceID: DeviceID) { do { guard let identity = Utils.importIdentityFromPKCS12() else { logger.error("[networkBrowser] could not import identity") return } guard let certificateData = Utils.getCertificateData(from: identity) else { logger.error("[networkBrowser] could not read certificate data") return } let builder = try makeQUICParametersBuilder(identity: identity, certificateData: certificateData) let connection = NetworkConnection(to: endpoint, using: builder) let connectionID = ConnectionID(connection) // connectionIDToConnection[connectionID] = connection // associateConnection(connectionID, with: deviceID) print("handleOutboundConnection: connection added") setupConnectionStateTask(for: connection, connectionID: connectionID, origin: .browser, deviceID: deviceID) setupConnectionReceiveTask(for: connection, connectionID: connectionID) } catch { print("could not create NetworkConnection: \(error)") } }
2w
Reply to iOS 26 Network Framework AWDL not working
Hi Quinn @DTS Engineer I am curious if my post is missing any information needed to troubleshoot my issue. I searched through the forums and online and haven't found my specific issue anywhere. The more I think about it I come to the following: true peer to peer with no wifi network works with iOS devices without cellular (so AWDL is used) once cellular is introduced there needs to be a wifi network because using AWDL is not an option Maybe some kind of option can be passed into the NetworkListener or when creating a NetworkConnection that would prompt apple's code to try to use AWDL if the peer to peer option is true? [quote='867952022, DTS Engineer, /thread/808917?answerId=867952022#867952022'] Share and Enjoy [/quote]
1w
Reply to How to close / cancel a NetworkConnection
[quote='867322022, DTS Engineer, /thread/808198?answerId=867322022#867322022'] Can you share an example crash report? [/quote] my app was crashing because I was improperly saving the stream I would create like this try await connection.inboundStreams(prepending: { quicStream in TLV { quicStream } }) { stream in await self.receiveMessages(from: stream, connectionID: connectionID) } I learned via Cursor that those streams are one time use and do not need to be saved.
1w