diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index e6e3150f3b..076e2d2be1 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -245,6 +245,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, if (tcp_packet.has_syn() || payload_size > 0) { Locker locker(m_not_acked_lock); m_not_acked.append({ m_sequence_number, move(packet), ipv4_payload_offset, *routing_decision.adapter }); + m_not_acked_size += payload_size; enqueue_for_retransmit(); } @@ -269,6 +270,10 @@ void TCPSocket::receive_tcp_packet(const TCPPacket& packet, u16 size) auto old_adapter = packet.adapter.strong_ref(); if (old_adapter) old_adapter->release_packet_buffer(*packet.buffer); + TCPPacket& tcp_packet = *(TCPPacket*)(packet.buffer->buffer.data() + packet.ipv4_payload_offset); + auto payload_size = packet.buffer->buffer.data() + packet.buffer->buffer.size() - (u8*)tcp_packet.payload(); + m_not_acked_size -= payload_size; + evaluate_block_conditions(); m_not_acked.take_first(); removed++; } else { @@ -566,4 +571,16 @@ void TCPSocket::retransmit_packets() } } +bool TCPSocket::can_write(const FileDescription& file_description, size_t size) const +{ + if (!IPv4Socket::can_write(file_description, size)) + return false; + + if (!file_description.is_blocking()) + return true; + + Locker lock(m_not_acked_lock); + return m_not_acked_size + size <= m_send_window_size; +} + } diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 7dab47d57f..c3ac398301 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -157,6 +157,8 @@ public: virtual KResult close() override; + virtual bool can_write(const FileDescription&, size_t) const override; + protected: void set_direction(Direction direction) { m_direction = direction; } @@ -200,8 +202,9 @@ private: int tx_counter { 0 }; }; - Lock m_not_acked_lock { "TCPSocket unacked packets" }; + mutable Lock m_not_acked_lock { "TCPSocket unacked packets" }; SinglyLinkedList m_not_acked; + size_t m_not_acked_size { 0 }; u32 m_duplicate_acks { 0 }; @@ -212,6 +215,9 @@ private: static constexpr u32 maximum_retransmits = 5; Time m_last_retransmit_time; u32 m_retransmit_attempts { 0 }; + + // FIXME: Parse window size TCP option from the peer + u32 m_send_window_size { 64 * KiB }; }; }