📄 tcpserver.cpp
字号:
// -----------------------------------------------------------------// libpion: a C++ framework for building lightweight HTTP interfaces// -----------------------------------------------------------------// Copyright (C) 2007 Atomic Labs, Inc. (http://www.atomiclabs.com)//// Distributed under the Boost Software License, Version 1.0.// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt//#include <libpion/TCPServer.hpp>#include <libpion/PionEngine.hpp>#include <boost/bind.hpp>using boost::asio::ip::tcp;namespace pion { // begin namespace pion// TCPServer member functionsTCPServer::TCPServer(const unsigned int tcp_port) : m_logger(PION_GET_LOGGER("Pion.TCPServer")), m_tcp_acceptor(PionEngine::getInstance().getIOService()),#ifdef PION_HAVE_SSL m_ssl_context(PionEngine::getInstance().getIOService(), boost::asio::ssl::context::sslv23),#else m_ssl_context(0),#endif m_tcp_port(tcp_port), m_ssl_flag(false), m_is_listening(false){}void TCPServer::start(void){ // lock mutex for thread safety boost::mutex::scoped_lock server_lock(m_mutex); if (! m_is_listening) { PION_LOG_INFO(m_logger, "Starting server on port " << getPort()); beforeStarting(); // configure the acceptor service tcp::endpoint endpoint(tcp::v4(), m_tcp_port); m_tcp_acceptor.open(endpoint.protocol()); // allow the acceptor to reuse the address (i.e. SO_REUSEADDR) m_tcp_acceptor.set_option(tcp::acceptor::reuse_address(true)); m_tcp_acceptor.bind(endpoint); m_tcp_acceptor.listen(); m_is_listening = true; // unlock the mutex since listen() requires its own lock server_lock.unlock(); listen(); }}void TCPServer::stop(void){ // lock mutex for thread safety boost::mutex::scoped_lock server_lock(m_mutex); if (m_is_listening) { PION_LOG_INFO(m_logger, "Shutting down server on port " << getPort()); m_is_listening = false; // this terminates any pending connections m_tcp_acceptor.close(); // close all of the TCP connections managed by this server instance std::for_each(m_conn_pool.begin(), m_conn_pool.end(), boost::bind(&TCPConnection::close, _1)); // clear the TCP connection management pool m_conn_pool.clear(); afterStopping(); }}void TCPServer::listen(void){ // lock mutex for thread safety boost::mutex::scoped_lock server_lock(m_mutex); if (m_is_listening) { // create a new TCP connection object TCPConnectionPtr new_connection(TCPConnection::create(m_tcp_acceptor.io_service(), m_ssl_context, m_ssl_flag, boost::bind(&TCPServer::finishConnection, this, _1))); m_conn_pool.insert(new_connection); // use the new object to accept a connection if (m_ssl_flag) {#ifdef PION_HAVE_SSL m_tcp_acceptor.async_accept(new_connection->getSSLSocket().lowest_layer(), boost::bind(&TCPServer::handleAccept, this, new_connection, boost::asio::placeholders::error) );#else PION_LOG_ERROR(m_logger, "SSL flag set for server, but support is not enabled"); new_connection->finish();#endif } else { m_tcp_acceptor.async_accept(new_connection->getSocket(), boost::bind(&TCPServer::handleAccept, this, new_connection, boost::asio::placeholders::error) ); } }}void TCPServer::handleAccept(TCPConnectionPtr& tcp_conn, const boost::system::error_code& accept_error){ if (accept_error) { // an error occured while trying to a accept a new connection // this happens when the server is being shut down if (m_is_listening) { tcp_conn->setKeepAlive(false); // make sure it will get closed finishConnection(tcp_conn); } } else { // got a new TCP connection PION_LOG_INFO(m_logger, "New" << (tcp_conn->getSSLFlag() ? " SSL " : " ") << "connection on port " << getPort()); // schedule the acceptance of another new connection // (this returns immediately since it schedules it as an event) if (m_is_listening) listen(); // handle the new connection if (tcp_conn->getSSLFlag()) {#ifdef PION_HAVE_SSL // SSL -> perform handshake first tcp_conn->getSSLSocket().async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&TCPServer::handleSSLHandshake, this, tcp_conn, boost::asio::placeholders::error) );#else PION_LOG_ERROR(m_logger, "SSL flag set for server, but support is not enabled"); tcp_conn->setKeepAlive(false); // make sure it will get closed finishConnection(tcp_conn);#endif } else { // not SSL -> call the handler immediately handleConnection(tcp_conn); } }}void TCPServer::handleSSLHandshake(TCPConnectionPtr& tcp_conn, const boost::system::error_code& handshake_error){ if (handshake_error) { // an error occured while trying to establish the SSL connection PION_LOG_WARN(m_logger, "SSL handshake failed on port " << getPort() << " (" << handshake_error.message() << ')'); tcp_conn->setKeepAlive(false); // make sure it will get closed finishConnection(tcp_conn); } else { // handle the new connection PION_LOG_DEBUG(m_logger, "SSL handshake succeeded on port " << getPort()); handleConnection(tcp_conn); }}void TCPServer::finishConnection(TCPConnectionPtr& tcp_conn){ if (tcp_conn->getKeepAlive()) { // keep the connection alive handleConnection(tcp_conn); } else { PION_LOG_INFO(m_logger, "Closing connection on port " << getPort()); // remove the connection from the server's management pool boost::mutex::scoped_lock server_lock(m_mutex); ConnectionPool::iterator conn_itr = m_conn_pool.find(tcp_conn); if (conn_itr != m_conn_pool.end()) m_conn_pool.erase(conn_itr); server_lock.unlock(); }}} // end namespace pion
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -