Kernel: Implement super simple TCP stack
No SACK support and windows are fixed size
This commit is contained in:
@@ -12,6 +12,7 @@ namespace Kernel
|
||||
enum NetworkProtocol : uint8_t
|
||||
{
|
||||
ICMP = 0x01,
|
||||
TCP = 0x06,
|
||||
UDP = 0x11,
|
||||
};
|
||||
|
||||
|
||||
118
kernel/include/kernel/Networking/TCPSocket.h
Normal file
118
kernel/include/kernel/Networking/TCPSocket.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Endianness.h>
|
||||
#include <kernel/Memory/VirtualRange.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
#include <kernel/Networking/NetworkSocket.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/Semaphore.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
struct TCPHeader
|
||||
{
|
||||
BAN::NetworkEndian<uint16_t> src_port { 0 };
|
||||
BAN::NetworkEndian<uint16_t> dst_port { 0 };
|
||||
BAN::NetworkEndian<uint32_t> seq_number { 0 };
|
||||
BAN::NetworkEndian<uint32_t> ack_number { 0 };
|
||||
uint8_t reserved : 4 { 0 };
|
||||
uint8_t data_offset : 4 { 0 };
|
||||
uint8_t fin : 1 { 0 };
|
||||
uint8_t syn : 1 { 0 };
|
||||
uint8_t rst : 1 { 0 };
|
||||
uint8_t psh : 1 { 0 };
|
||||
uint8_t ack : 1 { 0 };
|
||||
uint8_t urg : 1 { 0 };
|
||||
uint8_t ece : 1 { 0 };
|
||||
uint8_t cwr : 1 { 0 };
|
||||
BAN::NetworkEndian<uint16_t> window_size { 0 };
|
||||
BAN::NetworkEndian<uint16_t> checksum { 0 };
|
||||
BAN::NetworkEndian<uint16_t> urgent_pointer { 0 };
|
||||
uint8_t options[0];
|
||||
};
|
||||
static_assert(sizeof(TCPHeader) == 20);
|
||||
|
||||
class TCPSocket final : public NetworkSocket
|
||||
{
|
||||
public:
|
||||
static constexpr size_t m_tcp_options_bytes = 4;
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
~TCPSocket();
|
||||
|
||||
virtual NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
|
||||
|
||||
virtual size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
|
||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||
|
||||
protected:
|
||||
virtual void on_close_impl() override;
|
||||
|
||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||
|
||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
|
||||
|
||||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan message, sockaddr* address, socklen_t* address_len) override;
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
Closed = 0,
|
||||
Listen,
|
||||
SynSent,
|
||||
SynReceived,
|
||||
Established,
|
||||
FinWait1,
|
||||
FinWait2,
|
||||
CloseWait,
|
||||
Closing,
|
||||
LastAck,
|
||||
TimeWait,
|
||||
};
|
||||
|
||||
struct WindowInfo
|
||||
{
|
||||
uint32_t mss { 0 };
|
||||
uint16_t size { 0 };
|
||||
uint8_t scale { 0 };
|
||||
uint32_t start_seq { 0 };
|
||||
uint32_t current_seq { 0 };
|
||||
BAN::Atomic<uint32_t> ack_number { 0 };
|
||||
uint32_t data_size { 0 };
|
||||
uint64_t send_time_ms { 0 };
|
||||
BAN::UniqPtr<VirtualRange> window;
|
||||
};
|
||||
|
||||
private:
|
||||
TCPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
void process_task();
|
||||
|
||||
void set_connection_as_closed();
|
||||
|
||||
private:
|
||||
State m_state = State::Closed;
|
||||
|
||||
Process* m_process { nullptr };
|
||||
|
||||
uint64_t m_time_wait_start_ms { 0 };
|
||||
|
||||
RecursiveSpinLock m_lock;
|
||||
Semaphore m_semaphore;
|
||||
|
||||
BAN::Atomic<bool> m_should_ack { false };
|
||||
|
||||
WindowInfo m_recv_window;
|
||||
WindowInfo m_send_window;
|
||||
|
||||
struct ConnectionInfo
|
||||
{
|
||||
sockaddr_storage address;
|
||||
socklen_t address_len;
|
||||
};
|
||||
BAN::Optional<ConnectionInfo> m_connection_info;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user