summaryrefslogtreecommitdiff
path: root/louloulibs
diff options
context:
space:
mode:
Diffstat (limited to 'louloulibs')
-rw-r--r--louloulibs/network/resolver.hpp2
-rw-r--r--louloulibs/network/tcp_client_socket_handler.cpp25
-rw-r--r--louloulibs/network/tcp_client_socket_handler.hpp7
-rw-r--r--louloulibs/network/tcp_server_socket.hpp86
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;
+ }
+};