NWConnection ctx.isFinal/isComplete/TCP FIN/TLS close-notify

Say we have a TCP client that:
  1. Sends data A, .defaultMessage, isComplete* = true

  2. Sends data B, .finalMessage, isComplete* = true

(* I assume I have to say true here so it doesn't buffer, while on server isComplete is not true until end of stream; but even if I do isComplete = false here, it doesn't matter)

I would expect the server to:
  1. Receive data A, ctx.isFinal = false, isComplete = false

  2. Receive data B, ctx.isFinal = true, isComplete = true

or
  1. Receive data A, ctx.isFinal = false, isComplete = false

  2. Receive data B, ctx.isFinal = false, isComplete = false

  3. Receive nil data, ctx.isFinal = true, isComplete = true

... or A and B split at any other boundary, of course.

The actuality is:
  1. Receive data A, ctx.isFinal = true, isComplete = false

  2. Receive data B, ctx.isFinal = true, isComplete = false

  3. Receive nil data, ctx.isFinal = true, isComplete = true

Why is isFinal always true?

But okay, whatever, I can just rely on isComplete.

However, then I turn on TLS, and the result is:
  1. Receive data A, ctx.isFinal = true, isComplete = false

  2. Receive data B, ctx.isFinal = true, isComplete = false

  3. ... crickets ...

How am I supposed to know the client has EOF'd?

Does Network.framework not sent TLS close-notify?

I realize I can cancel() the entire connection on the client, and then I get isComplete = true, but I want to close just one half of the stream; the server still needs to send its response.



Replies

I would recommend opening a TSI so we can look deeper into what is happening here and what both sides of the connection look like.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
I am trying to and am using that form, however instead of "DTS Auto-Ack" like previously I'm getting "Thank you for contacting us.", and an agent replied with:

Thank you for contacting Apple Developer Program Support. My name is Nedra, and I am more than happy to assist. 

Apple Developer Support provides administrative-level support to members of the Developer Programs. We are not able to review or respond to threads that are posted in Developer Forums. 

I do have an incident available in my account. Looks like it's not getting routed properly. I am a bit at a loss...

Case numbers:
  • 101319294793

  • 101319947452

Thank you for the response. It looks like you may have contacted Apple Developer Program Support instead of Apple Developer Technical Support. Make sure that you use the link for Code-level Support under how to Submit a TSI. Those incident numbers do not look like they came through DTS.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
There is really something wrong with the system. See here for video:

hXXps://paste.jaka.io/2021-02-11/TSI.mov

Form says "Request Code-level Support". After submission it says "You will receive an email shortly with a follow-up number from Apple Developer Technical Support".

And now I have a third open case where the poor Program Support guys cannot help me:
  • 101319294793

  • 101319947452

  • 101320880570 <-

Man, are we off-topic to troubleshoot some completely unrelated issue now :-D

The TSI form is located here. It should start you off with a form to select the team you are requesting technical support for. Do you see this if you log into your account?


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Matt,

Have you seen the video above?

Jaka
Thanks Jaka. I am currently investigating this internally. Sorry for the delay here.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Looks like there might have been a glitch internally during the TSI submission process.
Can you file a bug report against this with the video that you have and the information on this thread. Please respond back with the Feedback ID so I can pass it along internally.
Again, sorry about the delay here.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Matt,

I submitted the report, ticket ID is FB9008451.

Jaka
Jaka,

Thank you for the Feedback ID and for calling this to our attention. We are looking into this now.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Hi,

No response on the Feedback yet.
Also, tried to re-submit a TSI... Still a problem, and opened another Program Support ticket (101329668227).

Any chance you can look at this, and I submit a TSI retroactively? :-)

Jaka
Regarding:

How am I supposed to know the client has EOF'd?

You could be marking your context as isFinal because you are telling the connection that you are finished writing on both sends. Looking at the docs:

Specifically, to send a "write close", pass .finalMessage or .defaultStream for the context (or create a custom context and set .isFinal), and pass true for isComplete.

If you try:
Code Block swift
clientConn.send(content: "Hello, Server!".data(using: .utf8), contentContext: .defaultMessage, isComplete: false, completion: .contentProcessed({ ... })
clientConn.send(content: "End.".data(using: .utf8), contentContext: .finalMessage, isComplete: true, completion: .contentProcessed({ ... })


Does this change the behavior that you see on your completion handler?


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Jaka,

I wanted to update you that your TSI was just added to my queue internally. Thank you for your patience in this matter. One thing that I do want to mention though is when opening a TSI, please make sure to include a full technical writeup of your issue - even if it's copied from this Forum's Post. This will help make sure that your question is routed correctly internally and does not get lost because it only contains a link this post.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Update:

If you want to get "EOF"/half-close connections over TLS, you will have to implement a custom framing protocol.

Apple (or at least Matt) states this is not a bug and works as expected (DTS 762944544).

Implementing something like a "byte count server" (server receives arbitrary bytes, then upon end of stream, replies with a byte count) reliably is not possible using TLS & Network.framework.