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.