Implement TCPRep for reporting bound/connected TCP Sockets.

Fix ARP not updating cached entries on ARPCachePut calls.
Fix DNS not updating cached entries on DNSCachePut calls.
Clean up repeated gross syntax in DHCPOfferParse.
Fix Host() and DNSRep IPV4 kludge, use proper switch case block based on result address family type.
Change CNetQueueEntry member variable length to packet_length.
Remove Debug statements when sockets use AF_INET6 or AF_UNSPEC, change to NetErr.
Change UDP message queues to be allocated and initialized when UDPSocket is called, instead of when binding.
Standardize filenames in Tests/ folder.
Remove old test files.
Remove outdated TODO comments.
This commit is contained in:
TomAwezome 2021-05-18 02:09:59 -04:00
parent cf7ad1a5a7
commit 239a5cdf87
41 changed files with 351 additions and 1902 deletions

View file

@ -118,7 +118,10 @@ CARPHash *ARPCachePut(U32 ip_address, U8 *mac_address)
HashAdd(entry, arp_cache);
}
else
NetWarn("ARP CACHE Put: Entry was already found in Cache. TODO: overwrite?");
{
NetWarn("ARP CACHE Put: Entry was already found in Cache. Overwriting.");
MemCopy(entry->mac_address, mac_address, 6);
}
return entry;
}

View file

