mirror of
https://github.com/RGBCube/serenity
synced 2025-05-17 19:15:08 +00:00
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:
parent
34d0e96aec
commit
65409e8f04
2 changed files with 26 additions and 23 deletions
|
@ -229,34 +229,36 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size
|
||||||
ASSERT_NOT_REACHED();
|
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);
|
auto role = this->role(description);
|
||||||
if (role == Role::Accepted) {
|
if (role == Role::Accepted)
|
||||||
if (!description.is_blocking()) {
|
return m_for_server;
|
||||||
if (m_for_server.is_empty()) {
|
if (role == Role::Connected)
|
||||||
if (!has_attached_peer(description))
|
return m_for_client;
|
||||||
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);
|
|
||||||
}
|
|
||||||
ASSERT_NOT_REACHED();
|
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
|
StringView LocalSocket::socket_path() const
|
||||||
{
|
{
|
||||||
int len = strnlen(m_address.sun_path, sizeof(m_address.sun_path));
|
int len = strnlen(m_address.sun_path, sizeof(m_address.sun_path));
|
||||||
|
|
|
@ -36,6 +36,7 @@ private:
|
||||||
virtual bool is_local() const override { return true; }
|
virtual bool is_local() const override { return true; }
|
||||||
bool has_attached_peer(const FileDescription&) const;
|
bool has_attached_peer(const FileDescription&) const;
|
||||||
static Lockable<InlineLinkedList<LocalSocket>>& all_sockets();
|
static Lockable<InlineLinkedList<LocalSocket>>& all_sockets();
|
||||||
|
DoubleBuffer& buffer_for(FileDescription&);
|
||||||
|
|
||||||
// An open socket file on the filesystem.
|
// An open socket file on the filesystem.
|
||||||
RefPtr<FileDescription> m_file;
|
RefPtr<FileDescription> m_file;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue