I’m pulling out my hair trying to reverse-engineer the more-or-less undocumented Network framework. It appears that two things are happening, one is that the listener is accepting two connection requests, one on ipv4 and one on ipv6. Secondly, it seems that the the connection immediately sets isComplete.
Also, what does prohibit joining mean in the connection?
server: did accept connection: [C1 ::1.63423 tcp, local: ::1.63406, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]
It sure would be nice to have more examples of this framework in action, it feels like Apple is not really committed to it and that worries me.
Also, what does prohibit joining mean in the connection?
server: did accept connection: [C1 ::1.63423 tcp, local: ::1.63406, server, prohibit joining, path satisfied (Path is satisfied), interface: lo0]
It sure would be nice to have more examples of this framework in action, it feels like Apple is not really committed to it and that worries me.
Code Block class Server { var publisher = PassthroughSubject<Data, NWError>() private var connection: NWConnection? = nil let listener: NWListener init() { listener = try! NWListener(using: .tcp) } func report(_ msg: String) { print("server: \(msg)") } func start() throws { report("start server") listener.service = NWListener.Service(name: bonjourName, type: bonjourService, domain: nil) listener.stateUpdateHandler = self.stateDidChange(to:) listener.newConnectionHandler = self.didAccept(nwConnection:) listener.serviceRegistrationUpdateHandler = self.serviceRegistrationUpdateHandler listener.start(queue: .main) } private func stateDidChange(to newState: NWListener.State) { switch newState { case .ready: report("Server ready service=\(listener.service) port=\(listener.port)") case .failed(let error): report("Server failure, error: \(error.localizedDescription)") publisher.send(completion: Subscribers.Completion.failure(error)) default: break } } private func serviceRegistrationUpdateHandler(_ change: NWListener.ServiceRegistrationChange) { report("registration did change: \(change)") } private func didAccept(nwConnection: NWConnection) { report("did accept connection: \(nwConnection)") connection = nwConnection connection?.stateUpdateHandler = self.stateDidChange connection?.start(queue: .main) receive() } private func stateDidChange(to state: NWConnection.State) { switch state { case .waiting(let error): publisher.send(completion: Subscribers.Completion.failure(error)) case .ready: report("connection ready") case .failed(let error): publisher.send(completion: Subscribers.Completion.failure(error)) connectionDidFail(error: error) default: break } } // functions removed to make space private func receive() { connection?.receive(minimumIncompleteLength: 1, maximumLength: Int.max) { (data, _, isComplete, error) in if let error = error { self.report("connection failed: \(error)") self.connectionDidFail(error: error) return } if let data = data, !data.isEmpty { self.report("connection did receive, data: \(data)") self.publisher.send(data) } if isComplete { self.report("is complete") // self.connectionDidEnd() return } else { self.report("setup next read") self.receive() } } } func send(data: Data) { report("connection will send data: \(data)") self.connection?.send(content: data, contentContext: .defaultStream, completion: .contentProcessed( { error in if let error = error { self.connectionDidFail(error: error) return } self.report("connection did send, data: \(data)") })) } func sendStreamOriented(connection: NWConnection, data: Data) { connection.send(content: data, completion: .contentProcessed({ error in if let error = error { self.connectionDidFail(error: error) } })) } }