Adam/Net/Tcp: more fixes & improvements to connection closing

v5
minexew 2 years ago
parent 0f26d0bfbb
commit d18b27643e
  1. 81
      Adam/Net/Tcp.HC

@ -280,8 +280,22 @@ I64 TcpSend2(CTcpSocket* s, U8 flags) {
s->snd_nxt++;
//"Sent #%d, to %08X, err = %d\n", s->seq, s->remote_addr, error;
// FIXME: If the packet is SYN or FIN, we also need to queue for retransmit!
return TcpPacketFinish(index, s->local_addr, s->remote_addr, frame, 0, NULL);
if (flags & (TCP_FLAG_SYN | TCP_FLAG_FIN)) {
CTcpSendBufHeader* sb;
TcpPacketFinish(index, s->local_addr, s->remote_addr, frame, 0, &sb);
sb->seq_end = s->snd_nxt;
// Append to SendBuf chain
if (s->send_buf_first)
s->send_buf_last->next = sb;
else
s->send_buf_first = sb;
s->send_buf_last = sb;
}
else {
return TcpPacketFinish(index, s->local_addr, s->remote_addr, frame, 0, NULL);
}
}
// Send a TCP frame with flags and data
@ -507,28 +521,53 @@ I64 TcpSocketClose(CTcpSocket* s) {
*/
// Send FIN & wait for acknowledge
TcpSend2(s, TCP_FLAG_FIN);
s->state = TCP_STATE_FIN_WAIT_1;
// "FIN-WAIT-1\n";
// Block until all outgoing data including our FIN have been acknowledged (una == nxt)
//
// TODO: what other states are permissible here?
// TODO: this can block for ever if our receive buffer fills up, but the other side
// insists on pushing more data before closing the connection
while ((s->state == TCP_STATE_ESTABLISHED || s->state == TCP_STATE_FIN_WAIT_1)
&& s->snd_una != s->snd_nxt) {
TcpSocketCheckSendBufs(s);
Yield;
if (s->state == TCP_STATE_ESTABLISHED) {
while (TcpSend2(s, TCP_FLAG_FIN) < 0) {
TcpSocketCheckSendBufs(s);
Yield;
}
s->state = TCP_STATE_FIN_WAIT_1;
// "FIN-WAIT-1\n";
// Block until all outgoing data including our FIN have been acknowledged (una == nxt)
//
// TODO: what other states are permissible here?
// TODO: this can block for ever if our receive buffer fills up, but the other side
// insists on pushing more data before closing the connection
while ((s->state == TCP_STATE_FIN_WAIT_1)
&& s->snd_una != s->snd_nxt) {
TcpSocketCheckSendBufs(s);
Yield;
}
if (s->state == TCP_STATE_FIN_WAIT_1) {
s->state = TCP_STATE_FIN_WAIT_2;
// "FIN-WAIT-2 (%d/%d)\n", s->snd_una, s->snd_nxt;
}
// Now we should wait for the other side's FIN and acknowledge it
// TODO: time-out
while (s->state == TCP_STATE_FIN_WAIT_2) {
Yield;
}
}
else if (s->state == TCP_STATE_CLOSE_WAIT) {
while (TcpSend2(s, TCP_FLAG_FIN | TCP_FLAG_ACK) < 0) {
TcpSocketCheckSendBufs(s);
Yield;
}
s->state = TCP_STATE_FIN_WAIT_2;
// "FIN-WAIT-2 (%d = %d)...\n", s->snd_una, s->snd_nxt;
if (s->state == TCP_STATE_CLOSE_WAIT) {
s->state = TCP_STATE_LAST_ACK;
// "LAST-ACK (%d/%d)\n", s->snd_una, s->snd_nxt;
}
// Now we should wait for the other side's FIN and acknowledge it
// TODO: time-out
while (s->state == TCP_STATE_FIN_WAIT_2) {
Yield;
// Block until all outgoing data including our FIN have been acknowledged (una == nxt)
while (s->state == TCP_STATE_LAST_ACK && s->snd_una != s->snd_nxt) {
TcpSocketCheckSendBufs(s);
Yield;
}
}
// Still connected? RST it!

Loading…
Cancel
Save