From 776377bb21ee1cfe0bcdbc000f7c6fa0be227226 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 20 May 2009 01:08:16 +0200 Subject: Netzwerk-Code auf boost::asio umgestellt --- src/Net/CMakeLists.txt | 6 +- src/Net/ClientConnection.cpp | 87 ++--------- src/Net/ClientConnection.h | 23 +-- src/Net/Connection.cpp | 364 ++++++++++++++----------------------------- src/Net/Connection.h | 144 ++++++----------- src/Net/Exception.cpp | 3 - src/Net/Exception.h | 2 +- src/Net/FdManager.cpp | 174 --------------------- src/Net/FdManager.h | 77 --------- src/Net/IPAddress.cpp | 92 ----------- src/Net/IPAddress.h | 58 ------- src/Net/Listener.cpp | 95 ++++------- src/Net/Listener.h | 41 +++-- src/Net/ServerConnection.cpp | 90 ----------- src/Net/ServerConnection.h | 57 ------- src/Net/ThreadManager.cpp | 14 +- src/Net/ThreadManager.h | 6 +- 17 files changed, 259 insertions(+), 1074 deletions(-) delete mode 100644 src/Net/FdManager.cpp delete mode 100644 src/Net/FdManager.h delete mode 100644 src/Net/IPAddress.cpp delete mode 100644 src/Net/IPAddress.h delete mode 100644 src/Net/ServerConnection.cpp delete mode 100644 src/Net/ServerConnection.h (limited to 'src/Net') diff --git a/src/Net/CMakeLists.txt b/src/Net/CMakeLists.txt index aa3f857..fae358b 100644 --- a/src/Net/CMakeLists.txt +++ b/src/Net/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(${INCLUDES}) link_directories(${Boost_LIBRARY_DIRS}) add_library(Net - ClientConnection.cpp Connection.cpp Exception.cpp FdManager.cpp IPAddress.cpp - Listener.cpp Packet.cpp ServerConnection.cpp ThreadManager.cpp + ClientConnection.cpp Connection.cpp Exception.cpp Listener.cpp + Packet.cpp ThreadManager.cpp ) -target_link_libraries(Net ${Boost_LIBRARIES} ${GNUTLS_LIBRARIES}) +target_link_libraries(Net ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES}) diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp index 087d95f..9cdf796 100644 --- a/src/Net/ClientConnection.cpp +++ b/src/Net/ClientConnection.cpp @@ -18,99 +18,36 @@ */ #include "ClientConnection.h" -#include "FdManager.h" -#include "IPAddress.h" -#include - -#include -#include -#include -#include +#include namespace Mad { namespace Net { -// TODO Error handling -void ClientConnection::connectionHeaderReceiveHandler(const void *data, unsigned long length) { - if(length != sizeof(ConnectionHeader)) - // Error... disconnect - return; - - const ConnectionHeader *header = (const ConnectionHeader*)(data); - - if(header->m != 'M' || header->a != 'A' || header->d != 'D') - // Error... disconnect +void ClientConnection::handleConnect(const boost::system::error_code& error) { + if(error) { + // TODO Error handling + doDisconnect(); return; + } - if(header->protVerMin != 1) - // Unsupported protocol... disconnect - return; - - enterReceiveLoop(); -} - -void ClientConnection::connectionHeader() { - ConnectionHeader header = {'M', 'A', 'D', daemon ? 'D' : 'C', 0, 1, 1, 1}; + boost::lock_guard lock(connectionLock); - rawSend((uint8_t*)&header, sizeof(header)); - rawReceive(sizeof(ConnectionHeader), boost::bind(&ClientConnection::connectionHeaderReceiveHandler, this, _1, _2)); + socket.async_handshake(boost::asio::ssl::stream_base::client, boost::bind(&ClientConnection::handleHandshake, this, boost::asio::placeholders::error)); } -void ClientConnection::connect(const IPAddress &address, bool daemon0) throw(Exception) { - boost::unique_lock lock(stateLock); - - daemon = daemon0; +void ClientConnection::connect(const boost::asio::ip::tcp::endpoint &address) throw(Exception) { + boost::lock_guard lock(connectionLock); if(_isConnected()) { return; // TODO Error } - sock = socket(PF_INET, SOCK_STREAM, 0); - if(sock < 0) { - throw Exception("socket()", Exception::INTERNAL_ERRNO, errno); - } - - if(peer) - delete peer; - peer = new IPAddress(address); - - if(::connect(sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) { - close(sock); - delete peer; - peer = 0; - - throw Exception("connect()", 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)); - - gnutls_init(&session, GNUTLS_CLIENT); - gnutls_set_default_priority(session); - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); - gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)sock); - - FdManager::get()->registerFd(sock, boost::bind(&ClientConnection::sendReceive, this, _1)); - + peer = address; state = CONNECT; - lock.unlock(); - - updateEvents(); + socket.lowest_layer().async_connect(address, boost::bind(&ClientConnection::handleConnect, this, boost::asio::placeholders::error)); } } diff --git a/src/Net/ClientConnection.h b/src/Net/ClientConnection.h index bdd7872..f93c2fc 100644 --- a/src/Net/ClientConnection.h +++ b/src/Net/ClientConnection.h @@ -23,24 +23,27 @@ #include "Connection.h" #include "Exception.h" +#include + + namespace Mad { namespace Net { class IPAddress; -class ClientConnection : public Connection { +class ClientConnection : private boost::base_from_member, public Connection { private: - bool daemon; - - void connectionHeaderReceiveHandler(const void *data, unsigned long length); - - protected: - virtual void connectionHeader(); + void handleConnect(const boost::system::error_code& error); public: - ClientConnection() : daemon(0) {} - - void connect(const IPAddress &address, bool daemon0 = false) throw(Exception); + ClientConnection() + : boost::base_from_member(boost::ref(Connection::ioService), boost::asio::ssl::context::sslv23), + Connection(member) + { + member.set_verify_mode(boost::asio::ssl::context::verify_none); + } + + void connect(const boost::asio::ip::tcp::endpoint &address) throw(Exception); }; } diff --git a/src/Net/Connection.cpp b/src/Net/Connection.cpp index 4e5029f..b9691cb 100644 --- a/src/Net/Connection.cpp +++ b/src/Net/Connection.cpp @@ -18,361 +18,225 @@ */ #include "Connection.h" -#include "FdManager.h" -#include "IPAddress.h" #include "ThreadManager.h" -#include -#include +#include +#include #include namespace Mad { namespace Net { - -Connection::StaticInit Connection::staticInit; +boost::asio::io_service Connection::ioService; Connection::~Connection() { if(_isConnected()) doDisconnect(); - - if(transR.data) - delete [] transR.data; - - while(!_sendQueueEmpty()) { - delete [] transS.front().data; - transS.pop(); - } - - gnutls_certificate_free_credentials(x509_cred); - - if(peer) - delete peer; -} - -void Connection::handshake() { - boost::unique_lock lock(stateLock); - if(state != CONNECT) - return; - - state = HANDSHAKE; - lock.unlock(); - - doHandshake(); } -void Connection::bye() { - boost::unique_lock lock(stateLock); - if(state != DISCONNECT) - return; - - state = BYE; - lock.unlock(); +void Connection::handleHandshake(const boost::system::error_code& error) { + if(error) { + Common::Logger::logf("Error: %s", error.message().c_str()); - doBye(); -} - -void Connection::doHandshake() { - boost::shared_lock lock(stateLock); - if(state != HANDSHAKE) + // TODO Error handling + doDisconnect(); return; + } - int ret = gnutls_handshake(session); - if(ret < 0) { - lock.unlock(); + { + boost::lock_guard lock(connectionLock); + state = CONNECTED; - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { - updateEvents(); - return; - } + receiving = false; + sending = 0; - // TODO: Error - doDisconnect(); - return; + received = 0; } - state = CONNECTION_HEADER; - lock.unlock(); + ThreadManager::get()->pushWork(boost::bind((void (boost::signal0::*)())&boost::signal0::operator(), &connectedSignal)); - connectionHeader(); + enterReceiveLoop(); } -void Connection::doBye() { - if(state != BYE) - return; - - int ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); - if(ret < 0) { - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { - updateEvents(); - return; - } +void Connection::handleShutdown(const boost::system::error_code& error) { + boost::lock_guard lock(connectionLock); - // TODO: Error - doDisconnect(); - return; + if(error) { + // TODO Error } - doDisconnect(); + state = DISCONNECTED; + ThreadManager::get()->pushWork(boost::bind((void (boost::signal0::*)())&boost::signal0::operator(), &disconnectedSignal)); } void Connection::enterReceiveLoop() { - boost::unique_lock lock(stateLock); - - if(!_isConnected() || _isDisconnecting()) - return; - - if(_isConnecting()) - ThreadManager::get()->pushWork(boost::bind((void (boost::signal0::*)())&boost::signal0::operator(), &connectedSignal)); + { + boost::lock_guard lock(connectionLock); - state = PACKET_HEADER; - lock.unlock(); + if(!_isConnected() || _isDisconnecting()) + return; + } - rawReceive(sizeof(Packet::Data), boost::bind(&Connection::packetHeaderReceiveHandler, this, _1, _2)); + rawReceive(sizeof(Packet::Data), boost::bind(&Connection::handleHeaderReceive, this, _1)); } -void Connection::packetHeaderReceiveHandler(const void *data, unsigned long length) { - if(state != PACKET_HEADER) - return; +void Connection::handleHeaderReceive(const std::vector &data) { + { + boost::lock_guard lock(connectionLock); - if(length != sizeof(Packet::Data)) { - // TODO: Error - doDisconnect(); - return; + header = *reinterpret_cast(data.data()); } - header = *(const Packet::Data*)data; - if(header.length == 0) { ThreadManager::get()->pushWork(boost::bind((void (boost::signal1::*)(const Packet&))&boost::signal1::operator(), &receiveSignal, Packet(ntohs(header.requestId)))); enterReceiveLoop(); } else { - state = PACKET_DATA; - rawReceive(ntohs(header.length), boost::bind(&Connection::packetDataReceiveHandler, this, _1, _2)); + rawReceive(ntohs(header.length), boost::bind(&Connection::handleDataReceive, this, _1)); } } -void Connection::packetDataReceiveHandler(const void *data, unsigned long length) { - if(state != PACKET_DATA) - return; +void Connection::handleDataReceive(const std::vector &data) { + { + boost::upgrade_lock lock(connectionLock); - if(length != ntohs(header.length)) { - // TODO: Error - doDisconnect(); - return; + Packet packet(ntohs(header.requestId), data.data(), ntohs(header.length)); + ThreadManager::get()->pushWork(boost::bind((void (boost::signal1::*)(const Packet&))&boost::signal1::operator(), &receiveSignal, packet)); } - ThreadManager::get()->pushWork(boost::bind((void (boost::signal1::*)(const Packet&))&boost::signal1::operator(), &receiveSignal, Packet(ntohs(header.requestId), data, length))); - enterReceiveLoop(); } -void Connection::doReceive() { - if(!isConnected()) - return; - - boost::unique_lock lock(receiveLock); - - if(_receiveComplete()) - return; - - ssize_t ret = gnutls_record_recv(session, transR.data+transR.transmitted, transR.length-transR.transmitted); +void Connection::handleRead(const boost::system::error_code& error, std::size_t bytes_transferred, std::size_t length, const boost::function1& > ¬ify) { + if(error || (bytes_transferred+received) < length) { + Common::Logger::logf(Common::Logger::VERBOSE, "Read error: %s", error.message().c_str()); - if(ret < 0) { - lock.unlock(); - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) - return; - - // TODO: Error + // TODO Error doDisconnect(); return; } - transR.transmitted += ret; - - if(_receiveComplete()) { - // Save data pointer, as transR.notify might start a new reception - uint8_t *data = transR.data; - transR.data = 0; + std::vector buffer; - lock.unlock(); + { + boost::shared_lock lock(connectionLock); - transR.notify(data, transR.length); + if(state != CONNECTED || !receiving) + return; - delete [] data; - } - else { - lock.unlock(); + buffer.insert(buffer.end(), receiveBuffer.data(), receiveBuffer.data()+length); } - updateEvents(); -} - -bool Connection::rawReceive(unsigned long length, - const boost::function2 ¬ify) -{ - if(!isConnected()) - return false; - - boost::unique_lock lock(receiveLock); - if(!_receiveComplete()) - return false; - - transR.data = new uint8_t[length]; - transR.length = length; - transR.transmitted = 0; - transR.notify = notify; + { + boost::lock_guard lock(connectionLock); - lock.unlock(); + receiving = false; + received = received + bytes_transferred - length; - updateEvents(); + if(received) + std::memmove(receiveBuffer.data(), receiveBuffer.data()+length, received); + } - return true; + notify(buffer); } -void Connection::doSend() { - if(!isConnected()) - return; +void Connection::rawReceive(std::size_t length, const boost::function1& > ¬ify) { + boost::upgrade_lock lock(connectionLock); - boost::unique_lock lock(sendLock); - while(!_sendQueueEmpty()) { - ssize_t ret = gnutls_record_send(session, transS.front().data+transS.front().transmitted, - transS.front().length-transS.front().transmitted); - - if(ret < 0) { - lock.unlock(); + if(!_isConnected()) + return; - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) - return; + { + boost::upgrade_to_unique_lock upgradeLock(lock); - // TODO: Error - doDisconnect(); + if(receiving) return; - } - transS.front().transmitted += ret; + receiving = true; - if(transS.front().transmitted == transS.front().length) { - delete [] transS.front().data; - transS.pop(); + if(length > received) { + boost::asio::async_read(socket, boost::asio::buffer(receiveBuffer.data()+received, receiveBuffer.size()-received), boost::asio::transfer_at_least(length), + boost::bind(&Connection::handleRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, + length, notify)); + + return; } } lock.unlock(); - updateEvents(); + handleRead(boost::system::error_code(), 0, length, notify); } -bool Connection::rawSend(const uint8_t *data, unsigned long length) { - if(!isConnected()) - return false; +void Connection::handleWrite(const boost::system::error_code& error, std::size_t) { + { + boost::unique_lock lock(connectionLock); - Transmission trans = {length, 0, new uint8_t[length], boost::function2()}; - std::memcpy(trans.data, data, length); + sending--; - sendLock.lock(); - transS.push(trans); - sendLock.unlock(); - - updateEvents(); + if(state == DISCONNECT && !sending) { + lock.unlock(); + doDisconnect(); + return; + } + } - return true; -} + if(error) { + Common::Logger::logf(Common::Logger::VERBOSE, "Write error: %s", error.message().c_str()); -void Connection::sendReceive(short events) { - if(events & POLLHUP || events & POLLERR) { + // TODO Error doDisconnect(); - return; } +} - switch(state) { - case CONNECT: - handshake(); - return; - case HANDSHAKE: - doHandshake(); - return; - case DISCONNECT: - if(!_sendQueueEmpty()) - break; +void Connection::rawSend(const uint8_t *data, std::size_t length) { + boost::upgrade_lock lock(connectionLock); - bye(); - return; - case BYE: - doBye(); - return; - default: - break; - } + if(!_isConnected()) + return; - if(events & POLLIN) - doReceive(); + { + boost::upgrade_to_unique_lock upgradeLock(lock); - if(events & POLLOUT) - doSend(); + sending++; + boost::asio::async_write(socket, Buffer(data, length), boost::bind(&Connection::handleWrite, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } } bool Connection::send(const Packet &packet) { - stateLock.lock_shared(); - bool err = (!_isConnected() || _isConnecting() || _isDisconnecting()); - stateLock.unlock_shared(); - - if(err) - return false; + { + boost::shared_lock lock(connectionLock); + if(!_isConnected() || _isConnecting() || _isDisconnecting()) + return false; + } - return rawSend((const uint8_t*)packet.getRawData(), packet.getRawDataLength()); + rawSend((const uint8_t*)packet.getRawData(), packet.getRawDataLength()); + return true; } void Connection::disconnect() { - boost::unique_lock lock(stateLock); - if(!_isConnected() || _isDisconnecting()) - return; + { + boost::lock_guard lock(connectionLock); + if(!_isConnected() || _isDisconnecting()) + return; - state = DISCONNECT; + state = DISCONNECT; - lock.unlock(); + if(sending) + return; + } - updateEvents(); + doDisconnect(); } void Connection::doDisconnect() { - boost::unique_lock lock(stateLock); - - if(_isConnected()) { - FdManager::get()->unregisterFd(sock); - - shutdown(sock, SHUT_RDWR); - close(sock); + boost::lock_guard lock(connectionLock); - gnutls_deinit(session); - - ThreadManager::get()->pushWork(boost::bind((void (boost::signal0::*)())&boost::signal0::operator(), &disconnectedSignal)); - - state = DISCONNECTED; - } -} - -void Connection::updateEvents() { - receiveLock.lock(); - short events = (_receiveComplete() ? 0 : POLLIN); - receiveLock.unlock(); - - sendLock.lock(); - events |= (_sendQueueEmpty() ? 0 : POLLOUT); - sendLock.unlock(); - - stateLock.lock_shared(); - if(state == HANDSHAKE || state == BYE) - events = ((gnutls_record_get_direction(session) == 0) ? POLLIN : POLLOUT); - else if(state == CONNECT || state == DISCONNECT) - events |= POLLOUT; - - FdManager::get()->setFdEvents(sock, events); - stateLock.unlock_shared(); + if(_isConnected()) + socket.async_shutdown(boost::bind(&Connection::handleShutdown, this, boost::asio::placeholders::error)); } } diff --git a/src/Net/Connection.h b/src/Net/Connection.h index a0b95ea..303485d 100644 --- a/src/Net/Connection.h +++ b/src/Net/Connection.h @@ -24,155 +24,111 @@ #include "Packet.h" -#include -#include -#include -#include +#include +#include #include -#include -#include -#include +#include namespace Mad { namespace Net { -class IPAddress; -class Packet; +class ThreadManager; -class Connection { +class Connection : boost::noncopyable { private: - class StaticInit { - public: - StaticInit() { - gnutls_global_init(); - } + friend class ThreadManager; - ~StaticInit() { - gnutls_global_deinit(); - } - }; - static StaticInit staticInit; + class Buffer { + public: + Buffer(const uint8_t *data0, std::size_t length) : data(new std::vector(data0, data0+length)), buffer(boost::asio::buffer(*data)) {} - struct Transmission { - unsigned long length; - unsigned long transmitted; + typedef boost::asio::const_buffer value_type; + typedef const boost::asio::const_buffer* const_iterator; - uint8_t *data; + const boost::asio::const_buffer* begin() const { return &buffer; } + const boost::asio::const_buffer* end() const { return &buffer + 1; } - boost::function2 notify; + private: + boost::shared_ptr > data; + boost::asio::const_buffer buffer; }; - boost::mutex receiveLock; - Transmission transR; - boost::mutex sendLock; - std::queue transS; + std::vector receiveBuffer; + std::size_t received; Packet::Data header; - boost::signal1 receiveSignal; + boost::signal1 receiveSignal; boost::signal0 connectedSignal; boost::signal0 disconnectedSignal; - void doHandshake(); - - void packetHeaderReceiveHandler(const void *data, unsigned long length); - void packetDataReceiveHandler(const void *data, unsigned long length); + bool receiving; + unsigned long sending; - void doReceive(); - void doSend(); - - void doBye(); - - void doDisconnect(); + void enterReceiveLoop(); - bool _receiveComplete() const { - return (transR.length == transR.transmitted); - } + void handleHeaderReceive(const std::vector &data); + void handleDataReceive(const std::vector &data); - bool _sendQueueEmpty() const {return transS.empty();} + void handleRead(const boost::system::error_code& error, std::size_t bytes_transferred, std::size_t length, const boost::function1& > ¬ify); + void handleWrite(const boost::system::error_code& error, std::size_t); - void bye(); + void handleShutdown(const boost::system::error_code& error); - // Prevent shallow copy - Connection(const Connection &o); - Connection& operator=(const Connection &o); + void rawReceive(std::size_t length, const boost::function1& > ¬ify); + void rawSend(const uint8_t *data, std::size_t length); protected: - struct ConnectionHeader { - uint8_t m; - uint8_t a; - uint8_t d; - uint8_t type; - - uint8_t versionMajor; - uint8_t versionMinor; - uint8_t protVerMin; - uint8_t protVerMax; - }; + static boost::asio::io_service ioService; - boost::shared_mutex stateLock; + boost::shared_mutex connectionLock; enum State { - DISCONNECTED, CONNECT, HANDSHAKE, CONNECTION_HEADER, PACKET_HEADER, PACKET_DATA, DISCONNECT, BYE + DISCONNECTED, CONNECT, CONNECTED, DISCONNECT } state; - int sock; - gnutls_session_t session; - gnutls_certificate_credentials_t x509_cred; - IPAddress *peer; + boost::asio::ssl::stream socket; + boost::asio::ip::tcp::endpoint peer; - void handshake(); - - virtual void connectionHeader() = 0; - - bool rawReceive(unsigned long length, const boost::function2 ¬ify); - bool rawSend(const uint8_t *data, unsigned long length); - - void enterReceiveLoop(); - - void sendReceive(short events); + void handleHandshake(const boost::system::error_code& error); bool _isConnected() const {return (state != DISCONNECTED);} bool _isConnecting() const { - return (state == CONNECT || state == HANDSHAKE || state == CONNECTION_HEADER); + return (state == CONNECT); } bool _isDisconnecting() const { - return (state == DISCONNECT || state == BYE); + return (state == DISCONNECT); } - void updateEvents(); - - public: - Connection() : state(DISCONNECTED), peer(0) { - transR.length = transR.transmitted = 0; - transR.data = 0; + void doDisconnect(); - gnutls_certificate_allocate_credentials(&x509_cred); - } + Connection(boost::asio::ssl::context &sslContext) : + receiveBuffer(1024*1024), state(DISCONNECTED), socket(ioService, sslContext) {} + public: virtual ~Connection(); bool isConnected() { - boost::shared_lock lock(stateLock); + boost::shared_lock lock(connectionLock); return _isConnected(); } bool isConnecting() { - boost::shared_lock lock(stateLock); + boost::shared_lock lock(connectionLock); return _isConnecting(); } bool isDisconnecting() { - boost::shared_lock lock(stateLock); + boost::shared_lock lock(connectionLock); return _isDisconnecting(); } - const gnutls_datum_t* getCertificate() const { + /*const gnutls_datum_t* getCertificate() const { // TODO Thread-safeness return gnutls_certificate_get_ours(session); } @@ -181,16 +137,18 @@ class Connection { // TODO Thread-safeness unsigned int n; return gnutls_certificate_get_peers(session, &n); - } + }*/ - // TODO Thread-safeness - const IPAddress* getPeer() const {return peer;} + boost::asio::ip::tcp::endpoint getPeer() { + boost::shared_lock lock(connectionLock); + return peer; + } void disconnect(); bool send(const Packet &packet); - boost::signal1& signalReceive() {return receiveSignal;} + boost::signal1& signalReceive() {return receiveSignal;} boost::signal0& signalConnected() {return connectedSignal;} boost::signal0& signalDisconnected() {return disconnectedSignal;} }; diff --git a/src/Net/Exception.cpp b/src/Net/Exception.cpp index 34b8033..e082948 100644 --- a/src/Net/Exception.cpp +++ b/src/Net/Exception.cpp @@ -20,7 +20,6 @@ #include "Exception.h" #include -#include namespace Mad { namespace Net { @@ -46,8 +45,6 @@ std::string Exception::strerror() const { return ret + "Not implemented"; case INTERNAL_ERRNO: return ret + std::strerror(subCode); - case INTERNAL_GNUTLS: - return ret + "GnuTLS error: " + gnutls_strerror(subCode); case INVALID_ADDRESS: return ret + "Invalid address"; case ALREADY_IDENTIFIED: diff --git a/src/Net/Exception.h b/src/Net/Exception.h index 48e86d1..8522528 100644 --- a/src/Net/Exception.h +++ b/src/Net/Exception.h @@ -29,7 +29,7 @@ class Exception { public: enum ErrorCode { SUCCESS = 0x0000, UNEXPECTED_PACKET = 0x0001, INVALID_ACTION = 0x0002, NOT_AVAILABLE = 0x0003, NOT_FINISHED = 0x0004, NOT_IMPLEMENTED = 0x0005, - INTERNAL_ERRNO = 0x0010, INTERNAL_GNUTLS = 0x0011, + INTERNAL_ERRNO = 0x0010, INVALID_ADDRESS = 0x0020, ALREADY_IDENTIFIED = 0x0030, UNKNOWN_DAEMON = 0x0031 }; diff --git a/src/Net/FdManager.cpp b/src/Net/FdManager.cpp deleted file mode 100644 index d8faef4..0000000 --- a/src/Net/FdManager.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * FdManager.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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "FdManager.h" -#include "ThreadManager.h" - -#include -#include -#include - - -namespace Mad { -namespace Net { - -FdManager FdManager::fdManager; - - -FdManager::FdManager() : running(false) { - pipe(interruptPipe); - - int flags = fcntl(interruptPipe[0], F_GETFL, 0); - fcntl(interruptPipe[0], F_SETFL, flags | O_NONBLOCK); - - flags = fcntl(interruptPipe[1], F_GETFL, 0); - fcntl(interruptPipe[1], F_SETFL, flags | O_NONBLOCK); - - registerFd(interruptPipe[0], boost::bind(&FdManager::readInterrupt, this), POLLIN); -} - -FdManager::~FdManager() { - unregisterFd(interruptPipe[0]); - - close(interruptPipe[0]); - close(interruptPipe[1]); -} - - -bool FdManager::registerFd(int fd, const boost::function1 &handler, short events) { - struct pollfd pollfd = {fd, events, 0}; - - boost::lock(handlerLock, eventLock); - pollfds.insert(std::make_pair(fd, pollfd)); - - bool ret = handlers.insert(std::make_pair(fd, handler)).second; - - eventLock.unlock(); - handlerLock.unlock(); - - interrupt(); - - return ret; -} - -bool FdManager::unregisterFd(int fd) { - boost::lock(handlerLock, eventLock); - pollfds.erase(fd); - bool ret = handlers.erase(fd); - eventLock.unlock(); - handlerLock.unlock(); - - interrupt(); - - return ret; -} - -bool FdManager::setFdEvents(int fd, short events) { - boost::unique_lock lock(eventLock); - - std::map::iterator pollfd = pollfds.find(fd); - - if(pollfd == pollfds.end()) - return false; - - if(pollfd->second.events != events) { - pollfd->second.events = events; - interrupt(); - } - - return true; -} - -short FdManager::getFdEvents(int fd) { - boost::shared_lock lock(eventLock); - - std::map::const_iterator pollfd = pollfds.find(fd); - - if(pollfd == pollfds.end()) - return -1; - - return pollfd->second.events; -} - -void FdManager::readInterrupt() { - char buf[20]; - - while(read(interruptPipe[0], buf, sizeof(buf)) > 0) {} -} - -void FdManager::interrupt() { - char buf = 0; - - write(interruptPipe[1], &buf, sizeof(buf)); -} - -void FdManager::ioThread() { - runLock.lock(); - running = true; - runLock.unlock_and_lock_shared(); - - while(running) { - runLock.unlock_shared(); - - handlerLock.lock_shared(); - eventLock.lock_shared(); - readInterrupt(); - - size_t count = pollfds.size(); - struct pollfd *fdarray = new struct pollfd[count]; - - std::map::iterator pollfd = pollfds.begin(); - - for(size_t n = 0; n < count; ++n) { - fdarray[n] = pollfd->second; - ++pollfd; - } - - eventLock.unlock_shared(); - handlerLock.unlock_shared(); - - if(poll(fdarray, count, -1) > 0) { - handlerLock.lock_shared(); - - std::queue > calls; - - for(size_t n = 0; n < count; ++n) { - if(fdarray[n].revents) - calls.push(boost::bind(handlers[fdarray[n].fd], fdarray[n].revents)); - } - - handlerLock.unlock_shared(); - - while(!calls.empty()) { - calls.front()(); - calls.pop(); - } - - } - - delete [] fdarray; - - runLock.lock_shared(); - } - - runLock.unlock_shared(); -} - -} -} diff --git a/src/Net/FdManager.h b/src/Net/FdManager.h deleted file mode 100644 index 1cb95bc..0000000 --- a/src/Net/FdManager.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * FdManager.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_NET_FDMANAGER_H_ -#define MAD_NET_FDMANAGER_H_ - -#include -#include - -#include -#include - -namespace Mad { -namespace Net { - -class ThreadManager; - -class FdManager { - private: - friend class ThreadManager; - - static FdManager fdManager; - - boost::shared_mutex runLock, handlerLock, eventLock; - bool running; - - std::map pollfds; - std::map > handlers; - - int interruptPipe[2]; - - void readInterrupt(); - void interrupt(); - - FdManager(); - - void ioThread(); - void stopIOThread() { - runLock.lock(); - running = false; - runLock.unlock(); - - interrupt(); - } - - public: - virtual ~FdManager(); - - static FdManager *get() {return &fdManager;} - - bool registerFd(int fd, const boost::function1 &handler, short events = 0); - bool unregisterFd(int fd); - - bool setFdEvents(int fd, short events); - short getFdEvents(int fd); -}; - -} -} - -#endif /* MAD_NET_FDMANAGER_H_ */ diff --git a/src/Net/IPAddress.cpp b/src/Net/IPAddress.cpp deleted file mode 100644 index eb9d3be..0000000 --- a/src/Net/IPAddress.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * IPAddress.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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "IPAddress.h" - -#include - -namespace Mad { -namespace Net { - -IPAddress::IPAddress(uint16_t port0) : addr(INADDR_ANY), port(port0) { - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr.s_addr = INADDR_ANY; -} - -IPAddress::IPAddress(uint32_t address, uint16_t port0) : addr(address), port(port0) { - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr.s_addr = htonl(addr); -} - -IPAddress::IPAddress(const std::string &address) throw(Exception) { - std::string ip; - size_t pos = address.find_first_of(':'); - - if(pos == std::string::npos) { - ip = address; - // TODO Default port - port = 6666; - } - else { - ip = address.substr(0, pos); - - char *endptr; - port = std::strtol(address.substr(pos+1).c_str(), &endptr, 10); - if(*endptr != 0 || port == 0) - throw Exception(Exception::INVALID_ADDRESS); - } - - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - - if(ip == "*") - sa.sin_addr.s_addr = INADDR_ANY; - else if(!inet_pton(AF_INET, ip.c_str(), &sa.sin_addr)) - throw Exception(Exception::INVALID_ADDRESS); - - addr = ntohl(sa.sin_addr.s_addr); -} - -IPAddress::IPAddress(const std::string &address, uint16_t port0) throw(Exception) : port(port0) { - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - - if(!inet_pton(AF_INET, address.c_str(), &sa.sin_addr)) - throw Exception(Exception::INVALID_ADDRESS); - - addr = ntohl(sa.sin_addr.s_addr); -} - -IPAddress::IPAddress(const struct sockaddr_in &address) : sa(address) { - port = ntohs(sa.sin_port); - addr = ntohl(sa.sin_addr.s_addr); -} - -std::string IPAddress::getAddressString() const { - char buf[INET_ADDRSTRLEN]; - uint32_t address = htonl(addr); - - inet_ntop(AF_INET, &address, buf, sizeof(buf)); - return std::string(buf); -} - -} -} diff --git a/src/Net/IPAddress.h b/src/Net/IPAddress.h deleted file mode 100644 index 3541891..0000000 --- a/src/Net/IPAddress.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * IPAddress.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_NET_IPADDRESS_H_ -#define MAD_NET_IPADDRESS_H_ - -#include "Exception.h" - -#include -#include -#include - -namespace Mad { -namespace Net { - -class IPAddress { - private: - uint32_t addr; - uint16_t port; - struct sockaddr_in sa; - - public: - // TODO Default port - IPAddress(uint16_t port0 = 6666); - IPAddress(uint32_t address, uint16_t port0); - IPAddress(const std::string &address) throw(Exception); - IPAddress(const std::string &address, uint16_t port0) throw(Exception); - IPAddress(const struct sockaddr_in &address); - - uint32_t getAddress() const {return addr;} - uint16_t getPort() const {return port;} - - std::string getAddressString() const; - - struct sockaddr* getSockAddr() {return (struct sockaddr*)&sa;} - socklen_t getSockAddrLength() const {return sizeof(sa);} -}; - -} -} - -#endif /*MAD_NET_IPADDRESS_H_*/ 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 @@ -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 con) { + if(error) + return; + + { + boost::lock_guard 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 >::iterator it = connections.find(con); +void Listener::handleConnect(boost::shared_ptr con) { + std::map, std::pair >::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 >::iterator it = connections.find(con); - - if(it == connections.end()) - return; - - delete it->first; - connections.erase(it); +void Listener::handleDisconnect(boost::shared_ptr 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 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 >::iterator con = connections.begin(); con != connections.end(); ++con) { + for(std::map,std::pair >::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); } } diff --git a/src/Net/Listener.h b/src/Net/Listener.h index 26dffab..0833cdf 100644 --- a/src/Net/Listener.h +++ b/src/Net/Listener.h @@ -20,46 +20,45 @@ #ifndef MAD_NET_LISTENER_H_ #define MAD_NET_LISTENER_H_ -#include "IPAddress.h" - -#include #include #include -#include +#include "Connection.h" +#include "Exception.h" namespace Mad { namespace Net { -class ServerConnection; - // TODO XXX Thread-safeness XXX -class Listener { +class Listener : boost::noncopyable { private: - std::string x905CertFile, x905KeyFile; - IPAddress address; - int sock; + class ServerConnection : public Connection { + public: + friend class Listener; - gnutls_dh_params_t dh_params; + ServerConnection(boost::asio::ssl::context &sslContext) : Connection(sslContext) {} + }; - std::map > connections; + std::string x905CertFile, x905KeyFile; + boost::asio::ip::tcp::endpoint address; + boost::asio::ip::tcp::acceptor acceptor; + boost::asio::ssl::context sslContext; - boost::signal1 signal; + std::map, std::pair > connections; - void acceptHandler(int); + boost::signal1 > signal; - void connectHandler(ServerConnection *con); - void disconnectHandler(ServerConnection *con); + void handleAccept(const boost::system::error_code &error, boost::shared_ptr con); - // Prevent shallow copy - Listener(const Listener &o); - Listener& operator=(const Listener &o); + void handleConnect(boost::shared_ptr con); + void handleDisconnect(boost::shared_ptr con); public: - Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, const IPAddress &address0 = IPAddress()) throw(Exception); + Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, + const boost::asio::ip::tcp::endpoint &address0 = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 6666)) throw(Exception); virtual ~Listener(); - boost::signal1& signalNewConnection() {return signal;} + boost::signal1 >& signalNewConnection() {return signal;} }; } diff --git a/src/Net/ServerConnection.cpp b/src/Net/ServerConnection.cpp deleted file mode 100644 index 1f01ce5..0000000 --- a/src/Net/ServerConnection.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ServerConnection.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 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "ServerConnection.h" -#include "FdManager.h" -#include "IPAddress.h" - -#include - -#include -#include -#include -#include - -namespace Mad { -namespace Net { - -void ServerConnection::connectionHeaderReceiveHandler(const void *data, unsigned long length) { - if(length != sizeof(ConnectionHeader)) - // Error... disconnect - return; - - const ConnectionHeader *header = (const ConnectionHeader*)data; - - if(header->m != 'M' || header->a != 'A' || header->d != 'D') - // Error... disconnect - return; - - if(header->protVerMin > 1 || header->protVerMax < 1) - // Unsupported protocol... disconnect - return; - - if(header->type == 'C') - daemon = false; - else if(header->type == 'D') - daemon = true; - else - // Error... disconnect - return; - - ConnectionHeader header2 = {'M', 'A', 'D', 0, 0, 1, 1, 0}; - - enterReceiveLoop(); - - rawSend((uint8_t*)&header2, sizeof(header2)); -} - -ServerConnection::ServerConnection(int sock0, const IPAddress &address, gnutls_dh_params_t dh_params, const std::string &x905CertFile, const std::string &x905KeyFile) -: daemon(false) { - boost::unique_lock lock(stateLock); - - sock = sock0; - - peer = new IPAddress(address); - - gnutls_certificate_set_dh_params(x509_cred, dh_params); - gnutls_certificate_set_x509_key_file(x509_cred, x905CertFile.c_str(), x905KeyFile.c_str(), GNUTLS_X509_FMT_PEM); - - gnutls_init(&session, GNUTLS_SERVER); - gnutls_set_default_priority(session); - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); - gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)sock); - - FdManager::get()->registerFd(sock, boost::bind(&ServerConnection::sendReceive, this, _1)); - - state = CONNECT; - - lock.unlock(); - - updateEvents(); -} - -} -} diff --git a/src/Net/ServerConnection.h b/src/Net/ServerConnection.h deleted file mode 100644 index d52cd7c..0000000 --- a/src/Net/ServerConnection.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ServerConnection.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_NET_SERVERCONNECTION_H_ -#define MAD_NET_SERVERCONNECTION_H_ - -#include "Connection.h" -#include - -namespace Mad { -namespace Net { - -class Listener; - -class ServerConnection : public Connection { - friend class Listener; - - private: - IPAddress *peer; - - bool daemon; - - gnutls_anon_server_credentials_t anoncred; - - void connectionHeaderReceiveHandler(const void *data, unsigned long length); - - protected: - ServerConnection(int sock0, const IPAddress &address, gnutls_dh_params_t dh_params, const std::string &x905certFile, const std::string &x905keyFile); - - virtual void connectionHeader() { - rawReceive(sizeof(ConnectionHeader), boost::bind(&ServerConnection::connectionHeaderReceiveHandler, this, _1, _2)); - } - - public: - bool isDaemonConnection() const {return daemon;} -}; - -} -} - -#endif /*MAD_NET_SERVERCONNECTION_H_*/ diff --git a/src/Net/ThreadManager.cpp b/src/Net/ThreadManager.cpp index 71a754e..0fb0716 100644 --- a/src/Net/ThreadManager.cpp +++ b/src/Net/ThreadManager.cpp @@ -18,11 +18,13 @@ */ #include "ThreadManager.h" -#include "FdManager.h" +#include "Connection.h" #include #include +#include + #include namespace Mad { @@ -97,10 +99,12 @@ void ThreadManager::doInit() { threadLock.lock(); + ioWorker.reset(new boost::asio::io_service::work(Connection::ioService)); + mainThreadId = boost::this_thread::get_id(); - workerThread = new boost::thread(std::mem_fun(&ThreadManager::workerFunc), this); - loggerThread = new boost::thread(std::mem_fun(&Common::LogManager::loggerThread), Common::LogManager::get()); - ioThread = new boost::thread(std::mem_fun(&FdManager::ioThread), FdManager::get()); + workerThread = new boost::thread(&ThreadManager::workerFunc, this); + loggerThread = new boost::thread(&Common::LogManager::loggerThread, Common::LogManager::get()); + ioThread = new boost::thread((std::size_t(boost::asio::io_service::*)())&boost::asio::io_service::run, &Connection::ioService); threadLock.unlock(); } @@ -128,7 +132,7 @@ void ThreadManager::doDeinit() { threads.join_all(); // IO thread is next - FdManager::get()->stopIOThread(); + ioWorker.reset(); ioThread->join(); delete ioThread; diff --git a/src/Net/ThreadManager.h b/src/Net/ThreadManager.h index fd903af..2c57747 100644 --- a/src/Net/ThreadManager.h +++ b/src/Net/ThreadManager.h @@ -27,7 +27,8 @@ #include #include -#include +#include + #include #include #include @@ -50,11 +51,14 @@ class ThreadManager : public Common::Initializable { boost::condition_variable workCond; std::queue > work; + boost::scoped_ptr ioWorker; + static ThreadManager threadManager; ThreadManager() {} void workerFunc(); + void ioFunc(); void threadFinished(boost::thread *thread) { threadLock.lock(); -- cgit v1.2.3