mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-27 07:46:33 +00:00
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:
parent
05dd1af872
commit
3917898085
11 changed files with 172 additions and 90 deletions
Binary file not shown.
|
@ -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)
|
||||
|
@ -1313,6 +1328,7 @@ I64 TCPSocketSend(CTCPSocket *tcp_socket, U8 *buffer, I64 length)
|
|||
{
|
||||
buffer += send_length;
|
||||
length -= send_length;
|
||||
sent_total += send_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
65
src/Home/Net/Tests/TCPEchoClient.CC
Executable file
65
src/Home/Net/Tests/TCPEchoClient.CC
Executable 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;
|
|
@ -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);
|
|
@ -23,7 +23,7 @@ while (TRUE)
|
|||
|
||||
if (new)
|
||||
{
|
||||
"\n\nSocket accepted, HOOoOO BOOYYY\n\n";
|
||||
"\n\nSocket accepted\n\n";
|
||||
ClassRep(new);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue