Fix TCP socket connect not sending ACK after receiving SYN ACK.

Fix missing socket FSM state transition after binding a new connection.
Fix TCP socket send unused sent_total variable.
Integrate INADDR_ANY address handling procedure used in TCP to UDP.
Change two TCP tests into TCPEchoClient.CC and TCPEchoServer.CC, alter to make compatible with Shrine's echo tests.
Split long lines of code to multiple lines to fit better in default resolution.
This commit is contained in:
TomAwezome 2021-05-12 02:42:33 -04:00
parent 05dd1af872
commit 3917898085
11 changed files with 172 additions and 90 deletions

View file

@ -94,7 +94,8 @@ I64 TCPPacketAllocate(U8 **frame_out,
header->source_port = EndianU16(source_port);
header->destination_port = EndianU16(destination_port);
NetDebug("TCP PACKET ALLOCATE: Outputting header port src/dest 0x%0X/0x%0X:", header->source_port, header->destination_port);
NetDebug("TCP PACKET ALLOCATE: Outputting header port src/dest 0x%0X/0x%0X:",
header->source_port, header->destination_port);
header->seq_num = EndianU32(seq_num);
header->ack_num = EndianU32(ack_num);
@ -205,7 +206,8 @@ I64 TCPSendFlags(CTCPSocket *tcp_socket, U8 flags)
case AF_INET:
source_ipv4 = source;
NetDebug("TCP SEND FLAGS: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X", source_ipv4->port, dest_ipv4->port);
NetDebug("TCP SEND FLAGS: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X",
source_ipv4->port, dest_ipv4->port);
de_index = TCPPacketAllocate(&payload_frame,
source_ipv4->address.address,
@ -329,7 +331,8 @@ I64 TCPSendData(CTCPSocket *tcp_socket, U8 flags, U8 *data, I64 length)
case AF_INET:
source_ipv4 = source;
NetDebug("TCP SEND DATA: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X", source_ipv4->port, dest_ipv4->port);
NetDebug("TCP SEND DATA: Trying TCP Packet Allocate... port src/dest 0x%0X/0x%0X",
source_ipv4->port, dest_ipv4->port);
de_index = TCPPacketAllocate(&payload_frame,
source_ipv4->address.address,
@ -474,6 +477,8 @@ U0 TCPAcknowledgePacket(CTCPSocket *tcp_socket, U32 segment_ack)
I64 segment_ack_relative;
I64 send_next_relative;
NetDebug("TCP ACKNOWLEDGE PACKET: Looking to see if there are any send buffers");
while (send_buffer != tcp_socket->ack_queue)
{
segment_ack_relative = (segment_ack - send_buffer->end_seq_num) & 0xFFFFFFFF;
@ -482,8 +487,11 @@ U0 TCPAcknowledgePacket(CTCPSocket *tcp_socket, U32 segment_ack)
if (segment_ack_relative <= send_next_relative)
{
NetDebug("TCP ACKNOWLEDGE PACKET: Saw send buffer entry with ACK <= next relative send ACK, removing.");
rtt = time - send_buffer->time_sent; // Round-Trip Time
tcp_socket->srtt = (tcp_socket->srtt * TCP_SRTT_ALPHA) + ((1.0 - TCP_SRTT_ALPHA) * rtt); // Smoothed Round-Trip Time
tcp_socket->srtt = (tcp_socket->srtt * TCP_SRTT_ALPHA) + ((1.0 - TCP_SRTT_ALPHA) * rtt);
// Smoothed Round-Trip Time
QueueRemove(send_buffer);
Free(send_buffer->tcp_packet);
@ -1050,8 +1058,8 @@ I64 TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
tcp_socket->connection_time = tS;
TCPSendFlags(tcp_socket, TCPF_SYN);
tcp_socket->state = TCP_STATE_SYN_SENT;
TCPSendFlags(tcp_socket, TCPF_SYN);
timeout = counts.jiffies + tcp_socket->timeout * JIFFY_FREQ / 1000;
while (counts.jiffies < timeout)
@ -1161,7 +1169,9 @@ CTCPSocket *TCPSocketAccept(CTCPSocket *tcp_socket)
ipv4_address.port = temp_addr->port;
ipv4_address.address.address = pending->ipv4_address;
NetDebug("TCP SOCKET ACCEPT: Attempting to Bind to pending connection %0X @ src/dst ports %d,%d.", pending->ipv4_address, ipv4_address.port, pending->port);
NetDebug("TCP SOCKET ACCEPT: Attempting to Bind to pending connection %0X @ src/dst ports %d,%d.",
pending->ipv4_address, ipv4_address.port, pending->port);
TCPSocketBind(new_socket, &ipv4_address);
temp_addr = &new_socket->destination_address;
@ -1194,6 +1204,8 @@ CTCPSocket *TCPSocketAccept(CTCPSocket *tcp_socket)
return NULL;
}
new_socket->socket->state = SOCKET_STATE_OPEN;
return new_socket;
}
@ -1274,7 +1286,9 @@ I64 TCPSocketSend(CTCPSocket *tcp_socket, U8 *buffer, I64 length)
return NULL;
}
while (counts.jiffies < timeout && (tcp_socket->state == TCP_STATE_ESTABLISHED || tcp_socket->state == TCP_STATE_CLOSE_WAIT) && length)
while (counts.jiffies < timeout &&
(tcp_socket->state == TCP_STATE_ESTABLISHED || tcp_socket->state == TCP_STATE_CLOSE_WAIT) &&
length)
{
send_length = (tcp_socket->first_unacked_seq + tcp_socket->send_window - tcp_socket->next_send_seq_num) & 0xFFFFFFFF;
@ -1298,6 +1312,7 @@ I64 TCPSocketSend(CTCPSocket *tcp_socket, U8 *buffer, I64 length)
if (send_length > tcp_socket->max_segment_size)
send_length = tcp_socket->max_segment_size;
NetDebug("TCP SOCKET SEND: Trying TCPSendData().");
if (TCPSendData(tcp_socket, TCPF_ACK, buffer, send_length) < 0)
{ // Stall until outgoing data acknowledged.
if (sent_total > 0)
@ -1311,8 +1326,9 @@ I64 TCPSocketSend(CTCPSocket *tcp_socket, U8 *buffer, I64 length)
}
else
{
buffer += send_length;
length -= send_length;
buffer += send_length;
length -= send_length;
sent_total += send_length;
}
}
}

View file

@ -71,7 +71,8 @@ Bool TCPHandleValidSEQ(CTCPSocket *tcp_socket, CTCPHeader *header, U32 segment_s
}
Bool TCPHandleACK(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *header, U32 segment_seq_num, U32 segment_ack_num, U32 segment_length)
Bool TCPHandleACK(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *header,
U32 segment_seq_num, U32 segment_ack_num, U32 segment_length)
{ // returns the value of must_ack, used later in TCPHandleSocket
I64 ack_relative;
I64 ack_next_relative;
@ -93,6 +94,7 @@ Bool TCPHandleACK(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *heade
switch (tcp_socket->state)
{
case TCP_STATE_SYN_SENT:
NetDebug("TCP HANDLE ACK: Acceptable ACK; state: SYN_SENT");
if (!Bt(&header->flags, TCPf_SYN))
break;
// else, fall-through
@ -105,6 +107,7 @@ Bool TCPHandleACK(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *heade
default:
break;
}
NetDebug("TCP HANDLE ACK: Acceptable ACK returning; state: 0x%0X", tcp_socket->state);
}
else
{
@ -228,6 +231,7 @@ U0 TCPHandleSocket(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *head
if (segment_length == 0 && tcp_socket->receive_window == 0)
{
NetDebug("TCP HANDLE SOCKET: segment length == 0 && receive window == 0, SEQ valid if seq == next recv seq");
is_seq_valid = (segment_seq_num == tcp_socket->next_recv_seq_num);
}
else
@ -242,7 +246,7 @@ U0 TCPHandleSocket(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *head
if (!is_seq_valid)
NetWarn("TCP HANDLE SOCKET: Invalid SEQ.");
must_ack = TCPHandleACK(tcp_socket, packet, header, segment_seq_num, segment_ack_num, segment_length);
must_ack |= TCPHandleACK(tcp_socket, packet, header, segment_seq_num, segment_ack_num, segment_length);
if (TCPHandleReset(tcp_socket, header, is_seq_valid))
@ -252,7 +256,7 @@ U0 TCPHandleSocket(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *head
// make sure to double check.
if (is_seq_valid)
must_ack = TCPHandleValidSEQ(tcp_socket, header, segment_seq_num, length, data);
must_ack |= TCPHandleValidSEQ(tcp_socket, header, segment_seq_num, length, data);
if (must_ack)
TCPSendFlags(tcp_socket, TCPF_ACK);

View file

@ -117,7 +117,8 @@ CTCPTreeQueue *TCPTreeNodeQueueIPV4Find(U32 address, CTCPTreeNode *node, Bool sp
}
}
else
NetErr("TCPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X", temp_queue->socket->destination_address.family);
NetErr("TCPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X",
temp_queue->socket->destination_address.family);
temp_queue = temp_queue->next;
}
@ -144,7 +145,8 @@ CTCPTreeQueue *TCPTreeNodeQueueIPV4Find(U32 address, CTCPTreeNode *node, Bool sp
}
}
else
NetErr("TCPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X", temp_queue->socket->destination_address.family);
NetErr("TCPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X",
temp_queue->socket->destination_address.family);
temp_queue = temp_queue->next;
}

View file

@ -0,0 +1,65 @@
CTCPSocket *tcp = TCPSocket(AF_INET);
U8 buffer_size = 16;
U8 *buffer = CAlloc(buffer_size);
CSocketAddressIPV4 *socket_addr = CAlloc(sizeof(CSocketAddressIPV4));
*buffer = EndianU64(0xDEADBEEFC0DEFADE);
U0 TCPTest()
{
tcp->timeout = TCP_TIMEOUT * 3;
ClassRep(tcp);
CIPV4Address addr;
PresentationToNetwork(AF_INET, "10.0.2.7", &addr);
socket_addr->port = EndianU16(0xBEEF);
socket_addr->family = AF_INET;
socket_addr->address.address = addr.address;
"\nTrying to connect the socket\n";
if (TCPSocketConnect(tcp, socket_addr) == 0)
"\nSocket connected.\n";
else
"\nFailed to connect.\n";
ClassRep(tcp);
"\n\nTrying to Send data\n";
if (TCPSocketSend(tcp, buffer, buffer_size) > 0)
"\nData sent\n";
else
"\nData not sent\n";
"\n\nTrying to Receive data\n";
if (TCPSocketReceive(tcp, buffer, buffer_size) > 0)
"\nData received\n";
else
"\nData not received\n";
"\n\n";
Dm(buffer, buffer_size);
ClassRep(tcp_globals.bound_socket_tree);
Sleep(5000);
"\n\nTrying to close the connected socket\n";
if (TCPSocketClose(tcp) == 0)
"\nSocket closed.";
else
"\nSocket close failed.";
Sleep(500);
//NetStop;
//NetStart;
}
TCPTest;

View file

@ -49,6 +49,12 @@ U0 TCPTest()
"\n\n";
"\nTrying to Send data\n";
if (TCPSocketSend(new, buffer, buffer_size) > 0) // echo back
"\nData sent.\n";
else
"\nData not sent\n";
ClassRep(tcp_globals.bound_socket_tree);
Sleep(5000);

View file

@ -23,7 +23,7 @@ while (TRUE)
if (new)
{
"\n\nSocket accepted, HOOoOO BOOYYY\n\n";
"\n\nSocket accepted\n\n";
ClassRep(new);
break;
}

View file

@ -6,7 +6,7 @@ ClassRep(tcp);
CSocketAddressIPV4 *socket_addr = CAlloc(sizeof(CSocketAddressIPV4));
CIPV4Address addr;
PresentationToNetwork(AF_INET, "127.0.0.1", &addr);
PresentationToNetwork(AF_INET, "10.0.2.7", &addr);
socket_addr->port = EndianU16(0xBEEF);
socket_addr->family = AF_INET;

View file

@ -1,43 +0,0 @@
CTCPSocket *tcp = TCPSocket(AF_INET);
U8 *buffer = CAlloc(8);
*buffer = EndianU64(0xDEADBEEFC0DEFADE);
tcp->timeout = TCP_TIMEOUT;
ClassRep(tcp);
CSocketAddressIPV4 *socket_addr = CAlloc(sizeof(CSocketAddressIPV4));
CIPV4Address addr;
PresentationToNetwork(AF_INET, "127.0.0.1", &addr);
socket_addr->port = EndianU16(0xBEEF);
socket_addr->family = AF_INET;
socket_addr->address.address = addr.address;
"\nTrying to connect the socket\n";
if (TCPSocketConnect(tcp, socket_addr) == 0)
"\nSocket connected.\n";
else
"\nFailed to connect.\n";
"\n\nTrying to Send data\n";
if (TCPSocketSend(tcp, buffer, 8) > 0)
"\nData sent\n";
else
"\nData not sent\n";
ClassRep(tcp_globals.bound_socket_tree);
Sleep(5000);
"\n\nTrying to close the socket\n";
TCPSocketClose(tcp);
"\nSocket Closed.";
Sleep(500);
//NetStop;
//NetStart;

View file

@ -172,7 +172,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
{
case AF_INET:
// TODO: will any INADDR_ANY sockets bound at the port break this?
if (UDPTreeNodeQueueIPV4Find(ipv4_receive->address.address, temp_node))
if (UDPTreeNodeQueueIPV4Find(ipv4_receive->address.address, temp_node, TRUE))
{
NetErr("UDP SOCKET BIND: Address already in Bound Socket Tree !");
return -1;

View file

@ -80,36 +80,6 @@ CUDPTreeQueue *UDPTreeNodeQueueSocketFind(CUDPSocket *socket, CUDPTreeNode *node
return NULL;
}
CUDPTreeQueue *UDPTreeNodeQueueIPV4Find(U32 address, CUDPTreeNode *node)
{ // address should be pulled from an instance of CIPV4Address (TODO... double check what bit order we're in ?)
// TODO: should INADDR_ANY entries be stored and looped, or keep current returning ASAP at INNADDR_ANY ?
CUDPTreeQueue *temp_queue = node->queue->next;
CSocketAddressIPV4 *temp_ip;
while (temp_queue != node->queue)
{
if (temp_queue->socket->receive_address.family == AF_INET)
{
temp_ip = &temp_queue->socket->receive_address;
NetLog("UDPTreeNodeQueueIPV4Find: Comparing: addr, nodequeue addr: %08X, %08X",
address, temp_ip->address.address);
if (temp_ip->address.address == address || temp_ip->address.address == INADDR_ANY)
{
NetLog("UDPTreeNodeQueueIPV4Find: Address match: addr, nodequeue addr: %08X, %08X ",
address, temp_ip->address.address);
return temp_queue;
}
}
temp_queue = temp_queue->next;
}
return NULL;
}
CUDPTreeQueue *UDPTreeNodeQueueSocketSinglePop(CUDPSocket *socket, CUDPTreeNode *node)
{ // search by socket, pop a single UDPTreeQueue off the node, return popped queue.
CUDPTreeQueue *temp_queue = UDPTreeNodeQueueSocketFind(socket, node);
@ -122,3 +92,65 @@ CUDPTreeQueue *UDPTreeNodeQueueSocketSinglePop(CUDPSocket *socket, CUDPTreeNode
return temp_queue; // if not found, NULL.
}
CUDPTreeQueue *UDPTreeNodeQueueIPV4Find(U32 address, CUDPTreeNode *node, Bool specific=FALSE)
{ // address should be pulled from an instance of CIPV4Address (TODO... double check what bit order we're in ?)
// use TRUE or FALSE in specific arg to dictate how to handle INADDR_ANY.
CUDPTreeQueue *temp_queue = node->queue->next;
CSocketAddressIPV4 *temp_ip;
while (temp_queue != node->queue)
{
if (temp_queue->socket->receive_address.family == AF_INET)
{
temp_ip = &temp_queue->socket->receive_address;
NetLog("UDPTreeNodeQueueIPV4Find: Comparing: addr, nodequeue addr: %08X, %08X",
address, temp_ip->address.address);
if (temp_ip->address.address == address)
{
NetLog("UDPTreeNodeQueueIPV4Find: Address match: addr, nodequeue addr: %08X, %08X ",
address, temp_ip->address.address);
return temp_queue;
}
}
else
NetErr("UDPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X",
temp_queue->socket->receive_address.family);
temp_queue = temp_queue->next;
}
if (!specific)
{
temp_queue = node->queue->next;
NetDebug("UDPTreeNodeQueueIPV4Find: Exact match not found, looking for an INADDR_ANY address.");
while (temp_queue != node->queue)
{
if (temp_queue->socket->receive_address.family == AF_INET)
{
temp_ip = &temp_queue->socket->receive_address;
NetLog("UDPTreeNodeQueueIPV4Find: Comparing: addr, nodequeue addr: %08X, %08X",
address, temp_ip->address.address);
if (temp_ip->address.address == INADDR_ANY)
{
NetLog("UDPTreeNodeQueueIPV4Find: Address match: addr, nodequeue addr: %08X, %08X ",
address, temp_ip->address.address);
return temp_queue;
}
}
else
NetErr("UDPTreeNodeQueueIPV4Find: Skipped iteration of a non AF_INET family: %0X",
temp_queue->socket->receive_address.family);
temp_queue = temp_queue->next;
}
}
return NULL;
}