Post

Replies

Boosts

Views

Activity

How to add a String to NWProtocolTLS.Options()?
I want achieve what @eskimo said in his answer on this page - https://developer.apple.com/forums/thread/663596: Have each peer decide on its own unique ID. When a client connects to a server, the first message it sends across that connection contains its unique ID. The server then responds with its own unique ID. If either end discovers that a connection with that unique ID pair already exists, it drops one of the connections. As long as they both agree to drop the same connection, everything will be fine. A good strategy here is to drop the one with the lesser ID. I looked at Apple's TicTokToe example app and they set a password string using a custom initializer. I followed some of their code but once the Listener starts and the connection.stateUpdateHandler is called it never goes past .preparing: connection.stateUpdateHandler = { [weak self](nwConnectionState) in 	 switch nwConnectionState { 				case .preparing:            	 print("Connection preparing") // it's stuck here 				// ... 		} } Here is how I use the custom param (rest of setup is in this question): - https://developer.apple.com/forums/thread/669062?answerId=651917022#651917022 var listener: NWListener? init () { 		do { 				let uid = UUID().uuidString 				let parameters = NWParameters(uid: uid) 				listener = try NWListener(using: parameters) 				listener?.service = NWListener.Service(name: "MyName", type: "_myApp._tcp") 				startListening() 		} catch { 		} } I'm using UUID().uuidString to create the uid just so that I can attempt what @eskimo proposed in step 2 and step 4. Once the user kills the app and opens it again a new uid will be generated every time they try to connect with other devices. Because of this I don't need the uid to be secure. The Apple TikTokToe tls code seemed like overkill for my situation so I removed all of the encryption features that they used. How do I add the uid string to the NWProtocolTLS.Options()? extension NWParameters { convenience init(uid: String) { 	let tcpOptions = NWProtocolTCP.Options()       tcpOptions.enableKeepalive = true       tcpOptions.keepaliveIdle = 2    	 self.init(tls: NWParameters.tlsOptions(uid: uid), tcp: tcpOptions) } private static func tlsOptions(uid: String) -> NWProtocolTLS.Options { 	let tlsOptions = NWProtocolTLS.Options() 	return tlsOptions } } It should be noted that outside of the problems inside the link, - https://developer.apple.com/forums/thread/669062?answerId=651917022#651917022 the problem from this question is avoided and .ready is called when I use the normal initializer: let tcpOptions = NWProtocolTCP.Options() tcpOptions.enableKeepalive = true tcpOptions.keepaliveIdle = 2 let parameters = NWParameters(tls: nil, tcp: tcpOptions) parameters.includePeerToPeer = true
5
0
836
Dec ’20
NWConnection's connection.receiveMessage method gets breakpoint hit but callback not entered
I have a NWBrowser and a NWConnection on my iPhone 7+ (real device) that sends out some data. On the simulator I have a NWListener and a NWConnection that receives the data. Inside the NWListener class named PeerListener, inside the listener.newConnectionHandler callback I have a delegate to create a NWConnection that gets hit multiple times when I put a break point on it. This results in the NWConnection's connection.stateUpdateHandler printing out the following multiple times below: // these are all .preparing and .ready cases Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established Connection preparing Connection established After the last print statement, which is .ready, the connection is sent over to the VC via a delegate where connection.receiveMessage runs. I put a break point on it, it gets hit, but the call back is never entered. I'm not sure what the problem is because the connection is definitely happening between the device and simulator, all the correct methods are hit (unfortunately multiple times), but the callback is never entered. What is the problem here? NWListener protocol PeerListenerDelegate: class {     func createNewIncoming(_ connection: NWConnection) } class PeerListener {     weak var delegate: PeerListenerDelegate?     fileprivate var listener: NWListener? 		init () {         do {             let tcpOptions = NWProtocolTCP.Options()             tcpOptions.enableKeepalive = true             tcpOptions.keepaliveIdle = 2             let parameters = NWParameters(tls: nil, tcp: tcpOptions)             parameters.includePeerToPeer = true             listener = try NWListener(using: parameters)             listener?.service = NWListener.Service(name: "MyName", type: "_myApp._tcp")             startListening()         } catch let error as NSError {             print("Failed to create listener", error.debugDescription)         }     } 		fileprivate func startListening() {         guard let listener = listener else { return }         listener.stateUpdateHandler = { [weak self](newState) in             switch newState { 						case .setup: print("listener setup")             case .ready: print("Listener ready on \(String(describing: listener.port))")             case .cancelled: print("listener cancelled")             case .failed(let error):                 if error == NWError.dns(DNSServiceErrorType(kDNSServiceErr_DefunctConnection)) {                     listener.cancel()                     self?.startListening()                 } else {                     print(error.debugDescription)                     listener.cancel()                 }             default:break             }         }         receivedNewConnectionFrom(listener)         listener.start(queue: .main)     } 		fileprivate func receivedNewConnectionFrom(_ listener: NWListener) {         listener.newConnectionHandler = { [weak self](newConnection) in             self?.delegate?.createNewIncoming(newConnection)         }     } } VC that initializes the Listener, connection.receiveMessage is in here, last function at the bottom, line 23 class ViewController: UIViewController { 		fileprivate var listener: PeerListener? 		fileprivate var connectionIncoming: ConnectionIncoming? 		override func viewDidLoad() {         super.viewDidLoad() 				listener = PeerListener()         listener?.delegate = self 		} 		// 1. PeerListenerDelegate to create NWConnection object 		func createNewIncoming(_ connection: NWConnection) {         self.connectionIncoming = ConnectionIncoming(connection:connection, delegate: self)     } 		// 2. ConnectionIncomingDelegate to receive data from connection object 		func receivedIncoming(_ connection: NWConnection) {         connection.receiveMessage { [weak self](data, context, isComplete, error) in             print(" *** callback entered * THIS NEVER GETS HIT *** ")             if let err = error {                 print("Recieve error: \(err.debugDescription)")                 return             }             if isComplete {                 print("Receive is complete")                 if let data = data, !data.isEmpty { 										self?.received(data, from: connection)                 }             } else {                 print("Not Complete")             }         }     } } NWConnection protocol ConnectionIncomingDelegate: class {     func receivedIncoming(_ connection: NWConnection) } class ConnectionIncoming {     weak var delegate: ConnectionIncomingDelegate?     private var connection: NWConnection?     init(connection: NWConnection, delegate: ConnectionIncomingDelegate) {         self.delegate = delegate         self.connection = connection         startConnection()     }     func startConnection() {         guard let connection = connection else { return }         connection.stateUpdateHandler = { [weak self](nwConnectionState) in             switch nwConnectionState { 						case .preparing: print("Connection preparing")             case .setup: print("Connection setup")             case .waiting(let error): print("Connection waiting: ", error.debugDescription)             case .ready:                 print("Connection established")                 self?.delegate?.receivedIncoming(connection)             case .failed(let error):                 print("Connection failed: ", error.debugDescription)                 connection.cancel()             default:break             }         }         connection.start(queue: .main)     } }
5
0
2.2k
Dec ’20
How to set peer limit when using NWConnection
When using MultipeerSession I can set a limit to the number of peers on each connection using: func peerDiscovered(_ peer: MCPeerID) -> Bool {     if multipeerSession.connectedPeers.count > 4 {         // Do not accept more than four users in the experience.         return false     } } Im using peer-to-peer with NWConnection, NWListener, and NWBrowser: let params = NWParameters() params.includePeerToPeer = true How can I set a limit to the number of users/peers allowed per connection? self.connection?.receiveMessage { (data, context, isComplete, error) in     if (isComplete) {         if let data = data, !data.isEmpty { 						// do something with data 				} 		} }
2
0
781
Dec ’20