diff options
Diffstat (limited to 'louloulibs/network')
-rw-r--r-- | louloulibs/network/resolver.hpp | 2 | ||||
-rw-r--r-- | louloulibs/network/tcp_client_socket_handler.cpp | 25 | ||||
-rw-r--r-- | louloulibs/network/tcp_client_socket_handler.hpp | 7 | ||||
-rw-r--r-- | louloulibs/network/tcp_server_socket.hpp | 86 |
4 files changed, 118 insertions, 2 deletions
diff --git a/louloulibs/network/resolver.hpp b/louloulibs/network/resolver.hpp index 29e6f3a..7365f93 100644 --- a/louloulibs/network/resolver.hpp +++ b/louloulibs/network/resolver.hpp @@ -125,5 +125,3 @@ private: }; std::string addr_to_string(const struct addrinfo* rp); - - diff --git a/louloulibs/network/tcp_client_socket_handler.cpp b/louloulibs/network/tcp_client_socket_handler.cpp index f22d756..dc9221d 100644 --- a/louloulibs/network/tcp_client_socket_handler.cpp +++ b/louloulibs/network/tcp_client_socket_handler.cpp @@ -154,6 +154,25 @@ void TCPClientSocketHandler::connect(const std::string& address, const std::stri #endif this->connection_date = std::chrono::system_clock::now(); + // Get our local TCP port and store it + this->local_port = static_cast<uint16_t>(-1); + if (rp->ai_family == AF_INET6) + { + struct sockaddr_in6 a; + socklen_t l = sizeof(a); + if (::getsockname(this->socket, (struct sockaddr*)&a, &l) != -1) + this->local_port = ::ntohs(a.sin6_port); + } + else if (rp->ai_family == AF_INET) + { + struct sockaddr_in a; + socklen_t l = sizeof(a); + if (::getsockname(this->socket, (struct sockaddr*)&a, &l) != -1) + this->local_port = ::ntohs(a.sin_port); + } + + log_debug("Local port: ", this->local_port, ", and remote port: ", this->port); + this->on_connected(); return ; } @@ -231,3 +250,9 @@ std::string TCPClientSocketHandler::get_port() const { return this->port; } + +bool TCPClientSocketHandler::match_port_pairt(const uint16_t local, const uint16_t remote) const +{ + const uint16_t remote_port = static_cast<uint16_t>(std::stoi(this->port)); + return this->is_connected() && local == this->local_port && remote == remote_port; +} diff --git a/louloulibs/network/tcp_client_socket_handler.hpp b/louloulibs/network/tcp_client_socket_handler.hpp index 7dd476c..3ad8ec3 100644 --- a/louloulibs/network/tcp_client_socket_handler.hpp +++ b/louloulibs/network/tcp_client_socket_handler.hpp @@ -31,6 +31,11 @@ class TCPClientSocketHandler: public TCPSocketHandler void close() override final; std::chrono::system_clock::time_point connection_date; + /** + * Whether or not this connection is using the two given TCP ports. + */ + bool match_port_pairt(const uint16_t local, const uint16_t remote) const; + protected: bool hostname_resolution_failed; /** @@ -70,6 +75,8 @@ class TCPClientSocketHandler: public TCPSocketHandler */ std::string port; + uint16_t local_port; + bool connected; bool connecting; }; diff --git a/louloulibs/network/tcp_server_socket.hpp b/louloulibs/network/tcp_server_socket.hpp new file mode 100644 index 0000000..a54d3bf --- /dev/null +++ b/louloulibs/network/tcp_server_socket.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include <network/socket_handler.hpp> +#include <network/resolver.hpp> +#include <network/poller.hpp> + +#include <string> + +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/ip.h> + +#include <logger/logger.hpp> + +#include <cstring> +#include <cassert> + +using namespace std::string_literals; + +template <typename RemoteSocketType> +class TcpSocketServer: public SocketHandler +{ + public: + TcpSocketServer(std::shared_ptr<Poller> poller, const uint16_t port): + SocketHandler(poller, -1) + { + if ((this->socket = ::socket(AF_INET6, SOCK_STREAM, 0)) == -1) + throw std::runtime_error("Could not create socket: "s + std::strerror(errno)); + + int opt = 1; + if (::setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) + throw std::runtime_error("Failed to set socket option: "s + std::strerror(errno)); + + struct sockaddr_in6 addr{}; + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(port); + addr.sin6_addr = IN6ADDR_ANY_INIT; + if ((::bind(this->socket, (const struct sockaddr*)&addr, sizeof(addr))) == -1) + { // If we can’t listen on this port, we just give up, but this is not fatal. + log_warning("Failed to bind on port ", std::to_string(port), ": ", std::strerror(errno)); + return; + } + + if ((::listen(this->socket, 10)) == -1) + throw std::runtime_error("listen() failed"); + + this->accept(); + } + ~TcpSocketServer() = default; + + void on_recv() override + { + // Accept a RemoteSocketType + int socket = ::accept(this->socket, nullptr, nullptr); + + auto client = std::make_unique<RemoteSocketType>(poller, socket, *this); + this->poller->add_socket_handler(client.get()); + this->sockets.push_back(std::move(client)); + } + + protected: + std::vector<std::unique_ptr<RemoteSocketType>> sockets; + + private: + void accept() + { + this->poller->add_socket_handler(this); + } + void on_send() override + { + assert(false); + } + void connect() override + { + assert(false); + } + bool is_connected() const override + { + return true; + } + bool is_connecting() const override + { + return false; + } +}; |