/* * Listener.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "Listener.h" #include #include #include namespace Mad { namespace Net { void Listener::accept() { boost::shared_ptr con(Connection::create(application, context)); con->unsetStart(); acceptor.async_accept(con->socket.lowest_layer(), boost::bind(&Listener::handleAccept, this, boost::asio::placeholders::error, con)); } void Listener::handleAccept(const boost::system::error_code &error, boost::shared_ptr con) { if(error) return; boost::lock_guard lock(mutex); { boost::lock_guard conLock(con->connectionLock); con->_setState(Connection::HANDSHAKE); Core::Signals::Connection con1 = con->connectSignalConnected(boost::bind(&Listener::handleConnect, this, con)); Core::Signals::Connection con2 = con->connectSignalDisconnected(boost::bind(&Listener::handleDisconnect, this, con)); connections.insert(std::make_pair(con, std::make_pair(con1, con2))); con->socket.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&Connection::handleHandshake, con, boost::asio::placeholders::error)); } accept(); } void Listener::handleConnect(boost::shared_ptr con) { { boost::lock_guard lock(mutex); std::map, std::pair >::iterator it = connections.find(con); if(it == connections.end()) return; // Disconnect signal handlers con->disconnectSignalConnected(it->second.first); con->disconnectSignalDisconnected(it->second.second); connections.erase(it); } signal.emit(con); } void Listener::handleDisconnect(boost::shared_ptr con) { boost::lock_guard lock(mutex); connections.erase(con); } Listener::Listener(Core::Application *application0, const Core::String &x905CertFile0, const Core::String &x905KeyFile0, const boost::asio::ip::tcp::endpoint &address0) throw(Core::Exception) : application(application0), x905CertFile(x905CertFile0), x905KeyFile(x905KeyFile0), address(address0), context(new boost::asio::ssl::context(application->getIOService(), boost::asio::ssl::context::sslv23)), acceptor(application->getIOService(), address), signal(application) { context->set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); context->use_certificate_chain_file(x905CertFile.toLocale()); context->use_private_key_file(x905KeyFile.toLocale(), boost::asio::ssl::context::pem); accept(); } Listener::~Listener() { for(std::map,std::pair >::iterator con = connections.begin(); con != connections.end(); ++con) { con->first->disconnect(); con->first->waitWhileConnected(); // TODO Optimize } } } }