I’ve had hackers start to load pages and apparently stop reading without closing the connection (unfortunately I’m not there to watch with WireShark when it happens). Successful SEND commands result in Sn_IR being set to SEND_OK, but if the connection is held open while the client’s TCP window is deliberately left full the send can’t complete. If this happens, will Sn_IR be set to TIMEOUT like it is when ARP or TCP reads see no response?
I think so (I am sure you can test it yourself). When you issue SEND command chip sends data packet(s) to the remote device, and that device must respond with ACK to confirm data reception. If ACK does not happen, originator must resend data (and I think W5500 does it). And at the retry set in respective register communication must time out.
The worst impact of your described situation is that socket remains open until time out, and this event. depending on register setting, may take up to several minutes. Thus configure the server to have 15 seconds timeout maximum.
The scenario I’m seeing is a bit different… I think the W5500 never finishes putting the data on the wire because the TCP window is full, so it wouldn’t expect an ACK. Instead, it’s waiting for a Window Update that tells it to send the data in its TX buffer.
You’d hope it times out, but I can’t find anything in the datasheet that says it does.
I added code to test for it. I’ll watch my log file to see if the condition occurs.
This is the question I wanted to ask Eugeny too. I am under the impression that there is no “built-in” timeout for an established socket. I know W5500 supports TCP KeepAlive via setSn_KPALVTR() API from the ioLibrary. Could this be used on the server side to detect a half-open connection?
The W5500 supports timeouts for ARP and (some?) TCP operations. See pages 39 & 40 in the datasheet for info about RTR (retry time-value register) and RCR (retry count register). When a timeout occurs, Sn_IR is set to TIMEOUT (0x08) (page 49).
From page 39: “While waiting for ARP-response from the peer, if there is no response during the configured RTR time, a temporary timeout is occurred and ARP-request is retransmitted. It is
repeated as many as ‘RCR + 1’ times. Even after the ARP-request retransmissions are repeated as ‘RCR+1’ and there is no response to the ARP-request, the final timeout is occurred and Sn_IR(TIMEOUT) becomes ‘1’.”
Further down on page 39: “At the TCP packet retransmission timeout, W5500 transmits TCP packets (SYN, FIN, RST, DATA packets) and waits for the acknowledgement (ACK) during the configured RTR time and RCR. If there is no ACK from the peer, a temporary timeout occurs and the TCP packet is retransmitted. The retransmission is repeated as many as ‘RCR+1’. Even after TCP retransmission is repeated as ‘RCR+1’ and there is no response to the TCP retransmission, the final timeout is occurred and Sn_IR(TIMEOUT) becomes ‘1’.”
What’s unclear (to me, anyway) is whether a timeout will occur when the send operation that would result in an ACK from the other end can’t be completed.
This is different story, probably I misunderstood. Here you mean that your local TX buffer is not full, but it is remote device’s RX buffer which is full. I was talking about local TX queue.
Very probable than you are right.
There’s certainly at least one timeout condition when W5x00 sends packet, but remote device does not respond with ACK. But IMHO there’re circumstances when built-in network stack may “hung” and the only way to recover is the driving code timing out and performing forceful operations on the socket (e.g. close and reopen).
This call just sends last ACK (aka duplicate ACK) to the remote device. Logically if there was no prior communication it can not be done (nothing to be ACKed so far) and that’s why datasheet explicitly says that it will work only if there was communication before invoking this call.
Thus this “keep alive packet”, being sent by W5x00, requires ACK from remote device, and it works in absolutely the same was as any other data packet - if there is no ACK from out there or RST is received, timeout occurs and socket closes.
I do not know answer to this question. In the described situation W5x00 receives ACK, but it does not satisfy sending conditions with remote device’s RX window being zero, right? I am afraid it will continue trying forever… will be extremely glad if you can test it!
I’ve built and deployed a version of my code that will log the value of Sn_IR if the loop that waits for a buffer to be transmitted doesn’t detect a SEND_OK in Sn_IR within 35 seconds (since timeout with default values of RTR and RCR is 31.8 seconds) OR if Sn_IR is set to TIMEOUT. I’ll leave it on the internet for a few days and see if it catches anything.
Will let you know what happens.