Andrija
I have started looking into the case where you could overrun the peers input buffer.
1) I believe that it is true that the length of transmitted data which hasn't been acknowledged is not being considered when the peer's window size if updated. This happens only when windowing is in operation and the transmitter is sending multiple frame before waiting for an ACK, "and" when the peer acknowledges only a part of the outstanding data.
2) If I am not mistaken, the correction can therefore also be restricted to the case when we receive ACKs to parts of outstanding data (reference TCP_EVENT_PARTIAL_ACK). Therefore I propose to leave it generally as
ptr_TCP->usTxWindowSize = rx_tcp_packet.usWindowSize; // save the present windows size advertised by the peer
Since the correction will usually result in no change it is also more efficient to not adjust the value when not needed.
3) I propose that the adjustment be made only when handling partial ACKs. That is, when we are expecting an ACK to outstanding data [ptr_TCP->ulSendUnackedNumber != ptr_TCP->ulNextTransmissionNumber] but the peer is not acknowledging "all" outstanding data [rx_tcp_packet.ulAckNo != ptr_TCP->ulNextTransmissionNumber].
4) This is handled as follows at the moment:
if ((ptr_TCP->ulNextTransmissionNumber != rx_tcp_packet.ulAckNo) && (APP_REQUEST_CLOSE & (iAppTCP |= ptr_TCP->event_listener(ptr_TCP->MySocketNumber, TCP_EVENT_PARTIAL_ACK, ptr_TCP->ucRemoteIP, (unsigned short)(ptr_TCP->ulNextTransmissionNumber - rx_tcp_packet.ulAckNo))))) {
if (rx_tcp_packet.usHeaderLengthAndFlags & TCP_FLAG_FIN) { // the application has commanded the close of the connection
// we have just received FIN + ACK, meaning that the other side has also initiated a close
fnNewTCPState(ptr_TCP, TCP_STATE_CLOSING); // this a simultaneous close, so we go to state closing and wait for the last ack
}
return;
}
iAppTCP |= HANDLING_PARTICAL_ACK; // mark that we are dealing with a partial ACK
5)
I propose changing this as follows:
unsigned short usPartialDataLength = (unsigned short)(ptr_TCP->ulNextTransmissionNumber - rx_tcp_packet.ulAckNo); // the length of the data being acknowledged
if (usPartialDataLength != 0) {
ptr_TCP->usTxWindowSize -= usPartialDataLength; // since there is still data underway to the peer respect this in the window size
if (APP_REQUEST_CLOSE & (iAppTCP |= ptr_TCP->event_listener(ptr_TCP->MySocketNumber, TCP_EVENT_PARTIAL_ACK, ptr_TCP->ucRemoteIP, usPartialDataLength))) {
if (rx_tcp_packet.usHeaderLengthAndFlags & TCP_FLAG_FIN) { // the application has commanded the close of the connection
// We have just received FIN + ACK, meaning that the other side has also initiated a close
//
fnNewTCPState(ptr_TCP, TCP_STATE_CLOSING); // this a simultaneous close, so we go to state closing and wait for the last ack
}
return;
}
}
iAppTCP |= HANDLING_PARTICAL_ACK; // mark that we are dealing with a partial ACK
This restricts the adjustment (correction) to the case where it is relevant (efficiency).
Regards
Mark