diff options
Diffstat (limited to 'src/Net/Listener.cpp')
-rw-r--r-- | src/Net/Listener.cpp | 95 |
1 files changed, 31 insertions, 64 deletions
diff --git a/src/Net/Listener.cpp b/src/Net/Listener.cpp index 11cbaf5..6f49a74 100644 --- a/src/Net/Listener.cpp +++ b/src/Net/Listener.cpp @@ -18,8 +18,6 @@ */ #include "Listener.h" -#include "FdManager.h" -#include "ServerConnection.h" #include <Common/Logger.h> @@ -30,26 +28,29 @@ namespace Mad { namespace Net { -void Listener::acceptHandler(int) { - int sd; - struct sockaddr_in sa; - socklen_t addrlen = sizeof(sa); +void Listener::handleAccept(const boost::system::error_code &error, boost::shared_ptr<ServerConnection> con) { + if(error) + return; + + { + boost::lock_guard<boost::shared_mutex> lock(con->connectionLock); + con->state = ServerConnection::CONNECT; - while((sd = accept(sock, (struct sockaddr*)&sa, &addrlen)) >= 0) { - ServerConnection *con = new ServerConnection(sd, IPAddress(sa), dh_params, x905CertFile, x905KeyFile); - boost::signals::connection con1 = con->signalConnected().connect(boost::bind(&Listener::connectHandler, this, con)); - boost::signals::connection con2 = con->signalDisconnected().connect(boost::bind(&Listener::disconnectHandler, this, con)); + boost::signals::connection con1 = con->signalConnected().connect(boost::bind(&Listener::handleConnect, this, con)); + boost::signals::connection con2 = con->signalDisconnected().connect(boost::bind(&Listener::handleDisconnect, this, con)); connections.insert(std::make_pair(con, std::make_pair(con1, con2))); - addrlen = sizeof(sa); + con->socket.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&ServerConnection::handleHandshake, con, boost::asio::placeholders::error)); } -} + con.reset(new ServerConnection(sslContext)); + acceptor.async_accept(con->socket.lowest_layer(), boost::bind(&Listener::handleAccept, this, boost::asio::placeholders::error, con)); +} -void Listener::connectHandler(ServerConnection *con) { - std::map<ServerConnection*, std::pair<boost::signals::connection, boost::signals::connection> >::iterator it = connections.find(con); +void Listener::handleConnect(boost::shared_ptr<ServerConnection> con) { + std::map<boost::shared_ptr<ServerConnection>, std::pair<boost::signals::connection, boost::signals::connection> >::iterator it = connections.find(con); if(it == connections.end()) return; @@ -62,67 +63,33 @@ void Listener::connectHandler(ServerConnection *con) { signal(con); } -void Listener::disconnectHandler(ServerConnection *con) { - std::map<ServerConnection*, std::pair<boost::signals::connection, boost::signals::connection> >::iterator it = connections.find(con); - - if(it == connections.end()) - return; - - delete it->first; - connections.erase(it); +void Listener::handleDisconnect(boost::shared_ptr<ServerConnection> con) { + connections.erase(con); } -Listener::Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, const IPAddress &address0) throw(Exception) -: x905CertFile(x905CertFile0), x905KeyFile(x905KeyFile0), address(address0) { - gnutls_dh_params_init(&dh_params); - gnutls_dh_params_generate2(dh_params, 768); +Listener::Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, + const boost::asio::ip::tcp::endpoint &address0) throw(Exception) +: x905CertFile(x905CertFile0), x905KeyFile(x905KeyFile0), address(address0), acceptor(Connection::ioService, address), +sslContext(Connection::ioService, boost::asio::ssl::context::sslv23) +{ + sslContext.set_options(boost::asio::ssl::context::default_workarounds + | boost::asio::ssl::context::no_sslv2 + | boost::asio::ssl::context::single_dh_use); + sslContext.use_certificate_chain_file(x905CertFile0); + sslContext.use_private_key_file(x905KeyFile0, boost::asio::ssl::context::pem); - sock = socket(PF_INET, SOCK_STREAM, 0); - if(sock < 0) - throw Exception("socket()", Exception::INTERNAL_ERRNO, errno); - // Set non-blocking flag - int flags = fcntl(sock, F_GETFL, 0); - - if(flags < 0) { - close(sock); - - throw Exception("fcntl()", Exception::INTERNAL_ERRNO, errno); - } - - fcntl(sock, F_SETFL, flags | O_NONBLOCK); - - // Don't linger - struct linger linger = {1, 0}; - setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); - - if(bind(sock, address.getSockAddr(), address.getSockAddrLength()) < 0) { - close(sock); - - throw Exception("bind()", Exception::INTERNAL_ERRNO, errno); - } - - if(listen(sock, 64) < 0) { - close(sock); - - throw Exception("listen()", Exception::INTERNAL_ERRNO, errno); - } - - FdManager::get()->registerFd(sock, boost::bind(&Listener::acceptHandler, this, _1), POLLIN); + boost::shared_ptr<ServerConnection> con(new ServerConnection(sslContext)); + acceptor.async_accept(con->socket.lowest_layer(), boost::bind(&Listener::handleAccept, this, boost::asio::placeholders::error, con)); } Listener::~Listener() { - for(std::map<ServerConnection*,std::pair<boost::signals::connection, boost::signals::connection> >::iterator con = connections.begin(); con != connections.end(); ++con) { + for(std::map<boost::shared_ptr<ServerConnection>,std::pair<boost::signals::connection, boost::signals::connection> >::iterator con = connections.begin(); con != connections.end(); ++con) { con->first->disconnect(); - delete con->first; + // TODO wait... } - - shutdown(sock, SHUT_RDWR); - close(sock); - - gnutls_dh_params_deinit(dh_params); } } |