Kernel: Add MSG_PEEK support for the IPv4Socket

This commit will add MSG_PEEK support, which allows a package to be
seen without taking it from the buffer, so that a subsequent recv()
without the MSG_PEEK flag can pick it up.
This commit is contained in:
Justin 2021-04-28 23:22:55 +02:00 committed by Andreas Kling
parent 2d098c88dc
commit e6401d65bd
3 changed files with 22 additions and 5 deletions

View file

@ -217,7 +217,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer&
return nsent_or_error;
}
KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int, Userspace<sockaddr*>, Userspace<socklen_t*>)
KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description, UserOrKernelBuffer& buffer, size_t buffer_length, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>)
{
Locker locker(lock());
if (m_receive_buffer.is_empty()) {
@ -241,8 +241,14 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description
}
VERIFY(!m_receive_buffer.is_empty());
int nreceived = m_receive_buffer.read(buffer, buffer_length);
if (nreceived > 0)
int nreceived;
if (flags & MSG_PEEK)
nreceived = m_receive_buffer.peek(buffer, buffer_length);
else
nreceived = m_receive_buffer.read(buffer, buffer_length);
if (nreceived > 0 && !(flags & MSG_PEEK))
Thread::current()->did_ipv4_socket_read((size_t)nreceived);
set_can_read(!m_receive_buffer.is_empty());
@ -264,7 +270,11 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
}
if (!m_receive_queue.is_empty()) {
packet = m_receive_queue.take_first();
if (flags & MSG_PEEK)
packet = m_receive_queue.first();
else
packet = m_receive_queue.take_first();
set_can_read(!m_receive_queue.is_empty());
dbgln_if(IPV4_SOCKET_DEBUG, "IPv4Socket({}): recvfrom without blocking {} bytes, packets in queue: {}",
@ -293,7 +303,12 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
}
VERIFY(m_can_read);
VERIFY(!m_receive_queue.is_empty());
packet = m_receive_queue.take_first();
if (flags & MSG_PEEK)
packet = m_receive_queue.first();
else
packet = m_receive_queue.take_first();
set_can_read(!m_receive_queue.is_empty());
dbgln_if(IPV4_SOCKET_DEBUG, "IPv4Socket({}): recvfrom with blocking {} bytes, packets in queue: {}",

View file

@ -496,6 +496,7 @@ struct pollfd {
#define MSG_TRUNC 0x1
#define MSG_CTRUNC 0x2
#define MSG_PEEK 0x4
#define MSG_DONTWAIT 0x40
#define SOL_SOCKET 1

View file

@ -46,6 +46,7 @@ __BEGIN_DECLS
#define MSG_TRUNC 0x1
#define MSG_CTRUNC 0x2
#define MSG_PEEK 0x4
#define MSG_DONTWAIT 0x40
typedef uint16_t sa_family_t;