Post

Replies

Boosts

Views

Activity

Reply to NWListener, P2P and awdl interfaces
Thank you for your response, Quinn. The short answer is that it's a user requirement for my app. The longer answer is that very few enterprises use IPv6 addressing, some explicitly block it from their routing tables, and if someone elects to manually enter an IP address of a known system in their environment to connect to and it's in IPv4 format, when my app connects to it and reports success - it should be able to report that it connected to the same address that was entered. Instead, I am forced to use the remoteEndPoint which is only reported as an IPv6 address. It's confusing for the user. A better question is why is there an option to force IPv4 and it doesn't work but rather breaks things? I can live with this quirk, but it somewhat defeats the purpose of the flexibility advertised by the Network Framework. I'm more interested in solving why I can connect across SSID / VLAN using Bonjour, but not using a direct IP Address and Port. I would be grateful if you please help me solve this part of my issue. I'm using wired Ethernet and not Wi-Fi - does that change your answer at all or does P2P only work for Bonjour? Your footnote says this is something you are able to discuss here. Should I assume that means you are not? If not, is there another framework you would recommend to connect P2P to a direct IP Address? Thanks!
1w
Reply to NWListener, P2P and awdl interfaces
After posting this, I did some more testing and found that simply removing where I forced IPv4 at the bottom of the code in the previous post solved this issue..... partially. I can now connect across a network broadcast domain boundary, but I still cannot manually input an IP Address. I have to use Bonjour to cross the boundary. I can manually input the IP Address and connect when within the broadcast domain. I would ideally like to limit everything to IPv4 addressing in my app, but given that that doesn't seem to work and connecting across SSID / VLAN / broadcast / multicast boundaries is more important, how can I either still limit to IPv4 or how can I connect directly to a given IP Address across SSID / VLAN boundaries with the Network Framework? Here is my code. First up are the Constructors to my Connection object, including the one that takes an IP Address as a String: // Bonjour Endpoint Constructor public init( endpoint: NWEndpoint, key: Data ) async throws { let parameters = NWParameters( authenticatingWithKey: key ) self.connection = NWConnection( to: endpoint, using: parameters ) ( data, dataContinuation ) = AsyncThrowingStream.makeStream() try await connect() } // Explicit IP Address Constructor public init( ipAddress: String, key: Data ) async throws { let parameters = NWParameters( authenticatingWithKey: key ) let host: NWEndpoint.Host = NWEndpoint.Host( ipAddress ) let port: NWEndpoint.Port = advertisedPort // Fixed self.connection = NWConnection( host: host, port: port, using: parameters ) ( data, dataContinuation ) = AsyncThrowingStream.makeStream() try await connect() } // Server Constructor public init( connection: NWConnection ) async throws { self.connection = connection ( data, dataContinuation ) = AsyncThrowingStream.makeStream() try await connect() } And here is my Connection.connect(): public func connect() async throws { try await withCheckedThrowingContinuation { continuation in connection.stateUpdateHandler = { [weak connection] state in switch state { case .ready: connection?.stateUpdateHandler = { state in switch state { case .failed( let error ): dataContinuation.finish( throwing: error ) break case .cancelled: dataContinuation.finish() break default: break } } continuation.resume() break case .preparing: break case .waiting( let waitingError ): break case .failed( let error ): let out = "Failed with Error: \( error.localizedDescription )" Task { await AppDelegate.log( out ) } continuation.resume( throwing: error ) break default: let out = "Other Connection Status: \( state )" Task { await AppDelegate.log( out ) } print( out ) break } } connection.start( queue: .main ) } Self.receiveNextMessage( connection: connection, continuation: dataContinuation ) } I can get as far as ".preparing" the connection with the manually-entered IP Address. Then, it hangs.
1w
Reply to NWListener, P2P and awdl interfaces
Did setting includePeerToPeer solve your issues? I have the same issues you describe above, but I am setting includePeerToPeer=true. The only real difference is that I'm using TLS with a key. This works with simulated or real devices on the same broadcast domain, e.g. same VLAN, same SSID, or same multicast domain. I can see the advertisement on a different SSID or VLAN, but I cannot connect. I also have a function where you can specify an IP Address. Since I force advertising on a specific port and can start a connection with Bonjour locating the service, I am at a loss why I can't connect across the broadcast domain. Here is how I'm setting my NWParameters: extension NWParameters { convenience init( authenticatingWithKey key: Data ) { let tlsOptions = NWProtocolTLS.Options() let symmetricKey = SymmetricKey( data: key ) let code = HMAC<SHA256>.authenticationCode( for: Data( "AppleConnect".utf8 ), using: symmetricKey ).withUnsafeBytes( DispatchData.init ) sec_protocol_options_add_pre_shared_key( tlsOptions.securityProtocolOptions, code as dispatch_data_t, Data( "WindowProjectionTest".utf8 ).withUnsafeBytes( DispatchData.init ) as dispatch_data_t ) sec_protocol_options_append_tls_ciphersuite( tlsOptions.securityProtocolOptions, tls_ciphersuite_t( rawValue: numericCast( TLS_PSK_WITH_AES_128_GCM_SHA256 ) )! ) // TLS PSK requires TLSv1.2 on Apple platforms - See https://developer.apple.com/forums/thread/688508. sec_protocol_options_set_max_tls_protocol_version( tlsOptions.securityProtocolOptions, .TLSv12 ) sec_protocol_options_set_min_tls_protocol_version( tlsOptions.securityProtocolOptions, .TLSv12 ) // Requires Second Attempt self.init( tls: tlsOptions ) defaultProtocolStack.applicationProtocols.insert( NWProtocolFramer.Options( definition: .init( implementation: ConnectProtocol.self ) ), at: 0 ) // Set Connection Configuration acceptLocalOnly = false allowLocalEndpointReuse = true includePeerToPeer = true prohibitedInterfaceTypes = [ NWInterface.InterfaceType.loopback ] // Force IPv4 if let isOption = defaultProtocolStack.internetProtocol as? NWProtocolIP.Options { isOption.version = .v4 } } }
1w