diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-09-22 21:30:30 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-09-22 21:30:30 +0200 |
commit | 65409e8f04b0cdbc7df76d4e6edb4265ad5ded9c (patch) | |
tree | 650f2e5efd79efd5d2900f5dc3d292a23a67edc5 /Kernel/Net | |
parent | 34d0e96aec89ea643cd5eb3e279a46a7542aac64 (diff) | |
download | serenity-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.cpp | 46 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.h | 1 |
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; |