From 66d55f8e0c16c641ec3ca47711835de974320b06 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 14 Mar 2019 00:20:44 +0100 Subject: [PATCH] IPv4: More work on the TCP implementation. I can now establish a connection to my little test server on the host. --- Kernel/IPv4Socket.cpp | 19 ++++++++++++++----- Kernel/IPv4Socket.h | 3 --- Kernel/NetworkTask.cpp | 9 +++++++-- Kernel/Process.cpp | 5 +++-- Kernel/Process.h | 3 +-- Kernel/Scheduler.cpp | 4 ++-- Kernel/Socket.cpp | 1 + Kernel/Socket.h | 4 ++++ Kernel/TCP.h | 6 ++++-- 9 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Kernel/IPv4Socket.cpp b/Kernel/IPv4Socket.cpp index 9d3a9b70e6..a749ddf9ee 100644 --- a/Kernel/IPv4Socket.cpp +++ b/Kernel/IPv4Socket.cpp @@ -42,7 +42,6 @@ Retained IPv4Socket::create(int type, int protocol) IPv4Socket::IPv4Socket(int type, int protocol) : Socket(AF_INET, type, protocol) - , m_lock("IPv4Socket") { kprintf("%s(%u) IPv4Socket{%p} created with type=%u, protocol=%d\n", current->name().characters(), current->pid(), this, type, protocol); LOCKER(all_sockets().lock()); @@ -103,8 +102,17 @@ KResult IPv4Socket::connect(const sockaddr* address, socklen_t address_size) auto* adapter = NetworkAdapter::from_ipv4_address(IPv4Address(192, 168, 5, 2)); if (!adapter) ASSERT_NOT_REACHED(); + + allocate_source_port_if_needed(); + send_tcp_packet(*adapter, TCPFlags::SYN); m_tcp_state = TCPState::Connecting1; + + current->set_blocked_socket(this); + block(Process::BlockedConnect); + Scheduler::yield(); + + ASSERT(is_connected()); return KSuccess; } @@ -216,11 +224,12 @@ void IPv4Socket::send_tcp_packet(NetworkAdapter& adapter, word flags, const void { auto buffer = ByteBuffer::create_zeroed(sizeof(TCPPacket) + payload_size); auto& tcp_packet = *(TCPPacket*)(buffer.pointer()); + ASSERT(m_source_port); tcp_packet.set_source_port(m_source_port); tcp_packet.set_destination_port(m_destination_port); tcp_packet.set_window_size(1024); tcp_packet.set_sequence_number(m_tcp_sequence_number); - tcp_packet.set_data_offset(5); + tcp_packet.set_data_offset(sizeof(TCPPacket) / sizeof(dword)); tcp_packet.set_flags(flags); if (flags & TCPFlags::ACK) @@ -310,7 +319,7 @@ ssize_t IPv4Socket::recvfrom(void* buffer, size_t buffer_length, int flags, sock ByteBuffer packet_buffer; { - LOCKER(m_lock); + LOCKER(lock()); if (!m_receive_queue.is_empty()) { packet_buffer = m_receive_queue.take_first(); m_can_read = !m_receive_queue.is_empty(); @@ -322,7 +331,7 @@ ssize_t IPv4Socket::recvfrom(void* buffer, size_t buffer_length, int flags, sock block(Process::BlockedReceive); Scheduler::yield(); - LOCKER(m_lock); + LOCKER(lock()); if (!m_can_read) { // Unblocked due to timeout. return -EAGAIN; @@ -378,7 +387,7 @@ ssize_t IPv4Socket::recvfrom(void* buffer, size_t buffer_length, int flags, sock void IPv4Socket::did_receive(ByteBuffer&& packet) { - LOCKER(m_lock); + LOCKER(lock()); m_receive_queue.append(move(packet)); m_can_read = true; #ifdef IPV4_SOCKET_DEBUG diff --git a/Kernel/IPv4Socket.h b/Kernel/IPv4Socket.h index dbfb5c606d..6d948c78ed 100644 --- a/Kernel/IPv4Socket.h +++ b/Kernel/IPv4Socket.h @@ -42,8 +42,6 @@ public: void did_receive(ByteBuffer&&); - Lock& lock() { return m_lock; } - word source_port() const { return m_source_port; } word destination_port() const { return m_destination_port; } @@ -78,7 +76,6 @@ private: dword m_tcp_ack_number { 0 }; TCPState m_tcp_state { Disconnected }; - Lock m_lock; bool m_can_read { false }; }; diff --git a/Kernel/NetworkTask.cpp b/Kernel/NetworkTask.cpp index 9902bd8777..96783ecb12 100644 --- a/Kernel/NetworkTask.cpp +++ b/Kernel/NetworkTask.cpp @@ -281,8 +281,10 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) { 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()) + if (it == IPv4Socket::sockets_by_tcp_port().resource().end()) { + kprintf("handle_tcp: No TCP socket for port %u\n", tcp_packet.destination_port()); return; + } ASSERT((*it).value); socket = *(*it).value; } @@ -291,15 +293,18 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) ASSERT(socket->type() == SOCK_STREAM); ASSERT(socket->source_port() == tcp_packet.destination_port()); - size_t payload_size = ipv4_packet.payload_size() - sizeof(TCPPacket); + size_t payload_size = ipv4_packet.payload_size() - tcp_packet.header_size(); if (tcp_packet.has_syn() && tcp_packet.has_ack()) { socket->set_tcp_ack_number(socket->tcp_sequence_number() + payload_size + 1); socket->send_tcp_packet(*adapter, TCPFlags::ACK); + socket->set_connected(true); kprintf("Connected!\n"); socket->set_tcp_state(Connected); return; } + socket->send_tcp_packet(*adapter, TCPFlags::ACK); + socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size())); } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 2a5883ebdc..2977b36e04 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2329,6 +2329,7 @@ void Process::finalize() } } } + m_blocked_socket = nullptr; set_state(Dead); } @@ -2511,10 +2512,10 @@ KResult Process::wait_for_connect(Socket& socket) { if (socket.is_connected()) return KSuccess; - m_blocked_connecting_socket = socket; + m_blocked_socket = socket; block(BlockedConnect); Scheduler::yield(); - m_blocked_connecting_socket = nullptr; + m_blocked_socket = nullptr; if (!socket.is_connected()) return KResult(-ECONNREFUSED); return KSuccess; diff --git a/Kernel/Process.h b/Kernel/Process.h index b380ab5f8d..f830fddb9d 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -372,7 +372,6 @@ private: dword m_times_scheduled { 0 }; pid_t m_waitee_pid { -1 }; int m_blocked_fd { -1 }; - Socket* m_blocked_socket { nullptr }; Vector m_select_read_fds; Vector m_select_write_fds; Vector m_select_exceptional_fds; @@ -382,7 +381,7 @@ private: SignalActionData m_signal_action_data[32]; dword m_pending_signals { 0 }; dword m_signal_mask { 0 }; - RetainPtr m_blocked_connecting_socket; + RetainPtr m_blocked_socket; byte m_termination_status { 0 }; byte m_termination_signal { 0 }; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 7a8748c051..7370144d7c 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -95,8 +95,8 @@ bool Scheduler::pick_next() } if (process.state() == Process::BlockedConnect) { - ASSERT(process.m_blocked_connecting_socket); - if (process.m_blocked_connecting_socket->is_connected()) + ASSERT(process.m_blocked_socket); + if (process.m_blocked_socket->is_connected()) process.unblock(); return true; } diff --git a/Kernel/Socket.cpp b/Kernel/Socket.cpp index 3998bdbd48..8866c282d2 100644 --- a/Kernel/Socket.cpp +++ b/Kernel/Socket.cpp @@ -22,6 +22,7 @@ Socket::Socket(int domain, int type, int protocol) : m_domain(domain) , m_type(type) , m_protocol(protocol) + , m_lock("Socket") { m_origin_pid = current->pid(); } diff --git a/Kernel/Socket.h b/Kernel/Socket.h index 867c7e970c..127394ae2f 100644 --- a/Kernel/Socket.h +++ b/Kernel/Socket.h @@ -46,6 +46,10 @@ public: timeval receive_deadline() const { return m_receive_deadline; } timeval send_deadline() const { return m_send_deadline; } + void set_connected(bool connected) { m_connected = connected; } + + Lock& lock() { return m_lock; } + protected: Socket(int domain, int type, int protocol); diff --git a/Kernel/TCP.h b/Kernel/TCP.h index 6552702c07..d7f48b1c2b 100644 --- a/Kernel/TCP.h +++ b/Kernel/TCP.h @@ -18,6 +18,8 @@ public: TCPPacket() { } ~TCPPacket() { } + size_t header_size() const { return data_offset() * sizeof(dword); } + word source_port() const { return m_source_port; } void set_source_port(word port) { m_source_port = port; } @@ -48,8 +50,8 @@ public: word urgent() const { return m_urgent; } void set_urgent(word urgent) { m_urgent = urgent; } - const void* payload() const { return this + 1; } - void* payload() { return this + 1; } + const void* payload() const { return ((const byte*)this) + header_size(); } + void* payload() { return ((byte*)this) + header_size(); } private: NetworkOrdered m_source_port;