// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // // Bytecoin 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. // // Bytecoin 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 Bytecoin. If not, see . #include "HttpServer.h" #include #include #include #include #include using namespace Logging; namespace CryptoNote { HttpServer::HttpServer(System::Dispatcher& dispatcher, Logging::ILogger& log) : m_dispatcher(dispatcher), logger(log, "HttpServer"), m_shutdownCompleteEvent(dispatcher) { } void HttpServer::start(const std::string& address, uint16_t port) { m_listener = System::TcpListener(m_dispatcher, System::Ipv4Address(address), port); ++m_spawnCount; m_dispatcher.spawn(std::bind(&HttpServer::acceptLoop, this)); } void HttpServer::stop() { m_listener.stop(); for (auto connPtr : m_connections) { connPtr->stop(); } if (m_spawnCount) { m_shutdownCompleteEvent.wait(); } } void HttpServer::acceptLoop() { try { System::TcpConnection connection; bool accepted = false; while (!accepted) { try { connection = m_listener.accept(); accepted = true; } catch (System::InterruptedException&) { throw; } catch (std::exception&) { // try again } } m_connections.insert(&connection); BOOST_SCOPE_EXIT_ALL(this, &connection) { m_connections.erase(&connection); }; auto addr = connection.getPeerAddressAndPort(); logger(DEBUGGING) << "Incoming connection from " << addr.first.toDottedDecimal() << ":" << addr.second; ++m_spawnCount; m_dispatcher.spawn(std::bind(&HttpServer::acceptLoop, this)); System::TcpStreambuf streambuf(connection); std::iostream stream(&streambuf); HttpParser parser; for (;;) { HttpRequest req; HttpResponse resp; parser.receiveRequest(stream, req); processRequest(req, resp); stream << resp; stream.flush(); } logger(DEBUGGING) << "Closing connection from " << addr.first.toDottedDecimal() << ":" << addr.second << " total=" << m_connections.size(); } catch (System::InterruptedException&) { } catch (std::exception& e) { logger(WARNING) << "Connection error: " << e.what(); } if (--m_spawnCount == 0) { m_shutdownCompleteEvent.set(); } } }