From ed66f1d6d445cb9cc15421a60c85556da9e2aaed Mon Sep 17 00:00:00 2001 From: Conrad Pankoff Date: Mon, 5 Aug 2019 20:47:30 +1000 Subject: LibCore: Add CTCPServer This is pretty much a find/replace copy of CLocalServer, and some modifications to CTCPSocket and CSocketAddress to support it. --- Libraries/LibCore/CSocketAddress.h | 22 ++++++++++++++- Libraries/LibCore/CTCPServer.cpp | 55 ++++++++++++++++++++++++++++++++++++++ Libraries/LibCore/CTCPServer.h | 26 ++++++++++++++++++ Libraries/LibCore/CTCPSocket.cpp | 9 +++++++ Libraries/LibCore/CTCPSocket.h | 6 +++++ Libraries/LibCore/Makefile | 1 + 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 Libraries/LibCore/CTCPServer.cpp create mode 100644 Libraries/LibCore/CTCPServer.h (limited to 'Libraries/LibCore') diff --git a/Libraries/LibCore/CSocketAddress.h b/Libraries/LibCore/CSocketAddress.h index 9a558a9008..07dcf1fb8f 100644 --- a/Libraries/LibCore/CSocketAddress.h +++ b/Libraries/LibCore/CSocketAddress.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -19,6 +20,13 @@ public: { } + CSocketAddress(const IPv4Address& address, u16 port) + : m_type(Type::IPv4) + , m_ipv4_address(address) + , m_port(port) + { + } + static CSocketAddress local(const String& address) { CSocketAddress addr; @@ -30,12 +38,13 @@ public: Type type() const { return m_type; } bool is_valid() const { return m_type != Type::Invalid; } IPv4Address ipv4_address() const { return m_ipv4_address; } + u16 port() const { return m_port; } String to_string() const { switch (m_type) { case Type::IPv4: - return m_ipv4_address.to_string(); + return String::format("%s:%d", m_ipv4_address.to_string().characters(), m_port); case Type::Local: return m_local_address; default: @@ -53,9 +62,20 @@ public: return address; } + sockaddr_in to_sockaddr_in() const + { + ASSERT(type() == Type::IPv4); + sockaddr_in address; + address.sin_family = AF_INET; + address.sin_addr.s_addr = m_ipv4_address.to_in_addr_t(); + address.sin_port = htons(m_port); + return address; + } + private: Type m_type { Type::Invalid }; IPv4Address m_ipv4_address; + u16 m_port; String m_local_address; }; diff --git a/Libraries/LibCore/CTCPServer.cpp b/Libraries/LibCore/CTCPServer.cpp new file mode 100644 index 0000000000..fa51156246 --- /dev/null +++ b/Libraries/LibCore/CTCPServer.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include + +CTCPServer::CTCPServer(CObject* parent) + : CObject(parent) +{ + m_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); + ASSERT(m_fd >= 0); +} + +CTCPServer::~CTCPServer() +{ +} + +bool CTCPServer::listen(const IPv4Address& address, u16 port) +{ + if (m_listening) + return false; + + int rc; + auto socket_address = CSocketAddress(address, port); + auto in = socket_address.to_sockaddr_in(); + rc = ::bind(m_fd, (const sockaddr*)&in, sizeof(in)); + 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; +} + +CTCPSocket* CTCPServer::accept() +{ + ASSERT(m_listening); + sockaddr_in in; + socklen_t in_size = sizeof(in); + int accepted_fd = ::accept(m_fd, (sockaddr*)&in, &in_size); + if (accepted_fd < 0) { + perror("accept"); + return nullptr; + } + + return new CTCPSocket({}, accepted_fd); +} diff --git a/Libraries/LibCore/CTCPServer.h b/Libraries/LibCore/CTCPServer.h new file mode 100644 index 0000000000..09b3852118 --- /dev/null +++ b/Libraries/LibCore/CTCPServer.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +class CTCPSocket; + +class CTCPServer : public CObject { + C_OBJECT(CTCPServer) +public: + explicit CTCPServer(CObject* parent = nullptr); + virtual ~CTCPServer() override; + + bool is_listening() const { return m_listening; } + bool listen(const IPv4Address& address, u16 port); + + CTCPSocket* accept(); + + Function on_ready_to_accept; + +private: + int m_fd { -1 }; + bool m_listening { false }; + OwnPtr m_notifier; +}; diff --git a/Libraries/LibCore/CTCPSocket.cpp b/Libraries/LibCore/CTCPSocket.cpp index 5f3702a482..4bfe37d4fe 100644 --- a/Libraries/LibCore/CTCPSocket.cpp +++ b/Libraries/LibCore/CTCPSocket.cpp @@ -1,5 +1,14 @@ #include #include +#include + +CTCPSocket::CTCPSocket(Badge, int fd, CObject* parent) + : CSocket(CSocket::Type::TCP, parent) +{ + set_fd(fd); + set_mode(CIODevice::ReadWrite); + set_error(0); +} CTCPSocket::CTCPSocket(CObject* parent) : CSocket(CSocket::Type::TCP, parent) diff --git a/Libraries/LibCore/CTCPSocket.h b/Libraries/LibCore/CTCPSocket.h index d7e72fb824..7eccc7a6b7 100644 --- a/Libraries/LibCore/CTCPSocket.h +++ b/Libraries/LibCore/CTCPSocket.h @@ -1,8 +1,14 @@ +#pragma once + +#include #include +class CTCPServer; + class CTCPSocket final : public CSocket { C_OBJECT(CTCPSocket) public: explicit CTCPSocket(CObject* parent = nullptr); + CTCPSocket(Badge, int fd, CObject* parent = nullptr); virtual ~CTCPSocket() override; }; diff --git a/Libraries/LibCore/Makefile b/Libraries/LibCore/Makefile index 5c714cd84a..ac7a75cdaa 100644 --- a/Libraries/LibCore/Makefile +++ b/Libraries/LibCore/Makefile @@ -9,6 +9,7 @@ OBJS = \ CLocalSocket.o \ CLocalServer.o \ CTCPSocket.o \ + CTCPServer.o \ CElapsedTimer.o \ CNotifier.o \ CHttpRequest.o \ -- cgit v1.2.3