diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-07-27 10:21:25 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-07-27 10:32:40 +0200 |
commit | b3fe9cde523eac6f545270446078a6c6866820e1 (patch) | |
tree | f04306e3ded363922fad9784cf8e5732d3934b88 | |
parent | 9b7e1eb287f8aa6c807303bf221e5498c8964960 (diff) | |
download | serenity-b3fe9cde523eac6f545270446078a6c6866820e1.zip |
LibCore: Add CLocalServer, a server-only local socket class.
Instead of trying to support both client and server in CLocalSocket, let's
have a specialized server class.
The basic usage is:
CLocalServer server;
server.listen("/tmp/name-of-portal");
server.on_ready_to_accept = [&] {
CLocalSocket* client = server.accept();
...
};
This will make things a lot simpler, since an accepting socket doesn't need
half of the stuff that a regular CIODevice provides. :^)
-rw-r--r-- | Libraries/LibCore/CLocalServer.cpp | 54 | ||||
-rw-r--r-- | Libraries/LibCore/CLocalServer.h | 25 | ||||
-rw-r--r-- | Libraries/LibCore/CLocalSocket.cpp | 8 | ||||
-rw-r--r-- | Libraries/LibCore/CLocalSocket.h | 5 | ||||
-rw-r--r-- | Libraries/LibCore/Makefile | 1 |
5 files changed, 93 insertions, 0 deletions
diff --git a/Libraries/LibCore/CLocalServer.cpp b/Libraries/LibCore/CLocalServer.cpp new file mode 100644 index 0000000000..30abcc5f2b --- /dev/null +++ b/Libraries/LibCore/CLocalServer.cpp @@ -0,0 +1,54 @@ +#include <LibCore/CLocalServer.h> +#include <LibCore/CLocalSocket.h> +#include <LibCore/CNotifier.h> +#include <stdio.h> +#include <sys/socket.h> + +CLocalServer::CLocalServer(CObject* parent) + : CObject(parent) +{ + m_fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); + ASSERT(m_fd >= 0); +} + +CLocalServer::~CLocalServer() +{ +} + +bool CLocalServer::listen(const String& address) +{ + if (m_listening) + return false; + + int rc; + + auto socket_address = CSocketAddress::local(address); + auto un = socket_address.to_sockaddr_un(); + rc = ::bind(m_fd, (const sockaddr*)&un, sizeof(un)); + ASSERT(rc == 0); + + rc = ::listen(m_fd, 5); + ASSERT(rc == 0); + m_listening = true; + + m_notifier = make<CNotifier>(m_fd, CNotifier::Event::Read); + m_notifier->on_ready_to_read = [this] { + if (on_ready_to_accept) + on_ready_to_accept(); + }; + return true; +} + +CLocalSocket* CLocalServer::accept() +{ + ASSERT(m_listening); + sockaddr_un un; + socklen_t un_size = sizeof(un); + int accepted_fd = ::accept(m_fd, (sockaddr*)&un, &un_size); + if (accepted_fd < 0) { + perror("accept"); + return nullptr; + } + + return new CLocalSocket({}, accepted_fd); +} diff --git a/Libraries/LibCore/CLocalServer.h b/Libraries/LibCore/CLocalServer.h new file mode 100644 index 0000000000..ae7768e284 --- /dev/null +++ b/Libraries/LibCore/CLocalServer.h @@ -0,0 +1,25 @@ +#pragma once + +#include <LibCore/CNotifier.h> +#include <LibCore/CObject.h> + +class CLocalSocket; + +class CLocalServer : public CObject { + C_OBJECT(CLocalServer) +public: + explicit CLocalServer(CObject* parent = nullptr); + virtual ~CLocalServer() override; + + bool is_listening() const { return m_listening; } + bool listen(const String& address); + + CLocalSocket* accept(); + + Function<void()> on_ready_to_accept; + +private: + int m_fd { -1 }; + bool m_listening { false }; + OwnPtr<CNotifier> m_notifier; +}; diff --git a/Libraries/LibCore/CLocalSocket.cpp b/Libraries/LibCore/CLocalSocket.cpp index f4b05fa9bb..73355faa84 100644 --- a/Libraries/LibCore/CLocalSocket.cpp +++ b/Libraries/LibCore/CLocalSocket.cpp @@ -2,6 +2,14 @@ #include <sys/socket.h> #include <errno.h> +CLocalSocket::CLocalSocket(Badge<CLocalServer>, int fd, CObject* parent) + : CSocket(CSocket::Type::Local, parent) +{ + set_fd(fd); + set_mode(CIODevice::ReadWrite); + set_error(0); +} + CLocalSocket::CLocalSocket(CObject* parent) : CSocket(CSocket::Type::Local, parent) { diff --git a/Libraries/LibCore/CLocalSocket.h b/Libraries/LibCore/CLocalSocket.h index c515bb83db..aab1546561 100644 --- a/Libraries/LibCore/CLocalSocket.h +++ b/Libraries/LibCore/CLocalSocket.h @@ -1,10 +1,15 @@ #pragma once + +#include <AK/Badge.h> #include <LibCore/CSocket.h> +class CLocalServer; + class CLocalSocket final : public CSocket { C_OBJECT(CLocalSocket) public: explicit CLocalSocket(CObject* parent = nullptr); + CLocalSocket(Badge<CLocalServer>, int fd, CObject* parent = nullptr); virtual ~CLocalSocket() override; virtual bool bind(const CSocketAddress&) override; diff --git a/Libraries/LibCore/Makefile b/Libraries/LibCore/Makefile index 9c169d1520..5c714cd84a 100644 --- a/Libraries/LibCore/Makefile +++ b/Libraries/LibCore/Makefile @@ -7,6 +7,7 @@ OBJS = \ CFile.o \ CSocket.o \ CLocalSocket.o \ + CLocalServer.o \ CTCPSocket.o \ CElapsedTimer.o \ CNotifier.o \ |