#include <SSLSession.h> #include <boost/bind.hpp> #include <boost/lexical_cast.hpp> namespace DataExporter_ns { //============================================================================== // SSLSession::SSLSession() //============================================================================== SSLSession::SSLSession(Tango::DeviceImpl* deviceImpl_p, Configuration::SP configuration_sp, DBManager::SP dBManager_sp, boost::shared_ptr<boost::asio::io_service> ioService_sp, boost::shared_ptr<boost::asio::ssl::context> context_sp) : Session::Session(deviceImpl_p, configuration_sp, dBManager_sp, ioService_sp), m_sslSocket(*ioService_sp, *context_sp) { DEBUG_STREAM << "SSLSession::SSLSession()" << endl; } //============================================================================== // SSLSession::~SSLSession() //============================================================================== SSLSession::~SSLSession() { DEBUG_STREAM << "SSLSession::~SSLSession()" << endl; INFO_STREAM << "SSLSession::~SSLSession() Disconnection from " << m_remoteEndpoint << endl; boost::system::error_code errorCode; m_sslSocket.shutdown(errorCode); m_sslSocket.lowest_layer().shutdown( boost::asio::ip::tcp::socket::shutdown_both, errorCode); m_sslSocket.lowest_layer().close(errorCode); } //============================================================================== // SSLSession::create() //============================================================================== Session::SP SSLSession::create(Tango::DeviceImpl* deviceImpl_p, Configuration::SP configuration_sp, DBManager::SP dBManager_sp, boost::shared_ptr<boost::asio::io_service> ioService_sp, boost::shared_ptr<boost::asio::ssl::context> context_sp) { Session::SP s_sp(new SSLSession(deviceImpl_p, configuration_sp, dBManager_sp, ioService_sp, context_sp), SSLSession::Deleter()); return s_sp; } //============================================================================== // SSLSession::getSocket() //============================================================================== boost::asio::ip::tcp::socket& SSLSession::getSocket() { DEBUG_STREAM << "SSLSession::getSocket()" << endl; return m_sslSocket.next_layer(); } //============================================================================== // SSLSession::start() //============================================================================== void SSLSession::start() { DEBUG_STREAM << "SSLSession::start()" << endl; m_remoteEndpoint = boost::lexical_cast<std::string>( m_sslSocket.lowest_layer().remote_endpoint()); INFO_STREAM << "SSLSession::start() Connection from " << m_remoteEndpoint << endl; m_protocolManager_sp->setRemoteEndpoint(m_remoteEndpoint); startHandShake(); } //============================================================================== // SSLSession::startHandShake() //============================================================================== void SSLSession::startHandShake() { DEBUG_STREAM << "SSLSession::startHandShake()" << endl; m_sslSocket.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&SSLSession::handleHandShake, shared_from_this(), boost::asio::placeholders::error)); } //============================================================================== // SSLSession::handleRequest() //============================================================================== void SSLSession::handleHandShake(const boost::system::error_code& errorCode) { DEBUG_STREAM << "SSLSession::handleHandShake()" << endl; if(!errorCode) { startReadRequestHeader(); } else { ERROR_STREAM << "SSLSession::handleHandShake() error " << errorCode.message() << " from " << m_remoteEndpoint << endl; } } //============================================================================== // SSLSession::startReadRequestHeader() //============================================================================== void SSLSession::startReadRequestHeader() { DEBUG_STREAM << "SSLSession::startReadRequestHeader()" << endl; m_readBuff.resize(HEADER_SIZE); boost::asio::async_read(m_sslSocket, boost::asio::buffer(m_readBuff), m_strand.wrap(boost::bind(&SSLSession::handleReadRequestHeader, shared_from_this(), boost::asio::placeholders::error))); } //============================================================================== // SSLSession::startReadRequestBody() //============================================================================== void SSLSession::startReadRequestBody(boost::uint32_t bodySize) { DEBUG_STREAM << "SSLSession::startReadRequestBody()" << endl; m_readBuff.resize(HEADER_SIZE + bodySize); boost::asio::mutable_buffers_1 mutableBuffer = boost::asio::buffer(&m_readBuff[HEADER_SIZE], bodySize); #ifdef VERBOSE_DEBUG INFO_STREAM << "SSLSession::startReadRequestBody() " << m_remoteEndpoint << " >>>> " << bodySize << " byte" << endl; #endif boost::asio::async_read(m_sslSocket, mutableBuffer, m_strand.wrap(boost::bind(&SSLSession::handleReadRequestBody, shared_from_this(), boost::asio::placeholders::error))); } //============================================================================== // SSLSession::startWriteResponse() //============================================================================== void SSLSession::startWriteResponse() { DEBUG_STREAM << "SSLSession::startWriteResponse()" << endl; try { RequestSP request_sp(new Request); request_sp->ParseFromArray(&m_readBuff[HEADER_SIZE], m_readBuff.size() - HEADER_SIZE); ResponseSP response_sp = m_protocolManager_sp->prepareResponse(request_sp); boost::uint32_t bodySize = response_sp->ByteSizeLong(); std::vector<boost::uint8_t> writeBuff; writeBuff.resize(HEADER_SIZE + bodySize); encodeHeader(writeBuff, bodySize); response_sp->SerializeToArray(&writeBuff[HEADER_SIZE], bodySize); #ifdef VERBOSE_DEBUG INFO_STREAM << "SSLSession::startWriteResponse() " << m_remoteEndpoint << " <<<< " << bodySize << " byte" << endl; #endif boost::asio::async_write(m_sslSocket, boost::asio::buffer(writeBuff), m_strand.wrap(boost::bind(&SSLSession::handleWriteResponse, shared_from_this(), boost::asio::placeholders::error))); } catch(std::exception& ec) { ERROR_STREAM << "SSLSession::startWriteResponse() " << ec.what() << " from " << m_remoteEndpoint << endl; } catch(...) { ERROR_STREAM << "SSLSession::startWriteResponse() unknown error from " << m_remoteEndpoint << endl; } } //============================================================================== // SSLSession::startWriteData() //============================================================================== void SSLSession::startWriteData(FileWrapper::SP fileWrapper_sp) { try { if(!fileWrapper_sp->isBad()) { if(!fileWrapper_sp->isCompleted()) { std::vector<char> writeBuff; fileWrapper_sp->read(writeBuff); boost::asio::async_write(m_sslSocket, boost::asio::buffer(writeBuff), m_strand.wrap(boost::bind(&SSLSession::handleWriteData, shared_from_this(), fileWrapper_sp, boost::asio::placeholders::error))); } else { INFO_STREAM << "SSLSession::startWriteData() " << " transfer completed " << endl; startReadRequestHeader(); } } else { ERROR_STREAM << "SSLSession::startWriteData() error on file I/O " << "from " << m_remoteEndpoint << endl; } } catch(std::exception& ec) { ERROR_STREAM << "SSLSession::startWriteData() " << ec.what() << " from " << m_remoteEndpoint << endl; } catch(...) { ERROR_STREAM << "SSLSession::startWriteData() unknown error from " << m_remoteEndpoint << endl; } } } //namespace