No longer stores pointer to Server/Client instance in Session objects. Some other cleanups as well.
This commit is contained in:
parent
f3f527467f
commit
6c2c8d680b
5 changed files with 107 additions and 123 deletions
|
|
@ -35,9 +35,6 @@ namespace SimpleWeb {
|
|||
|
||||
template <class socket_type>
|
||||
class ClientBase {
|
||||
ClientBase(const ClientBase &) = delete;
|
||||
ClientBase &operator=(const ClientBase &) = delete;
|
||||
|
||||
public:
|
||||
class Content : public std::istream {
|
||||
friend class ClientBase<socket_type>;
|
||||
|
|
@ -119,7 +116,8 @@ namespace SimpleWeb {
|
|||
protected:
|
||||
class Connection {
|
||||
public:
|
||||
Connection(std::unique_ptr<socket_type> &&socket) : socket(std::move(socket)) {}
|
||||
template <typename... Args>
|
||||
Connection(Args &&... args) : socket(new socket_type(std::forward<Args>(args)...)) {}
|
||||
|
||||
std::unique_ptr<socket_type> socket; // Socket must be unique_ptr since asio::ssl::stream<asio::ip::tcp::socket> is not movable
|
||||
std::mutex socket_close_mutex;
|
||||
|
|
@ -136,12 +134,14 @@ namespace SimpleWeb {
|
|||
|
||||
class Session {
|
||||
public:
|
||||
Session(ClientBase<socket_type> *client, const std::shared_ptr<Connection> &connection, std::unique_ptr<asio::streambuf> &&request_buffer)
|
||||
: client(client), cancel_callbacks(client->cancel_callbacks), cancel_callbacks_mutex(client->cancel_callbacks_mutex),
|
||||
connection(connection), request_buffer(std::move(request_buffer)), response(new Response()) {}
|
||||
Session(std::shared_ptr<bool> cancel_handlers, std::shared_ptr<SharedMutex> cancel_handlers_mutex, long timeout,
|
||||
std::shared_ptr<Connection> connection, std::unique_ptr<asio::streambuf> request_buffer)
|
||||
: cancel_handlers(std::move(cancel_handlers)), cancel_handlers_mutex(std::move(cancel_handlers_mutex)), timeout(timeout),
|
||||
connection(std::move(connection)), request_buffer(std::move(request_buffer)), response(new Response()) {}
|
||||
ClientBase<socket_type> *client;
|
||||
std::shared_ptr<bool> cancel_callbacks;
|
||||
std::shared_ptr<SharedMutex> cancel_callbacks_mutex;
|
||||
std::shared_ptr<bool> cancel_handlers;
|
||||
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
|
||||
long timeout;
|
||||
std::shared_ptr<Connection> connection;
|
||||
std::unique_ptr<asio::streambuf> request_buffer;
|
||||
std::shared_ptr<Response> response;
|
||||
|
|
@ -151,7 +151,7 @@ namespace SimpleWeb {
|
|||
|
||||
void set_timeout(long seconds = 0) {
|
||||
if(seconds == 0)
|
||||
seconds = client->config.timeout;
|
||||
seconds = timeout;
|
||||
if(seconds == 0) {
|
||||
timer = nullptr;
|
||||
return;
|
||||
|
|
@ -244,25 +244,24 @@ namespace SimpleWeb {
|
|||
/// Do not use concurrently with the synchronous request functions.
|
||||
void request(const std::string &method, const std::string &path, string_view content, const CaseInsensitiveMultimap &header,
|
||||
std::function<void(std::shared_ptr<Response>, const error_code &)> &&request_callback_) {
|
||||
auto session = std::make_shared<Session>(this, get_connection(), create_request_header(method, path, header));
|
||||
auto client = session->client;
|
||||
auto session = std::make_shared<Session>(cancel_handlers, cancel_handlers_mutex, config.timeout, get_connection(), create_request_header(method, path, header));
|
||||
auto connection = session->connection;
|
||||
auto response = session->response;
|
||||
auto request_callback = std::make_shared<std::function<void(std::shared_ptr<Response>, const error_code &)>>(std::move(request_callback_));
|
||||
session->callback = [client, connection, response, request_callback](const error_code &ec) {
|
||||
session->callback = [this, connection, response, request_callback](const error_code &ec) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(client->connections_mutex);
|
||||
std::unique_lock<std::mutex> lock(this->connections_mutex);
|
||||
connection->in_use = false;
|
||||
|
||||
// Remove unused connections, but keep one open for HTTP persistent connection:
|
||||
size_t unused_connections = 0;
|
||||
for(auto it = client->connections.begin(); it != client->connections.end();) {
|
||||
for(auto it = this->connections.begin(); it != this->connections.end();) {
|
||||
if((*it)->in_use)
|
||||
++it;
|
||||
else {
|
||||
++unused_connections;
|
||||
if(unused_connections > 1)
|
||||
it = client->connections.erase(it);
|
||||
it = this->connections.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
|
@ -303,25 +302,24 @@ namespace SimpleWeb {
|
|||
/// Asynchronous request where setting and/or running Client's io_service is required.
|
||||
void request(const std::string &method, const std::string &path, std::istream &content, const CaseInsensitiveMultimap &header,
|
||||
std::function<void(std::shared_ptr<Response>, const error_code &)> &&request_callback_) {
|
||||
auto session = std::make_shared<Session>(this, get_connection(), create_request_header(method, path, header));
|
||||
auto client = session->client;
|
||||
auto session = std::make_shared<Session>(cancel_handlers, cancel_handlers_mutex, config.timeout, get_connection(), create_request_header(method, path, header));
|
||||
auto connection = session->connection;
|
||||
auto response = session->response;
|
||||
auto request_callback = std::make_shared<std::function<void(std::shared_ptr<Response>, const error_code &)>>(std::move(request_callback_));
|
||||
session->callback = [client, connection, response, request_callback](const error_code &ec) {
|
||||
session->callback = [this, connection, response, request_callback](const error_code &ec) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(client->connections_mutex);
|
||||
std::unique_lock<std::mutex> lock(this->connections_mutex);
|
||||
connection->in_use = false;
|
||||
|
||||
// Remove unused connections, but keep one open for HTTP persistent connection:
|
||||
size_t unused_connections = 0;
|
||||
for(auto it = client->connections.begin(); it != client->connections.end();) {
|
||||
for(auto it = this->connections.begin(); it != this->connections.end();) {
|
||||
if((*it)->in_use)
|
||||
++it;
|
||||
else {
|
||||
++unused_connections;
|
||||
if(unused_connections > 1)
|
||||
it = client->connections.erase(it);
|
||||
it = this->connections.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
|
@ -363,8 +361,8 @@ namespace SimpleWeb {
|
|||
|
||||
virtual ~ClientBase() {
|
||||
{
|
||||
auto lock = cancel_callbacks_mutex->unique_lock();
|
||||
*cancel_callbacks = true;
|
||||
auto lock = cancel_handlers_mutex->unique_lock();
|
||||
*cancel_handlers = true;
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
|
@ -378,13 +376,13 @@ namespace SimpleWeb {
|
|||
std::vector<std::shared_ptr<Connection>> connections;
|
||||
std::mutex connections_mutex;
|
||||
|
||||
std::shared_ptr<bool> cancel_callbacks;
|
||||
std::shared_ptr<SharedMutex> cancel_callbacks_mutex;
|
||||
std::shared_ptr<bool> cancel_handlers;
|
||||
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
|
||||
|
||||
size_t concurrent_synchronous_requests = 0;
|
||||
std::mutex concurrent_synchronous_requests_mutex;
|
||||
|
||||
ClientBase(const std::string &host_port, unsigned short default_port) : io_service(new asio::io_service()), cancel_callbacks(new bool(false)), cancel_callbacks_mutex(new SharedMutex()) {
|
||||
ClientBase(const std::string &host_port, unsigned short default_port) : io_service(new asio::io_service()), cancel_handlers(new bool(false)), cancel_handlers_mutex(new SharedMutex()) {
|
||||
auto parsed_host_port = parse_host_port(host_port, default_port);
|
||||
host = parsed_host_port.first;
|
||||
port = parsed_host_port.second;
|
||||
|
|
@ -455,8 +453,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_write(*session->connection->socket, session->request_buffer->data(), [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
this->read(session);
|
||||
|
|
@ -471,8 +469,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n\r\n", [this, session](const error_code &ec, size_t bytes_transferred) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
session->connection->attempt_reconnect = true;
|
||||
|
|
@ -488,8 +486,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_read(*session->connection->socket, session->response->content_buffer, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
session->callback(ec);
|
||||
|
|
@ -510,8 +508,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_read(*session->connection->socket, session->response->content_buffer, [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
session->callback(ec);
|
||||
|
|
@ -547,8 +545,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n", [this, session, tmp_streambuf](const error_code &ec, size_t bytes_transferred) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
std::string line;
|
||||
|
|
@ -585,8 +583,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout();
|
||||
asio::async_read(*session->connection->socket, session->response->content_buffer, asio::transfer_exactly(2 + length - num_additional_bytes), [this, session, post_process](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
post_process();
|
||||
|
|
@ -614,16 +612,12 @@ namespace SimpleWeb {
|
|||
|
||||
template <>
|
||||
class Client<HTTP> : public ClientBase<HTTP> {
|
||||
friend ClientBase<HTTP>;
|
||||
Client(const Client &) = delete;
|
||||
Client &operator=(const Client &) = delete;
|
||||
|
||||
public:
|
||||
Client(const std::string &server_port_path) : ClientBase<HTTP>::ClientBase(server_port_path, 80) {}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Connection> create_connection() override {
|
||||
return std::make_shared<Connection>(std::unique_ptr<HTTP>(new HTTP(*io_service)));
|
||||
return std::make_shared<Connection>(*io_service);
|
||||
}
|
||||
|
||||
void connect(const std::shared_ptr<Session> &session) override {
|
||||
|
|
@ -632,15 +626,15 @@ namespace SimpleWeb {
|
|||
session->set_timeout(config.timeout_connect);
|
||||
resolver->async_resolve(*query, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator it) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
session->set_timeout(config.timeout_connect);
|
||||
asio::async_connect(*session->connection->socket, it, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator /*it*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
asio::ip::tcp::no_delay option(true);
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@ namespace SimpleWeb {
|
|||
|
||||
template <>
|
||||
class Client<HTTPS> : public ClientBase<HTTPS> {
|
||||
friend ClientBase<HTTPS>;
|
||||
Client(const Client &) = delete;
|
||||
Client &operator=(const Client &) = delete;
|
||||
|
||||
public:
|
||||
Client(const std::string &server_port_path, bool verify_certificate = true, const std::string &cert_file = std::string(),
|
||||
const std::string &private_key_file = std::string(), const std::string &verify_file = std::string())
|
||||
|
|
@ -45,22 +41,22 @@ namespace SimpleWeb {
|
|||
asio::ssl::context context;
|
||||
|
||||
std::shared_ptr<Connection> create_connection() override {
|
||||
return std::make_shared<Connection>(std::unique_ptr<HTTPS>(new HTTPS(*io_service, context)));
|
||||
return std::make_shared<Connection>(*io_service, context);
|
||||
}
|
||||
|
||||
void connect(const std::shared_ptr<Session> &session) override {
|
||||
if(!session->connection->socket->lowest_layer().is_open()) {
|
||||
auto resolver = std::make_shared<asio::ip::tcp::resolver>(*io_service);
|
||||
resolver->async_resolve(*query, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator it) {
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
session->set_timeout(this->config.timeout_connect);
|
||||
asio::async_connect(session->connection->socket->lowest_layer(), it, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator /*it*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
asio::ip::tcp::no_delay option(true);
|
||||
|
|
@ -76,16 +72,16 @@ namespace SimpleWeb {
|
|||
session->set_timeout(this->config.timeout_connect);
|
||||
asio::async_write(session->connection->socket->next_layer(), *write_buffer, [this, session, write_buffer](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
std::shared_ptr<Response> response(new Response());
|
||||
session->set_timeout(this->config.timeout_connect);
|
||||
asio::async_read_until(session->connection->socket->next_layer(), response->content_buffer, "\r\n\r\n", [this, session, response](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
response->parse_header();
|
||||
|
|
@ -131,8 +127,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout(this->config.timeout_connect);
|
||||
session->connection->socket->async_handshake(asio::ssl::stream_base::client, [this, session](const error_code &ec) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
this->write(session);
|
||||
|
|
|
|||
|
|
@ -46,24 +46,22 @@ namespace SimpleWeb {
|
|||
|
||||
template <class socket_type>
|
||||
class ServerBase {
|
||||
ServerBase(const ServerBase &) = delete;
|
||||
ServerBase &operator=(const ServerBase &) = delete;
|
||||
|
||||
protected:
|
||||
class Session;
|
||||
|
||||
public:
|
||||
class Response : public std::enable_shared_from_this<Response>, public std::ostream {
|
||||
class Response : public std::ostream {
|
||||
friend class ServerBase<socket_type>;
|
||||
friend class Server<socket_type>;
|
||||
|
||||
asio::streambuf streambuf;
|
||||
|
||||
std::shared_ptr<Session> session;
|
||||
long timeout_content;
|
||||
|
||||
Response(const std::shared_ptr<Session> &session) : std::ostream(&streambuf), session(session) {}
|
||||
Response(std::shared_ptr<Session> session, long timeout_content) : std::ostream(&streambuf), session(std::move(session)), timeout_content(timeout_content) {}
|
||||
|
||||
template <class size_type>
|
||||
template <typename size_type>
|
||||
void write_header(const CaseInsensitiveMultimap &header, size_type size) {
|
||||
bool content_length_written = false;
|
||||
bool chunked_transfer_encoding = false;
|
||||
|
|
@ -88,15 +86,15 @@ namespace SimpleWeb {
|
|||
|
||||
/// Use this function if you need to recursively send parts of a longer message
|
||||
void send(const std::function<void(const error_code &)> &callback = nullptr) {
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
auto self = this->shared_from_this();
|
||||
session->set_timeout(session->server->config.timeout_content);
|
||||
asio::async_write(*session->connection->socket, streambuf, [self, callback](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
self->session->cancel_timeout();
|
||||
auto lock = self->session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*self->session->cancel_callbacks)
|
||||
session->set_timeout(timeout_content);
|
||||
auto session = this->session;
|
||||
asio::async_write(*session->connection->socket, streambuf, [session, callback](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(callback)
|
||||
callback(ec);
|
||||
|
|
@ -199,14 +197,8 @@ namespace SimpleWeb {
|
|||
private:
|
||||
asio::streambuf streambuf;
|
||||
|
||||
Request(const socket_type &socket) : content(streambuf) {
|
||||
try {
|
||||
remote_endpoint_address = socket.lowest_layer().remote_endpoint().address().to_string();
|
||||
remote_endpoint_port = socket.lowest_layer().remote_endpoint().port();
|
||||
}
|
||||
catch(...) {
|
||||
}
|
||||
}
|
||||
Request(const std::string &remote_endpoint_address = std::string(), unsigned short remote_endpoint_port = 0)
|
||||
: content(streambuf), remote_endpoint_address(remote_endpoint_address), remote_endpoint_port(remote_endpoint_port) {}
|
||||
|
||||
bool parse() {
|
||||
std::string line;
|
||||
|
|
@ -268,7 +260,8 @@ namespace SimpleWeb {
|
|||
protected:
|
||||
class Connection {
|
||||
public:
|
||||
Connection(std::unique_ptr<socket_type> &&socket) : socket(std::move(socket)) {}
|
||||
template <typename... Args>
|
||||
Connection(Args &&... args) : socket(new socket_type(std::forward<Args>(args)...)) {}
|
||||
|
||||
std::unique_ptr<socket_type> socket; // Socket must be unique_ptr since asio::ssl::stream<asio::ip::tcp::socket> is not movable
|
||||
std::mutex socket_close_mutex;
|
||||
|
|
@ -283,13 +276,19 @@ namespace SimpleWeb {
|
|||
|
||||
class Session {
|
||||
public:
|
||||
Session(ServerBase<socket_type> *server, const std::shared_ptr<Connection> &connection)
|
||||
: server(server), cancel_callbacks(server->cancel_callbacks), cancel_callbacks_mutex(server->cancel_callbacks_mutex),
|
||||
connection(connection), request(new Request(*connection->socket)) {}
|
||||
Session(std::shared_ptr<bool> cancel_handlers, std::shared_ptr<SharedMutex> cancel_handlers_mutex, std::shared_ptr<Connection> connection)
|
||||
: cancel_handlers(std::move(cancel_handlers)), cancel_handlers_mutex(std::move(cancel_handlers_mutex)), connection(std::move(connection)) {
|
||||
try {
|
||||
auto remote_endpoint = this->connection->socket->lowest_layer().remote_endpoint();
|
||||
request = std::shared_ptr<Request>(new Request(remote_endpoint.address().to_string(), remote_endpoint.port()));
|
||||
}
|
||||
catch(...) {
|
||||
request = std::shared_ptr<Request>(new Request());
|
||||
}
|
||||
}
|
||||
|
||||
ServerBase<socket_type> *server;
|
||||
std::shared_ptr<bool> cancel_callbacks;
|
||||
std::shared_ptr<SharedMutex> cancel_callbacks_mutex;
|
||||
std::shared_ptr<bool> cancel_handlers;
|
||||
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
|
||||
std::shared_ptr<Connection> connection;
|
||||
std::shared_ptr<Request> request;
|
||||
|
||||
|
|
@ -347,7 +346,7 @@ namespace SimpleWeb {
|
|||
|
||||
public:
|
||||
regex_orderable(const char *regex_cstr) : regex::regex(regex_cstr), str(regex_cstr) {}
|
||||
regex_orderable(const std::string ®ex_str) : regex::regex(regex_str), str(regex_str) {}
|
||||
regex_orderable(std::string regex_str) : regex::regex(regex_str), str(std::move(regex_str)) {}
|
||||
bool operator<(const regex_orderable &rhs) const {
|
||||
return str < rhs.str;
|
||||
}
|
||||
|
|
@ -427,8 +426,8 @@ namespace SimpleWeb {
|
|||
|
||||
virtual ~ServerBase() {
|
||||
{
|
||||
auto lock = cancel_callbacks_mutex->unique_lock();
|
||||
*cancel_callbacks = true;
|
||||
auto lock = cancel_handlers_mutex->unique_lock();
|
||||
*cancel_handlers = true;
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
|
@ -442,18 +441,19 @@ namespace SimpleWeb {
|
|||
std::shared_ptr<std::unordered_set<Connection *>> connections;
|
||||
std::shared_ptr<std::mutex> connections_mutex;
|
||||
|
||||
std::shared_ptr<bool> cancel_callbacks;
|
||||
std::shared_ptr<SharedMutex> cancel_callbacks_mutex;
|
||||
std::shared_ptr<bool> cancel_handlers;
|
||||
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
|
||||
|
||||
ServerBase(unsigned short port) : config(port), connections(new std::unordered_set<Connection *>()), connections_mutex(new std::mutex()),
|
||||
cancel_callbacks(new bool(false)), cancel_callbacks_mutex(new SharedMutex()) {}
|
||||
cancel_handlers(new bool(false)), cancel_handlers_mutex(new SharedMutex()) {}
|
||||
|
||||
virtual void accept() = 0;
|
||||
|
||||
std::shared_ptr<Connection> create_connection(socket_type *socket) {
|
||||
template <typename... Args>
|
||||
std::shared_ptr<Connection> create_connection(Args &&... args) {
|
||||
auto connections = this->connections;
|
||||
auto connections_mutex = this->connections_mutex;
|
||||
auto connection = std::shared_ptr<Connection>(new Connection(std::unique_ptr<socket_type>(socket)), [connections, connections_mutex](Connection *connection) {
|
||||
auto connection = std::shared_ptr<Connection>(new Connection(std::forward<Args>(args)...), [connections, connections_mutex](Connection *connection) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(*connections_mutex);
|
||||
auto it = connections->find(connection);
|
||||
|
|
@ -473,8 +473,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout(config.timeout_request);
|
||||
asio::async_read_until(*session->connection->socket, session->request->streambuf, "\r\n\r\n", [this, session](const error_code &ec, size_t bytes_transferred) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec) {
|
||||
//request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
|
||||
|
|
@ -502,8 +502,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout(config.timeout_content);
|
||||
asio::async_read(*session->connection->socket, session->request->streambuf, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
this->find_resource(session);
|
||||
|
|
@ -551,7 +551,7 @@ namespace SimpleWeb {
|
|||
void write_response(const std::shared_ptr<Session> &session,
|
||||
std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Response>, std::shared_ptr<typename ServerBase<socket_type>::Request>)> &resource_function) {
|
||||
session->set_timeout(config.timeout_content);
|
||||
auto response = std::shared_ptr<Response>(new Response(session), [this](Response *response_ptr) {
|
||||
auto response = std::shared_ptr<Response>(new Response(session, config.timeout_content), [this](Response *response_ptr) {
|
||||
auto response = std::shared_ptr<Response>(response_ptr);
|
||||
response->send([this, response](const error_code &ec) {
|
||||
if(!ec) {
|
||||
|
|
@ -563,13 +563,13 @@ namespace SimpleWeb {
|
|||
if(case_insensitive_equal(it->second, "close"))
|
||||
return;
|
||||
else if(case_insensitive_equal(it->second, "keep-alive")) {
|
||||
auto new_session = std::make_shared<Session>(response->session->server, response->session->connection);
|
||||
auto new_session = std::make_shared<Session>(this->cancel_handlers, this->cancel_handlers_mutex, response->session->connection);
|
||||
this->read_request_and_content(new_session);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(response->session->request->http_version >= "1.1") {
|
||||
auto new_session = std::make_shared<Session>(response->session->server, response->session->connection);
|
||||
auto new_session = std::make_shared<Session>(this->cancel_handlers, this->cancel_handlers_mutex, response->session->connection);
|
||||
this->read_request_and_content(new_session);
|
||||
return;
|
||||
}
|
||||
|
|
@ -597,19 +597,16 @@ namespace SimpleWeb {
|
|||
|
||||
template <>
|
||||
class Server<HTTP> : public ServerBase<HTTP> {
|
||||
Server(const Server &) = delete;
|
||||
Server &operator=(const Server &) = delete;
|
||||
|
||||
public:
|
||||
Server() : ServerBase<HTTP>::ServerBase(80) {}
|
||||
|
||||
protected:
|
||||
void accept() override {
|
||||
auto session = std::make_shared<Session>(this, create_connection(new HTTP(*io_service)));
|
||||
auto session = std::make_shared<Session>(cancel_handlers, cancel_handlers_mutex, create_connection(*io_service));
|
||||
|
||||
acceptor->async_accept(*session->connection->socket, [this, session](const error_code &ec) {
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
|
||||
//Immediately start accepting a new connection (unless io_service has been stopped)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ namespace SimpleWeb {
|
|||
|
||||
template <>
|
||||
class Server<HTTPS> : public ServerBase<HTTPS> {
|
||||
Server(const Server &) = delete;
|
||||
Server &operator=(const Server &) = delete;
|
||||
|
||||
std::string session_id_context;
|
||||
bool set_session_id_context = false;
|
||||
|
||||
|
|
@ -51,11 +48,11 @@ namespace SimpleWeb {
|
|||
asio::ssl::context context;
|
||||
|
||||
void accept() override {
|
||||
auto session = std::make_shared<Session>(this, create_connection(new HTTPS(*io_service, context)));
|
||||
auto session = std::make_shared<Session>(cancel_handlers, cancel_handlers_mutex, create_connection(*io_service, context));
|
||||
|
||||
acceptor->async_accept(session->connection->socket->lowest_layer(), [this, session](const error_code &ec) {
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
|
||||
if(ec != asio::error::operation_aborted)
|
||||
|
|
@ -69,8 +66,8 @@ namespace SimpleWeb {
|
|||
session->set_timeout(config.timeout_request);
|
||||
session->connection->socket->async_handshake(asio::ssl::stream_base::server, [this, session](const error_code &ec) {
|
||||
session->cancel_timeout();
|
||||
auto lock = session->cancel_callbacks_mutex->shared_lock();
|
||||
if(*session->cancel_callbacks)
|
||||
auto lock = session->cancel_handlers_mutex->shared_lock();
|
||||
if(*session->cancel_handlers)
|
||||
return;
|
||||
if(!ec)
|
||||
this->read_request_and_content(session);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public:
|
|||
void accept() override {}
|
||||
|
||||
void parse_request_test() {
|
||||
auto session = std::make_shared<Session>(this, create_connection(new HTTP(*io_service)));
|
||||
auto session = std::make_shared<Session>(cancel_handlers, cancel_handlers_mutex, create_connection(*io_service));
|
||||
|
||||
std::ostream stream(&session->request->content.streambuf);
|
||||
stream << "GET /test/ HTTP/1.1\r\n";
|
||||
|
|
@ -151,7 +151,7 @@ int main() {
|
|||
|
||||
asio::io_service io_service;
|
||||
asio::ip::tcp::socket socket(io_service);
|
||||
SimpleWeb::Server<HTTP>::Request request(socket);
|
||||
SimpleWeb::Server<HTTP>::Request request;
|
||||
{
|
||||
request.query_string = "";
|
||||
auto queries = request.parse_query_string();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue