This is a large update that brings many internal and architectural changes. The most obvious change to the user is the presence of configuration files for extractLargeNetwork and routed. Optimistically speaking, it should not break anything. Thanks to rskr for support patches and suggestions.
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef BASIC_DATASTRUCTURES_H
|
||||
#define BASIC_DATASTRUCTURES_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace http {
|
||||
|
||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||
|
||||
const char okHTML[] = "";
|
||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
||||
const char seperators[] = { ':', ' ' };
|
||||
const char crlf[] = { '\r', '\n' };
|
||||
|
||||
struct Header {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct Request {
|
||||
std::string uri;
|
||||
};
|
||||
|
||||
struct Reply {
|
||||
Reply() { content.reserve(1000000); }
|
||||
enum status_type {
|
||||
ok = 200,
|
||||
badRequest = 400,
|
||||
internalServerError = 500
|
||||
} status;
|
||||
|
||||
std::vector<Header> headers;
|
||||
std::string content;
|
||||
std::vector<boost::asio::const_buffer> toBuffers();
|
||||
static Reply stockReply(status_type status);
|
||||
};
|
||||
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
return boost::asio::buffer(okString);
|
||||
case Reply::internalServerError:
|
||||
return boost::asio::buffer(internalServerErrorString);
|
||||
default:
|
||||
return boost::asio::buffer(badRequestString);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ToString(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
return okHTML;
|
||||
case Reply::badRequest:
|
||||
return badRequestHTML;
|
||||
default:
|
||||
return internalServerErrorHTML;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.push_back(ToBuffer(status));
|
||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||
Header& h = headers[i];
|
||||
buffers.push_back(boost::asio::buffer(h.name));
|
||||
buffers.push_back(boost::asio::buffer(seperators));
|
||||
buffers.push_back(boost::asio::buffer(h.value));
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
buffers.push_back(boost::asio::buffer(content));
|
||||
return buffers;
|
||||
}
|
||||
|
||||
Reply Reply::stockReply(Reply::status_type status) {
|
||||
Reply rep;
|
||||
rep.status = status;
|
||||
rep.content = ToString(status);
|
||||
rep.headers.resize(2);
|
||||
rep.headers[0].name = "Content-Length";
|
||||
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
|
||||
rep.headers[1].name = "Content-Type";
|
||||
rep.headers[1].value = "text/html";
|
||||
return rep;
|
||||
}
|
||||
} // namespace http
|
||||
|
||||
#endif //BASIC_DATASTRUCTURES_H
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H
|
||||
#define CONNECTION_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include "BasicDatastructures.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
/// Represents a single connection from a client.
|
||||
class Connection : public boost::enable_shared_from_this<Connection>, private boost::noncopyable {
|
||||
public:
|
||||
explicit Connection(boost::asio::io_service& io_service, RequestHandler& handler) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {}
|
||||
|
||||
boost::asio::ip::tcp::socket& socket() {
|
||||
return TCPsocket;
|
||||
}
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void start() {
|
||||
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
|
||||
}
|
||||
|
||||
private:
|
||||
void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) {
|
||||
if (!e) {
|
||||
boost::tribool result;
|
||||
boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred);
|
||||
|
||||
if (result) {
|
||||
requestHandler.handle_request(request, reply);
|
||||
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
|
||||
} else if (!result) {
|
||||
reply = Reply::stockReply(Reply::badRequest);
|
||||
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
|
||||
} else {
|
||||
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handleWrite(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignoredEC;
|
||||
TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
|
||||
}
|
||||
// No new asynchronous operations are started. This means that all shared_ptr
|
||||
// references to the connection object will disappear and the object will be
|
||||
// destroyed automatically after this handler returns. The connection class's
|
||||
// destructor closes the socket.
|
||||
}
|
||||
|
||||
boost::asio::io_service::strand strand;
|
||||
boost::asio::ip::tcp::socket TCPsocket;
|
||||
RequestHandler& requestHandler;
|
||||
boost::array<char, 8192> incomingDataBuffer;
|
||||
Request request;
|
||||
RequestParser requestParser;
|
||||
Reply reply;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
#endif // CONNECTION_H
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef REQUEST_HANDLER_H
|
||||
#define REQUEST_HANDLER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include "BasicDatastructures.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../Plugins/BasePlugin.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
class RequestHandler : private boost::noncopyable {
|
||||
public:
|
||||
explicit RequestHandler() { }
|
||||
|
||||
~RequestHandler() {
|
||||
pluginMap.EraseAll();
|
||||
}
|
||||
|
||||
void handle_request(const Request& req, Reply& rep){
|
||||
//parse command
|
||||
std::string request(req.uri);
|
||||
std::string command;
|
||||
std::size_t firstAmpPosition = request.find_first_of("&");
|
||||
command = request.substr(1,firstAmpPosition-1);
|
||||
std::cout << "[debug] looking for handler for command: " << command << std::endl;
|
||||
try {
|
||||
if(pluginMap.Holds(command)) {
|
||||
|
||||
std::vector<std::string> parameters;
|
||||
std::stringstream ss(( firstAmpPosition == std::string::npos ? "" : request.substr(firstAmpPosition+1) ));
|
||||
std::string item;
|
||||
while(std::getline(ss, item, '&')) {
|
||||
parameters.push_back(item);
|
||||
}
|
||||
// std::cout << "[debug] found handler for '" << command << "' at version: " << pluginMap.Find(command)->GetVersionString() << std::endl;
|
||||
// std::cout << "[debug] remaining parameters: " << parameters.size() << std::endl;
|
||||
rep.status = Reply::ok;
|
||||
pluginMap.Find(command)->HandleRequest(parameters, rep );
|
||||
} else {
|
||||
rep = Reply::stockReply(Reply::badRequest);
|
||||
}
|
||||
return;
|
||||
} catch(std::exception& e) {
|
||||
rep = Reply::stockReply(Reply::internalServerError);
|
||||
std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
void RegisterPlugin(BasePlugin * plugin) {
|
||||
std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
|
||||
pluginMap.Add(plugin->GetDescriptor(), plugin);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::mutex pluginMutex;
|
||||
HashTable<std::string, BasePlugin *> pluginMap;
|
||||
};
|
||||
} // namespace http
|
||||
|
||||
#endif // REQUEST_HANDLER_H
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef REQUEST_PARSER_H
|
||||
#define REQUEST_PARSER_H
|
||||
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include "BasicDatastructures.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
class RequestParser {
|
||||
public:
|
||||
RequestParser() : state_(method_start) { }
|
||||
void Reset() { state_ = method_start; }
|
||||
|
||||
boost::tuple<boost::tribool, char*> Parse(Request& req, char* begin, char* end) {
|
||||
while (begin != end) {
|
||||
boost::tribool result = consume(req, *begin++);
|
||||
if (result || !result){
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
}
|
||||
boost::tribool result = boost::indeterminate;
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::tribool consume(Request& req, char input) {
|
||||
switch (state_) {
|
||||
case method_start:
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = method;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case method:
|
||||
if (input == ' ') {
|
||||
state_ = uri;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case uri_start:
|
||||
if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = uri;
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case uri:
|
||||
if (input == ' ') {
|
||||
state_ = http_version_h;
|
||||
return boost::indeterminate;
|
||||
} else if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case http_version_h:
|
||||
if (input == 'H') {
|
||||
state_ = http_version_t_1;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_t_1:
|
||||
if (input == 'T') {
|
||||
state_ = http_version_t_2;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_t_2:
|
||||
if (input == 'T') {
|
||||
state_ = http_version_p;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_p:
|
||||
if (input == 'P') {
|
||||
state_ = http_version_slash;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_slash:
|
||||
if (input == '/') {
|
||||
state_ = http_version_major_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_major_start:
|
||||
if (isDigit(input)) {
|
||||
state_ = http_version_major;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_major:
|
||||
if (input == '.') {
|
||||
state_ = http_version_minor_start;
|
||||
return boost::indeterminate;
|
||||
} else if (isDigit(input)) {
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_minor_start:
|
||||
if (isDigit(input)) {
|
||||
state_ = http_version_minor;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case http_version_minor:
|
||||
if (input == '\r') {
|
||||
state_ = expecting_newline_1;
|
||||
return boost::indeterminate;
|
||||
} else if (isDigit(input)) {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
case expecting_newline_1:
|
||||
if (input == '\n') {
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case header_line_start:
|
||||
if (input == '\r') {
|
||||
state_ = expecting_newline_3;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = header_name;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case header_lws:
|
||||
if (input == '\r') {
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
} else if (input == ' ' || input == '\t') {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
else if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case header_name:
|
||||
if (input == ':') {
|
||||
state_ = space_before_header_value;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case space_before_header_value:
|
||||
if (input == ' ') {
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case header_value:
|
||||
if (input == '\r') {
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
} else if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
case expecting_newline_2:
|
||||
if (input == '\n') {
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
case expecting_newline_3:
|
||||
return (input == '\n');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isChar(int c) {
|
||||
return c >= 0 && c <= 127;
|
||||
}
|
||||
|
||||
inline bool isCTL(int c) {
|
||||
return (c >= 0 && c <= 31) || (c == 127);
|
||||
}
|
||||
|
||||
inline bool isTSpecial(int c) {
|
||||
switch (c) {
|
||||
case '(': case ')': case '<': case '>': case '@':
|
||||
case ',': case ';': case ':': case '\\': case '"':
|
||||
case '/': case '[': case ']': case '?': case '=':
|
||||
case '{': case '}': case ' ': case '\t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isDigit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
enum state {
|
||||
method_start,
|
||||
method,
|
||||
uri_start,
|
||||
uri,
|
||||
http_version_h,
|
||||
http_version_t_1,
|
||||
http_version_t_2,
|
||||
http_version_p,
|
||||
http_version_slash,
|
||||
http_version_major_start,
|
||||
http_version_major,
|
||||
http_version_minor_start,
|
||||
http_version_minor,
|
||||
expecting_newline_1,
|
||||
header_line_start,
|
||||
header_lws,
|
||||
header_name,
|
||||
space_before_header_value,
|
||||
header_value,
|
||||
expecting_newline_2,
|
||||
expecting_newline_3
|
||||
} state_;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
#endif // REQUEST_PARSER_H
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include <vector>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include "Connection.h"
|
||||
#include "RequestHandler.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
class Server: private boost::noncopyable {
|
||||
public:
|
||||
explicit Server(const std::string& address, const std::string& port, unsigned thread_pool_size) : threadPoolSize(thread_pool_size), acceptor(ioService), newConnection(new Connection(ioService, requestHandler)), requestHandler(){
|
||||
boost::asio::ip::tcp::resolver resolver(ioService);
|
||||
boost::asio::ip::tcp::resolver::query query(address, port);
|
||||
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
|
||||
|
||||
acceptor.open(endpoint.protocol());
|
||||
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||
acceptor.bind(endpoint);
|
||||
acceptor.listen();
|
||||
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void Run() {
|
||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||
for (unsigned i = 0; i < threadPoolSize; ++i) {
|
||||
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService)));
|
||||
threads.push_back(thread);
|
||||
}
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
threads[i]->join();
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
ioService.stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
RequestHandler * GetRequestHandlerPtr() {
|
||||
return &requestHandler;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef boost::shared_ptr<Connection > ConnectionPtr;
|
||||
|
||||
void handleAccept(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
newConnection->start();
|
||||
newConnection.reset(new Connection(ioService, requestHandler));
|
||||
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned threadPoolSize;
|
||||
boost::asio::io_service ioService;
|
||||
boost::asio::ip::tcp::acceptor acceptor;
|
||||
ConnectionPtr newConnection;
|
||||
RequestHandler requestHandler;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
#endif // SERVER_H
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* ServerConfiguration.h
|
||||
*
|
||||
* Created on: 26.11.2010
|
||||
* Author: dennis
|
||||
*/
|
||||
|
||||
#ifndef SERVERCONFIGURATION_H_
|
||||
#define SERVERCONFIGURATION_H_
|
||||
|
||||
#include "../Util/BaseConfiguration.h"
|
||||
|
||||
typedef BaseConfiguration ServerConfiguration;
|
||||
|
||||
#endif /* SERVERCONFIGURATION_H_ */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
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 Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
Created on: 26.11.2010
|
||||
Author: dennis
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SERVERFACTORY_H_
|
||||
#define SERVERFACTORY_H_
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "Server.h"
|
||||
#include "ServerConfiguration.h"
|
||||
|
||||
#include "../Util/InputFileUtil.h"
|
||||
|
||||
typedef http::Server Server;
|
||||
|
||||
struct ServerFactory {
|
||||
static Server * CreateServer(ServerConfiguration& serverConfig) {
|
||||
|
||||
if(!testDataFile(serverConfig.GetParameter("nodesData").c_str())) {
|
||||
std::cerr << "[error] nodes file not found" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!testDataFile(serverConfig.GetParameter("hsgrData").c_str())) {
|
||||
std::cerr << "[error] hsgr file not found" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!testDataFile(serverConfig.GetParameter("namesData").c_str())) {
|
||||
std::cerr << "[error] names file not found" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!testDataFile(serverConfig.GetParameter("ramIndex").c_str())) {
|
||||
std::cerr << "[error] ram index file not found" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!testDataFile(serverConfig.GetParameter("fileIndex").c_str())) {
|
||||
std::cerr << "[error] file index file not found" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
unsigned threads = omp_get_num_procs();
|
||||
if(serverConfig.GetParameter("IP") == "")
|
||||
serverConfig.SetParameter("IP", "0.0.0.0");
|
||||
if(serverConfig.GetParameter("Port") == "")
|
||||
serverConfig.SetParameter("Port", "5000");
|
||||
|
||||
if(atoi(serverConfig.GetParameter("Threads").c_str()) != 0 && atoi(serverConfig.GetParameter("Threads").c_str()) <= threads)
|
||||
threads = atoi( serverConfig.GetParameter("Threads").c_str() );
|
||||
|
||||
Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads);
|
||||
return server;
|
||||
}
|
||||
|
||||
static Server * CreateServer(const char * iniFile) {
|
||||
ServerConfiguration serverConfig(iniFile);
|
||||
return CreateServer(serverConfig);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SERVERFACTORY_H_ */
|
||||
Reference in New Issue
Block a user