mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:28:12 +00:00
Kernel: Drop the receive buffer when socket enters the TimeWait state
The TimeWait state is intended to prevent another socket from taking the address tuple in case any packets are still in transit after the final close. Since this state never delivers packets to userspace, it doesn't make sense to keep the receive buffer around.
This commit is contained in:
parent
f4d3c54c12
commit
0ccef94a49
3 changed files with 19 additions and 1 deletions
|
@ -248,6 +248,9 @@ KResultOr<size_t> IPv4Socket::sendto(OpenFileDescription&, const UserOrKernelBuf
|
||||||
KResultOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>)
|
KResultOr<size_t> IPv4Socket::receive_byte_buffered(OpenFileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>)
|
||||||
{
|
{
|
||||||
MutexLocker locker(mutex());
|
MutexLocker locker(mutex());
|
||||||
|
|
||||||
|
VERIFY(m_receive_buffer);
|
||||||
|
|
||||||
if (m_receive_buffer->is_empty()) {
|
if (m_receive_buffer->is_empty()) {
|
||||||
if (protocol_is_disconnected())
|
if (protocol_is_disconnected())
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -408,6 +411,8 @@ bool IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port,
|
||||||
auto packet_size = packet.size();
|
auto packet_size = packet.size();
|
||||||
|
|
||||||
if (buffer_mode() == BufferMode::Bytes) {
|
if (buffer_mode() == BufferMode::Bytes) {
|
||||||
|
VERIFY(m_receive_buffer);
|
||||||
|
|
||||||
size_t space_in_receive_buffer = m_receive_buffer->space_for_writing();
|
size_t space_in_receive_buffer = m_receive_buffer->space_for_writing();
|
||||||
if (packet_size > space_in_receive_buffer) {
|
if (packet_size > space_in_receive_buffer) {
|
||||||
dbgln("IPv4Socket({}): did_receive refusing packet since buffer is full.", this);
|
dbgln("IPv4Socket({}): did_receive refusing packet since buffer is full.", this);
|
||||||
|
@ -764,4 +769,9 @@ void IPv4Socket::set_can_read(bool value)
|
||||||
evaluate_block_conditions();
|
evaluate_block_conditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPv4Socket::drop_receive_buffer()
|
||||||
|
{
|
||||||
|
m_receive_buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ protected:
|
||||||
void set_peer_address(IPv4Address address) { m_peer_address = address; }
|
void set_peer_address(IPv4Address address) { m_peer_address = address; }
|
||||||
|
|
||||||
static KResultOr<NonnullOwnPtr<DoubleBuffer>> try_create_receive_buffer();
|
static KResultOr<NonnullOwnPtr<DoubleBuffer>> try_create_receive_buffer();
|
||||||
|
void drop_receive_buffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_ipv4() const override { return true; }
|
virtual bool is_ipv4() const override { return true; }
|
||||||
|
@ -115,7 +116,7 @@ private:
|
||||||
|
|
||||||
SinglyLinkedListWithCount<ReceivedPacket> m_receive_queue;
|
SinglyLinkedListWithCount<ReceivedPacket> m_receive_queue;
|
||||||
|
|
||||||
NonnullOwnPtr<DoubleBuffer> m_receive_buffer;
|
OwnPtr<DoubleBuffer> m_receive_buffer;
|
||||||
|
|
||||||
u16 m_local_port { 0 };
|
u16 m_local_port { 0 };
|
||||||
u16 m_peer_port { 0 };
|
u16 m_peer_port { 0 };
|
||||||
|
|
|
@ -43,6 +43,13 @@ void TCPSocket::set_state(State new_state)
|
||||||
[[maybe_unused]] auto rc = set_so_error(KSuccess);
|
[[maybe_unused]] auto rc = set_so_error(KSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_state == State::TimeWait) {
|
||||||
|
// Once we hit TimeWait, we are only holding the socket in case there
|
||||||
|
// are packets on the way which we wouldn't want a new socket to get hit
|
||||||
|
// with, so there's no point in keeping the receive buffer around.
|
||||||
|
drop_receive_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
if (new_state == State::Closed) {
|
if (new_state == State::Closed) {
|
||||||
closing_sockets().with_exclusive([&](auto& table) {
|
closing_sockets().with_exclusive([&](auto& table) {
|
||||||
table.remove(tuple());
|
table.remove(tuple());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue