Create network connections to send and receive data using the QUIC protocol.

Posts under QUIC tag

65 Posts

Post

Replies

Boosts

Views

Activity

NWConnectionGroup no way to send/receive on QUIC stream with identifier `0`
Hello! I'm playing around with QUIC and Swift and using the Network framework. So far, the process has been really straightforward, but I noticed that I can't seem to get a handle on the stream with identifier 0. If I use NWConnection directly, I only have access to the first stream, which has the stream ID 0. This not what I want since I wanna use multiple streams. Following the documentation, I started using NWMultiplexGroup and starting a NWConnectionGroup with it. Everything works fine and I can get all streams that my backend service opens using NWMultiplexGroup's newConnectionHandler property. However, whenever backend sends a message on stream_id 0, none of my connections receive it. Looking around with connection.metadata(definition: NWProtocolQUIC.definition) as? NWProtocolQUIC.Metadata for each connection, I see that all streams are accounted for except stream 0. Then, using the NWConnectionGroup variant of the above connectionGroup.metadata(definition: NWProtocolQUIC.definition) as? NWProtocolQUIC.Metadata I see that the connection group itself has Stream ID 0. However, calling setReceiveHandler does nothing (it's never called, even when backend is sending messages) and when I attempt to send a message using NWConnectionGroup's -send method, a new stream is opened (instead of it being sent on stream ID 0). How can one get a handle on NWConnection for stream ID 0?
2
0
1.1k
Apr ’24
Crash in Network framework nw_queue_context_async + 76 (queue.m:87)
Hi, We recently released a version of our app where we use 'NWParameters.PrivacyContext'. On iOS 17.4 and iOS 17.4.1 the app crashes with a following crash: Distributor ID: com.apple.AppStore Hardware Model: iPhone12,1 Process: <app> Path: <path to app> Identifier: <bundle id> Version: <version> AppStoreTools: 15E204 AppVariant: 1:iPhone12,1:15 Code Type: ARM-64 (Native) Role: Foreground Parent Process: launchd [1] Coalition: <our bundle id> [4899] Date/Time: 2024-04-29 01:50:13.4113 +0300 Launch Time: 2024-04-29 01:13:47.6252 +0300 OS Version: iPhone OS 17.4.1 (21E236) Release Type: User Baseband Version: 5.00.00 Report Version: 104 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000054 Exception Codes: 0x0000000000000001, 0x0000000000000054 VM Region Info: 0x54 is not in any region. Bytes before following region: 4334124972 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL UNUSED SPACE AT START ---> __TEXT 102558000-1063e4000 [ 62.5M] r-x/r-x SM=COW <path to app> Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [24308] Triggered by Thread: 18 Kernel Triage: VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter Thread 18 name: Thread 18 Crashed: 0 libdispatch.dylib 0x00000001a573b7d8 dispatch_async + 192 (queue.c:940) 1 Network 0x000000019ddbdb38 nw_queue_context_async + 76 (queue.m:87) 2 Network 0x000000019e512748 invocation function for block in nw_socket_init_socket_event_source(nw_socket*, unsigned int) + 1488 (protocol_socket.cpp:4351) 3 libdispatch.dylib 0x00000001a5736dd4 _dispatch_client_callout + 20 (object.m:576) 4 libdispatch.dylib 0x00000001a573a2d8 _dispatch_continuation_pop + 600 (queue.c:321) 5 libdispatch.dylib 0x00000001a574e1c8 _dispatch_source_latch_and_call + 420 (source.c:596) 6 libdispatch.dylib 0x00000001a574cd8c _dispatch_source_invoke + 832 (source.c:961) 7 libdispatch.dylib 0x00000001a5740284 _dispatch_workloop_invoke + 1756 (queue.c:4570) 8 libdispatch.dylib 0x00000001a5749cb4 _dispatch_root_queue_drain_deferred_wlh + 288 (queue.c:6998) 9 libdispatch.dylib 0x00000001a5749528 _dispatch_workloop_worker_thread + 404 (queue.c:6592) 10 libsystem_pthread.dylib 0x00000001f981cf20 _pthread_wqthread + 288 (pthread.c:2665) 11 libsystem_pthread.dylib 0x00000001f981cfc0 start_wqthread + 8 (:-1) Thread 18 crashed with ARM Thread State (64-bit): x0: 0x0000000301a922e0 x1: 0x000000032471a720 x2: 0x0000000000000000 x3: 0x00000003015e2300 x4: 0x0000000000000003 x5: 0x00000000000022e0 x6: 0x0000000172462ef0 x7: 0x000000000000008b x8: 0x00000000000008ff x9: 0x0000000000000000 x10: 0x0000000000010000 x11: 0x0000000000000020 x12: 0x00000003016f3854 x13: 0x00000000001ff800 x14: 0x00000000000007fb x15: 0x0000000089800118 x16: 0x00000001a573511c x17: 0x000000019e514740 x18: 0x0000000000000000 x19: 0x0000000000000000 x20: 0x0000000308eae8c0 x21: 0x000000032471a730 x22: 0x000000032471b0e0 x23: 0x000000000000e023 x24: 0x0000000172463085 x25: 0x000000002b1d034c x26: 0x0000000000000800 x27: 0x0000000000000000 x28: 0x0000000000000000 fp: 0x000000032471a6b0 lr: 0xad5ba301a573b750 sp: 0x000000032471a690 pc: 0x00000001a573b7d8 cpsr: 0x80000000 esr: 0x92000006 (Data Abort) byte read Translation fault What could be the reason for it?
2
0
946
Apr ’24
Troubleshooting Peer-to-Peer Connection Failure between iOS Apps Using NWListener, NWConnection, and STUN
I am currently developing two iOS applications that require peer-to-peer connectivity. To facilitate this, I've implemented NWListener and NWConnection in both apps for network communication. To determine each device's public IP address and port—necessary for establishing a connection over the internet through my mobile operator's Carrier-Grade NAT (CGNAT)—I'm using a STUN server. Despite successfully retrieving the external IP addresses and ports for both devices, I am unable to establish a peer-to-peer connection between them. My current setup involves initiating a connection using the public addresses and ports discovered through the STUN server response. However, all attempts to connect the devices directly have been unsuccessful. I am seeking guidance on whether there are additional considerations or specific configurations needed when using NWListener, NWConnection, and a STUN server to establish a direct connection between devices in a CGNAT environment. Is there a particular step or network configuration I might be missing to successfully connect both iOS devices to each other using their external network details?
1
0
1k
Mar ’24
QUIC connection error
Hi, we are currently implementing below method for a quick POC in iOS (Xcode 15.3/macOS Sonoma 14.0): func startQUICConnection() async { // Set the initial stream to bidirectional. options.direction = .bidirectional self.mainConn?.stateUpdateHandler = { [weak self] state in print("Main Connection State: \(state)") switch state { case .ready: print("Ready...") default: break } } // Don't forget to start the connection. self.mainConn?.start(queue: self.queue) } This is what we have in the initializer of the class: parameters = NWParameters(quic: options) mainConn = NWConnection(to: endpoint, using: parameters) These are the class's properties: let endpoint = NWEndpoint.hostPort(host: "0.0.0.0", port: .init(integerLiteral: 6667)) let options = NWProtocolQUIC.Options(alpn: ["echo"]) let queue = DispatchQueue(label: "quic", qos: .userInteractive) var mainConn: NWConnection? = nil let parameters: NWParameters! As per the logs, we never get to the .ready state for the NWConnection. Logs: nw_path_evaluator_create_flow_inner failed NECP_CLIENT_ACTION_ADD_FLOW (null) evaluator parameters: quic, attach protocol listener, attribution: developer, context: Default Network Context (private), proc: 022B7C28-0271-3628-8E5E-26B590B50E5B nw_path_evaluator_create_flow_inner NECP_CLIENT_ACTION_ADD_FLOW 8FEBF750-979D-437F-B4A8-FB71F4C5A882 [22: Invalid argument] nw_endpoint_flow_setup_channel [C2 0.0.0.0:6667 in_progress channel-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] failed to request add nexus flow Main Connection State: preparing Main Connection State: waiting(POSIXErrorCode(rawValue: 22): Invalid argument) We're running a local server using proxygen on port 6667. It connects with the proxygen client though... Have tried several thing but results are the same.
1
0
2.6k
Mar ’24
QUIC receive get NWProtocolMetadata for all involved protocols
I working on a QUIC Client/Server and would like to inspect all underlying protocols via NWConnection.ContextContent in the receive method. receiveMessage(completion: {(receivedContent, context, isComplete, receivedError) .receive(minimumIncompleteLength: 1, maximumLength: 65535) { (receivedContent, context, isComplete, receivedError) As far as I understand is that the parameter .protocolMetadata in ContextContent should provide a list of all involved protocols. I expect an array of 3 NWProtocolMetadata like [NWProtocolIP.Metadata, NWProtocolUDP.Metadata, NWProtocolQUIC.Metadata] but I only get [NWProtocolQUIC.Metadata]. I already managed to get [NWProtocolIP.Metadata, NWProtocolUDP.Metadata] for a UDP connection but I can't get it to work for QUIC. Is it possible to get NWProtocolIP.Metadata, NWProtocolUDP.Metadata for a QUIC connection within the receive function? Regards Jan
0
0
890
Feb ’24
I want to use a QUIC stream with Swift's NWProtocolQUIC
I would like to use NWProtocolQUIC in Swift's Network.framework to prepare multiple QUIC Streams and send different data to the server for each. class QuicConnection { var acceptConnection: NWConnection? var openConnection: NWConnection? var acceptConnectionState: NWConnection.State? var openConnectionState: NWConnection.State? var receiveFromAcceptConnection: String? static func makeNWParameters() -> NWParameters { let options = NWProtocolQUIC.Options(alpn: ["echo"]) options.direction = .bidirectional let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions sec_protocol_options_set_verify_block(securityProtocolOptions, { (_: sec_protocol_metadata_t, _: sec_trust_t, complete: @escaping sec_protocol_verify_complete_t) in complete(true) }, DispatchQueue.main) return NWParameters(quic: options) } let group: NWConnectionGroup init() { print("init") let parameters = Self.makeNWParameters() let descriptor = NWMultiplexGroup(to: .hostPort(host: "192.168.0.20", port: 4242)) group = NWConnectionGroup(with: descriptor, using: parameters) //subscribe() group.stateUpdateHandler = { (state: NWConnectionGroup.State) in print("state: \(state)") switch state { case .ready: print("quic connected!") default: break } } group.newConnectionHandler = { [weak self] (connection: NWConnection) in print("new connection: \(connection)") self?.acceptConnection = connection self?.acceptConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in self?.acceptConnectionState = state } self?.subscribeAcceptConnection() self?.acceptConnection?.start(queue: DispatchQueue.main) } group.start(queue: DispatchQueue.main) } func createStream() { //guard let group else { return } let options = NWProtocolQUIC.Options() options.direction = .bidirectional let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions sec_protocol_options_set_verify_block(securityProtocolOptions, { (_: sec_protocol_metadata_t, _: sec_trust_t, complete: @escaping sec_protocol_verify_complete_t) in complete(true) // Insecure !!! }, DispatchQueue.main) openConnection = NWConnection(from: group) openConnectionState = openConnection?.state openConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in self?.openConnectionState = state print("state: \(state)") switch state { case .ready: print("stream connected!") DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self?.send(message: "marker1") } default: break } } openConnection?.start(queue: DispatchQueue.main) } func send(message: String) { print("send start") let completion: NWConnection.SendCompletion = .contentProcessed { (error: Error?) in if let error = error { print("send error: \(error)") } else { print("send successful") } } openConnection?.send(content: message.data(using: .utf8)!, contentContext: .defaultMessage, isComplete: true, completion: completion) print("message: \(message)") } } When the app starts, it calls the init function of this QuicConnection class to create an instance and build the QUIC tunnel." quic connected" log appears, and when a specific action is performed in the app, the createStream function is called to put up a stream." stream connected" log is displayed, but when I then try to send data using the send function, the "send successful" message is displayed, but there is no output on the server side indicating that the message was received from the client. However, when I try to send data using the send function after that, I get a "send successful" message. I don't think there is a problem on the server side, because I can communicate well when only NWConnection is used without NQConnectionGroup. The server is using quic-go. I would like to borrow knowledge from those who have handled QUIC streams in Swift. Below are Apple's announcement and official documents that I referred to. I wrote the code referring to these, but even though I can connect the QUIC tunnels, I can not send data by setting up individual streams. https://developer.apple.com/videos/play/wwdc2021/10094/ https://developer.apple.com/documentation/network/nwprotocolquic
3
1
1.9k
Jan ’24
Weird behaviour with Network Framework and QUIC Multiplex Groups.
Hey all here is an example you can try out: https://github.com/paxsonsa/quic-swift-demo I am prototype a QUIC base application system with a client and server. My server is a simple test to experiment with QUIC and Network Framework but I am see some odd behaviour. Selecting Stream Direction for new streams In the example below, we are creating a new multiplexed QUIC connection and establish a new stream once the group connection is ready. In some cases, I want to be able to use a different stream kind (uni/bi). By specifying the options, I get an error in Xcode console like so: running.... group state: waiting(POSIXErrorCode(rawValue: 50): Network is down) group state: ready Connected using QUIC! nw_endpoint_flow_setup_cloned_protocols [C3 127.0.0.1:4567 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] could not find protocol to join in existing protocol stack nw_endpoint_flow_failed_with_error [C3 127.0.0.1:4567 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] failed to clone from flow, moving directly to failed state Main Connection State: failed(POSIXErrorCode(rawValue: 50): Network is down) quic_recovery_pto PTO fired after validation Here is my swift code: // // main.swift // QuicTool // // Created by Andrew Paxson on 2024-01-14. // import Foundation import Network /// Helper function to create a message frame. func createMessage(version: UInt8, messageType: UInt8, message: String) -> Data { let messageData = message.data(using: .utf8) ?? Data() let length = UInt32(messageData.count) var data = Data() data.append(version) data.append(messageType) // Convert length to 4 bytes and append (big-endian format) let bigEndianLength = length.bigEndian data.append(contentsOf: withUnsafeBytes(of: bigEndianLength) { Array($0) }) // Append 2 bytes of padding for 8-byte alignment data.append(Data(repeating: 0, count: 2)) // Add Message Data. data.append(messageData) return data } // Queue for QUIC things. let queue = DispatchQueue(label: "quic", qos: .userInteractive) // Create Inital Options for the tunnel. // This is using an insecure connection as this operation is meant to be local network. let endpoint = NWEndpoint.hostPort(host: "127.0.0.1", port: .init(integerLiteral: 4567)) let options = NWProtocolQUIC.Options(alpn: ["demo"]) // Set the initial stream to bidirectional. options.direction = .bidirectional sec_protocol_options_set_verify_block(options.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in sec_protocol_verify_complete(true) }, queue) let parameters = NWParameters(quic: options) // 1) Create a new multiplexed connection let descriptor = NWMultiplexGroup(to: endpoint) let group = NWConnectionGroup(with: descriptor, using: parameters) var mainConn: NWConnection? = nil // Here we are establishing a state handler for when the connection to the // the server is neogiated and "ready". Once its ready we want to establish a // stream using the group with the options set. // // This is the main location of the issue we are seeing where the stream is // established and the data is sent but never updated. group.stateUpdateHandler = { newState in print("group state: \(newState)") switch newState { // Once the tunnel is established, create a new stream with bidirectional parameters. case .ready: print("Connected using QUIC!") // 2) In normal application I may want to open different kinds of streams in providing // new options. Is there a better way to select the stream kind for subsequent streams? let options = NWProtocolQUIC.Options(alpn: ["demo"]) options.direction = .bidirectional // When providing unique options the stream will fail. Removeing the using argument works. mainConn = group.extract()! // force unwrap mainConn?.stateUpdateHandler = { state in print("Main Connection State: \(state)") switch state { case .ready: // Once the connection is ready, lets send some sweet data sauce. // // By establishing this new stream and sending data, on the server this causes the inital // stream with no handle to be open. let version: UInt8 = 1 let messageType: UInt8 = 1 let message = "hello, I am from the multiplex group ready." let messageData = createMessage(version: version, messageType: messageType, message: message) mainConn?.send(content: messageData, isComplete: true, completion: .contentProcessed({ sendError in if let error = sendError { print("There was an error sending data: \(error)") } else { print("Data was sent successfully from Main Connection.") } })) default: break } } // Don't forget to start the connection. mainConn?.start(queue: queue) default: break } } // Receive new incoming streams initiated by the remote endpoint // this is not used for this example. group.newConnectionHandler = { conn in print("New Connection: \(conn)") // Set state update handler on incoming stream conn.stateUpdateHandler = { newState in print("newState: \(newState) for \(conn)") switch newState { case .ready: print("got a new stream!") default: break } } // Start the incoming stream conn.start(queue: queue) } // Start the group with callback queue group.start(queue: queue) print("running....") // We iterate trying to send data on the new stream we created after the // connection is established. while true { switch mainConn?.state { case .ready: // Once the connection is ready, lets send some sweet data sauce. let version: UInt8 = 1 let messageType: UInt8 = 1 let message = "hello, im from the main loop" let messageData = createMessage(version: version, messageType: messageType, message: message) print("Local Stream Send: \(messageData)") mainConn?.send(content: messageData, completion: .contentProcessed({ sendError in if let error = sendError { print("There was an error sending data: \(error)") } })) sleep(1) default: continue } }
8
0
2.5k
Jan ’24
NWConnectionGroup stateUpdateHandler not called for failed states
I'm building a network client with Swift (using QUIC). I set everything up properly (I know this because I can successfully connect, send and receive streams). But I'm trying to catch connection errors. For example if I try to connect to a totally bogus IP address, I would like to display Connecting, then ConnectionFailed I do the following: create my NWMultiplexGroup descriptor set my appropriate NWParameters create my NWConnectionGroup set up my handlers (setReceiveHandler, newConnectionHandler) and my state update handler i call connection.start When I pass a valid address to a server that is listening for the connection, all is good - in my stateUpdateHandler I get the .ready state, but I don't get any intermediate states, and if I pass it a bogus IP address, I get absolutely no callbacks to my handler (I would have expected to get .waiting and/or .failed) I couldn't find any quic options that I'm not doing, and the apple documentation is not helpful Any suggestions as to what I might be missing?
0
0
817
Jan ’24
Does Facetime use QUIC ?
Hello, I noticed that Facetime attempts to use the QUIC protocol during a Facetime session with the following ports 3478 through 3497 (UDP). Can Facetime use the QUIC protocol for the following ports 3478 through 3497 (UDP) because on the internet I have not found anywhere the possibility that QUIC can be used other than ports 80 and 443?
1
0
1.3k
Jan ’24
iOS17.0 quic_recovery_declare_packets_lost Crash
A large number of crashes occurred only on iOS 17.0 online from July 27, which is consistent with the release time of the 17.0 beta4 version. I suspect something is wrong with 17.0 beta4. Does anyone have the same problem and is there a solution? Thanks a lot Crashed: com.apple.CFNetwork.Connection 0 libquic.dylib 0x21120 quic_recovery_declare_packets_lost + 928 1 libquic.dylib 0x20788 quic_recovery_find_lost_packet_inner + 1272 2 libquic.dylib 0x1e564 quic_recovery_find_lost_packets + 352 3 libquic.dylib 0x11b74 quic_recovery_received_ack + 1180 4 libquic.dylib 0x52634 quic_frame_process_ACK + 368 5 libquic.dylib 0xb3bc8 quic_conn_process_frame + 964 6 libquic.dylib 0xb0370 quic_conn_process_inbound + 1840 7 Network 0x323c40 nw_protocol_data_access_buffer + 840 8 libquic.dylib 0xb6b48 __quic_conn_handle_inbound_block_invoke + 168 9 libquic.dylib 0xb690c quic_conn_handle_inbound + 124 10 Network 0x3102ac __nw_protocol_implementation_get_input_internal_block_invoke + 136 11 Network 0x30f8d4 nw_protocol_implementation_read + 408 12 Network 0x30f128 nw_protocol_implementation_input_available + 96 13 Network 0x1f5c4 nw_channel_update_input_source(nw_channel*, nw_protocol*, bool) + 7024 14 Network 0x2d880 nw_channel_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 124 15 Network 0x911ac0 nw_protocol_ipv6_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 268 16 Network 0x1da8a4 nw_protocol_udp_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 208 17 Network 0x30f868 nw_protocol_implementation_read + 300 18 Network 0x3153e4 nw_protocol_implementation_get_input_frames + 148 19 Network 0x3572e0 nw_flow_service_reads(NWConcrete_nw_endpoint_handler*, NWConcrete_nw_endpoint_flow*, nw_flow_protocol*, bool) + 992 20 Network 0x363ef0 __nw_endpoint_handler_add_read_request_block_invoke + 452 21 Network 0x7ba20 nw_hash_table_apply + 2696 22 Network 0x34d84 nw_endpoint_handler_add_read_request + 1688 23 Network 0x34848 nw_endpoint_handler_add_read_request + 348 24 Network 0x936c nw_connection_add_read_request_on_queue + 232 25 Network 0x9204 nw_connection_add_read_request + 344 26 Network 0x8cc4 nw_connection_receive_internal + 140 27 CFNetwork 0xa7620 CFURLDownloadStart + 66020 28 CFNetwork 0xe194c _CFStreamErrorFromCFError + 24656 29 CFNetwork 0x101918 _CFStreamErrorFromCFError + 155676 30 CFNetwork 0xfe2d8 _CFStreamErrorFromCFError + 141788 31 CFNetwork 0x1008dc _CFStreamErrorFromCFError + 151520 32 CFNetwork 0x1344d4 _CFStreamErrorFromCFError + 363480 33 CFNetwork 0xa73c8 CFURLDownloadStart + 65420 34 CFNetwork 0xb68c0 CFURLDownloadStart + 128132 35 CFNetwork 0x135c5c _CFStreamErrorFromCFError + 369504 36 CFNetwork 0x34f18 CFHTTPMessageCopySerializedMessage + 47008 37 CFNetwork 0x1e8180 CFHTTPCookieStorageUnscheduleFromRunLoop + 225244 38 CFNetwork 0x13585c _CFStreamErrorFromCFError + 368480 39 CFNetwork 0xb4d9c CFURLDownloadStart + 121184 40 libdispatch.dylib 0x13250 _dispatch_block_async_invoke2 + 148 41 libdispatch.dylib 0x4300 _dispatch_client_callout + 20 42 libdispatch.dylib 0xb894 _dispatch_lane_serial_drain + 748 43 libdispatch.dylib 0xc3f8 _dispatch_lane_invoke + 432 44 libdispatch.dylib 0xd6a8 _dispatch_workloop_invoke + 1756 45 libdispatch.dylib 0x17004 _dispatch_root_queue_drain_deferred_wlh + 288 46 libdispatch.dylib 0x16878 _dispatch_workloop_worker_thread + 404 47 libsystem_pthread.dylib 0x1964 _pthread_wqthread + 288 48 libsystem_pthread.dylib 0x1a04 start_wqthread + 8
14
6
4.2k
Oct ’23
tvOS libquic.dylib not found
When debugging a tvOS application that calls Data(contentsOf: URL) I get an error: nw_protocol_get_quic_image_block_invoke dlopen libquic failed: dlopen(/usr/lib/libquic.dylib, 0x0005): tried: [...a number of folders it tried to find the file in...]. I found similar problems here (https://developer.apple.com/forums/thread/693245), but it is not equal, nor does it have a solution. Any suggestions on how to fix this? I also tried to copy a libquic.tbd file present in other simulators to one of the paths it looks for (a suggestion somewhere on StackOverflow), but it does not help unfortunately.
11
0
3.0k
Sep ’23
iOS HTTP/3 not support zero-rtt?
Hi, I have run the system h3 on iphone OS 16.6 by learning this:TN3102: HTTP/3 in your app | Apple Developer Documentation; However, I have found that the request iOS sending not support zero rtt. When using chrome to request(h3), it‘s doing zero rtt successfully. So, may I ask if there any plan to support zero-rtt in http/3 ? PS.The UA:CFNetwork/1410.0.3 Darwin/22.6.0
3
0
1.4k
Sep ’23
Background URLSession http/3 URLSessionUploadTask not started in real device
I'm trying to upload large files in a background URLSession to a server that accepts HTTP/3 requests. Per its design, the server uses a self-signed SSL certificate. In my testing, I can create a regular URLSession (foreground) with the following: var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0) request.assumesHTTP3Capable = true request.httpMethod = "POST" self.session.dataTask(with: request) { &lt;snip&gt; } And handles the SSL certificate challenge by implementing the following for the delegate: func urlSession( _ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -&gt; Void ) This approach works and I can communicate with the server. But when I try to apply the same for a background session for an upload task, the task seems to be stuck, i.e. never started by the system. More specifically, the background session upload task works with iOS simulator. But on a real device connected to macOS, the task never started, and none of the delegate methods are called. The http/3 server didn't receive any request either. The background session was created: let appBundleName = Bundle.main.bundleURL.lastPathComponent.lowercased().replacingOccurrences(of: " ", with: ".") let sessionIdentifier: String = "com.networking.\(appBundleName)" let config = URLSessionConfiguration.background(withIdentifier: sessionIdentifier) self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil) later, an upload task was created : var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0) request.assumesHTTP3Capable = true request.httpMethod = "POST" let backgroundTask = self.session.uploadTask(with: request, fromFile: src) backgroundTask.resume() My question(s): why is the background session upload task stuck? Is there a way to find out where it is stuck? Does a background URLSession support app's delegate handling SSL certificate challenge? The test env: Xcode 14.2 macOS 12.6.7 iOS 15.7.7 Thanks!
4
0
1.5k
Aug ’23
NWConnection not connecting with QUIC
In an iOS network extension setup as a Packet Tunnel. I am accepting packets in using NEPacketTunnelFlow and open a NWConnection up to the destination like so let parameters = .quic(alpn: []) let connection = NWConnection(to: .hostPort(host: host, port: port!), using: parameters) but my state handler is never receiving the .ready state. My NWConnection code works fine for TCP and DNS using let parameters = .tcp // OR let parameters = .udp On my NWConnection state handler I am receiving .waiting with an error of dns. I am testing quic by navigating onto the Facebook app and with wireshark intercepting the traffic I can see the DNS queries resolving I have NEDNSSettings applied to my NEPacketTunnelNetworkSettings Is my issue to do with not passing in the alpn value or is there an extra permission/setting I am missing? I have not found a value which changes the outcome at all. I have tried following [https://developer.apple.com/videos/play/wwdc2021/10094/) but no success.
4
0
1.7k
Aug ’23
IS Https://IP/query support HTTP/3 ?
I'm use host to request https://MyHost/ the networkProtocolName return "h3" assumesHTTP3Capable = YES - (void)URLSession:(NSURLSession *)session        task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10)) { for (NSURLSessionTaskTransactionMetrics * m in metrics.transactionMetrics){              if(m.networkProtocolName.length &gt; 0){         NSLog(@"networkProtocolName %@", m.networkProtocolName);         break;       }     } } but when I use ip replace MyHost to request, and add MyHost to http header @{@"host": "ip"}, the networkProtocolName return "h2" - (void)URLSession:(NSURLSession *)session        task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {  NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;     NSURLCredential *credential = nil; //get header host replace ip     NSString *host = [[task.currentRequest allHTTPHeaderFields] objectForKey:@"host"];     if (!host) {       host = task.currentRequest.URL.host;     }     if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {       if ([weak evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {         disposition = NSURLSessionAuthChallengeUseCredential;         credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];       } else {         disposition = NSURLSessionAuthChallengePerformDefaultHandling;       }     } else {       disposition = NSURLSessionAuthChallengePerformDefaultHandling;     }     // 对于其他的 challenges 直接使用默认的验证方案     completionHandler(disposition,credential); } -(BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {   //创建证书校验策略   NSMutableArray *policies = [NSMutableArray array];   if (domain) {     [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];   } else {     [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];   }   //绑定校验策略到服务端的证书上   SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);   //评估当前 serverTrust 是否可信任,   //官方建议在 result = kSecTrustResultUnspecified 或 kSecTrustResultProceed 的情况下 serverTrust 可以被验证通过,   //https://developer.apple.com/library/ios/technotes/tn2232/_index.html   //关于SecTrustResultType的详细信息请参考SecTrust.h   SecTrustResultType result;   SecTrustEvaluate(serverTrust, &amp;result);   return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); } https://ip/ networkProtocolName return "h2" does ip request do not supprt HTTP/3? hope to respone thank you.
3
0
2.2k
Mar ’23
HTTP/3 Quic support in MacOS?
I work with .Net Core a lot, and whenever I look at docs like [censored] that say "HTTP/3 is not currently supported on macOS but may be available in a future release." So when will it be supported? I've seen where it's an experimental feature in Safari, and has to be explicitly enabled for it to work...when will be a full part of the OS so that third parties can make use of it in their tech stacks?
7
1
3.7k
Feb ’23
NWConnectionGroup no way to send/receive on QUIC stream with identifier `0`
Hello! I'm playing around with QUIC and Swift and using the Network framework. So far, the process has been really straightforward, but I noticed that I can't seem to get a handle on the stream with identifier 0. If I use NWConnection directly, I only have access to the first stream, which has the stream ID 0. This not what I want since I wanna use multiple streams. Following the documentation, I started using NWMultiplexGroup and starting a NWConnectionGroup with it. Everything works fine and I can get all streams that my backend service opens using NWMultiplexGroup's newConnectionHandler property. However, whenever backend sends a message on stream_id 0, none of my connections receive it. Looking around with connection.metadata(definition: NWProtocolQUIC.definition) as? NWProtocolQUIC.Metadata for each connection, I see that all streams are accounted for except stream 0. Then, using the NWConnectionGroup variant of the above connectionGroup.metadata(definition: NWProtocolQUIC.definition) as? NWProtocolQUIC.Metadata I see that the connection group itself has Stream ID 0. However, calling setReceiveHandler does nothing (it's never called, even when backend is sending messages) and when I attempt to send a message using NWConnectionGroup's -send method, a new stream is opened (instead of it being sent on stream ID 0). How can one get a handle on NWConnection for stream ID 0?
Replies
2
Boosts
0
Views
1.1k
Activity
Apr ’24
Crash in Network framework nw_queue_context_async + 76 (queue.m:87)
Hi, We recently released a version of our app where we use 'NWParameters.PrivacyContext'. On iOS 17.4 and iOS 17.4.1 the app crashes with a following crash: Distributor ID: com.apple.AppStore Hardware Model: iPhone12,1 Process: <app> Path: <path to app> Identifier: <bundle id> Version: <version> AppStoreTools: 15E204 AppVariant: 1:iPhone12,1:15 Code Type: ARM-64 (Native) Role: Foreground Parent Process: launchd [1] Coalition: <our bundle id> [4899] Date/Time: 2024-04-29 01:50:13.4113 +0300 Launch Time: 2024-04-29 01:13:47.6252 +0300 OS Version: iPhone OS 17.4.1 (21E236) Release Type: User Baseband Version: 5.00.00 Report Version: 104 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000054 Exception Codes: 0x0000000000000001, 0x0000000000000054 VM Region Info: 0x54 is not in any region. Bytes before following region: 4334124972 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL UNUSED SPACE AT START ---> __TEXT 102558000-1063e4000 [ 62.5M] r-x/r-x SM=COW <path to app> Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [24308] Triggered by Thread: 18 Kernel Triage: VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter Thread 18 name: Thread 18 Crashed: 0 libdispatch.dylib 0x00000001a573b7d8 dispatch_async + 192 (queue.c:940) 1 Network 0x000000019ddbdb38 nw_queue_context_async + 76 (queue.m:87) 2 Network 0x000000019e512748 invocation function for block in nw_socket_init_socket_event_source(nw_socket*, unsigned int) + 1488 (protocol_socket.cpp:4351) 3 libdispatch.dylib 0x00000001a5736dd4 _dispatch_client_callout + 20 (object.m:576) 4 libdispatch.dylib 0x00000001a573a2d8 _dispatch_continuation_pop + 600 (queue.c:321) 5 libdispatch.dylib 0x00000001a574e1c8 _dispatch_source_latch_and_call + 420 (source.c:596) 6 libdispatch.dylib 0x00000001a574cd8c _dispatch_source_invoke + 832 (source.c:961) 7 libdispatch.dylib 0x00000001a5740284 _dispatch_workloop_invoke + 1756 (queue.c:4570) 8 libdispatch.dylib 0x00000001a5749cb4 _dispatch_root_queue_drain_deferred_wlh + 288 (queue.c:6998) 9 libdispatch.dylib 0x00000001a5749528 _dispatch_workloop_worker_thread + 404 (queue.c:6592) 10 libsystem_pthread.dylib 0x00000001f981cf20 _pthread_wqthread + 288 (pthread.c:2665) 11 libsystem_pthread.dylib 0x00000001f981cfc0 start_wqthread + 8 (:-1) Thread 18 crashed with ARM Thread State (64-bit): x0: 0x0000000301a922e0 x1: 0x000000032471a720 x2: 0x0000000000000000 x3: 0x00000003015e2300 x4: 0x0000000000000003 x5: 0x00000000000022e0 x6: 0x0000000172462ef0 x7: 0x000000000000008b x8: 0x00000000000008ff x9: 0x0000000000000000 x10: 0x0000000000010000 x11: 0x0000000000000020 x12: 0x00000003016f3854 x13: 0x00000000001ff800 x14: 0x00000000000007fb x15: 0x0000000089800118 x16: 0x00000001a573511c x17: 0x000000019e514740 x18: 0x0000000000000000 x19: 0x0000000000000000 x20: 0x0000000308eae8c0 x21: 0x000000032471a730 x22: 0x000000032471b0e0 x23: 0x000000000000e023 x24: 0x0000000172463085 x25: 0x000000002b1d034c x26: 0x0000000000000800 x27: 0x0000000000000000 x28: 0x0000000000000000 fp: 0x000000032471a6b0 lr: 0xad5ba301a573b750 sp: 0x000000032471a690 pc: 0x00000001a573b7d8 cpsr: 0x80000000 esr: 0x92000006 (Data Abort) byte read Translation fault What could be the reason for it?
Replies
2
Boosts
0
Views
946
Activity
Apr ’24
Does IOS support WebTransport yet?
Hi, wondering if IOS supports WebTransport (HTTP/3) yet? If so, where can I find information on implementing it in my app?
Replies
2
Boosts
3
Views
1.5k
Activity
Apr ’24
Troubleshooting Peer-to-Peer Connection Failure between iOS Apps Using NWListener, NWConnection, and STUN
I am currently developing two iOS applications that require peer-to-peer connectivity. To facilitate this, I've implemented NWListener and NWConnection in both apps for network communication. To determine each device's public IP address and port—necessary for establishing a connection over the internet through my mobile operator's Carrier-Grade NAT (CGNAT)—I'm using a STUN server. Despite successfully retrieving the external IP addresses and ports for both devices, I am unable to establish a peer-to-peer connection between them. My current setup involves initiating a connection using the public addresses and ports discovered through the STUN server response. However, all attempts to connect the devices directly have been unsuccessful. I am seeking guidance on whether there are additional considerations or specific configurations needed when using NWListener, NWConnection, and a STUN server to establish a direct connection between devices in a CGNAT environment. Is there a particular step or network configuration I might be missing to successfully connect both iOS devices to each other using their external network details?
Replies
1
Boosts
0
Views
1k
Activity
Mar ’24
QUIC connection error
Hi, we are currently implementing below method for a quick POC in iOS (Xcode 15.3/macOS Sonoma 14.0): func startQUICConnection() async { // Set the initial stream to bidirectional. options.direction = .bidirectional self.mainConn?.stateUpdateHandler = { [weak self] state in print("Main Connection State: \(state)") switch state { case .ready: print("Ready...") default: break } } // Don't forget to start the connection. self.mainConn?.start(queue: self.queue) } This is what we have in the initializer of the class: parameters = NWParameters(quic: options) mainConn = NWConnection(to: endpoint, using: parameters) These are the class's properties: let endpoint = NWEndpoint.hostPort(host: "0.0.0.0", port: .init(integerLiteral: 6667)) let options = NWProtocolQUIC.Options(alpn: ["echo"]) let queue = DispatchQueue(label: "quic", qos: .userInteractive) var mainConn: NWConnection? = nil let parameters: NWParameters! As per the logs, we never get to the .ready state for the NWConnection. Logs: nw_path_evaluator_create_flow_inner failed NECP_CLIENT_ACTION_ADD_FLOW (null) evaluator parameters: quic, attach protocol listener, attribution: developer, context: Default Network Context (private), proc: 022B7C28-0271-3628-8E5E-26B590B50E5B nw_path_evaluator_create_flow_inner NECP_CLIENT_ACTION_ADD_FLOW 8FEBF750-979D-437F-B4A8-FB71F4C5A882 [22: Invalid argument] nw_endpoint_flow_setup_channel [C2 0.0.0.0:6667 in_progress channel-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, ipv6, dns, uses wifi)] failed to request add nexus flow Main Connection State: preparing Main Connection State: waiting(POSIXErrorCode(rawValue: 22): Invalid argument) We're running a local server using proxygen on port 6667. It connects with the proxygen client though... Have tried several thing but results are the same.
Replies
1
Boosts
0
Views
2.6k
Activity
Mar ’24
QUIC receive get NWProtocolMetadata for all involved protocols
I working on a QUIC Client/Server and would like to inspect all underlying protocols via NWConnection.ContextContent in the receive method. receiveMessage(completion: {(receivedContent, context, isComplete, receivedError) .receive(minimumIncompleteLength: 1, maximumLength: 65535) { (receivedContent, context, isComplete, receivedError) As far as I understand is that the parameter .protocolMetadata in ContextContent should provide a list of all involved protocols. I expect an array of 3 NWProtocolMetadata like [NWProtocolIP.Metadata, NWProtocolUDP.Metadata, NWProtocolQUIC.Metadata] but I only get [NWProtocolQUIC.Metadata]. I already managed to get [NWProtocolIP.Metadata, NWProtocolUDP.Metadata] for a UDP connection but I can't get it to work for QUIC. Is it possible to get NWProtocolIP.Metadata, NWProtocolUDP.Metadata for a QUIC connection within the receive function? Regards Jan
Replies
0
Boosts
0
Views
890
Activity
Feb ’24
I want to use a QUIC stream with Swift's NWProtocolQUIC
I would like to use NWProtocolQUIC in Swift's Network.framework to prepare multiple QUIC Streams and send different data to the server for each. class QuicConnection { var acceptConnection: NWConnection? var openConnection: NWConnection? var acceptConnectionState: NWConnection.State? var openConnectionState: NWConnection.State? var receiveFromAcceptConnection: String? static func makeNWParameters() -> NWParameters { let options = NWProtocolQUIC.Options(alpn: ["echo"]) options.direction = .bidirectional let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions sec_protocol_options_set_verify_block(securityProtocolOptions, { (_: sec_protocol_metadata_t, _: sec_trust_t, complete: @escaping sec_protocol_verify_complete_t) in complete(true) }, DispatchQueue.main) return NWParameters(quic: options) } let group: NWConnectionGroup init() { print("init") let parameters = Self.makeNWParameters() let descriptor = NWMultiplexGroup(to: .hostPort(host: "192.168.0.20", port: 4242)) group = NWConnectionGroup(with: descriptor, using: parameters) //subscribe() group.stateUpdateHandler = { (state: NWConnectionGroup.State) in print("state: \(state)") switch state { case .ready: print("quic connected!") default: break } } group.newConnectionHandler = { [weak self] (connection: NWConnection) in print("new connection: \(connection)") self?.acceptConnection = connection self?.acceptConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in self?.acceptConnectionState = state } self?.subscribeAcceptConnection() self?.acceptConnection?.start(queue: DispatchQueue.main) } group.start(queue: DispatchQueue.main) } func createStream() { //guard let group else { return } let options = NWProtocolQUIC.Options() options.direction = .bidirectional let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions sec_protocol_options_set_verify_block(securityProtocolOptions, { (_: sec_protocol_metadata_t, _: sec_trust_t, complete: @escaping sec_protocol_verify_complete_t) in complete(true) // Insecure !!! }, DispatchQueue.main) openConnection = NWConnection(from: group) openConnectionState = openConnection?.state openConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in self?.openConnectionState = state print("state: \(state)") switch state { case .ready: print("stream connected!") DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self?.send(message: "marker1") } default: break } } openConnection?.start(queue: DispatchQueue.main) } func send(message: String) { print("send start") let completion: NWConnection.SendCompletion = .contentProcessed { (error: Error?) in if let error = error { print("send error: \(error)") } else { print("send successful") } } openConnection?.send(content: message.data(using: .utf8)!, contentContext: .defaultMessage, isComplete: true, completion: completion) print("message: \(message)") } } When the app starts, it calls the init function of this QuicConnection class to create an instance and build the QUIC tunnel." quic connected" log appears, and when a specific action is performed in the app, the createStream function is called to put up a stream." stream connected" log is displayed, but when I then try to send data using the send function, the "send successful" message is displayed, but there is no output on the server side indicating that the message was received from the client. However, when I try to send data using the send function after that, I get a "send successful" message. I don't think there is a problem on the server side, because I can communicate well when only NWConnection is used without NQConnectionGroup. The server is using quic-go. I would like to borrow knowledge from those who have handled QUIC streams in Swift. Below are Apple's announcement and official documents that I referred to. I wrote the code referring to these, but even though I can connect the QUIC tunnels, I can not send data by setting up individual streams. https://developer.apple.com/videos/play/wwdc2021/10094/ https://developer.apple.com/documentation/network/nwprotocolquic
Replies
3
Boosts
1
Views
1.9k
Activity
Jan ’24
Weird behaviour with Network Framework and QUIC Multiplex Groups.
Hey all here is an example you can try out: https://github.com/paxsonsa/quic-swift-demo I am prototype a QUIC base application system with a client and server. My server is a simple test to experiment with QUIC and Network Framework but I am see some odd behaviour. Selecting Stream Direction for new streams In the example below, we are creating a new multiplexed QUIC connection and establish a new stream once the group connection is ready. In some cases, I want to be able to use a different stream kind (uni/bi). By specifying the options, I get an error in Xcode console like so: running.... group state: waiting(POSIXErrorCode(rawValue: 50): Network is down) group state: ready Connected using QUIC! nw_endpoint_flow_setup_cloned_protocols [C3 127.0.0.1:4567 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] could not find protocol to join in existing protocol stack nw_endpoint_flow_failed_with_error [C3 127.0.0.1:4567 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] failed to clone from flow, moving directly to failed state Main Connection State: failed(POSIXErrorCode(rawValue: 50): Network is down) quic_recovery_pto PTO fired after validation Here is my swift code: // // main.swift // QuicTool // // Created by Andrew Paxson on 2024-01-14. // import Foundation import Network /// Helper function to create a message frame. func createMessage(version: UInt8, messageType: UInt8, message: String) -> Data { let messageData = message.data(using: .utf8) ?? Data() let length = UInt32(messageData.count) var data = Data() data.append(version) data.append(messageType) // Convert length to 4 bytes and append (big-endian format) let bigEndianLength = length.bigEndian data.append(contentsOf: withUnsafeBytes(of: bigEndianLength) { Array($0) }) // Append 2 bytes of padding for 8-byte alignment data.append(Data(repeating: 0, count: 2)) // Add Message Data. data.append(messageData) return data } // Queue for QUIC things. let queue = DispatchQueue(label: "quic", qos: .userInteractive) // Create Inital Options for the tunnel. // This is using an insecure connection as this operation is meant to be local network. let endpoint = NWEndpoint.hostPort(host: "127.0.0.1", port: .init(integerLiteral: 4567)) let options = NWProtocolQUIC.Options(alpn: ["demo"]) // Set the initial stream to bidirectional. options.direction = .bidirectional sec_protocol_options_set_verify_block(options.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in sec_protocol_verify_complete(true) }, queue) let parameters = NWParameters(quic: options) // 1) Create a new multiplexed connection let descriptor = NWMultiplexGroup(to: endpoint) let group = NWConnectionGroup(with: descriptor, using: parameters) var mainConn: NWConnection? = nil // Here we are establishing a state handler for when the connection to the // the server is neogiated and "ready". Once its ready we want to establish a // stream using the group with the options set. // // This is the main location of the issue we are seeing where the stream is // established and the data is sent but never updated. group.stateUpdateHandler = { newState in print("group state: \(newState)") switch newState { // Once the tunnel is established, create a new stream with bidirectional parameters. case .ready: print("Connected using QUIC!") // 2) In normal application I may want to open different kinds of streams in providing // new options. Is there a better way to select the stream kind for subsequent streams? let options = NWProtocolQUIC.Options(alpn: ["demo"]) options.direction = .bidirectional // When providing unique options the stream will fail. Removeing the using argument works. mainConn = group.extract()! // force unwrap mainConn?.stateUpdateHandler = { state in print("Main Connection State: \(state)") switch state { case .ready: // Once the connection is ready, lets send some sweet data sauce. // // By establishing this new stream and sending data, on the server this causes the inital // stream with no handle to be open. let version: UInt8 = 1 let messageType: UInt8 = 1 let message = "hello, I am from the multiplex group ready." let messageData = createMessage(version: version, messageType: messageType, message: message) mainConn?.send(content: messageData, isComplete: true, completion: .contentProcessed({ sendError in if let error = sendError { print("There was an error sending data: \(error)") } else { print("Data was sent successfully from Main Connection.") } })) default: break } } // Don't forget to start the connection. mainConn?.start(queue: queue) default: break } } // Receive new incoming streams initiated by the remote endpoint // this is not used for this example. group.newConnectionHandler = { conn in print("New Connection: \(conn)") // Set state update handler on incoming stream conn.stateUpdateHandler = { newState in print("newState: \(newState) for \(conn)") switch newState { case .ready: print("got a new stream!") default: break } } // Start the incoming stream conn.start(queue: queue) } // Start the group with callback queue group.start(queue: queue) print("running....") // We iterate trying to send data on the new stream we created after the // connection is established. while true { switch mainConn?.state { case .ready: // Once the connection is ready, lets send some sweet data sauce. let version: UInt8 = 1 let messageType: UInt8 = 1 let message = "hello, im from the main loop" let messageData = createMessage(version: version, messageType: messageType, message: message) print("Local Stream Send: \(messageData)") mainConn?.send(content: messageData, completion: .contentProcessed({ sendError in if let error = sendError { print("There was an error sending data: \(error)") } })) sleep(1) default: continue } }
Replies
8
Boosts
0
Views
2.5k
Activity
Jan ’24
NWConnectionGroup stateUpdateHandler not called for failed states
I'm building a network client with Swift (using QUIC). I set everything up properly (I know this because I can successfully connect, send and receive streams). But I'm trying to catch connection errors. For example if I try to connect to a totally bogus IP address, I would like to display Connecting, then ConnectionFailed I do the following: create my NWMultiplexGroup descriptor set my appropriate NWParameters create my NWConnectionGroup set up my handlers (setReceiveHandler, newConnectionHandler) and my state update handler i call connection.start When I pass a valid address to a server that is listening for the connection, all is good - in my stateUpdateHandler I get the .ready state, but I don't get any intermediate states, and if I pass it a bogus IP address, I get absolutely no callbacks to my handler (I would have expected to get .waiting and/or .failed) I couldn't find any quic options that I'm not doing, and the apple documentation is not helpful Any suggestions as to what I might be missing?
Replies
0
Boosts
0
Views
817
Activity
Jan ’24
Does Facetime use QUIC ?
Hello, I noticed that Facetime attempts to use the QUIC protocol during a Facetime session with the following ports 3478 through 3497 (UDP). Can Facetime use the QUIC protocol for the following ports 3478 through 3497 (UDP) because on the internet I have not found anywhere the possibility that QUIC can be used other than ports 80 and 443?
Replies
1
Boosts
0
Views
1.3k
Activity
Jan ’24
nw_quic_set_idle_timeout setting time max number
Use Quic to set the maximum connection idle timeout supported. The test supported a maximum of 120000 milliseconds
Replies
1
Boosts
0
Views
709
Activity
Nov ’23
iOS17.0 quic_recovery_declare_packets_lost Crash
A large number of crashes occurred only on iOS 17.0 online from July 27, which is consistent with the release time of the 17.0 beta4 version. I suspect something is wrong with 17.0 beta4. Does anyone have the same problem and is there a solution? Thanks a lot Crashed: com.apple.CFNetwork.Connection 0 libquic.dylib 0x21120 quic_recovery_declare_packets_lost + 928 1 libquic.dylib 0x20788 quic_recovery_find_lost_packet_inner + 1272 2 libquic.dylib 0x1e564 quic_recovery_find_lost_packets + 352 3 libquic.dylib 0x11b74 quic_recovery_received_ack + 1180 4 libquic.dylib 0x52634 quic_frame_process_ACK + 368 5 libquic.dylib 0xb3bc8 quic_conn_process_frame + 964 6 libquic.dylib 0xb0370 quic_conn_process_inbound + 1840 7 Network 0x323c40 nw_protocol_data_access_buffer + 840 8 libquic.dylib 0xb6b48 __quic_conn_handle_inbound_block_invoke + 168 9 libquic.dylib 0xb690c quic_conn_handle_inbound + 124 10 Network 0x3102ac __nw_protocol_implementation_get_input_internal_block_invoke + 136 11 Network 0x30f8d4 nw_protocol_implementation_read + 408 12 Network 0x30f128 nw_protocol_implementation_input_available + 96 13 Network 0x1f5c4 nw_channel_update_input_source(nw_channel*, nw_protocol*, bool) + 7024 14 Network 0x2d880 nw_channel_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 124 15 Network 0x911ac0 nw_protocol_ipv6_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 268 16 Network 0x1da8a4 nw_protocol_udp_get_input_frames(nw_protocol*, nw_protocol*, unsigned int, unsigned int, unsigned int, nw_frame_array_s*) + 208 17 Network 0x30f868 nw_protocol_implementation_read + 300 18 Network 0x3153e4 nw_protocol_implementation_get_input_frames + 148 19 Network 0x3572e0 nw_flow_service_reads(NWConcrete_nw_endpoint_handler*, NWConcrete_nw_endpoint_flow*, nw_flow_protocol*, bool) + 992 20 Network 0x363ef0 __nw_endpoint_handler_add_read_request_block_invoke + 452 21 Network 0x7ba20 nw_hash_table_apply + 2696 22 Network 0x34d84 nw_endpoint_handler_add_read_request + 1688 23 Network 0x34848 nw_endpoint_handler_add_read_request + 348 24 Network 0x936c nw_connection_add_read_request_on_queue + 232 25 Network 0x9204 nw_connection_add_read_request + 344 26 Network 0x8cc4 nw_connection_receive_internal + 140 27 CFNetwork 0xa7620 CFURLDownloadStart + 66020 28 CFNetwork 0xe194c _CFStreamErrorFromCFError + 24656 29 CFNetwork 0x101918 _CFStreamErrorFromCFError + 155676 30 CFNetwork 0xfe2d8 _CFStreamErrorFromCFError + 141788 31 CFNetwork 0x1008dc _CFStreamErrorFromCFError + 151520 32 CFNetwork 0x1344d4 _CFStreamErrorFromCFError + 363480 33 CFNetwork 0xa73c8 CFURLDownloadStart + 65420 34 CFNetwork 0xb68c0 CFURLDownloadStart + 128132 35 CFNetwork 0x135c5c _CFStreamErrorFromCFError + 369504 36 CFNetwork 0x34f18 CFHTTPMessageCopySerializedMessage + 47008 37 CFNetwork 0x1e8180 CFHTTPCookieStorageUnscheduleFromRunLoop + 225244 38 CFNetwork 0x13585c _CFStreamErrorFromCFError + 368480 39 CFNetwork 0xb4d9c CFURLDownloadStart + 121184 40 libdispatch.dylib 0x13250 _dispatch_block_async_invoke2 + 148 41 libdispatch.dylib 0x4300 _dispatch_client_callout + 20 42 libdispatch.dylib 0xb894 _dispatch_lane_serial_drain + 748 43 libdispatch.dylib 0xc3f8 _dispatch_lane_invoke + 432 44 libdispatch.dylib 0xd6a8 _dispatch_workloop_invoke + 1756 45 libdispatch.dylib 0x17004 _dispatch_root_queue_drain_deferred_wlh + 288 46 libdispatch.dylib 0x16878 _dispatch_workloop_worker_thread + 404 47 libsystem_pthread.dylib 0x1964 _pthread_wqthread + 288 48 libsystem_pthread.dylib 0x1a04 start_wqthread + 8
Replies
14
Boosts
6
Views
4.2k
Activity
Oct ’23
tvOS libquic.dylib not found
When debugging a tvOS application that calls Data(contentsOf: URL) I get an error: nw_protocol_get_quic_image_block_invoke dlopen libquic failed: dlopen(/usr/lib/libquic.dylib, 0x0005): tried: [...a number of folders it tried to find the file in...]. I found similar problems here (https://developer.apple.com/forums/thread/693245), but it is not equal, nor does it have a solution. Any suggestions on how to fix this? I also tried to copy a libquic.tbd file present in other simulators to one of the paths it looks for (a suggestion somewhere on StackOverflow), but it does not help unfortunately.
Replies
11
Boosts
0
Views
3.0k
Activity
Sep ’23
iOS HTTP/3 not support zero-rtt?
Hi, I have run the system h3 on iphone OS 16.6 by learning this:TN3102: HTTP/3 in your app | Apple Developer Documentation; However, I have found that the request iOS sending not support zero rtt. When using chrome to request(h3), it‘s doing zero rtt successfully. So, may I ask if there any plan to support zero-rtt in http/3 ? PS.The UA:CFNetwork/1410.0.3 Darwin/22.6.0
Replies
3
Boosts
0
Views
1.4k
Activity
Sep ’23
Background URLSession http/3 URLSessionUploadTask not started in real device
I'm trying to upload large files in a background URLSession to a server that accepts HTTP/3 requests. Per its design, the server uses a self-signed SSL certificate. In my testing, I can create a regular URLSession (foreground) with the following: var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0) request.assumesHTTP3Capable = true request.httpMethod = "POST" self.session.dataTask(with: request) { &lt;snip&gt; } And handles the SSL certificate challenge by implementing the following for the delegate: func urlSession( _ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -&gt; Void ) This approach works and I can communicate with the server. But when I try to apply the same for a background session for an upload task, the task seems to be stuck, i.e. never started by the system. More specifically, the background session upload task works with iOS simulator. But on a real device connected to macOS, the task never started, and none of the delegate methods are called. The http/3 server didn't receive any request either. The background session was created: let appBundleName = Bundle.main.bundleURL.lastPathComponent.lowercased().replacingOccurrences(of: " ", with: ".") let sessionIdentifier: String = "com.networking.\(appBundleName)" let config = URLSessionConfiguration.background(withIdentifier: sessionIdentifier) self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil) later, an upload task was created : var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0) request.assumesHTTP3Capable = true request.httpMethod = "POST" let backgroundTask = self.session.uploadTask(with: request, fromFile: src) backgroundTask.resume() My question(s): why is the background session upload task stuck? Is there a way to find out where it is stuck? Does a background URLSession support app's delegate handling SSL certificate challenge? The test env: Xcode 14.2 macOS 12.6.7 iOS 15.7.7 Thanks!
Replies
4
Boosts
0
Views
1.5k
Activity
Aug ’23
NWConnection not connecting with QUIC
In an iOS network extension setup as a Packet Tunnel. I am accepting packets in using NEPacketTunnelFlow and open a NWConnection up to the destination like so let parameters = .quic(alpn: []) let connection = NWConnection(to: .hostPort(host: host, port: port!), using: parameters) but my state handler is never receiving the .ready state. My NWConnection code works fine for TCP and DNS using let parameters = .tcp // OR let parameters = .udp On my NWConnection state handler I am receiving .waiting with an error of dns. I am testing quic by navigating onto the Facebook app and with wireshark intercepting the traffic I can see the DNS queries resolving I have NEDNSSettings applied to my NEPacketTunnelNetworkSettings Is my issue to do with not passing in the alpn value or is there an extra permission/setting I am missing? I have not found a value which changes the outcome at all. I have tried following [https://developer.apple.com/videos/play/wwdc2021/10094/) but no success.
Replies
4
Boosts
0
Views
1.7k
Activity
Aug ’23
nw_protocol_data_access_buffer crash for iOS 16.0
We are getting new Crashes in our Firebase recently for iOS 16.0 OS Devices. But we are not able to get any meaningful message from Crashlytics. Also when we are testing, we are not able to reproduce the issue as well.
Replies
8
Boosts
0
Views
2.1k
Activity
Mar ’23
IS Https://IP/query support HTTP/3 ?
I'm use host to request https://MyHost/ the networkProtocolName return "h3" assumesHTTP3Capable = YES - (void)URLSession:(NSURLSession *)session        task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10)) { for (NSURLSessionTaskTransactionMetrics * m in metrics.transactionMetrics){              if(m.networkProtocolName.length &gt; 0){         NSLog(@"networkProtocolName %@", m.networkProtocolName);         break;       }     } } but when I use ip replace MyHost to request, and add MyHost to http header @{@"host": "ip"}, the networkProtocolName return "h2" - (void)URLSession:(NSURLSession *)session        task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {  NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;     NSURLCredential *credential = nil; //get header host replace ip     NSString *host = [[task.currentRequest allHTTPHeaderFields] objectForKey:@"host"];     if (!host) {       host = task.currentRequest.URL.host;     }     if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {       if ([weak evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:host]) {         disposition = NSURLSessionAuthChallengeUseCredential;         credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];       } else {         disposition = NSURLSessionAuthChallengePerformDefaultHandling;       }     } else {       disposition = NSURLSessionAuthChallengePerformDefaultHandling;     }     // 对于其他的 challenges 直接使用默认的验证方案     completionHandler(disposition,credential); } -(BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {   //创建证书校验策略   NSMutableArray *policies = [NSMutableArray array];   if (domain) {     [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];   } else {     [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];   }   //绑定校验策略到服务端的证书上   SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);   //评估当前 serverTrust 是否可信任,   //官方建议在 result = kSecTrustResultUnspecified 或 kSecTrustResultProceed 的情况下 serverTrust 可以被验证通过,   //https://developer.apple.com/library/ios/technotes/tn2232/_index.html   //关于SecTrustResultType的详细信息请参考SecTrust.h   SecTrustResultType result;   SecTrustEvaluate(serverTrust, &amp;result);   return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); } https://ip/ networkProtocolName return "h2" does ip request do not supprt HTTP/3? hope to respone thank you.
Replies
3
Boosts
0
Views
2.2k
Activity
Mar ’23
HTTP/3 Quic support in MacOS?
I work with .Net Core a lot, and whenever I look at docs like [censored] that say "HTTP/3 is not currently supported on macOS but may be available in a future release." So when will it be supported? I've seen where it's an experimental feature in Safari, and has to be explicitly enabled for it to work...when will be a full part of the OS so that third parties can make use of it in their tech stacks?
Replies
7
Boosts
1
Views
3.7k
Activity
Feb ’23
Crash on libquic.dylib (com.apple.network.connections) EXC_BREAKPOINT (SIGTRAP)
Hi Getting a crash mainly on iOS 15 with the Apple network thread. From our logs seems like in many locations in the app. Anyone any advice on how to debug it. Apple crash log below: Apple Crash Log
Replies
25
Boosts
1
Views
16k
Activity
Dec ’22