diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-03-13 17:17:07 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-03-13 17:17:07 +0100 |
commit | c588653f76dcb579dd0e4bed04f6cf8ee4eee04c (patch) | |
tree | 2ac28ce42fd3b55e5369c7f420ae152e177e027b /Kernel/NetworkTask.cpp | |
parent | ef5d0a397c6a5be4a1ff077542ebf8051282836e (diff) | |
download | serenity-c588653f76dcb579dd0e4bed04f6cf8ee4eee04c.zip |
IPv4: Begin fleshing out TCP support.
Diffstat (limited to 'Kernel/NetworkTask.cpp')
-rw-r--r-- | Kernel/NetworkTask.cpp | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/Kernel/NetworkTask.cpp b/Kernel/NetworkTask.cpp index c96e17b721..8382fd8ca8 100644 --- a/Kernel/NetworkTask.cpp +++ b/Kernel/NetworkTask.cpp @@ -3,6 +3,7 @@ #include <Kernel/ARP.h> #include <Kernel/ICMP.h> #include <Kernel/UDP.h> +#include <Kernel/TCP.h> #include <Kernel/IPv4.h> #include <Kernel/IPv4Socket.h> #include <Kernel/Process.h> @@ -10,14 +11,16 @@ #include <AK/Lock.h> //#define ETHERNET_DEBUG -//#define IPV4_DEBUG +#define IPV4_DEBUG //#define ICMP_DEBUG #define UDP_DEBUG +#define TCP_DEBUG static void handle_arp(const EthernetFrameHeader&, int frame_size); static void handle_ipv4(const EthernetFrameHeader&, int frame_size); static void handle_icmp(const EthernetFrameHeader&, int frame_size); static void handle_udp(const EthernetFrameHeader&, int frame_size); +static void handle_tcp(const EthernetFrameHeader&, int frame_size); Lockable<HashMap<IPv4Address, MACAddress>>& arp_table() { @@ -152,6 +155,8 @@ void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) return handle_icmp(eth, frame_size); case IPv4Protocol::UDP: return handle_udp(eth, frame_size); + case IPv4Protocol::TCP: + return handle_tcp(eth, frame_size); default: kprintf("handle_ipv4: Unhandled protocol %u\n", packet.protocol()); break; @@ -244,3 +249,44 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size) ASSERT(socket->source_port() == udp_packet.destination_port()); socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } + +void handle_tcp(const EthernetFrameHeader& eth, int frame_size) +{ + (void)frame_size; + auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload()); + + auto* adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination()); + if (!adapter) { + kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters()); + return; + } + + auto& tcp_packet = *static_cast<const TCPPacket*>(ipv4_packet.payload()); +#ifdef TCP_DEBUG + kprintf("handle_tcp: source=%s:%u, destination=%s:%u seq=%u, ack=%u, flags=%w, window_size=%u\n", + ipv4_packet.source().to_string().characters(), + tcp_packet.source_port(), + ipv4_packet.destination().to_string().characters(), + tcp_packet.destination_port(), + tcp_packet.sequence_number(), + tcp_packet.ack_number(), + tcp_packet.flags(), + tcp_packet.window_size() + ); +#endif + + RetainPtr<IPv4Socket> socket; + { + LOCKER(IPv4Socket::sockets_by_tcp_port().lock()); + auto it = IPv4Socket::sockets_by_tcp_port().resource().find(tcp_packet.destination_port()); + if (it == IPv4Socket::sockets_by_tcp_port().resource().end()) + return; + ASSERT((*it).value); + socket = *(*it).value; + } + + LOCKER(socket->lock()); + ASSERT(socket->type() == SOCK_STREAM); + ASSERT(socket->source_port() == tcp_packet.destination_port()); + socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); +} |