summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-07-27 10:21:25 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-07-27 10:32:40 +0200
commitb3fe9cde523eac6f545270446078a6c6866820e1 (patch)
treef04306e3ded363922fad9784cf8e5732d3934b88
parent9b7e1eb287f8aa6c807303bf221e5498c8964960 (diff)
downloadserenity-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.cpp54
-rw-r--r--Libraries/LibCore/CLocalServer.h25
-rw-r--r--Libraries/LibCore/CLocalSocket.cpp8
-rw-r--r--Libraries/LibCore/CLocalSocket.h5
-rw-r--r--Libraries/LibCore/Makefile1
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 \