I have the following data structures:
@Published private(set) var endpoints: [DeviceID: NWEndpoint] = [:]
@Published private(set) var connections: [ConnectionID: NWConnection] = [:]
@Published private(set) var connectionDevice: [ConnectionID: DeviceID] = [:]
@Published private(set) var deviceConnection: [DeviceID: ConnectionID] = [:]
I changed my code such that the browser will first check if its deviceID is greater than the discovered device ID - if it is then it will try and connect to it. I also changed my code to save the connection in the newConnectionHandler. With all that I am experiencing some odd behavior. I have two physical devices, an iPhone and an iPad. The iPhone's deviceID is greater than the deviceID of the iPad. Due to this the iphone will create a connection to the ipad. Also due to this the ipad will not try and create a connection to the iphone.
I am able to see, via printIt(), that the iphone has one item in each data structure. The iPad only has one item in endpoints (this is due to me saving it from the ipad's browser) and one item in connections (the incoming connection from the iphone)
the odd behavior is as follows:
right after things hit steady state - meaning that the ipad and iphone are done discovering and connection to each other - when i go to send a message from the ipad to the iphone i get the following message on the iphone logs
nw_protocol_instance_add_new_flow [C18.1.1.1:1] No listener registered, cannot accept new flow
quic_stream_add_new_flow [C18.1.1.1:1] [-1fe5f3879e2c580d] failed to create new stream for received stream id 1
if i then send a message from the iphone to the ipad and then try and send a message from the ipad to the iphone - it works
Here is how i add an endpoint from the browser
browser.browseResultsChangedHandler = { [weak self] _, changes in
guard let self = self else { return }
Task { @MainActor in
guard let thisDeviceID = self.devicesService?.thisDevice?.id else {
print("[browseResultsChangedHandler] cant get device id")
return
}
for change in changes {
switch change {
case .added(let added):
guard let deviceID = self.devicesService?.deviceIDFromEndpoint(added.endpoint) else {
print("[browseResultsChangedHandler - .added] could not get device id")
continue
}
guard !self.endpoints.keys.contains(deviceID) else {
print("[browseResultsChangedHandler] already added device \(deviceID)")
continue
}
guard deviceID != thisDeviceID else {
print("found myself - ignoring")
continue
}
self.addEndpoint(added.endpoint)
case .removed(let removed):
print("browseResultsChangedHandler: removed peer \(removed)")
guard let deviceID = self.devicesService?.deviceIDFromEndpoint(removed.endpoint) else {
print("[browseResultsChangedHandler - .removed] could not get deviceID")
continue
}
guard self.endpoints.keys.contains(deviceID) else {
print("[browseResultsChangedHandler] endpoint was never added \(deviceID)")
continue
}
self.removeEndpoint(removed.endpoint)
default:
continue
}
}
}
}
private func addEndpoint(_ endpoint: NWEndpoint) {
guard !endpointExists(endpoint) else {
print("endpoint already exists")
return
}
guard let deviceID = devicesService?.deviceIDFromEndpoint(endpoint) else {
print("[removeEndpoint] could not get deviceID")
return
}
guard let thisDeviceID = devicesService?.thisDevice?.id else {
print("[removeEndpoint] could not get thisDeviceID")
return
}
if thisDeviceID > deviceID {
do {
let identity = importIdentityFromPKCS12()
let parameters = try NWParameters(identity: identity)
let connection = NWConnection(to: endpoint, using: parameters)
let connectionID = getConnectionID(connection)
connections[connectionID] = connection
connectionDevice[connectionID] = deviceID
deviceConnection[deviceID] = connectionID
connect(deviceID: deviceID)
} catch {
print("Failed to create connection parameters: \(error)")
}
}
endpoints[deviceID] = endpoint
devicesService?.addDevice(device: DevicesService.Device(id: deviceID, name: nil, model: nil, camera: nil))
}
Here is my new connection handler
listener?.newConnectionHandler = { [weak self] connection in
guard let self = self else { return }
print("New inbound connection received from: \(connection)")
Task { @MainActor in
let connectionID = self.getConnectionID(connection)
self.connections[connectionID] = connection
self.connect(connection)
}
}