@ -252,6 +252,7 @@ I64 DHCPOfferParse(U32 xid, U8 *data, I64 length,
U8 type;
U8 value_length;
U8 *value;
U32 address;
if (EndianU32(header->xid) != xid)
@ -274,6 +275,8 @@ I64 DHCPOfferParse(U32 xid, U8 *data, I64 length,
break;
}
address = EndianU32(*value(U32 *));
switch (type)
{
case DHCP_OPTION_MESSAGETYPE:
@ -286,7 +289,7 @@ I64 DHCPOfferParse(U32 xid, U8 *data, I64 length,
NetLog("DHCP PARSE OFFER: Parsed Option, Type DNS.");
if (value_length == 4)
{
*dns_ip_out = EndianU32(*value(U32 *)); // TODO: this syntax used on last 3 cases is gross, alter it
*dns_ip_out = address;
have_dns = TRUE;
}
break;
@ -295,7 +298,7 @@ I64 DHCPOfferParse(U32 xid, U8 *data, I64 length,
NetLog("DHCP PARSE OFFER: Parsed Option, Type ROUTER.");
if (value_length == 4)
{
*router_ip_out = EndianU32(*value(U32 *)); //
*router_ip_out = address;
have_router = TRUE;
}
break;
@ -304,7 +307,7 @@ I64 DHCPOfferParse(U32 xid, U8 *data, I64 length,
NetLog("DHCP PARSE OFFER: Parsed Option, Type SUBNET MASK.");
if (value_length == 4)
{
*subnet_mask_out = EndianU32(*value(U32 *)); //
*subnet_mask_out = address;
have_subnet = TRUE;
}
break;
@ -432,7 +435,7 @@ I64 DHCPInnerConfigure(CUDPSocket *udp_socket,
NetWarn("DHCP CONFIGURE INNER: Unsuccessful DHCP Parse Offer.");
}
if (count > 0 && error >= 0) // TODO: >= ? can DHCPDiscoverSend or DHCPOfferParse return greater than zero?
if (count > 0 && error >= 0)
{
dhcp_addr = EndianU32(ipv4_addr_in.address.address);
state = DHCP_STATE_CLIENT_REQUEST;
@ -466,7 +469,7 @@ I64 DHCPInnerConfigure(CUDPSocket *udp_socket,
NetWarn("DHCP CONFIGURE INNER: Unsuccessful DHCP Parse Ack.");
}
if (count > 0 && error >= 0) // see above TODO
if (count > 0 && error >= 0)
{
dhcp_addr = EndianU32(ipv4_addr_in.address.address);
state = DHCP_STATE_CLIENT_REQ_ACCEPTED;
@ -531,6 +534,7 @@ U0 NetRep()
{
"\n$$LTGREEN$$Network Report:$$FG$$\n\n";
UDPRep;
TCPRep;
DNSRep;
ARPRep;
IPV4Rep;

View file

@ -104,7 +104,11 @@ CDNSHash *DNSCachePut(U8 *hostname, CAddressInfo *info)
HashAdd(entry, dns_cache);
}
else
NetWarn("DNS CACHE PUT: Entry was already found in Cache. TODO: overwrite?");
{
NetWarn("DNS CACHE PUT: Entry was already found in Cache. Overwriting.");
Free(entry->info.address);
AddressInfoCopy(&entry->info, info);
}
return entry;
}
@ -617,10 +621,11 @@ U0 DNSResolverIPV4Set(U32 ip)
U0 Host(U8 *hostname)
{ // getaddrinfo() for whole system in Shrine ends up as pointer to DNSAddressInfoGet.. should we do something similar?
CAddressInfo *current;
CAddressInfo *result = NULL;
I64 error = DNSAddressInfoGet(hostname, NULL, &result);
I64 i = 0;
CAddressInfo *current;
CAddressInfo *result = NULL;
I64 error = DNSAddressInfoGet(hostname, NULL, &result);
I64 i = 0;
CSocketAddressIPV4 *ipv4_address;
if (error < 0)
{
@ -639,7 +644,25 @@ U0 Host(U8 *hostname)
" socket type: $FG,6$%d$FG$ \n", current->socket_type;
" protocol: $FG,6$%d$FG$ \n", current->protocol;
" address length: $FG,6$%d$FG$ \n", current->address_length;
" address: $FG,6$%s$FG$ \n", NetworkToPresentation(AF_INET, &current->address(CSocketAddressIPV4 *)->address);
switch (current->family)
{
case AF_INET:
ipv4_address = current->address;
" address: $FG,6$%s$FG$ \n", NetworkToPresentation(AF_INET, &ipv4_address->address);
break;
case AF_INET6:
" address: $FG,6$IPV6$FG$ \n"; // FIXME
break;
case AF_UNSPEC:
" address: $FG,6$AF_UNSPEC$FG$ \n";
break;
default:
" address: $FG,6$INVALID$FG$ \n";
break;
}
current = current->next;
}
@ -650,9 +673,10 @@ U0 Host(U8 *hostname)
}
U0 DNSRep()
{ // TODO: switch() on Socket Address types for NetworkToPresentation, etc
I64 i;
CDNSHash *temp_hash;
{
I64 i;
CDNSHash *temp_hash;
CSocketAddressIPV4 *ipv4_address;
"$$LTBLUE$$DNS Report:$$FG$$\n\n";
for (i = 0; i <= dns_cache->mask; i++)
@ -661,13 +685,30 @@ U0 DNSRep()
while (temp_hash)
{
"DNS Hash @ $FG,3$0x%X$FG$:\n", temp_hash;
" Hostname: $FG,6$%s$FG$\n", temp_hash->str;
" IP Address: $FG,6$%s$FG$\n",
NetworkToPresentation(temp_hash->info.family,
&temp_hash->info.address(CSocketAddressIPV4 *)->address);
// TODO: IPV4 kludge
switch (temp_hash->info.family)
{
case AF_INET:
ipv4_address = temp_hash->info.address;
" IP Address: $FG,6$%s$FG$\n",
NetworkToPresentation(temp_hash->info.family,
&ipv4_address->address);
break;
case AF_INET6:
" IP Address: $FG,6$IPV6$FG$\n"; // FIXME
break;
case AF_UNSPEC:
" IP Address: $FG,6$AF_UNSPEC$FG$";
break;
default:
" IP Address: $FG,6$INVALID$FG$";
break;
}
"\n";
temp_hash = temp_hash->next;

View file

@ -40,7 +40,7 @@ Stack progress: (# done, ~ WIP, . N/A)
- keep eyes on verifying socket logic sanity.
# IPV4 (Internet Protocol Version 4)
- double check, some FIXMEs.
- double check, some TODOs.
~ ICMP (Internet Control Message Protocol)
- needs ICMPSendRequest implemented.
@ -50,7 +50,7 @@ Stack progress: (# done, ~ WIP, . N/A)
- needs reviewing RFC for better compliance.
# UDP (User Datagram Protocol)
- double check, some FIXMEs.
- double check, some TODOs.
~ DNS (Domain Name System)
- needs clarifying/rewriting in certain methods.

View file

@ -30,7 +30,7 @@ U0 EthernetGlobalsInit()
//TODO: check length , figure out the length+4
U0 EthernetFrameParse(CEthernetFrame *frame_out, U8 *frame, U16 length)
{
//Shrine has a FIXME for check length! We need to figure out what
//TODO: Check length ! We need to figure out what
//lengths are appropriate ...... Shrine also says MemCopy has a
//high overhead. I'm almost tempted to say that means that a lot
//of the current system should be done with less extra allocation

View file

@ -110,7 +110,6 @@ I64 IPV4AddressMACGet(U32 ip_address, U8 **mac_out)
// "outside this subnet; needs routing"
if (ip_address & ipv4_globals.ipv4_subnet_mask != ipv4_globals.local_ip & ipv4_globals.ipv4_subnet_mask)
{
// TODO: Shrine recurses here... and says FIXME infinite loop if mis-configured...
NetWarn("GET MAC FOR IP: TODO: Doing IPV4AddressMACGet recursion, could infinite loop and overflow stack.");
return IPV4AddressMACGet(ipv4_globals.ipv4_router_address, mac_out);
}
@ -243,7 +242,7 @@ U0 IPV4PacketParse(CIPV4Packet *packet_out, CEthernetFrame *ethernet_frame)
{
//...if ethertype not ipv4 error?
//Shrine says FIXME check ethernet_frame length !! ... we need to know what's appropriate
// TODO: Check ethernet_frame length ! ... we need to know what's appropriate
CIPV4Header *header = ethernet_frame->data;
I64 header_length = (header->version_ihl & 0x0F) * 4;//this Has to go. at least abstract or something..

View file

@ -16,7 +16,6 @@ U0 IPV4Handler(CEthernetFrame *ethernet_frame)
case IP_PROTOCOL_TCP:
NetWarn("IPV4 HANDLER: TCP.");
TCPHandler(&packet);
// NetWarn("IPV4 HANDLER: TCP. TODO.");
break;
case IP_PROTOCOL_UDP:
@ -36,7 +35,7 @@ U0 NetQueueEntryHandle(CNetQueueEntry *entry)
{
CEthernetFrame ethernet_frame;
EthernetFrameParse(&ethernet_frame, entry->frame, entry->length);
EthernetFrameParse(&ethernet_frame, entry->frame, entry->packet_length);
switch (ethernet_frame.ethertype)
{
@ -51,7 +50,7 @@ U0 NetQueueEntryHandle(CNetQueueEntry *entry)
break;
case ETHERTYPE_IPV6:
NetWarn("HANDLE NETQUEUE ENTRY: IPV6. TODO.");
NetWarn("HANDLE NETQUEUE ENTRY: IPV6. FIXME");
break;
default:

View file

@ -9,7 +9,7 @@
class CNetQueueEntry:CQueue
{
I64 length; //todo: change to packet_length?
I64 packet_length;
U8 frame[ETHERNET_FRAME_SIZE];
};
@ -70,7 +70,7 @@ U0 NetQueuePush(U8 *data, I64 length)
CNetQueueEntry *entry = CAlloc(sizeof(CNetQueueEntry));
entry->length = length;
entry->packet_length = length;
MemCopy(entry->frame, data, length);

View file

@ -37,9 +37,9 @@ if (Fs != zenith_task)
{
NetRep;
"\nNow run one of the $MA,"Tests",LM="Cd(\"C:/Home/Net/Tests\");Dir;\n"$.\n";
"\nNow run one of the $MA,"Tests",LM="Cd(\"C:/Home/Net/Tests\");Dir;\n"$ or $MA,"Programs",LM="Cd(\"C:/Home/Net/Programs\");Dir;\n"$.\n";
"\nIf a test crashes to Debug, try typing $FG,0$G2;$FG$\n\n";
"\nIf a test crashes to Debug, try typing $BLACK$G2;$FG$\n\n";
}
else
{

View file

@ -537,7 +537,9 @@ I64 PCNetPacketReceive(U8 **packet_buffer_out, U16 *packet_length_out)
packet_length = entry->status2 & 0xFFFF;
NetDebug("PCNET RECEIVE PACKET: de_index = 0x%0X", de_index);
pcnet.current_rx_de_index = (pcnet.current_rx_de_index + 1) & (PCNET_RX_BUFF_COUNT - 1);
NetDebug("PCNET RECEIVE PACKET: de_index incremented = 0x%0X", pcnet.current_rx_de_index);
*packet_buffer_out = pcnet.rx_buffer_addr + de_index * ETHERNET_FRAME_SIZE;
*packet_length_out = packet_length;

View file

@ -249,10 +249,8 @@ I64 PresentationToNetwork(I64 address_family, U8 *string, CIPAddressStorage *des
ipv6_address = destination;
Debug("IPV6 support not implemented yet.\n");
break;
NetErr("IP to Socket Address failed: FIXME, IPV6 support not implemented yet.\n");
return -1;
default:
NetErr("IP to Socket Address failed: Invalid Address Family.");
@ -288,7 +286,8 @@ U8 *NetworkToPresentation(I64 address_family, CIPAddressStorage *source)
ipv6_source = source;
Debug("IPV6 support not implemented yet.\n");
NetErr("Socket Address to IP failed: FIXME, IPV6 support not implemented yet.\n");
return -1;
break;
default:

View file

@ -101,7 +101,7 @@ I64 TCPPacketAllocate(U8 **frame_out,
header->ack_num = EndianU32(ack_num);
header->data_offset = (sizeof(CTCPHeader) / 4) << 4; // ???
header->flags = flags;
header->window_size = EndianU16(TCP_WINDOW_SIZE / 2);// shrine has FIXME ... what should window size be...
header->window_size = EndianU16(TCP_WINDOW_SIZE / 2);// TODO: What is window size supposed to be ?
header->checksum = 0;
header->urgent_pointer = 0;
@ -227,20 +227,20 @@ I64 TCPSendFlags(CTCPSocket *tcp_socket, U8 flags)
break;
case AF_INET6:
source_ipv6 = source;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND FLAGS: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send from AF_UNSPEC\n");
NetErr("TCP SEND FLAGS: Error, TCP Send from AF_UNSPEC\n");
return -1;
}
break;
case AF_INET6:
dest_ipv6 = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND FLAGS: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send to AF_UNSPEC\n");
NetErr("TCP SEND FLAGS: Error, TCP Send to AF_UNSPEC\n");
return -1;
}
@ -288,20 +288,20 @@ I64 TCPSendFlags(CTCPSocket *tcp_socket, U8 flags)
break;
case AF_INET6:
source_ipv6 = source;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND FLAGS: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send from AF_UNSPEC\n");
NetErr("TCP SEND FLAGS: Error, TCP Send from AF_UNSPEC\n");
return -1;
}
break;
case AF_INET6:
dest_ipv6 = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND FLAGS: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send to AF_UNSPEC\n");
NetErr("TCP SEND FLAGS: Error, TCP Send to AF_UNSPEC\n");
return -1;
}
}
@ -345,27 +345,27 @@ I64 TCPSendData(CTCPSocket *tcp_socket, U8 flags, U8 *data, I64 length)
length);
if (de_index < 0)
{
NetLog("TCP SEND FLAGS: TCP Packet Allocate failed.");
NetLog("TCP SEND DATA: TCP Packet Allocate failed.");
return de_index;
}
break;
case AF_INET6:
source_ipv6 = source;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND DATA: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send from AF_UNSPEC\n");
NetErr("TCP SEND DATA: Error, TCP Send from AF_UNSPEC\n");
return -1;
}
break;
case AF_INET6:
dest_ipv6 = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND DATA: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send to AF_UNSPEC\n");
NetErr("TCP SEND DATA: Error, TCP Send to AF_UNSPEC\n");
return -1;
}
@ -408,20 +408,20 @@ I64 TCPSendData(CTCPSocket *tcp_socket, U8 flags, U8 *data, I64 length)
break;
case AF_INET6:
source_ipv6 = source;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND DATA: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send from AF_UNSPEC\n");
NetErr("TCP SEND DATA: Error, TCP Send from AF_UNSPEC\n");
return -1;
}
break;
case AF_INET6:
dest_ipv6 = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SEND DATA: FIXME, IPV6 not implemented yet");
return -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send to AF_UNSPEC\n");
NetErr("TCP SEND DATA: Error, TCP Send to AF_UNSPEC\n");
return -1;
}
}
@ -436,7 +436,7 @@ I64 TCPPacketParse(CTCPHeader **header_out,
// U32 checksum, sum;
// CTCPPseudoHeader *pseudoheader = CAlloc(sizeof(CTCPPseudoHeader));
// TODO: Shrine has FIXME, validate packet->length!
// TODO: Validate packet->length !
// Verify Checksum:
/* NetWarn("DEBUG: TCPPACKETPARSE: 0x%X = checksum from packet, verifying...", EndianU16(header->checksum));
@ -570,20 +570,20 @@ U0 TCPCheckACKQueue(CTCPSocket *tcp_socket)
case AF_INET6:
source_ipv6 = source;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP CHECK ACK QUEUE: FIXME, IPV6 not implemented yet");
return;// -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send from AF_UNSPEC\n");
NetErr("TCP CHECK ACK QUEUE: Error, TCP Send from AF_UNSPEC\n");
return;// -1;
}
break;
case AF_INET6:
dest_ipv6 = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP CHECK ACK QUEUE: FIXME, IPV6 not implemented yet");
return;// -1;
case AF_UNSPEC:
Debug("TODO: Error TCP Send to AF_UNSPEC\n");
NetErr("TCP CHECK ACK QUEUE: Error, TCP Send to AF_UNSPEC\n");
return;// -1;
}
@ -631,11 +631,11 @@ CTCPSocket TCPSocket(U16 domain=AF_UNSPEC)
case AF_INET6:
ipv6_address = &tcp_socket->source_address;
Debug("TODO: IPV6 Not implemented yet");
NetErr("TCP SOCKET: FIXME, IPV6 not implemented yet");
return NULL;
case AF_UNSPEC:
Debug("TODO: Error TCP Socket to AF_UNSPEC");
NetErr("TCP SOCKET: Error TCP Socket to AF_UNSPEC");
return NULL;
}
@ -682,7 +682,7 @@ I64 TCPSocketBind(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
if (tcp_socket->source_address.family == AF_INET6)
{
Debug("TODO: IPV6->IPV4 TCP BIND");
NetErr("TCP SOCKET BIND: FIXME, IPV6->IPV4 TCP BIND");
return -1;
}
@ -716,12 +716,12 @@ I64 TCPSocketBind(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
port = EndianU16(ipv6_address->port); // port member should be Big Endian, so now we're going L.E (?)
Debug("TODO: IPV6 TCP BIND");
NetErr("TCP SOCKET BIND: FIXME, IPV6 TCP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC TCP BIND -- param family");
NetErr("TCP SOCKET BIND: Error, AF_UNSPEC TCP BIND -- param family");
break;
}
@ -749,11 +749,11 @@ I64 TCPSocketBind(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
break;
case AF_INET6:
Debug("TODO: IPV6 TCP BIND");
NetErr("TCP SOCKET BIND: FIXME, IPV6 TCP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC TCP BIND -- found in bound tree");
NetErr("TCP SOCKET BIND: Error, AF_UNSPEC TCP BIND -- found in bound tree");
break;
}
}
@ -867,7 +867,7 @@ I64 TCPSocketClose(CTCPSocket *tcp_socket)
queue = TCPTreeNodeQueueSocketFind(tcp_socket, node);
else
{
Debug("Didn't find node at socket during TCPSocketClose!\n");
Debug("TODO: Didn't find node at socket during TCPSocketClose!\n");
return -1;
}
@ -926,7 +926,7 @@ I64 TCPSocketClose(CTCPSocket *tcp_socket)
}
else
{
Debug("Didn't find queue at socket during TCPSocketClose!\n");
Debug("TODO: Didn't find queue at socket during TCPSocketClose!\n");
return -1;
}
@ -966,7 +966,7 @@ I64 TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
if (tcp_socket->source_address.family == AF_INET6)
{
Debug("TODO: IPV6->IPV4 TCP CONNECT");
NetErr("TCP SOCKET CONNECT: FIXME, IPV6->IPV4 TCP CONNECT");
return -1;
}
@ -1000,12 +1000,12 @@ I64 TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
port = EndianU16(source_port); // port member should be Big Endian, so now we're going L.E (?)
Debug("TODO: IPV6 TCP CONNECT");
NetErr("TCP SOCKET CONNECT: FIXME, IPV6 TCP CONNECT");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC TCP CONNECT -- param family");
NetErr("TCP SOCKET CONNECT: Error, AF_UNSPEC TCP CONNECT -- param family");
break;
}
@ -1019,7 +1019,6 @@ I64 TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
switch (address->family)
{
case AF_INET:
// TODO: will any INADDR_ANY sockets bound at the port break this?
if (TCPTreeNodeQueueIPV4Find(ipv4_destination->address.address, temp_node, TRUE))
{
NetErr("TCP SOCKET CONNECT: Address already in Bound Socket Tree !");
@ -1034,11 +1033,11 @@ I64 TCPSocketConnect(CTCPSocket *tcp_socket, CSocketAddressStorage *address)
break;
case AF_INET6:
Debug("TODO: IPV6 TCP CONNECT");
NetErr("TCP SOCKET CONNECT: FIXME, IPV6 TCP CONNECT");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC TCP CONNECT -- found in bound tree");
NetErr("TCP SOCKET CONNECT: Error, AF_UNSPEC TCP CONNECT -- found in bound tree");
break;
}
}
@ -1373,6 +1372,168 @@ I64 TCPSocketSend(CTCPSocket *tcp_socket, U8 *buffer, I64 length)
return sent_total;
}
// TODO: TCPRep()
U0 TCPTreeNodeRep(CTCPTreeNode *node)
{
CTCPTreeQueue *queue = node->queue->next;
CTCPSocket *socket;
CSocketAddressIPV4 *ipv4_addr;
CSocketAddressIPV6 *ipv6_addr;
U8 *string;
CTCPAcceptQueue *pending;
"Local Port $$YELLOW$$%d$$FG$$ (TCP Node @ $$CYAN$$0x%X$$FG$$):\n", node->value, node;
while (queue != node->queue)
{
socket = queue->socket;
switch (socket->destination_address.family)
{
case AF_UNSPEC:
break;
case AF_INET:
ipv4_addr = &socket->destination_address;
string = MStrPrint("%d.%d.%d.%d",
ipv4_addr->address.address.u8[3],
ipv4_addr->address.address.u8[2],
ipv4_addr->address.address.u8[1],
ipv4_addr->address.address.u8[0]); // todo: kludge, endianness...
" $$BROWN$$%s$$FG$$ Destination Port $$YELLOW$$%d$$FG$$ (TCP Tree Queue @ $$CYAN$$0x%X$$FG$$):\n",
string, EndianU16(ipv4_addr->port), queue;
Free(string);
break;
case AF_INET6:
ipv6_addr = &socket->destination_address;
break;
default:
break;
}
" Timeout: %dms\n", socket->timeout;
pending = socket->accept_queue->next;
while (pending != socket->accept_queue->next)
{
" Pending connection from $$BROWN$$%d.%d.%d.%d$$FG$$:",
pending->ipv4_address.u8[3],
pending->ipv4_address.u8[2],
pending->ipv4_address.u8[1],
pending->ipv4_address.u8[0]; //todo: kludge, endianness?
pending = pending->next;
}
queue = queue->next;
}
"\n";
}
U0 TCPRep()
{
CTCPTreeNode *node = tcp_globals.bound_socket_tree;
CTCPRepEntry *head;
CTCPRepEntry *entry;
CTCPRepEntry *temp_entry;
"$$LTBLUE$$TCP Report:$$FG$$\n\n";
if (node)
{
head = CAlloc(sizeof(CTCPRepEntry));
QueueInit(head); // no QueueRemove the head
entry = CAlloc(sizeof(CTCPRepEntry));
entry->node = node;
QueueInsert(entry, head);
// perform depth-first-search while Entry Queue has nodes not fully visited.
while (entry != head)
{
if (entry->node->left)
{ // if node has one, add an Entry for the left branch, continue loop.
temp_entry = CAlloc(sizeof(CTCPRepEntry));
temp_entry->node = entry->node->left;
QueueInsertRev(temp_entry, head);
// if left branch, but no right: toss early, now fully traveled.
if (!entry->node->right)
{
QueueRemove(entry);
TCPTreeNodeRep(entry->node);
Free(entry);
}
entry = temp_entry;
}
else if (entry->node->right)
{ // if no left, but right: add right to queue, pop Entry, Rep, set entry to right.
temp_entry = CAlloc(sizeof(CTCPRepEntry));
temp_entry->node = entry->node->right;
QueueInsertRev(temp_entry, head);
QueueRemove(entry);
TCPTreeNodeRep(entry->node);
Free(entry);
entry = temp_entry;
}
else
{ // pop Entry, Rep, if last Entry in Queue has right add it, pop & Rep travelled Entry, entry = right.
QueueRemove(entry);
TCPTreeNodeRep(entry->node);
Free(entry);
if (head->last != head)
{
temp_entry = head->last;
if (temp_entry->node->right)
{
entry = temp_entry;
temp_entry = CAlloc(sizeof(CTCPRepEntry));
temp_entry->node = entry->node->right;
QueueInsertRev(temp_entry, head);
QueueRemove(entry);
TCPTreeNodeRep(entry->node);
Free(entry);
entry = temp_entry;
}
else
{
QueueRemove(temp_entry);
TCPTreeNodeRep(temp_entry->node);
Free(temp_entry);
entry = head->last;
}
}
else
break;
}
}
Free(head);
}
else
"No TCP Sockets currently bound.\n\n";
}
TCPGlobalsInit;

View file

@ -103,6 +103,11 @@ class CTCPTreeNode:CBST
CTCPTreeQueue *queue;
};
class CTCPRepEntry:CQueue
{
CTCPTreeNode *node;
};
class CTCPHeader
{

View file

@ -254,9 +254,6 @@ U0 TCPHandleSocket(CTCPSocket *tcp_socket, CIPV4Packet *packet, CTCPHeader *head
if (TCPHandleReset(tcp_socket, header, is_seq_valid))
return;
// shrine has FIXME check remote addr and port... we already do that.. right ?
// make sure to double check.
if (is_seq_valid)
must_ack |= TCPHandleValidSEQ(tcp_socket, header, segment_seq_num, length, data);

View file

@ -5,7 +5,7 @@ U8 trgt_mac[6] = {0xB0, 0xDE, 0xCA, 0x5E, 0xD0, 0xD0};
U32 send_ip = EndianU32(0x30313233);
U32 trgt_ip = EndianU32(0x01020304);
U0 ARPSendTrash()
U0 ARPTest()
{
while (TRUE)
{
@ -15,4 +15,4 @@ U0 ARPSendTrash()
}
}
ARPSendTrash;
ARPTest;

View file

@ -1,5 +1,5 @@
U0 DHCPSendTrash()
U0 DHCPTest()
{
while (TRUE)
{
@ -10,4 +10,4 @@ U0 DHCPSendTrash()
}
}
DHCPSendTrash;
DHCPTest;

View file

@ -2,8 +2,8 @@ U8 dst_mac[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U32 dst_ip = 0x01020304;
U0 DHCPSendTrash()
{ // DHCPConfigure (if not already configured), then send UDP trash.
U0 DHCPTest()
{ // DHCPConfigure (if not already configured), then send UDP test data.
U8 *udp_payload;
I64 de_index;
@ -25,4 +25,4 @@ U0 DHCPSendTrash()
}
}
DHCPSendTrash;
DHCPTest;

View file

@ -1,7 +1,7 @@
U8 src[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xC0, 0xDE};
U8 dst[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U0 DHCPSendTrash()
U0 DHCPTest()
{
CUDPSocket *udp_socket = UDPSocket(AF_INET);
U32 your_ip;
@ -36,4 +36,4 @@ U0 DHCPSendTrash()
}
DHCPSendTrash;
DHCPTest;

View file

@ -2,7 +2,7 @@ U8 dns_mac[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U32 dns_ip = 0x51525354;
U0 DNSSendTrash()
U0 DNSTest()
{
U8 **labels = CAlloc(4);
@ -31,4 +31,4 @@ U0 DNSSendTrash()
}
}
DNSSendTrash;
DNSTest;

View file

@ -2,7 +2,7 @@
U8 src[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xC0, 0xDE};
U8 dst[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U0 EthernetSendTrash()
U0 EthernetTest()
{
U8 *packet_buffer;
I64 de_index;
@ -18,4 +18,4 @@ U0 EthernetSendTrash()
}
}
EthernetSendTrash;
EthernetTest;

View file

@ -3,7 +3,7 @@ U8 dst_mac[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U32 dst_ip = 0x01020304;
U0 ICMPSendTrash()
U0 ICMPTest()
{
U8 *data_payload = CAlloc(8);
@ -19,4 +19,4 @@ U0 ICMPSendTrash()
}
ICMPSendTrash;
ICMPTest;

View file

@ -3,7 +3,7 @@ U8 dst_mac[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U32 src_ip = 0x30313233;
U32 dst_ip = 0x01020304;
U0 IPV4SendTrash()
U0 IPV4Test()
{
U8 *ipv4_packet_buffer;
I64 de_index;
@ -21,4 +21,4 @@ U0 IPV4SendTrash()
}
}
IPV4SendTrash;
IPV4Test;

View file

@ -1,4 +0,0 @@
#include "C:/Home/Net/DHCP"
#include "C:/Home/Net/NetHandlerTask"
NetConfigure;

View file

@ -1,16 +0,0 @@
#include "../DNS"
#include "../NetHandlerTask"
/*
"Manually setting DNS Resolver IP.\n";
CIPV4Address *addr = CAlloc(sizeof(CIPV4Address));
PresentationToNetwork(AF_INET, "192.168.1.254", addr);
DNSResolverIPV4Set(addr->address);
*/
"Trying Host() at \"google.com\".\n";
Host("google.com");
Free(addr);

View file

@ -1,33 +0,0 @@
#include "C:/Home/Net/Net.HH"
#include "C:/Home/Net/NetQueue"
#include "C:/Home/Net/PCNet"
#include "C:/Home/Net/Ethernet"
Sleep(300);
#include "C:/Home/Net/ARP"
#include "C:/Home/Net/IPV4"
#include "C:/Home/Net/ICMP"
#include "C:/Home/Net/Sockets"
#include "C:/Home/Net/UDP"
#include "C:/Home/Net/DNS"
#include "C:/Home/Net/DHCP"
Sleep(300);
#include "C:/Home/Net/NetHandlerTask" // needs IPV4, UDP, ICMP
NetConfigure;
//ClassRep(&pcnet);
Sleep(1000);
XTalk(Fs, "Host(\"google.com\");\n");
Dir;

View file

@ -1,94 +0,0 @@
//#define IP_PARSE_STATE_FIRST_NUM 0
#define IP_PARSE_STATE_NUM 1
#define IP_PARSE_STATE_DOT 2
#define IP_PARSE_STATE_ERROR 3
I64 IPV4AddressParse(U8 *string, U32 destination)
{//destination output in network order, only write on success
I64 i;
I64 parse_state = IP_PARSE_STATE_NUM;
U32 temp_destination = 0;
I64 current_chunk_index = 0;
U8 *digit_buffer = StrNew("");
// chunk is just IPV4 num 0 through 3. on last chunk, don't go to DOT state.
for (i = 0; i < 16; i++) //use the #define in Sockets
{
switch (parse_state)
{
case IP_PARSE_STATE_NUM:
switch (string[i])
{
case '.':
parse_state = IP_PARSE_STATE_DOT;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
StrPrint(digit_buffer, "%s%c", digit_buffer, string[i]);
break;
default:
NetErr("IPV4 Parse Failure: Unexpected char.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
break;
case IP_PARSE_STATE_DOT:
"%s, %X\n", digit_buffer, Str2I64(digit_buffer);
if (Str2I64(digit_buffer) > 255)
{
NetErr("IPV4 Parse Failure: Chunk exceeds 0 - 255 range.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
temp_destination |= Str2I64(digit_buffer) << (current_chunk_index * 8);
StrCopy(digit_buffer, ""); // clear digit buffer
current_chunk_index++;
if (current_chunk_index > 3)
{
NetErr("IPV4 Parse Failure: Too many dots in address string.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
parse_state = IP_PARSE_STATE_NUM;
break;
case IP_PARSE_STATE_ERROR:
NetErr("IPV4 Parse Failure: Invalid Address String.\n");
return -1; // error state!
}
}
return 0;
}

View file

@ -1,220 +0,0 @@
//#define IP_PARSE_STATE_FIRST_NUM 0
#define IP_PARSE_STATE_NUM 1
#define IP_PARSE_STATE_DOT 2
#define IP_PARSE_STATE_ERROR 3
/*
U8 *StrDotReplace(U8* source_string)
{
I64 i;
U8 *result = StrNew(source_string);
for (i = 0; i < StrLen(result); i++)
{
if (result[i] == ',')
{ // we're using commas internally for Lexing.
result[i] = '.';
} // so if we see a comma, set to dot, break lexer.
else if (result[i] == '.')
{ // Lex eats '.' as F64. Comma will split Lex tokens
result[i] = ',';
}
}
return result;
}
*/
Bool IPV4AddressParse(U8 *string, U32* destination)
{
// U8* lexable_string;
// lexable_string = StrReplace(string, ",", ","); // swap any commas with an unexpected value
U8 *lexable_string = StrReplace(string, ".", ","); // swap dots with commas since Lex is easier with them.
CCompCtrl* cc = CompCtrlNew(lexable_string);
//Bts(&cc->opts, OPTf_DECIMAL_ONLY);
cc->opts |= 1 << OPTf_DECIMAL_ONLY;
I64 tk;
I64 state = IP_PARSE_STATE_NUM;
U32 temp_destination = 0;
I64 current_section = 0; // IPV4 address has 4 total sections
while (tk = Lex(cc))
{
switch (state)
{
case IP_PARSE_STATE_NUM:
switch (tk)
{
case TK_I64:
if (cc->cur_i64 > 255 || cc->cur_i64 < 0)
{
NetErr("Invalid value, must be 0 - 255.\n");
return FALSE;
}
if (current_section > 3)
{
NetErr("IP Address can only have 4 sections.\n");
return FALSE;
}
temp_destination |= cc->cur_i64 << (current_section * 8);
current_section++;
state = IP_PARSE_STATE_DOT;
break;
default:
NetErr("Expected decimal. \n");
return FALSE;
}
break;
case IP_PARSE_STATE_DOT:
switch (tk)
{
case ',':
state = IP_PARSE_STATE_NUM;
break;
default:
NetErr("Expected dot. \n");
return FALSE;
}
break;
}
}
temp_destination = EndianU32(temp_destination); // store the address in Network Byte Order (Big-Endian)
*destination = temp_destination;
"\n\n%X\n\n",temp_destination;
return TRUE;
}
I64 IPV4AddressParseOOOOOOOOOOPS(U8 *string, U32 destination)
{//destination output in network order, only write on success
I64 i;
I64 parse_state = IP_PARSE_STATE_NUM;
U32 temp_destination = 0;
I64 current_chunk_index = 0;
U8 *digit_buffer = StrNew("");
destination = 'nigggg';
// chunk is just IPV4 num 0 through 3. on last chunk, don't go to DOT state.
for (i = 0; i < 16; i++) //use the #define in Sockets
{
switch (parse_state)
{
case IP_PARSE_STATE_NUM:
switch (string[i])
{
case '.':
parse_state = IP_PARSE_STATE_DOT;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
StrPrint(digit_buffer, "%s%c", digit_buffer, string[i]);
break;
default:
NetErr("IPV4 Parse Failure: Unexpected char.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
break;
case IP_PARSE_STATE_DOT:
"%s, %X\n", digit_buffer, Str2I64(digit_buffer);
if (Str2I64(digit_buffer) > 255)
{
NetErr("IPV4 Parse Failure: Chunk exceeds 0 - 255 range.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
temp_destination |= Str2I64(digit_buffer) << (current_chunk_index * 8);
StrCopy(digit_buffer, ""); // clear digit buffer
current_chunk_index++;
if (current_chunk_index > 3)
{
NetErr("IPV4 Parse Failure: Too many dots in address string.\n");
parse_state = IP_PARSE_STATE_ERROR;
break;
}
parse_state = IP_PARSE_STATE_NUM;
break;
case IP_PARSE_STATE_ERROR:
NetErr("IPV4 Parse Failure: Invalid Address String.\n");
return -1; // error state!
}
}
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,90 +0,0 @@
/*
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0000
15A984E32 $FG,2$port :$FG$0000
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$00000000
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000360s
addr->family = AF_INET;
0.000006s ans=0x00000002=2
addr->port = EndianU16(0xDEAF);
0.000007s ans=0x0000AFDE=45022
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
66210601
0.000027s ans=0x00000000=0
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0002
15A984E32 $FG,2$port :$FG$AFDE
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$66210601
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000385s
UDPSocketBind(s, addr);
0.000008s ans=0x00000000=0
ClassRep(s);
Class:"CUDPSocket"
15A982C58 $TR,"socket"$
$ID,2$Class:"CSocket"
15A9931E8 $FG,2$state :$FG$03
15A9931E9 $FG,2$type :$FG$0002
15A9931EB $FG,2$domain :$FG$0002
$ID,-2$15A982C60 $FG,2$receive_timeout_ms :$FG$0000000000000000
15A982C68 $FG,2$receive_max_timeout :$FG$0000000000000000
15A982C70 $FG,2$receive_buffer :$FG$
15A982C78 $FG,2$receive_len :$FG$0000000000000000
15A982C80 $TR-C,"receive_address"$
$ID,2$Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR,"address"$
$ID,2$$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
$ID,-2$15A982C90 $FG,2$bound_to :$FG$DEAF
0.000526s
ClassRep(&s->receive_address);
Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A982C84 $FG,2$address :$FG$66210601
$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000323s
*/
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s);
ClassRep(addr);
"\nSetting addr family to AF_INET and port to 0xDEAF in B.E., then P to N with 102.33.6.1\n";
addr->family = AF_INET;
addr->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
ClassRep(addr);
"\nUDPSocket bind with socket to addr\n";
UDPSocketBind(s, addr);
ClassRep(s);
ClassRep(&s->receive_address);
UDPSocketClose(s);

View file

@ -1,129 +0,0 @@
/*
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0000
15A984E32 $FG,2$port :$FG$0000
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$00000000
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000360s
addr->family = AF_INET;
0.000006s ans=0x00000002=2
addr->port = EndianU16(0xDEAF);
0.000007s ans=0x0000AFDE=45022
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
66210601
0.000027s ans=0x00000000=0
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0002
15A984E32 $FG,2$port :$FG$AFDE
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$66210601
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000385s
UDPSocketBind(s, addr);
0.000008s ans=0x00000000=0
ClassRep(s);
Class:"CUDPSocket"
15A982C58 $TR,"socket"$
$ID,2$Class:"CSocket"
15A9931E8 $FG,2$state :$FG$03
15A9931E9 $FG,2$type :$FG$0002
15A9931EB $FG,2$domain :$FG$0002
$ID,-2$15A982C60 $FG,2$receive_timeout_ms :$FG$0000000000000000
15A982C68 $FG,2$receive_max_timeout :$FG$0000000000000000
15A982C70 $FG,2$receive_buffer :$FG$
15A982C78 $FG,2$receive_len :$FG$0000000000000000
15A982C80 $TR-C,"receive_address"$
$ID,2$Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR,"address"$
$ID,2$$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
$ID,-2$15A982C90 $FG,2$bound_to :$FG$DEAF
0.000526s
ClassRep(&s->receive_address);
Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A982C84 $FG,2$address :$FG$66210601
$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000323s
*/
"\nMaking new socket\n";
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s);
ClassRep(addr);
"\nSetting addr family to AF_INET and port to 0xDEAF in B.E., then P to N with 102.33.6.1\n";
addr->family = AF_INET;
addr->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
ClassRep(addr);
"\nUDPSocket bind with socket to addr\n";
UDPSocketBind(s, addr);
ClassRep(s);
ClassRep(&s->receive_address);
"\nGlobal Tree:\n";
ClassRep(udp_globals.bound_socket_tree);
"\nGlobal Tree: Port 0xDEAF Queue\n";
ClassRep(udp_globals.bound_socket_tree->queue);
///
"\nMaking new socket\n";
CUDPSocket *s2 = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr2 = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s2);
ClassRep(addr2);
"\nSetting addr2 family to AF_INET and port to 0xDEAF in B.E., then P to N with 104.32.3.66\n";
addr2->family = AF_INET;
addr2->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET,"104.32.3.66",&addr2->address);
ClassRep(addr2);
"\nUDPSocket bind with socket2 to addr2\n";
UDPSocketBind(s2, addr2);
ClassRep(s2);
ClassRep(&s2->receive_address);
"\nGlobal Tree:\n";
ClassRep(udp_globals.bound_socket_tree);
"\nGlobal Tree: Port 0xDEAF Queue\n";
ClassRep(udp_globals.bound_socket_tree->queue);
"\nClosing first socket\n";
UDPSocketClose(s);
"\nGlobal Tree:\n";
ClassRep(udp_globals.bound_socket_tree);
"\nGlobal Tree: Port 0xDEAF Queue\n";
ClassRep(udp_globals.bound_socket_tree->queue);

View file

@ -1,147 +0,0 @@
/*
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0000
15A984E32 $FG,2$port :$FG$0000
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$00000000
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000360s
addr->family = AF_INET;
0.000006s ans=0x00000002=2
addr->port = EndianU16(0xDEAF);
0.000007s ans=0x0000AFDE=45022
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
66210601
0.000027s ans=0x00000000=0
ClassRep(addr);
Class:"CSocketAddressIPV4"
15A984E30 $FG,2$family :$FG$0002
15A984E32 $FG,2$port :$FG$AFDE
15A984E34 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A984E34 $FG,2$address :$FG$66210601
$ID,-2$15A984E38 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000385s
UDPSocketBind(s, addr);
0.000008s ans=0x00000000=0
ClassRep(s);
Class:"CUDPSocket"
15A982C58 $TR,"socket"$
$ID,2$Class:"CSocket"
15A9931E8 $FG,2$state :$FG$03
15A9931E9 $FG,2$type :$FG$0002
15A9931EB $FG,2$domain :$FG$0002
$ID,-2$15A982C60 $FG,2$receive_timeout_ms :$FG$0000000000000000
15A982C68 $FG,2$receive_max_timeout :$FG$0000000000000000
15A982C70 $FG,2$receive_buffer :$FG$
15A982C78 $FG,2$receive_len :$FG$0000000000000000
15A982C80 $TR-C,"receive_address"$
$ID,2$Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR,"address"$
$ID,2$$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
$ID,-2$15A982C90 $FG,2$bound_to :$FG$DEAF
0.000526s
ClassRep(&s->receive_address);
Class:"CSocketAddressIPV4"
15A982C80 $FG,2$family :$FG$0002
15A982C82 $FG,2$port :$FG$0000
15A982C84 $TR-C,"address"$
$ID,2$Class:"CIPV4Address"
15A982C84 $FG,2$address :$FG$66210601
$ID,-2$15A982C88 $FG,2$zeroes :$FG$00 00 00 00 00 00 00 00
0.000323s
*/
"\n$$TX+UL,\"Making new socket\"$$\n";
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s,, 9);
ClassRep(addr,, 9);
"\n$$TX+UL,\"Setting addr family to AF_INET and port to 0xDEAF in B.E., then P to N with 102.33.6.1\"$$\n";
addr->family = AF_INET;
addr->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
ClassRep(addr,, 9);
"\n$$TX+UL,\"UDPSocket bind with socket to addr\"$$\n";
UDPSocketBind(s, addr);
ClassRep(s,, 9);
//ClassRep(&s->receive_address,, 9);
"\n$$TX+UL,\"Global Tree:\"$$\n";
ClassRep(udp_globals.bound_socket_tree,, 9);
"\n$$TX+UL,\"Global Tree: Port 0xDEAF Queue\"$$\n";
ClassRep(udp_globals.bound_socket_tree->queue,, 9);
///
"\n$$TX+UL,\"Making new socket\"$$\n";
CUDPSocket *s2 = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr2 = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s2,, 9);
ClassRep(addr2,, 9);
"\n$$TX+UL,\"Setting addr2 family to AF_INET and port to 0xDEAF in B.E., then P to N with 104.32.3.66\"$$\n";
addr2->family = AF_INET;
addr2->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET, "104.32.3.66", &addr2->address);
ClassRep(addr2,, 9);
"\n$$TX+UL,\"UDPSocket bind with socket2 to addr2\"$$\n";
UDPSocketBind(s2, addr2);
ClassRep(s2,, 9);
//ClassRep(&s2->receive_address,, 9);
"\n$$TX+UL,\"Global Tree:\"$$\n";
ClassRep(udp_globals.bound_socket_tree,, 9);
"\n$$TX+UL,\"Global Tree: Port 0xDEAF Queue\"$$\n";
ClassRep(udp_globals.bound_socket_tree->queue,, 9);
ClassRep(udp_globals.bound_socket_tree->queue->socket,, 9);
"\n$$TX+UL,\"Closing first socket\"$$\n";
UDPSocketClose(s);
"\n$$TX+UL,\"Global Tree:\"$$\n";
ClassRep(udp_globals.bound_socket_tree,, 9);
"\n$$TX+UL,\"Global Tree: Port 0xDEAF Queue\"$$\n";
ClassRep(udp_globals.bound_socket_tree->queue,, 9);
ClassRep(udp_globals.bound_socket_tree->queue->socket,, 9);

View file

@ -1,47 +0,0 @@
"\n$$TX+UL,\"Making new socket\"$$\n";
CUDPSocket *s = UDPSocket(AF_INET);
CSocketAddressIPV4 *addr = CAlloc(sizeof(CSocketAddressIPV4));
ClassRep(s,, 9);
ClassRep(addr,, 9);
"\n$$TX+UL,\"Setting addr family to AF_INET and port to 0xDEAF in B.E., then P to N with 102.33.6.1\"$$\n";
addr->family = AF_INET;
addr->port = EndianU16(0xDEAF);
PresentationToNetwork(AF_INET,"102.33.6.1",&addr->address);
ClassRep(addr,, 9);
"\n$$TX+UL,\"UDPSocket bind with socket to addr\"$$\n";
UDPSocketBind(s, addr);
ClassRep(s,, 9);
"\n$$TX+UL,\"Global Tree:\"$$\n";
ClassRep(udp_globals.bound_socket_tree,, 9);
"\n$$TX+UL,\"Global Tree: Port 0xDEAF Queue\"$$\n";
ClassRep(udp_globals.bound_socket_tree->queue,, 9);
"\n$$TX+UL,\"Closing first socket\"$$\n";
UDPSocketClose(s);
"\n$$TX+UL,\"Global Tree:\"$$\n";
ClassRep(udp_globals.bound_socket_tree,, 9);
"\n$$TX+UL,\"Global Tree: Port 0xDEAF Queue\"$$\n";
ClassRep(udp_globals.bound_socket_tree->queue,, 9);
ClassRep(udp_globals.bound_socket_tree->queue->socket,, 9);

View file

@ -1,977 +0,0 @@
#define UDP_MAX_PORT 65535
class CUDPHeader
{
U16 source_port;
U16 destination_port;
U16 length;
U16 checksum;
};
class CUDPMessageQueue:CQueue
{ // each bound socket queues data. recv functions & handler use this.
U8 *data; // contains the UDP payload data.
I64 data_length; // size of payload data.
I64 received_length; // amount of the data received so far.
CSocketAddressStorage from_address; // when UDP Handler sees UDP packet, this is filled with where packet came from.
// recvfrom uses this to fill its address_out parameter.
};
class CUDPSocket
{
CSocket *socket;
CUDPMessageQueue *receive_queue;
CSocketAddressStorage receive_address; // based on ->family, cast or assign to a var as IPV4/IPV6 CSocketAddress
I64 receive_timeout_ms;
I64 receive_max_timeout;
U16 bound_to; // represents the currently bound port
};
/***************************************************
UDP Bound Socket Tree Classes & Functions
***************************************************/
class CUDPTreeQueue:CQueue
{
CUDPSocket *socket;
};
class CUDPTreeNode
{
CUDPTreeNode *left;
CUDPTreeNode *right;
CUDPTreeQueue *queue;
I64 port;
};
CUDPTreeNode *UDPTreeNodeInit()
{ // init new empty tree/node. Init socket queue head links.
CUDPTreeNode *tree_node = CAlloc(sizeof(CUDPTreeNode));
tree_node->queue = CAlloc(sizeof(CQueue));
QueueInit(tree_node->queue);
return tree_node;
}
U0 UDPTreeNodeAdd(CUDPTreeNode *node, CUDPTreeNode *tree)
{ // using temp and last allows avoiding recursion and non-growing stack issues.
CUDPTreeNode *temp_tree = tree;
CUDPTreeNode *last_tree = temp_tree;
while (temp_tree)
{ // loop ends when temp_tree hits a NULL node.
if (node->port < temp_tree->port)
{ // if node smaller, go left
last_tree = temp_tree;
temp_tree = temp_tree->left;
}
else
{ // if node equal or larger, go right
last_tree = temp_tree;
temp_tree = temp_tree->right;
}
}
// once while loop ends, this results in last_tree
// being the resulting tree to store the node inside of.
// recompute the direction and set.
if (node->port < last_tree->port)// if node smaller, go left
last_tree->left = node;
else // if node equal or larger, go right
last_tree->right = node;
}
CUDPTreeNode *UDPTreeNodeParamAdd(I64 node_port, CUDPTreeNode *tree)
{ // add a node using params, return pointer to the node
CUDPTreeNode *result = UDPTreeNodeInit;
result->port = node_port;
UDPTreeNodeAdd(result, tree);
return result;
}
CUDPTreeNode *UDPTreeNodeParamInit(I64 port)
{
CUDPTreeNode *result = UDPTreeNodeInit;
result->port = port;
return result;
}
CUDPTreeNode *UDPTreeNodeFind(I64 port, CUDPTreeNode *tree)
{
CUDPTreeNode *temp_tree = tree;
while (temp_tree)
{
if (port < temp_tree->port) // if value smaller, go left
temp_tree = temp_tree->left;
else if (port > temp_tree->port) // if value larger, go right
temp_tree = temp_tree->right;
else // if value equal, match found.
break;
}
return temp_tree; // ! NULL if not found.
}
CUDPTreeNode *UDPTreeNodePop(I64 port, CUDPTreeNode *tree)
{ // mimics TreeNodeFind. pops whole sub-tree, original tree loses whole branch.
CUDPTreeNode *parent_tree = tree;
CUDPTreeNode *temp_tree = parent_tree;
Bool is_left = FALSE;
Bool is_right = FALSE;
while (temp_tree)
{
if (port < temp_tree->port)
{
parent_tree = temp_tree;
temp_tree = temp_tree->left;
is_right = FALSE;
is_left = TRUE;
}
else if (port > temp_tree->port)
{
parent_tree = temp_tree;
temp_tree = temp_tree->right;
is_right = TRUE;
is_left = FALSE;
}
else // if value equal, match found.
break;
}
if (temp_tree)
{ //if we found it, clear its parents link to the node
if (is_left)
{
parent_tree->left = NULL;
}
else if (is_right)
{
parent_tree->right = NULL;
}
}
return temp_tree; // NULL if not found.
}
CUDPTreeNode *UDPTreeNodeSinglePop(I64 port, CUDPTreeNode *tree)
{ // pop a tree off, then add back in its sub-trees to main tree.
// original node sub-trees are cleared.
CUDPTreeNode *node = UDPTreeNodePop(port, tree);
CUDPTreeNode *left = node->left;
CUDPTreeNode *right = node->right;
if (node)
{
if (left)
{ // if node has left tree, add the tree
UDPTreeNodeAdd(left, tree);
node->left = NULL;
}
if (right)
{ // if node has right tree, add the tree.
UDPTreeNodeAdd(right, tree);
node->right = NULL;
}
}
return node;
}
U0 UDPTreeNodeQueueAdd(CUDPSocket *socket, CUDPTreeNode *node)
{
CUDPTreeQueue *new_entry;
new_entry = CAlloc(sizeof(CUDPTreeQueue));
new_entry->socket = socket;
QueueInsert(new_entry, node->queue->last);
}
CUDPTreeQueue *UDPTreeNodeQueueSocketFind(CUDPSocket *socket, CUDPTreeNode *node)
{
CUDPTreeQueue *temp_queue;
temp_queue = node->queue->next;
while (temp_queue != node->queue)
{
if (temp_queue->socket == socket)
return temp_queue;
temp_queue = temp_queue->next;
}
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);
if (temp_queue)
{
QueueRemove(temp_queue);
}
return temp_queue; // if not found, NULL.
}
/***************************************************/
class CUDPGlobals
{
CUDPTreeNode *bound_socket_tree;
} udp_globals;
U0 UDPGlobalsInit()
{
udp_globals.bound_socket_tree = NULL;
}
I64 UDPPacketAllocate(U8 **frame_out,
U32 source_ip,
U16 source_port,
U32 destination_ip,
U16 destination_port,
I64 length)
{
U8 *ethernet_frame;
I64 de_index;
CUDPHeader *header;
de_index = IPV4PacketAllocate(&ethernet_frame,
IP_PROTOCOL_UDP,
source_ip,
destination_ip,
sizeof(CUDPHeader) + length);
if (de_index < 0)
{
NetLog("UDP PACKET ALLOCATE: Ethernet Frame Allocate failed.");
return de_index;
}
header = ethernet_frame;
header->source_port = EndianU16(source_port);
header->destination_port = EndianU16(destination_port);
header->length = EndianU16(sizeof(CUDPHeader) + length);
header->checksum = 0;
*frame_out = ethernet_frame + sizeof(CUDPHeader);
return de_index;
}
U0 UDPPacketFinish(I64 de_index)
{ // alias for IPV4PacketFinish, alias for EthernetFrameFinish, alias for driver send packet
IPV4PacketFinish(de_index);
}
I64 UDPPacketParse(U16 *source_port_out,
U16 *destination_port_out,
U8 **data_out,
I64 *length_out,
CIPV4Packet *packet)
{
// check ip protocol? probably redundant
CUDPHeader *header = packet->data;
// TODO: Shrine has FIXME, validate packet length!
*source_port_out = EndianU16(header->source_port);
*destination_port_out = EndianU16(header->destination_port);
*data_out = packet->data + sizeof(CUDPHeader);
*length_out = packet->length - sizeof(CUDPHeader);
return 0;
}
CUDPSocket *UDPSocket(U16 domain=AF_UNSPEC)
{
U16 type = SOCKET_DATAGRAM;
CUDPSocket *udp_socket = CAlloc(sizeof(CUDPSocket));
udp_socket->socket = Socket(domain, type);
udp_socket->receive_address.family = domain; // INET, INET6, or unspecified
return udp_socket;
}
I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
{
CUDPTreeNode *head = udp_globals.bound_socket_tree;
CUDPTreeNode *temp_node;
CUDPMessageQueue *message_queue;
CSocketAddressIPV4 *ipv4_source;
CSocketAddressIPV4 *ipv4_receive;
CSocketAddressIPV6 *ipv6_source;
CSocketAddressIPV6 *ipv6_receive;
U16 port;
switch (udp_socket->socket->state)
{
case SOCKET_STATE_READY: // Socket State machine must be in init state
break;
default:
NetErr("UDP SOCKET BIND: Failed, Socket state-machine must be in READY state.");
return -1;
}
if (udp_socket->bound_to)
{
NetErr("UDP SOCKET BIND: UDP Socket currently Bound.");
return -1;
}
switch (address_source->family)
{
case AF_INET:
if (udp_socket->receive_address.family == AF_INET6)
{
NetErr("UDP SOCKET BIND: Incompatible Address type.");
return -1;
}
ipv4_source = address_source;
ipv4_receive = &udp_socket->receive_address;
ipv4_receive->address.address = ipv4_source->address.address; // bind socket to address in parameter.
ipv4_receive->port = ipv4_source->port; // ... consistency would say keep in Big Endian ...
port = EndianU16(ipv4_source->port); // port member should be Big Endian, so now we're going L.E (?)
break;
case AF_INET6:
if (udp_socket->receive_address.family == AF_INET)
{
NetErr("UDP SOCKET BIND: Incompatible Address type.");
return -1;
}
ipv6_source = address_source;
ipv6_receive = &udp_socket->receive_address;
// ...
// ...
port = EndianU16(ipv6_source->port); // port member should be Big Endian, so now we're going L.E (?)
Debug("TODO: IPV6 UDP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC UDP BIND -- param family");
break;
}
// at this point, Socket and Address have matching family values
if (head)
{
// look for our port.
temp_node = UDPTreeNodeFind(port, head);
if (temp_node)
{ // if we find we have bound sockets at port, check address before adding to queue
switch (address_source->family)
{
case AF_INET:
// TODO: will any INADDR_ANY sockets bound at the port break this?
if (UDPTreeNodeQueueIPV4Find(ipv4_receive->address.address, temp_node))
{
NetErr("UDP SOCKET BIND: Address already in Bound Socket Tree !");
return -1;
}
else
{ // if no address match, free to add socket to the node queue
UDPTreeNodeQueueAdd(udp_socket, temp_node);
}
break;
case AF_INET6:
Debug("TODO: IPV6 UDP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC UDP BIND -- found in bound tree");
break;
}
}
else
{ // if we get no node back from port search, we didn't find it and are free to add a new node.
temp_node = UDPTreeNodeParamAdd(port, head); // add new node with port, return its *.
UDPTreeNodeQueueAdd(udp_socket, temp_node);
}
}
else // if no bound sockets, we init the tree as a new node
{
udp_globals.bound_socket_tree = head = UDPTreeNodeParamInit(port); //... shouuuld be in L.E .. ?
UDPTreeNodeQueueAdd(udp_socket, head); // add the udp socket to the port queue
// maybe more checks to do before this, dunno rn.
}
udp_socket->bound_to = port;
udp_socket->receive_queue = message_queue = CAlloc(sizeof(CUDPMessageQueue));
QueueInit(message_queue); // acts as head. add messages to but don't remove head.
SocketBind(udp_socket->socket); // Advance Socket state-machine to BIND REQ state.
switch (udp_socket->socket->state)
{
case SOCKET_STATE_BIND_REQ: // if BIND request success, set BOUND.
udp_socket->socket->state = SOCKET_STATE_BOUND;
break;
default:
NetErr("UDP SOCKET BIND: Failed, Misconfigured Socket state-machine.");
return -1;
}
return 0;
}
I64 UDPSocketClose(CUDPSocket *udp_socket)
{ // close, pop, and free the socket from the bound tree.
CUDPTreeNode *head = udp_globals.bound_socket_tree;
CUDPTreeNode *node;
CUDPTreeQueue *queue;
CUDPMessageQueue *message;
SocketClose(udp_socket->socket); // TODO: testing on closing a socket while another task is using it
// after low-level socket close, even if protocol level socket fails close, it is now disabled (state is close request)
node = UDPTreeNodeFind(udp_socket->bound_to, head);
if (node)
queue = UDPTreeNodeQueueSocketFind(udp_socket, node);
else
{
Debug("Didn't find node at socket during UDPSocketClose!\n");
return -1;
}
if (queue)
{
UDPTreeNodeQueueSocketSinglePop(udp_socket, node);
if (node->queue == node->queue->next)
{ // if we popped the only queue on the node, remove the node.
if (node == head)
{ // head is the global. if node is the global, change it and add branches.
if (node->left)
{
udp_globals.bound_socket_tree = head = node->left;
if (node->right)
UDPTreeNodeAdd(node->right, head);
}
else if (node->right)
udp_globals.bound_socket_tree = node->right;
else
udp_globals.bound_socket_tree = NULL;
}
else // if node is not the global, just pop it from the tree
UDPTreeNodeSinglePop(node->port, head);
Free(node);
}
Free(udp_socket->socket);
message = udp_socket->receive_queue->next;
while (message != udp_socket->receive_queue)
{
NetWarn("UDP SOCKET CLOSE: Freeing message @ 0x%X", message);
Free(message->data);
QueueRemove(message);
Free(message);
message = udp_socket->receive_queue->next;
}
NetWarn("UDP SOCKET CLOSE: Freeing message queue & socket.");
Free(udp_socket->receive_queue);
Free(udp_socket);
Free(queue);
}
else
{
Debug("Didn't find queue at socket during UDPSocketClose!\n");
return -1;
}
return 0;
}
// UDPSocketConnect (Shrine just has FIXME: 'implement')
// UDPListen (Shrine just has no_warns, not implemented)
I64 UDPSocketReceiveFrom(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAddressStorage *address_out)
{ // ommitted I64 addrlen, flags not implemented
CSocketAddressIPV4 *ipv4_socket_addr;
CSocketAddressIPV6 *ipv6_socket_addr;
CUDPMessageQueue *message;
switch (udp_socket->socket->state)
{
case SOCKET_STATE_OPEN: // Socket State machine must
case SOCKET_STATE_BOUND: // be in connected or bound state
break;
default:
NetErr("UDP SOCKET RECEIVE FROM: Socket state-machine must be in OPEN or BOUND state.");
return -1;
}
if (len < 0)
{
NetErr("UDP SOCKET RECEIVE FROM: Invalid length requested.");
return -1;
}
if (udp_socket->receive_timeout_ms != 0)
udp_socket->receive_max_timeout = counts.jiffies + udp_socket->receive_timeout_ms * JIFFY_FREQ / 1000;
message = udp_socket->receive_queue;
while (message == message->next)
{ // wait for a message to be added to queue. head is non-message.
if (udp_socket->receive_timeout_ms == 0)
return -1; // if no timeout set and didn't see message, bail early
if (counts.jiffies > udp_socket->receive_max_timeout)
{ // Shrine has TODO: 'seterror(EWOULDBLOCK)' investigate this
NetErr("UDP SOCKET RECEIVE FROM: Timed out.");
return -1;
}
Yield;
}
NetLog("UDP SOCKET RECEIVE FROM: Saw message in receive queue.");
message = message->next;
if (address_out)
{
switch (message->from_address.family)
{
case AF_INET:
ipv4_socket_addr = address_out;
MemCopy(ipv4_socket_addr, &message->from_address, sizeof(CSocketAddressIPV4));
break;
case AF_INET6:
ipv6_socket_addr = address_out;
MemCopy(ipv6_socket_addr, &message->from_address, sizeof(CSocketAddressIPV6));
break;
case AF_UNSPEC:
NetWarn("UDP Receive From AF_UNSPEC UDPSocket Address Family\n");
break;
}
}
if (len >= message->data_length - message->received_length)
{
NetLog("UDP SOCKET RECEIVE FROM: Requested length longer than data. Truncating.");
len = message->data_length - message->received_length;
MemCopy(buffer, message->data + message->received_length, len);
NetWarn("UDP SOCKET RECEIVE FROM: Freeing message and removing from queue.");
// all data pulled, release message
QueueRemove(message);
Free(message->data);
Free(message);
}
else
{
NetLog("UDP SOCKET RECEIVE FROM: Requsted length shorter than data at message.");
MemCopy(buffer, message->data + message->received_length, len);
message->received_length += len;
}
SocketReceiveFrom(udp_socket->socket);
return len;
}
I64 UDPSocketSendTo(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAddressStorage *destination_addr)
{
CSocketAddressStorage *dest;
CSocketAddressIPV4 *ipv4_destination;
CSocketAddressIPV6 *ipv6_destination;
U8 *ethernet_frame;
I64 de_index;
switch (udp_socket->socket->state)
{
case SOCKET_STATE_OPEN: // Socket State machine must
case SOCKET_STATE_BOUND: // be in connected or bound state for send.
dest = &udp_socket->receive_address; // if already bound, ignore param destination
break; // and use stored address as send address.
case SOCKET_STATE_READY: // If socket state is initial, attempt to bind it to destination.
NetLog("UDP SOCKET SEND TO: Socket unbound. Attempting Bind at address parameter.");
UDPSocketBind(udp_socket, destination_addr);
dest = destination_addr;
break;
default:
NetErr("UDP SOCKET SEND TO: Socket state-machine must be in OPEN, BOUND or READY state.");
return -1;
}
switch (dest->family)
{
case AF_INET:
ipv4_destination = dest;
de_index = UDPPacketAllocate(&ethernet_frame,
IPV4AddressGet(),
0,
EndianU32(ipv4_destination->address.address),
EndianU16(ipv4_destination->port),
len); // is get address parens redundant?
break;
case AF_INET6:
ipv6_destination = dest;
Debug("TODO: IPV6 Not implemented yet");
break;
case AF_UNSPEC:
Debug("TODO: Error UDP Send To AF_UNSPEC\n");
break;
}
if (de_index < 0)
return -1;
MemCopy(ethernet_frame, buffer, len); // copies the data in buffer param into the ethernet frame
UDPPacketFinish(de_index);
return 0;
}
// UDPSocketSetOpt ?
I64 UDPHandler(CIPV4Packet *packet)
{ // TODO: Need either two UDP handlers for IPv4/IPv6, or logic changes if IPV6 is desired.
U16 source_port;
U16 destination_port;
U8 *data;
I64 length;
CUDPTreeNode *head = udp_globals.bound_socket_tree;
CUDPTreeNode *node;
CUDPTreeQueue *queue;
CUDPMessageQueue *messages_head;
CUDPMessageQueue *message;
CUDPSocket *udp_socket;
CSocketAddressIPV4 *ipv4_addr;
NetLog("UDP HANDLER: Beginning handling UDP Packet.");
I64 error = UDPPacketParse(&source_port, &destination_port, &data, &length, packet);
if (error < 0)
{
NetErr("UDP HANDLER: Packet Parse Error.");
return error;
}
if (head)
{
node = UDPTreeNodeFind(destination_port, head);
if (node)
{
queue = UDPTreeNodeQueueIPV4Find(packet->source_ip_address, node); // TODO: make sure bit order is correct here!!
if (queue)
{
udp_socket = queue->socket;
NetLog("UDP HANDLER: Port and Address are in bound tree.");
}
else
{
NetWarn("UDP HANDLER: Found node for port, but address is not in node queue.");
NetWarn(" UDP packet dest ip: 0x%0X.", packet->destination_ip_address);
return -1;
}
}
else
{
NetWarn("UDP HANDLER: Node for Port is not in tree.");
return -1;
}
}
else
{
NetWarn("UDP HANDLER: Socket tree is currently empty.");
return -1;
}
// at this point, udp_socket is set, otherwise has already returned -1.
NetLog("UDP HANDLER: Putting data payload into message queue.");
messages_head = udp_socket->receive_queue;
message = CAlloc(sizeof(CUDPMessageQueue));
QueueInsertRev(message, messages_head);
message->data = CAlloc(length);
MemCopy(message->data, data, length);
message->data_length = length;
ipv4_addr = &message->from_address;
ipv4_addr->family = AF_INET;
ipv4_addr->port = EndianU16(source_port);
ipv4_addr->address.address = EndianU32(packet->source_ip_address);
NetLog("UDP HANDLER: Copying packet source IP (BE) to FROM_ADDRESS of UDP Socket: %08X ", ipv4_addr->address.address);
NetLog("UDP HANDLER: Data payload succesfully placed in message queue.");
return error;
}
// the socket functions just act on the socket state machine.
// NetErr and return fail vals if socket FSM improperly used.
// Careful with Free()'s.
class CUDPRepEntry:CQueue
{
CUDPTreeNode *node;
};
U0 UDPTreeNodeRep(CUDPTreeNode *node)
{
CUDPTreeQueue *queue = node->queue->next;
CUDPSocket *socket;
CSocketAddressIPV4 *ipv4_addr;
CSocketAddressIPV6 *ipv6_addr;
U8 *string;
CUDPMessageQueue *message;
"Port $$YELLOW$$%d$$FG$$ (UDP Node @ $$CYAN$$0x%X$$FG$$):\n", node->port, node;
while (queue != node->queue)
{
socket = queue->socket;
switch (socket->receive_address.family)
{
case AF_UNSPEC:
break;
case AF_INET:
ipv4_addr = &socket->receive_address;
string = MStrPrint("%d.%d.%d.%d",
ipv4_addr->address.address.u8[3],
ipv4_addr->address.address.u8[2],
ipv4_addr->address.address.u8[1],
ipv4_addr->address.address.u8[0]); // todo: kludge, endianness...
" $$BROWN$$%s$$FG$$ (UDP Tree Queue @ $$CYAN$$0x%X$$FG$$):\n", string, queue;
Free(string);
break;
case AF_INET6:
ipv6_addr = &socket->receive_address;
break;
default:
break;
}
" Timeout: %dms\n", socket->receive_timeout_ms;
if (socket->receive_queue) // todo: move socket messages Queue alloc from bind to creation to avoid check?
{
message = socket->receive_queue->next;
while (message != socket->receive_queue)
{
" Queued Message @ $$CYAN$$0x%X$$FG$$:\n", message;
switch (message->from_address.family)
{
case AF_UNSPEC:
string = StrNew("AF_UNSPEC");
break;
case AF_INET:
ipv4_addr = &message->from_address;
string = NetworkToPresentation(ipv4_addr->family, &ipv4_addr->address);
break;
case AF_INET6:
string = StrNew("IPV6");
break;
default:
string = StrNew("INVALID");
break;
}
" From Address: $$BROWN$$%s$$FG$$\n", string;
" Data length: %d\n", message->data_length;
" Received data length: %d\n", message->received_length;
Free(string);
message = message->next;
}
}
queue = queue->next;
}
"\n";
}
U0 UDPRep()
{
CUDPTreeNode *node = udp_globals.bound_socket_tree;
CUDPRepEntry *head;
CUDPRepEntry *entry;
CUDPRepEntry *temp_entry;
"$$LTBLUE$$UDP Report:$$FG$$\n\n";
if (node)
{
head = CAlloc(sizeof(CUDPRepEntry));
QueueInit(head); // no QueueRemove the head
entry = CAlloc(sizeof(CUDPRepEntry));
entry->node = node;
QueueInsert(entry, head);
// perform depth-first-search while Entry Queue has nodes not fully visited.
while (entry != head)
{
if (entry->node->left)
{ // if node has one, add an Entry for the left branch, continue loop.
temp_entry = CAlloc(sizeof(CUDPRepEntry));
temp_entry->node = entry->node->left;
QueueInsertRev(temp_entry, head);
// if left branch, but no right: toss early, now fully traveled.
if (!entry->node->right)
{
QueueRemove(entry);
UDPTreeNodeRep(entry->node);
Free(entry);
}
entry = temp_entry;
}
else if (entry->node->right)
{ // if no left, but right: add right to queue, pop Entry, Rep, set entry to right.
temp_entry = CAlloc(sizeof(CUDPRepEntry));
temp_entry->node = entry->node->right;
QueueInsertRev(temp_entry, head);
QueueRemove(entry);
UDPTreeNodeRep(entry->node);
Free(entry);
entry = temp_entry;
}
else
{ // pop Entry, Rep, if last Entry in Queue has right add it, pop & Rep travelled Entry, entry = right.
QueueRemove(entry);
UDPTreeNodeRep(entry->node);
Free(entry);
if (head->last != head)
{
temp_entry = head->last;
if (temp_entry->node->right)
{
entry = temp_entry;
temp_entry = CAlloc(sizeof(CUDPRepEntry));
temp_entry->node = entry->node->right;
QueueInsertRev(temp_entry, head);
QueueRemove(entry);
UDPTreeNodeRep(entry->node);
Free(entry);
entry = temp_entry;
}
else
{
QueueRemove(temp_entry);
UDPTreeNodeRep(temp_entry->node);
Free(temp_entry);
entry = head->last;
}
}
else
break;
}
}
Free(head);
}
else
"No UDP Sockets currently bound.\n\n";
}
UDPGlobalsInit;

View file

@ -1,4 +1,4 @@
U0 PCNetSendTrash()
U0 PCNetTest()
{
U8 *packet_buffer;
I64 de_index;
@ -14,4 +14,4 @@ U0 PCNetSendTrash()
}
}
PCNetSendTrash;
PCNetTest;

View file

@ -3,7 +3,7 @@ U8 dst_mac[6] = {0xF0, 0x0D, 0xBE, 0xAD, 0xDE, 0xAF};
U32 src_ip = 0x30313233;
U32 dst_ip = 0x01020304;
U0 UDPSendTrash()
U0 UDPTest()
{
U8 *udp_payload;
I64 de_index;
@ -23,4 +23,4 @@ U0 UDPSendTrash()
}
UDPSendTrash;
UDPTest;

View file

@ -1,4 +1,4 @@
U0 UDPSendTrash()
U0 UDPTest()
{
CAddressInfo *result = NULL;
@ -35,4 +35,4 @@ U0 UDPSendTrash()
}
}
UDPSendTrash;
UDPTest;

View file

@ -59,7 +59,7 @@ I64 UDPPacketParse(U16 *source_port_out,
CUDPHeader *header = packet->data;
// TODO: Shrine has FIXME, validate packet length!
// TODO: Validate packet length !
// NetDebug("UDP PACKET PARSE: Caught packet, src port: 0x%0X (B.E.)", header->source_port);
// NetDebug("UDP PACKET PARSE: Caught packet, dest port: 0x%0X (B.E.)", header->destination_port);
@ -87,6 +87,9 @@ CUDPSocket *UDPSocket(U16 domain=AF_UNSPEC)
udp_socket->receive_address.family = domain; // INET, INET6, or unspecified
udp_socket->receive_queue = CAlloc(sizeof(CUDPMessageQueue));
QueueInit(udp_socket->receive_queue); // acts as head. add messages to but don't remove head.
return udp_socket;
}
@ -95,7 +98,6 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
{
CUDPTreeNode *head = udp_globals.bound_socket_tree;
CUDPTreeNode *temp_node;
CUDPMessageQueue *message_queue;
CSocketAddressIPV4 *ipv4_source;
CSocketAddressIPV4 *ipv4_receive;
CSocketAddressIPV6 *ipv6_source;
@ -149,12 +151,12 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
port = EndianU16(ipv6_source->port); // port member should be Big Endian, so now we're going L.E (?)
Debug("TODO: IPV6 UDP BIND");
NetErr("UDP SOCKET BIND: FIXME, IPV6 UDP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC UDP BIND -- param family");
NetErr("UDP SOCKET BIND: Error, AF_UNSPEC UDP BIND -- param family");
break;
}
@ -171,7 +173,6 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
switch (address_source->family)
{
case AF_INET:
// TODO: will any INADDR_ANY sockets bound at the port break this?
if (UDPTreeNodeQueueIPV4Find(ipv4_receive->address.address, temp_node, TRUE))
{
NetErr("UDP SOCKET BIND: Address already in Bound Socket Tree !");
@ -185,11 +186,11 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
break;
case AF_INET6:
Debug("TODO: IPV6 UDP BIND");
NetErr("UDP SOCKET BIND: FIXME, IPV6 UDP BIND");
break;
case AF_UNSPEC:
Debug("TODO: AF_UNSPEC UDP BIND -- found in bound tree");
NetErr("UDP SOCKET BIND: Error, AF_UNSPEC UDP BIND -- found in bound tree");
break;
}
}
@ -208,9 +209,6 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
udp_socket->bound_to = port;
udp_socket->receive_queue = message_queue = CAlloc(sizeof(CUDPMessageQueue));
QueueInit(message_queue); // acts as head. add messages to but don't remove head.
switch (udp_socket->socket->state)
{
case SOCKET_STATE_BIND_REQ: // if BIND request success, set BOUND.
@ -241,7 +239,7 @@ I64 UDPSocketClose(CUDPSocket *udp_socket)
queue = UDPTreeNodeQueueSocketFind(udp_socket, node);
else
{
Debug("Didn't find node at socket during UDPSocketClose!\n");
Debug("TODO: Didn't find node at socket during UDPSocketClose!\n");
return -1;
}
@ -289,7 +287,7 @@ I64 UDPSocketClose(CUDPSocket *udp_socket)
}
else
{
Debug("Didn't find queue at socket during UDPSocketClose!\n");
Debug("TODO: Didn't find queue at socket during UDPSocketClose!\n");
return -1;
}
@ -298,7 +296,7 @@ I64 UDPSocketClose(CUDPSocket *udp_socket)
return 0;
}
// UDPSocketConnect (Shrine just has FIXME: 'implement')
// UDPSocketConnect (TODO)
// UDPListen (Shrine just has no_warns, not implemented)
@ -331,7 +329,7 @@ I64 UDPSocketReceiveFrom(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAdd
return -1; // if no timeout set and didn't see message, bail early
if (counts.jiffies > udp_socket->receive_max_timeout)
{ // Shrine has TODO: 'seterror(EWOULDBLOCK)' investigate this
{
NetErr("UDP SOCKET RECEIVE FROM: Timed out.");
return -1;
}
@ -427,10 +425,10 @@ I64 UDPSocketSendTo(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAddressS
break;
case AF_INET6:
ipv6_destination = dest;
Debug("TODO: IPV6 Not implemented yet");
NetErr("UDP SOCKET SEND TO: FIXME, IPV6 not implemented yet");
break;
case AF_UNSPEC:
Debug("TODO: Error UDP Send To AF_UNSPEC\n");
NetErr("UDP SOCKET SEND TO: Error, UDP Send To AF_UNSPEC\n");
break;
}
@ -577,36 +575,34 @@ U0 UDPTreeNodeRep(CUDPTreeNode *node)
}
" Timeout: %dms\n", socket->receive_timeout_ms;
if (socket->receive_queue) // todo: move socket messages Queue alloc from bind to creation to avoid check?
message = socket->receive_queue->next;
while (message != socket->receive_queue)
{
message = socket->receive_queue->next;
while (message != socket->receive_queue)
" Queued Message @ $$CYAN$$0x%X$$FG$$:\n", message;
switch (message->from_address.family)
{
" Queued Message @ $$CYAN$$0x%X$$FG$$:\n", message;
switch (message->from_address.family)
{
case AF_UNSPEC:
string = StrNew("AF_UNSPEC");
break;
case AF_INET:
ipv4_addr = &message->from_address;
string = NetworkToPresentation(ipv4_addr->family, &ipv4_addr->address);
break;
case AF_INET6:
string = StrNew("IPV6");
break;
default:
string = StrNew("INVALID");
break;
}
" From Address: $$BROWN$$%s$$FG$$\n", string;
" Data length: %d\n", message->data_length;
" Received data length: %d\n", message->received_length;
Free(string);
message = message->next;
case AF_UNSPEC:
string = StrNew("AF_UNSPEC");
break;
case AF_INET:
ipv4_addr = &message->from_address;
string = NetworkToPresentation(ipv4_addr->family, &ipv4_addr->address);
break;
case AF_INET6:
string = StrNew("IPV6");
break;
default:
string = StrNew("INVALID");
break;
}
" From Address: $$BROWN$$%s$$FG$$\n", string;
" Data length: %d\n", message->data_length;
" Received data length: %d\n", message->received_length;
Free(string);
message = message->next;
}
queue = queue->next;