Browse Source

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.
Justin 4 years ago
parent
commit
e6401d65bd
3 changed files with 22 additions and 5 deletions
  1. 20 5
      Kernel/Net/IPv4Socket.cpp
  2. 1 0
      Kernel/UnixTypes.h
  3. 1 0
      Userland/Libraries/LibC/sys/socket.h

+ 20 - 5
Kernel/Net/IPv4Socket.cpp

@@ -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: {}",

+ 1 - 0
Kernel/UnixTypes.h

@@ -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

+ 1 - 0
Userland/Libraries/LibC/sys/socket.h

@@ -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;