diff options
author | Conrad Pankoff <deoxxa@fknsrs.biz> | 2019-08-05 20:47:30 +1000 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-05 12:53:07 +0200 |
commit | ed66f1d6d445cb9cc15421a60c85556da9e2aaed (patch) | |
tree | 72abe7a9035dcb3585818bd3e2b97ce77d665030 /Libraries/LibCore | |
parent | 79e22acb225d8aaa4d20540afa50faac17ea29bf (diff) | |
download | serenity-ed66f1d6d445cb9cc15421a60c85556da9e2aaed.zip |
LibCore: Add CTCPServer
This is pretty much a find/replace copy of CLocalServer, and some
modifications to CTCPSocket and CSocketAddress to support it.
Diffstat (limited to 'Libraries/LibCore')
-rw-r--r-- | Libraries/LibCore/CSocketAddress.h | 22 | ||||
-rw-r--r-- | Libraries/LibCore/CTCPServer.cpp | 55 | ||||
-rw-r--r-- | Libraries/LibCore/CTCPServer.h | 26 | ||||
-rw-r--r-- | Libraries/LibCore/CTCPSocket.cpp | 9 | ||||
-rw-r--r-- | Libraries/LibCore/CTCPSocket.h | 6 | ||||
-rw-r--r-- | Libraries/LibCore/Makefile | 1 |
6 files changed, 118 insertions, 1 deletions
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 <AK/IPv4Address.h> +#include <arpa/inet.h> #include <sys/socket.h> #include <sys/un.h> @@ -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 <AK/IPv4Address.h> +#include <AK/Types.h> +#include <LibCore/CTCPServer.h> +#include <LibCore/CTCPSocket.h> +#include <LibCore/CNotifier.h> +#include <stdio.h> +#include <sys/socket.h> + +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<CNotifier>(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 <AK/IPv4Address.h> +#include <LibCore/CNotifier.h> +#include <LibCore/CObject.h> + +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<void()> on_ready_to_accept; + +private: + int m_fd { -1 }; + bool m_listening { false }; + OwnPtr<CNotifier> 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 <LibCore/CTCPSocket.h> #include <sys/socket.h> +#include <errno.h> + +CTCPSocket::CTCPSocket(Badge<CTCPServer>, 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 <AK/Badge.h> #include <LibCore/CSocket.h> +class CTCPServer; + class CTCPSocket final : public CSocket { C_OBJECT(CTCPSocket) public: explicit CTCPSocket(CObject* parent = nullptr); + CTCPSocket(Badge<CTCPServer>, 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 \ |