Support the ident protocol

fix #3211
This commit is contained in:
louiz’
2016-11-15 00:23:19 +01:00
parent ed7e66471f
commit d872c2b492
14 changed files with 323 additions and 19 deletions
-2
View File
@@ -125,5 +125,3 @@ private:
};
std::string addr_to_string(const struct addrinfo* rp);
@@ -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;
}
@@ -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;
};
+86
View File
@@ -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;
}
};