Seems like I have found a solution which is to add .handlesExternalEvents(matching: []) to the WindowGroup.
Post
Replies
Boosts
Views
Activity
This is not AV data. I have to admit this is quite of a major let down, very surprised back pressure isn't part of the Network framework when a bare socket does it. I have filed a bug report already (FB9587908). Thank you very much Matt for clarifying the situation and saving me a lot of time and trouble trying to figure this out.
It does reach the other side. What I'm saying is that I can send data onto the connection much more quickly than it actually goes out on the network, which causes it to enqueue in memory (a lot). I was expecting the connection to have a small buffer and only call the completion handler of the send() method when enough data had left the buffer and went onto the network.
In the current state of things, how would I know how fast the data is coming out of this internal buffer and onto the network? I would certainly need some sort of back pressure information in order to know whether it is ok to give more data to the connection. Or am I missing something?
Right, I wouldn't even dare to write a custom TLS implementation. I am implementing custom encryption that will only work with my application on both ends, it's not meant to interoperate with other things.
I thought I might be able to subclass NWParameters to pass custom parameters to my protocol but alas Swift prevents it: although the class is not marked final, it is also not marked open and therefore subclassing is prevented outside of the Network module.
Thank you for this reply. It doesn't seem like the TLS security options is what I need since I am implementing my own protocol which needs to pass its own custom options (unless I try to abuse these security options by inserting a pointer into some dispatch data object that could be stashed somewhere in there). But it does seem like what I want is NWParameters but for my protocol, alas the Network API does not seem to allow this.
I do have a length value in the packet header but I can't call deliverInputNoCopy because my protocol needs to look at all the data (doing custom encryption/decryption, not TLS on purpose). Therefore I am trying to parse the whole length read in the header.
I have seen nothing in the documentation or wwdc sessions about the framer.parseInput() API potentially starving depending on the minimum amount of data requested. Would you be so kind to at least give us the range of values we can expect to pass safely to the API?
Further testing indicates the latter: data is not dropped but the framer fails to receive more data, and even though handleInput() is called again, the buffer does not contain more to parse. Consuming the available (partial) data seems to unblock the situation as the framer is then able to receive the missing piece of the data.
Is this the correct behavior? Am I trying to parse too much data at once? If so, what is the upper limit we can parse without possibly entering this deadlock situation?
Or is there some buffer size limit above which the framer would stop receiving more data? It's as-if it never receives the end of the data even though the other side has sent it. My code can't parse the needed amount and handleInput() stops being called.
If we could pass some context into NWProtocolFramer.Options and access it from the protocol framer, that would also solve my problem. Actually it wouldn't solve my problem, for the listener the options are inserted into NWListener and not NWConnection. Rather I need access to the connection itself from my protocol framer, or to storage/context associated with the connection.
How do people solve that problem? It seems to me this is a pretty basic need but it is seemingly impossible to do, am I missing something here?
If that helps, my handleOuptut() method looks like this:
func handleOutput(framer: NWProtocolFramer.Instance, message: NWProtocolFramer.Message, messageLength: Int, isComplete: Bool) {
print("Protocol2 handleOutput()")
var length = Int32(messageLength)
let data = Data(bytes: &length, count: MemoryLayout<Int32>.size)
framer.writeOutput(data: data)
try? framer.writeOutputNoCopy(length: messageLength)
}
Thanks for your reply. The server receives nothing, none of the protocol has its handleInput() method called. Here are the logs:
# Client
Protocol1 start()
Protocol2 start()
sending 2990 bytes
Protocol2 handleOutput()
# Server
Protocol1 start()
Protocol2 start()
Protocol1 is placed at index 1, Protocol2 is on top at index 0. Instead I would expect this to happen:
# Client
Protocol1 start()
Protocol2 start()
sending 2990 bytes
Protocol2 handleOutput()
Protocol1 handleOutput()
# Server
Protocol1 start()
Protocol2 start()
Protocol1 handleInput()
Protocol2 handleInput()
received 2990 bytes
I insert the protocols on the NWListener (server-side) and the NWConnection (client-side) like so:
let protocol1 = NWProtocolFramer.Options(definition: Protocol1.definition)
let protocol2 = NWProtocolFramer.Options(definition: Protocol2.definition)
let parameters: NWParameters = .tcp
parameters.defaultProtocolStack.applicationProtocols.insert(protocol1, at: 0)
parameters.defaultProtocolStack.applicationProtocols.insert(protocol2, at: 0)