1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:48:11 +00:00
serenity/Kernel/Net/TCPSocket.h
Conrad Pankoff 73c998dbfc Kernel: Refactor TCP/IP stack
This has several significant changes to the networking stack.

* Significant refactoring of the TCP state machine. Right now it's
  probably more fragile than it used to be, but handles quite a lot
  more of the handshake process.
* `TCPSocket` holds a `NetworkAdapter*`, assigned during `connect()` or
  `bind()`, whichever comes first.
* `listen()` is now virtual in `Socket` and intended to be implemented
  in its child classes
* `listen()` no longer works without `bind()` - this is a bit of a
  regression, but listening sockets didn't work at all before, so it's
  not possible to observe the regression.
* A file is exposed at `/proc/net_tcp`, which is a JSON document listing
  the current TCP sockets with a bit of metadata.
* There's an `ETHERNET_VERY_DEBUG` flag for dumping packet's content out
  to `kprintf`. It is, indeed, _very debug_.
2019-08-06 16:21:17 +02:00

112 lines
3.5 KiB
C++

#pragma once
#include <AK/Function.h>
#include <Kernel/Net/IPv4Socket.h>
class TCPSocket final : public IPv4Socket {
public:
static void for_each(Function<void(TCPSocket*&)>);
static NonnullRefPtr<TCPSocket> create(int protocol);
virtual ~TCPSocket() override;
enum class State {
Closed,
Listen,
SynSent,
SynReceived,
Established,
CloseWait,
LastAck,
FinWait1,
FinWait2,
Closing,
TimeWait,
};
static const char* to_string(State state)
{
switch (state) {
case State::Closed:
return "Closed";
case State::Listen:
return "Listen";
case State::SynSent:
return "SynSent";
case State::SynReceived:
return "SynReceived";
case State::Established:
return "Established";
case State::CloseWait:
return "CloseWait";
case State::LastAck:
return "LastAck";
case State::FinWait1:
return "FinWait1";
case State::FinWait2:
return "FinWait2";
case State::Closing:
return "Closing";
case State::TimeWait:
return "TimeWait";
default:
return "None";
}
}
State state() const { return m_state; }
void set_state(State state) { m_state = state; }
void set_ack_number(u32 n) { m_ack_number = n; }
void set_sequence_number(u32 n) { m_sequence_number = n; }
u32 ack_number() const { return m_ack_number; }
u32 sequence_number() const { return m_sequence_number; }
void send_tcp_packet(u16 flags, const void* = nullptr, int = 0);
static Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>& sockets_by_tuple();
static TCPSocketHandle from_tuple(const IPv4SocketTuple& tuple);
static TCPSocketHandle from_endpoints(const IPv4Address& local_address, u16 local_port, const IPv4Address& peer_address, u16 peer_port);
private:
explicit TCPSocket(int protocol);
virtual const char* class_name() const override { return "TCPSocket"; }
static NetworkOrdered<u16> compute_tcp_checksum(const IPv4Address& source, const IPv4Address& destination, const TCPPacket&, u16 payload_size);
virtual int protocol_receive(const KBuffer&, void* buffer, size_t buffer_size, int flags) override;
virtual int protocol_send(const void*, int) override;
virtual KResult protocol_connect(FileDescription&, ShouldBlock) override;
virtual int protocol_allocate_local_port() override;
virtual bool protocol_is_disconnected() const override;
virtual KResult protocol_bind() override;
virtual KResult protocol_listen() override;
NetworkAdapter* m_adapter { nullptr };
u32 m_sequence_number { 0 };
u32 m_ack_number { 0 };
State m_state { State::Closed };
};
class TCPSocketHandle : public SocketHandle {
public:
TCPSocketHandle() {}
TCPSocketHandle(RefPtr<TCPSocket>&& socket)
: SocketHandle(move(socket))
{
}
TCPSocketHandle(TCPSocketHandle&& other)
: SocketHandle(move(other))
{
}
TCPSocketHandle(const TCPSocketHandle&) = delete;
TCPSocketHandle& operator=(const TCPSocketHandle&) = delete;
TCPSocket* operator->() { return &socket(); }
const TCPSocket* operator->() const { return &socket(); }
TCPSocket& socket() { return static_cast<TCPSocket&>(SocketHandle::socket()); }
const TCPSocket& socket() const { return static_cast<const TCPSocket&>(SocketHandle::socket()); }
};