danicoin/src/Rpc/HttpServer.cpp

99 lines
2.8 KiB
C++
Raw Normal View History

2015-05-27 12:08:46 +00:00
// 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 <http://www.gnu.org/licenses/>.
#include "HttpServer.h"
#include <boost/scope_exit.hpp>
#include <HTTP/HttpParser.h>
#include <System/InterruptedException.h>
#include <System/TcpStream.h>
#include <System/Ipv4Address.h>
using namespace Logging;
namespace CryptoNote {
HttpServer::HttpServer(System::Dispatcher& dispatcher, Logging::ILogger& log)
2015-07-30 15:22:07 +00:00
: m_dispatcher(dispatcher), workingContextGroup(dispatcher), logger(log, "HttpServer") {
2015-05-27 12:08:46 +00:00
}
void HttpServer::start(const std::string& address, uint16_t port) {
m_listener = System::TcpListener(m_dispatcher, System::Ipv4Address(address), port);
2015-07-30 15:22:07 +00:00
workingContextGroup.spawn(std::bind(&HttpServer::acceptLoop, this));
2015-05-27 12:08:46 +00:00
}
void HttpServer::stop() {
2015-07-30 15:22:07 +00:00
workingContextGroup.interrupt();
workingContextGroup.wait();
2015-05-27 12:08:46 +00:00
}
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;
2015-07-30 15:22:07 +00:00
workingContextGroup.spawn(std::bind(&HttpServer::acceptLoop, this));
2015-05-27 12:08:46 +00:00
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();
2015-07-30 15:22:07 +00:00
if (stream.peek() == std::iostream::traits_type::eof()) {
break;
}
2015-05-27 12:08:46 +00:00
}
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();
}
}
}