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. :^)
This commit is contained in:
Andreas Kling 2019-09-22 21:30:30 +02:00
parent 34d0e96aec
commit 65409e8f04
Notes: sideshowbarker 2024-07-19 12:00:08 +09:00
2 changed files with 26 additions and 23 deletions

View file

@ -229,34 +229,36 @@ 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;
}
}
ASSERT(!m_for_client.is_empty());
return m_for_client.read((u8*)buffer, buffer_size);
}
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;
}
} else if (!can_read(description)) {
auto result = current->block<Thread::ReceiveBlocker>(description);
if (result == Thread::BlockResult::InterruptedBySignal)
return -EINTR;
}
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
{
int len = strnlen(m_address.sun_path, sizeof(m_address.sun_path));

View file

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