From b3fe9cde523eac6f545270446078a6c6866820e1 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 27 Jul 2019 10:21:25 +0200 Subject: [PATCH] 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. :^) --- Libraries/LibCore/CLocalServer.cpp | 54 ++++++++++++++++++++++++++++++ Libraries/LibCore/CLocalServer.h | 25 ++++++++++++++ Libraries/LibCore/CLocalSocket.cpp | 8 +++++ Libraries/LibCore/CLocalSocket.h | 5 +++ Libraries/LibCore/Makefile | 1 + 5 files changed, 93 insertions(+) create mode 100644 Libraries/LibCore/CLocalServer.cpp create mode 100644 Libraries/LibCore/CLocalServer.h 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 +#include +#include +#include +#include + +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(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 +#include + +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 on_ready_to_accept; + +private: + int m_fd { -1 }; + bool m_listening { false }; + OwnPtr 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 #include +CLocalSocket::CLocalSocket(Badge, 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 #include +class CLocalServer; + class CLocalSocket final : public CSocket { C_OBJECT(CLocalSocket) public: explicit CLocalSocket(CObject* parent = nullptr); + CLocalSocket(Badge, 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 \