renamed: Server/*/*.h -> server/*/*.hpp
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef APIGRAMMAR_H_
|
||||
#define APIGRAMMAR_H_
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/qi_action.hpp>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar : qi::grammar<Iterator>
|
||||
{
|
||||
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
|
||||
{
|
||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns);
|
||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | language | instruction | geometry | alt_route | old_API | num_results) ) ;
|
||||
|
||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
|
||||
location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)];
|
||||
hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)];
|
||||
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
|
||||
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAllUTurns, handler, ::_1)];
|
||||
language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)];
|
||||
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
|
||||
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
|
||||
num_results = (-qi::lit('&')) >> qi::lit("num_results") >> '=' >> qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)];
|
||||
|
||||
string = +(qi::char_("a-zA-Z"));
|
||||
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
|
||||
stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") ));
|
||||
}
|
||||
|
||||
qi::rule<Iterator> api_call, query;
|
||||
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
|
||||
stringwithDot, stringwithPercent, language, instruction, geometry,
|
||||
cmp, alt_route, u, uturns, old_API, num_results;
|
||||
|
||||
HandlerT * handler;
|
||||
};
|
||||
|
||||
#endif /* APIGRAMMAR_H_ */
|
||||
@@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Connection.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
#include "connection.hpp"
|
||||
#include "request_handler.hpp"
|
||||
#include "request_parser.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H
|
||||
#define CONNECTION_H
|
||||
|
||||
#include "http/compression_type.hpp"
|
||||
#include "http/reply.hpp"
|
||||
#include "http/request.hpp"
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// workaround for incomplete std::shared_ptr compatibility in old boost versions
|
||||
#if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T> const T *get_pointer(std::shared_ptr<T> const &p) { return p.get(); }
|
||||
|
||||
template <class T> T *get_pointer(std::shared_ptr<T> &p) { return p.get(); }
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
class RequestHandler;
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
/// Represents a single connection from a client.
|
||||
class Connection : public std::enable_shared_from_this<Connection>
|
||||
{
|
||||
public:
|
||||
explicit Connection(boost::asio::io_service &io_service, RequestHandler &handler);
|
||||
Connection(const Connection &) = delete;
|
||||
Connection() = delete;
|
||||
|
||||
boost::asio::ip::tcp::socket &socket();
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void start();
|
||||
|
||||
private:
|
||||
void handle_read(const boost::system::error_code &e, std::size_t bytes_transferred);
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handle_write(const boost::system::error_code &e);
|
||||
|
||||
std::vector<char> compress_buffers(const std::vector<char> &uncompressed_data,
|
||||
const compression_type compression_type);
|
||||
|
||||
boost::asio::io_service::strand strand;
|
||||
boost::asio::ip::tcp::socket TCP_socket;
|
||||
RequestHandler &request_handler;
|
||||
boost::array<char, 8192> incoming_data_buffer;
|
||||
request request;
|
||||
reply reply;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
#endif // CONNECTION_H
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "http/reply.hpp"
|
||||
#include "http/request.hpp"
|
||||
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/xml_renderer.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/route_parameters.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
RequestHandler::RequestHandler() : routing_machine(nullptr) {}
|
||||
|
||||
void RequestHandler::handle_request(const http::request ¤t_request,
|
||||
http::reply ¤t_reply)
|
||||
{
|
||||
// parse command
|
||||
try
|
||||
{
|
||||
std::string request_string;
|
||||
URIDecode(current_request.uri, request_string);
|
||||
|
||||
// deactivated as GCC apparently does not implement that, not even in 4.9
|
||||
// std::time_t t = std::time(nullptr);
|
||||
// SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
|
||||
// " " << current_request.endpoint.to_string() << " " <<
|
||||
// current_request.referrer << ( 0 == current_request.referrer.length() ? "- " :" ") <<
|
||||
// current_request.agent << ( 0 == current_request.agent.length() ? "- " :" ") <<
|
||||
// request;
|
||||
|
||||
time_t ltime;
|
||||
struct tm *time_stamp;
|
||||
|
||||
ltime = time(nullptr);
|
||||
time_stamp = localtime(<ime);
|
||||
|
||||
// log timestamp
|
||||
SimpleLogger().Write() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday
|
||||
<< "-" << (time_stamp->tm_mon + 1 < 10 ? "0" : "")
|
||||
<< (time_stamp->tm_mon + 1) << "-" << 1900 + time_stamp->tm_year
|
||||
<< " " << (time_stamp->tm_hour < 10 ? "0" : "")
|
||||
<< time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "")
|
||||
<< time_stamp->tm_min << ":" << (time_stamp->tm_sec < 10 ? "0" : "")
|
||||
<< time_stamp->tm_sec << " " << current_request.endpoint.to_string()
|
||||
<< " " << current_request.referrer
|
||||
<< (0 == current_request.referrer.length() ? "- " : " ")
|
||||
<< current_request.agent
|
||||
<< (0 == current_request.agent.length() ? "- " : " ")
|
||||
<< request_string;
|
||||
|
||||
RouteParameters route_parameters;
|
||||
APIGrammarParser api_parser(&route_parameters);
|
||||
|
||||
auto api_iterator = request_string.begin();
|
||||
const bool result =
|
||||
boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser);
|
||||
|
||||
JSON::Object json_result;
|
||||
// check if the was an error with the request
|
||||
if (!result || (api_iterator != request_string.end()))
|
||||
{
|
||||
current_reply = http::reply::stock_reply(http::reply::bad_request);
|
||||
current_reply.content.clear();
|
||||
const auto position = std::distance(request_string.begin(), api_iterator);
|
||||
|
||||
json_result.values["status"] = 400;
|
||||
std::string message = "Query string malformed close to position ";
|
||||
message += cast::integral_to_string(position);
|
||||
json_result.values["status_message"] = message;
|
||||
JSON::render(current_reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // prepend response with jsonp parameter
|
||||
const std::string json_p = (route_parameters.jsonp_parameter + "(");
|
||||
current_reply.content.insert(current_reply.content.end(), json_p.begin(), json_p.end());
|
||||
}
|
||||
const auto return_code = routing_machine->RunQuery(route_parameters, json_result);
|
||||
if (200 != return_code)
|
||||
{
|
||||
current_reply = http::reply::stock_reply(http::reply::bad_request);
|
||||
current_reply.content.clear();
|
||||
json_result.values["status"] = 400;
|
||||
std::string message = "Bad Request";
|
||||
json_result.values["status_message"] = message;
|
||||
JSON::render(current_reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
// set headers
|
||||
current_reply.headers.emplace_back("Content-Length",
|
||||
cast::integral_to_string(current_reply.content.size()));
|
||||
if ("gpx" == route_parameters.output_format)
|
||||
{ // gpx file
|
||||
JSON::gpx_render(current_reply.content, json_result.values["route"]);
|
||||
current_reply.headers.emplace_back("Content-Type",
|
||||
"application/gpx+xml; charset=UTF-8");
|
||||
current_reply.headers.emplace_back("Content-Disposition",
|
||||
"attachment; filename=\"route.gpx\"");
|
||||
}
|
||||
else if (route_parameters.jsonp_parameter.empty())
|
||||
{ // json file
|
||||
JSON::render(current_reply.content, json_result);
|
||||
current_reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
|
||||
current_reply.headers.emplace_back("Content-Disposition",
|
||||
"inline; filename=\"response.json\"");
|
||||
}
|
||||
else
|
||||
{ // jsonp
|
||||
JSON::render(current_reply.content, json_result);
|
||||
current_reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
|
||||
current_reply.headers.emplace_back("Content-Disposition",
|
||||
"inline; filename=\"response.js\"");
|
||||
}
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // append brace to jsonp response
|
||||
current_reply.content.push_back(')');
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
current_reply = http::reply::stock_reply(http::reply::internal_server_error);
|
||||
SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
|
||||
<< ", uri: " << current_request.uri;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef REQUEST_HANDLER_H
|
||||
#define REQUEST_HANDLER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
template <typename Iterator, class HandlerT> struct APIGrammar;
|
||||
struct RouteParameters;
|
||||
class OSRM;
|
||||
|
||||
namespace http
|
||||
{
|
||||
class reply;
|
||||
struct request;
|
||||
}
|
||||
|
||||
class RequestHandler
|
||||
{
|
||||
|
||||
public:
|
||||
using APIGrammarParser = APIGrammar<std::string::iterator, RouteParameters>;
|
||||
|
||||
RequestHandler();
|
||||
RequestHandler(const RequestHandler &) = delete;
|
||||
|
||||
void handle_request(const http::request ¤t_request, http::reply ¤t_reply);
|
||||
void RegisterRoutingMachine(OSRM *osrm);
|
||||
|
||||
private:
|
||||
OSRM *routing_machine;
|
||||
};
|
||||
|
||||
#endif // REQUEST_HANDLER_H
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "RequestParser.h"
|
||||
|
||||
#include "http/request.hpp"
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
RequestParser::RequestParser()
|
||||
: state(internal_state::method_start), header({"", ""}), compression_type(no_compression)
|
||||
{
|
||||
}
|
||||
|
||||
std::tuple<osrm::tribool, compression_type>
|
||||
RequestParser::parse(request ¤t_request, char *begin, char *end)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
osrm::tribool result = consume(current_request, *begin++);
|
||||
if (result != osrm::tribool::indeterminate)
|
||||
{
|
||||
return std::make_tuple(result, compression_type);
|
||||
}
|
||||
}
|
||||
osrm::tribool result = osrm::tribool::indeterminate;
|
||||
return std::make_tuple(result, compression_type);
|
||||
}
|
||||
|
||||
osrm::tribool RequestParser::consume(request ¤t_request, const char input)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case internal_state::method_start:
|
||||
if (!is_char(input) || is_CTL(input) || is_special(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
state = internal_state::method;
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::method:
|
||||
if (input == ' ')
|
||||
{
|
||||
state = internal_state::uri;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (!is_char(input) || is_CTL(input) || is_special(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::uri_start:
|
||||
if (is_CTL(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
state = internal_state::uri;
|
||||
current_request.uri.push_back(input);
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::uri:
|
||||
if (input == ' ')
|
||||
{
|
||||
state = internal_state::http_version_h;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (is_CTL(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
current_request.uri.push_back(input);
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::http_version_h:
|
||||
if (input == 'H')
|
||||
{
|
||||
state = internal_state::http_version_t_1;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_t_1:
|
||||
if (input == 'T')
|
||||
{
|
||||
state = internal_state::http_version_t_2;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_t_2:
|
||||
if (input == 'T')
|
||||
{
|
||||
state = internal_state::http_version_p;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_p:
|
||||
if (input == 'P')
|
||||
{
|
||||
state = internal_state::http_version_slash;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_slash:
|
||||
if (input == '/')
|
||||
{
|
||||
state = internal_state::http_version_major_start;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_major_start:
|
||||
if (is_digit(input))
|
||||
{
|
||||
state = internal_state::http_version_major;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_major:
|
||||
if (input == '.')
|
||||
{
|
||||
state = internal_state::http_version_minor_start;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (is_digit(input))
|
||||
{
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_minor_start:
|
||||
if (is_digit(input))
|
||||
{
|
||||
state = internal_state::http_version_minor;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::http_version_minor:
|
||||
if (input == '\r')
|
||||
{
|
||||
state = internal_state::expecting_newline_1;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (is_digit(input))
|
||||
{
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::expecting_newline_1:
|
||||
if (input == '\n')
|
||||
{
|
||||
state = internal_state::header_line_start;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::header_line_start:
|
||||
if (boost::iequals(header.name, "Accept-Encoding"))
|
||||
{
|
||||
/* giving gzip precedence over deflate */
|
||||
if (boost::icontains(header.value, "deflate"))
|
||||
{
|
||||
compression_type = deflate_rfc1951;
|
||||
}
|
||||
if (boost::icontains(header.value, "gzip"))
|
||||
{
|
||||
compression_type = gzip_rfc1952;
|
||||
}
|
||||
}
|
||||
|
||||
if (boost::iequals(header.name, "Referer"))
|
||||
{
|
||||
current_request.referrer = header.value;
|
||||
}
|
||||
|
||||
if (boost::iequals(header.name, "User-Agent"))
|
||||
{
|
||||
current_request.agent = header.value;
|
||||
}
|
||||
|
||||
if (input == '\r')
|
||||
{
|
||||
state = internal_state::expecting_newline_3;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (!is_char(input) || is_CTL(input) || is_special(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
state = internal_state::header_name;
|
||||
header.clear();
|
||||
header.name.push_back(input);
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::header_lws:
|
||||
if (input == '\r')
|
||||
{
|
||||
state = internal_state::expecting_newline_2;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (input == ' ' || input == '\t')
|
||||
{
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (is_CTL(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
state = internal_state::header_value;
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::header_name:
|
||||
if (input == ':')
|
||||
{
|
||||
state = internal_state::space_before_header_value;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (!is_char(input) || is_CTL(input) || is_special(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
header.name.push_back(input);
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::space_before_header_value:
|
||||
if (input == ' ')
|
||||
{
|
||||
state = internal_state::header_value;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
case internal_state::header_value:
|
||||
if (input == '\r')
|
||||
{
|
||||
state = internal_state::expecting_newline_2;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
if (is_CTL(input))
|
||||
{
|
||||
return osrm::tribool::no;
|
||||
}
|
||||
header.value.push_back(input);
|
||||
return osrm::tribool::indeterminate;
|
||||
case internal_state::expecting_newline_2:
|
||||
if (input == '\n')
|
||||
{
|
||||
state = internal_state::header_line_start;
|
||||
return osrm::tribool::indeterminate;
|
||||
}
|
||||
return osrm::tribool::no;
|
||||
default: // expecting_newline_3
|
||||
return (input == '\n' ? osrm::tribool::yes : osrm::tribool::no);
|
||||
}
|
||||
}
|
||||
|
||||
bool RequestParser::is_char(const int character) const
|
||||
{
|
||||
return character >= 0 && character <= 127;
|
||||
}
|
||||
|
||||
bool RequestParser::is_CTL(const int character) const
|
||||
{
|
||||
return (character >= 0 && character <= 31) || (character == 127);
|
||||
}
|
||||
|
||||
bool RequestParser::is_special(const int character) const
|
||||
{
|
||||
switch (character)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
bool RequestParser::is_digit(const int character) const
|
||||
{
|
||||
return character >= '0' && character <= '9';
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef REQUEST_PARSER_H
|
||||
#define REQUEST_PARSER_H
|
||||
|
||||
#include "http/compression_type.hpp"
|
||||
#include "http/header.hpp"
|
||||
#include "../data_structures/tribool.hpp"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
struct request;
|
||||
|
||||
class RequestParser
|
||||
{
|
||||
public:
|
||||
RequestParser();
|
||||
|
||||
std::tuple<osrm::tribool, compression_type>
|
||||
parse(request ¤t_request, char *begin, char *end);
|
||||
|
||||
private:
|
||||
osrm::tribool consume(request ¤t_request, const char input);
|
||||
|
||||
bool is_char(const int character) const;
|
||||
|
||||
bool is_CTL(const int character) const;
|
||||
|
||||
bool is_special(const int character) const;
|
||||
|
||||
bool is_digit(const int character) const;
|
||||
|
||||
enum class internal_state : unsigned char
|
||||
{
|
||||
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;
|
||||
|
||||
header header;
|
||||
compression_type compression_type;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
#endif // REQUEST_PARSER_H
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include "Connection.h"
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#include "../Util/cast.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
// Note: returns a shared instead of a unique ptr as it is captured in a lambda somewhere else
|
||||
static std::shared_ptr<Server>
|
||||
CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion();
|
||||
const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency());
|
||||
const unsigned real_num_threads = std::min(hardware_threads, requested_num_threads);
|
||||
return std::make_shared<Server>(ip_address, ip_port, real_num_threads);
|
||||
}
|
||||
|
||||
explicit Server(const std::string &address, const int port, const unsigned thread_pool_size)
|
||||
: thread_pool_size(thread_pool_size), acceptor(io_service),
|
||||
new_connection(std::make_shared<http::Connection>(io_service, request_handler))
|
||||
{
|
||||
const std::string port_string = cast::integral_to_string(port);
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver(io_service);
|
||||
boost::asio::ip::tcp::resolver::query query(address, port_string);
|
||||
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(
|
||||
new_connection->socket(),
|
||||
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
std::vector<std::shared_ptr<std::thread>> threads;
|
||||
for (unsigned i = 0; i < thread_pool_size; ++i)
|
||||
{
|
||||
std::shared_ptr<std::thread> thread = std::make_shared<std::thread>(
|
||||
boost::bind(&boost::asio::io_service::run, &io_service));
|
||||
threads.push_back(thread);
|
||||
}
|
||||
for (auto thread : threads)
|
||||
{
|
||||
thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
void Stop() { io_service.stop(); }
|
||||
|
||||
RequestHandler &GetRequestHandlerPtr() { return request_handler; }
|
||||
|
||||
private:
|
||||
void HandleAccept(const boost::system::error_code &e)
|
||||
{
|
||||
if (!e)
|
||||
{
|
||||
new_connection->start();
|
||||
new_connection = std::make_shared<http::Connection>(io_service, request_handler);
|
||||
acceptor.async_accept(
|
||||
new_connection->socket(),
|
||||
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned thread_pool_size;
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::ip::tcp::acceptor acceptor;
|
||||
std::shared_ptr<http::Connection> new_connection;
|
||||
RequestHandler request_handler;
|
||||
};
|
||||
|
||||
#endif // SERVER_H
|
||||
Reference in New Issue
Block a user