summaryrefslogtreecommitdiff
path: root/Kernel/Net
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-09-22 21:30:30 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-09-22 21:30:30 +0200
commit65409e8f04b0cdbc7df76d4e6edb4265ad5ded9c (patch)
tree650f2e5efd79efd5d2900f5dc3d292a23a67edc5 /Kernel/Net
parent34d0e96aec89ea643cd5eb3e279a46a7542aac64 (diff)
downloadserenity-65409e8f04b0cdbc7df76d4e6edb4265ad5ded9c.zip
LocalSocket: Teach recvfrom() how to block if needed, and simplify it
If we can't already read when we enter recvfrom() on a LocalSocket, we'll now block the current thread until we can. Also added a buffer_for(FileDescription&) helper so that the client and server can share some of the code. :^)
Diffstat (limited to 'Kernel/Net')
-rw-r--r--Kernel/Net/LocalSocket.cpp46
-rw-r--r--Kernel/Net/LocalSocket.h1
2 files changed, 25 insertions, 22 deletions
diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp
index 1d0309eb13..135306a272 100644
--- a/Kernel/Net/LocalSocket.cpp
+++ b/Kernel/Net/LocalSocket.cpp
@@ -229,32 +229,34 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size
ASSERT_NOT_REACHED();
}
-ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
+DoubleBuffer& LocalSocket::buffer_for(FileDescription& description)
{
auto role = this->role(description);
- if (role == Role::Accepted) {
- if (!description.is_blocking()) {
- if (m_for_server.is_empty()) {
- if (!has_attached_peer(description))
- return 0;
- return -EAGAIN;
- }
- }
- ASSERT(!m_for_server.is_empty());
- return m_for_server.read((u8*)buffer, buffer_size);
- }
- if (role == Role::Connected) {
- if (!description.is_blocking()) {
- if (m_for_client.is_empty()) {
- if (!has_attached_peer(description))
- return 0;
- return -EAGAIN;
- }
+ if (role == Role::Accepted)
+ return m_for_server;
+ if (role == Role::Connected)
+ return m_for_client;
+ ASSERT_NOT_REACHED();
+}
+
+ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
+{
+ auto& buffer_for_me = buffer_for(description);
+ if (!description.is_blocking()) {
+ if (buffer_for_me.is_empty()) {
+ if (!has_attached_peer(description))
+ return 0;
+ return -EAGAIN;
}
- ASSERT(!m_for_client.is_empty());
- return m_for_client.read((u8*)buffer, buffer_size);
+ } else if (!can_read(description)) {
+ auto result = current->block<Thread::ReceiveBlocker>(description);
+ if (result == Thread::BlockResult::InterruptedBySignal)
+ return -EINTR;
}
- ASSERT_NOT_REACHED();
+ if (!has_attached_peer(description) && buffer_for_me.is_empty())
+ return 0;
+ ASSERT(!buffer_for_me.is_empty());
+ return buffer_for_me.read((u8*)buffer, buffer_size);
}
StringView LocalSocket::socket_path() const
diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h
index 5ce1753653..2a6ee5bd2b 100644
--- a/Kernel/Net/LocalSocket.h
+++ b/Kernel/Net/LocalSocket.h
@@ -36,6 +36,7 @@ private:
virtual bool is_local() const override { return true; }
bool has_attached_peer(const FileDescription&) const;
static Lockable<InlineLinkedList<LocalSocket>>& all_sockets();
+ DoubleBuffer& buffer_for(FileDescription&);
// An open socket file on the filesystem.
RefPtr<FileDescription> m_file;