Merge branch 'new_asio' of https://gitlab.com/eidheim/Simple-Web-Server
This commit is contained in:
commit
45d39e3c18
6 changed files with 163 additions and 99 deletions
69
asio_compatibility.hpp
Normal file
69
asio_compatibility.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef SIMPLE_WEB_ASIO_HPP
|
||||||
|
#define SIMPLE_WEB_ASIO_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#ifdef USE_STANDALONE_ASIO
|
||||||
|
#include <asio.hpp>
|
||||||
|
#include <asio/steady_timer.hpp>
|
||||||
|
namespace SimpleWeb {
|
||||||
|
using error_code = std::error_code;
|
||||||
|
using errc = std::errc;
|
||||||
|
using system_error = std::system_error;
|
||||||
|
namespace make_error_code = std;
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
#else
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/steady_timer.hpp>
|
||||||
|
namespace SimpleWeb {
|
||||||
|
namespace asio = boost::asio;
|
||||||
|
using error_code = boost::system::error_code;
|
||||||
|
namespace errc = boost::system::errc;
|
||||||
|
using system_error = boost::system::system_error;
|
||||||
|
namespace make_error_code = boost::system::errc;
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SimpleWeb {
|
||||||
|
#if(USE_STANDALONE_ASIO && ASIO_VERSION >= 101300) || BOOST_ASIO_VERSION >= 101300
|
||||||
|
using io_context = asio::io_context;
|
||||||
|
using resolver_results = asio::ip::tcp::resolver::results_type;
|
||||||
|
using async_connect_endpoint = asio::ip::tcp::endpoint;
|
||||||
|
|
||||||
|
inline void restart(io_context &context) noexcept {
|
||||||
|
context.restart();
|
||||||
|
}
|
||||||
|
inline asio::ip::address make_address(const std::string &str) noexcept {
|
||||||
|
return asio::ip::make_address(str);
|
||||||
|
}
|
||||||
|
template <typename socket_type>
|
||||||
|
asio::executor get_socket_executor(socket_type &socket) {
|
||||||
|
return socket.get_executor();
|
||||||
|
}
|
||||||
|
template <typename handler_type>
|
||||||
|
void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair<std::string, std::string> &host_port, handler_type &&handler) {
|
||||||
|
resolver.async_resolve(host_port.first, host_port.second, std::forward<handler_type>(handler));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
using io_context = asio::io_service;
|
||||||
|
using resolver_results = asio::ip::tcp::resolver::iterator;
|
||||||
|
using async_connect_endpoint = asio::ip::tcp::resolver::iterator;
|
||||||
|
|
||||||
|
inline void restart(io_context &context) noexcept {
|
||||||
|
context.reset();
|
||||||
|
}
|
||||||
|
inline asio::ip::address make_address(const std::string &str) noexcept {
|
||||||
|
return asio::ip::address::from_string(str);
|
||||||
|
}
|
||||||
|
template <typename socket_type>
|
||||||
|
io_context &get_socket_executor(socket_type &socket) {
|
||||||
|
return socket.get_io_service();
|
||||||
|
}
|
||||||
|
template <typename handler_type>
|
||||||
|
void async_resolve(asio::ip::tcp::resolver &resolver, const std::pair<std::string, std::string> &host_port, handler_type &&handler) {
|
||||||
|
resolver.async_resolve(asio::ip::tcp::resolver::query(host_port.first, host_port.second), std::forward<handler_type>(handler));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
|
||||||
|
#endif /* SIMPLE_WEB_ASIO_HPP */
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef CLIENT_HTTP_HPP
|
#ifndef CLIENT_HTTP_HPP
|
||||||
#define CLIENT_HTTP_HPP
|
#define CLIENT_HTTP_HPP
|
||||||
|
|
||||||
|
#include "asio_compatibility.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -8,27 +9,6 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef USE_STANDALONE_ASIO
|
|
||||||
#include <asio.hpp>
|
|
||||||
#include <asio/steady_timer.hpp>
|
|
||||||
namespace SimpleWeb {
|
|
||||||
using error_code = std::error_code;
|
|
||||||
using errc = std::errc;
|
|
||||||
using system_error = std::system_error;
|
|
||||||
namespace make_error_code = std;
|
|
||||||
} // namespace SimpleWeb
|
|
||||||
#else
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
|
||||||
namespace SimpleWeb {
|
|
||||||
namespace asio = boost::asio;
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
namespace errc = boost::system::errc;
|
|
||||||
using system_error = boost::system::system_error;
|
|
||||||
namespace make_error_code = boost::system::errc;
|
|
||||||
} // namespace SimpleWeb
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace SimpleWeb {
|
namespace SimpleWeb {
|
||||||
template <class socket_type>
|
template <class socket_type>
|
||||||
class Client;
|
class Client;
|
||||||
|
|
@ -119,21 +99,25 @@ namespace SimpleWeb {
|
||||||
timer = nullptr;
|
timer = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(socket->get_io_service()));
|
timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds)));
|
||||||
timer->expires_from_now(std::chrono::seconds(seconds));
|
std::weak_ptr<Connection> self_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed
|
||||||
auto self = this->shared_from_this();
|
timer->async_wait([self_weak](const error_code &ec) {
|
||||||
timer->async_wait([self](const error_code &ec) {
|
|
||||||
if(!ec) {
|
if(!ec) {
|
||||||
error_code ec;
|
if(auto self = self_weak.lock()) {
|
||||||
self->socket->lowest_layer().cancel(ec);
|
error_code ec;
|
||||||
|
self->socket->lowest_layer().cancel(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel_timeout() noexcept {
|
void cancel_timeout() noexcept {
|
||||||
if(timer) {
|
if(timer) {
|
||||||
error_code ec;
|
try {
|
||||||
timer->cancel(ec);
|
timer->cancel();
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -155,7 +139,7 @@ namespace SimpleWeb {
|
||||||
|
|
||||||
/// If you have your own asio::io_service, store its pointer here before calling request().
|
/// If you have your own asio::io_service, store its pointer here before calling request().
|
||||||
/// When using asynchronous requests, running the io_service is up to the programmer.
|
/// When using asynchronous requests, running the io_service is up to the programmer.
|
||||||
std::shared_ptr<asio::io_service> io_service;
|
std::shared_ptr<io_context> io_service;
|
||||||
|
|
||||||
/// Convenience function to perform synchronous request. The io_service is run within this function.
|
/// Convenience function to perform synchronous request. The io_service is run within this function.
|
||||||
/// If reusing the io_service for other tasks, use the asynchronous request functions instead.
|
/// If reusing the io_service for other tasks, use the asynchronous request functions instead.
|
||||||
|
|
@ -178,7 +162,7 @@ namespace SimpleWeb {
|
||||||
std::lock_guard<std::mutex> lock(concurrent_synchronous_requests_mutex);
|
std::lock_guard<std::mutex> lock(concurrent_synchronous_requests_mutex);
|
||||||
--concurrent_synchronous_requests;
|
--concurrent_synchronous_requests;
|
||||||
if(!concurrent_synchronous_requests)
|
if(!concurrent_synchronous_requests)
|
||||||
io_service->reset();
|
restart(*io_service);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ec)
|
if(ec)
|
||||||
|
|
@ -208,7 +192,7 @@ namespace SimpleWeb {
|
||||||
std::lock_guard<std::mutex> lock(concurrent_synchronous_requests_mutex);
|
std::lock_guard<std::mutex> lock(concurrent_synchronous_requests_mutex);
|
||||||
--concurrent_synchronous_requests;
|
--concurrent_synchronous_requests;
|
||||||
if(!concurrent_synchronous_requests)
|
if(!concurrent_synchronous_requests)
|
||||||
io_service->reset();
|
restart(*io_service);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ec)
|
if(ec)
|
||||||
|
|
@ -362,7 +346,7 @@ namespace SimpleWeb {
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
unsigned short default_port;
|
unsigned short default_port;
|
||||||
|
|
||||||
std::unique_ptr<asio::ip::tcp::resolver::query> query;
|
std::unique_ptr<std::pair<std::string, std::string>> host_port;
|
||||||
|
|
||||||
std::unordered_set<std::shared_ptr<Connection>> connections;
|
std::unordered_set<std::shared_ptr<Connection>> connections;
|
||||||
std::mutex connections_mutex;
|
std::mutex connections_mutex;
|
||||||
|
|
@ -383,7 +367,7 @@ namespace SimpleWeb {
|
||||||
std::lock_guard<std::mutex> lock(connections_mutex);
|
std::lock_guard<std::mutex> lock(connections_mutex);
|
||||||
|
|
||||||
if(!io_service) {
|
if(!io_service) {
|
||||||
io_service = std::make_shared<asio::io_service>();
|
io_service = std::make_shared<io_context>();
|
||||||
internal_io_service = true;
|
internal_io_service = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,12 +384,12 @@ namespace SimpleWeb {
|
||||||
connection->attempt_reconnect = true;
|
connection->attempt_reconnect = true;
|
||||||
connection->in_use = true;
|
connection->in_use = true;
|
||||||
|
|
||||||
if(!query) {
|
if(!host_port) {
|
||||||
if(config.proxy_server.empty())
|
if(config.proxy_server.empty())
|
||||||
query = std::unique_ptr<asio::ip::tcp::resolver::query>(new asio::ip::tcp::resolver::query(host, std::to_string(port)));
|
host_port = std::unique_ptr<std::pair<std::string, std::string>>(new std::pair<std::string, std::string>(host, std::to_string(port)));
|
||||||
else {
|
else {
|
||||||
auto proxy_host_port = parse_host_port(config.proxy_server, 8080);
|
auto proxy_host_port = parse_host_port(config.proxy_server, 8080);
|
||||||
query = std::unique_ptr<asio::ip::tcp::resolver::query>(new asio::ip::tcp::resolver::query(proxy_host_port.first, std::to_string(proxy_host_port.second)));
|
host_port = std::unique_ptr<std::pair<std::string, std::string>>(new std::pair<std::string, std::string>(proxy_host_port.first, std::to_string(proxy_host_port.second)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,14 +640,14 @@ namespace SimpleWeb {
|
||||||
if(!session->connection->socket->lowest_layer().is_open()) {
|
if(!session->connection->socket->lowest_layer().is_open()) {
|
||||||
auto resolver = std::make_shared<asio::ip::tcp::resolver>(*io_service);
|
auto resolver = std::make_shared<asio::ip::tcp::resolver>(*io_service);
|
||||||
session->connection->set_timeout(config.timeout_connect);
|
session->connection->set_timeout(config.timeout_connect);
|
||||||
resolver->async_resolve(*query, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator it) {
|
async_resolve(*resolver, *host_port, [this, session, resolver](const error_code &ec, resolver_results results) {
|
||||||
session->connection->cancel_timeout();
|
session->connection->cancel_timeout();
|
||||||
auto lock = session->connection->handler_runner->continue_lock();
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
if(!lock)
|
if(!lock)
|
||||||
return;
|
return;
|
||||||
if(!ec) {
|
if(!ec) {
|
||||||
session->connection->set_timeout(config.timeout_connect);
|
session->connection->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*/) {
|
asio::async_connect(*session->connection->socket, results, [this, session, resolver](const error_code &ec, async_connect_endpoint /*endpoint*/) {
|
||||||
session->connection->cancel_timeout();
|
session->connection->cancel_timeout();
|
||||||
auto lock = session->connection->handler_runner->continue_lock();
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
if(!lock)
|
if(!lock)
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,13 @@ namespace SimpleWeb {
|
||||||
void connect(const std::shared_ptr<Session> &session) override {
|
void connect(const std::shared_ptr<Session> &session) override {
|
||||||
if(!session->connection->socket->lowest_layer().is_open()) {
|
if(!session->connection->socket->lowest_layer().is_open()) {
|
||||||
auto resolver = std::make_shared<asio::ip::tcp::resolver>(*io_service);
|
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) {
|
async_resolve(*resolver, *host_port, [this, session, resolver](const error_code &ec, resolver_results results) {
|
||||||
auto lock = session->connection->handler_runner->continue_lock();
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
if(!lock)
|
if(!lock)
|
||||||
return;
|
return;
|
||||||
if(!ec) {
|
if(!ec) {
|
||||||
session->connection->set_timeout(this->config.timeout_connect);
|
session->connection->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*/) {
|
asio::async_connect(session->connection->socket->lowest_layer(), results, [this, session, resolver](const error_code &ec, async_connect_endpoint /*endpoint*/) {
|
||||||
session->connection->cancel_timeout();
|
session->connection->cancel_timeout();
|
||||||
auto lock = session->connection->handler_runner->continue_lock();
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
if(!lock)
|
if(!lock)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef SERVER_HTTP_HPP
|
#ifndef SERVER_HTTP_HPP
|
||||||
#define SERVER_HTTP_HPP
|
#define SERVER_HTTP_HPP
|
||||||
|
|
||||||
|
#include "asio_compatibility.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -12,25 +13,6 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#ifdef USE_STANDALONE_ASIO
|
|
||||||
#include <asio.hpp>
|
|
||||||
#include <asio/steady_timer.hpp>
|
|
||||||
namespace SimpleWeb {
|
|
||||||
using error_code = std::error_code;
|
|
||||||
using errc = std::errc;
|
|
||||||
namespace make_error_code = std;
|
|
||||||
} // namespace SimpleWeb
|
|
||||||
#else
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
|
||||||
namespace SimpleWeb {
|
|
||||||
namespace asio = boost::asio;
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
namespace errc = boost::system::errc;
|
|
||||||
namespace make_error_code = boost::system::errc;
|
|
||||||
} // namespace SimpleWeb
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Late 2017 TODO: remove the following checks and always use std::regex
|
// Late 2017 TODO: remove the following checks and always use std::regex
|
||||||
#ifdef USE_BOOST_REGEX
|
#ifdef USE_BOOST_REGEX
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
@ -63,10 +45,10 @@ namespace SimpleWeb {
|
||||||
std::shared_ptr<Session> session;
|
std::shared_ptr<Session> session;
|
||||||
long timeout_content;
|
long timeout_content;
|
||||||
|
|
||||||
asio::io_service::strand strand;
|
std::mutex send_queue_mutex;
|
||||||
std::list<std::pair<std::shared_ptr<asio::streambuf>, std::function<void(const error_code &)>>> send_queue;
|
std::list<std::pair<std::shared_ptr<asio::streambuf>, std::function<void(const error_code &)>>> send_queue;
|
||||||
|
|
||||||
Response(std::shared_ptr<Session> session_, long timeout_content) noexcept : std::ostream(nullptr), session(std::move(session_)), timeout_content(timeout_content), strand(session->connection->socket->get_io_service()) {
|
Response(std::shared_ptr<Session> session_, long timeout_content) noexcept : std::ostream(nullptr), session(std::move(session_)), timeout_content(timeout_content) {
|
||||||
rdbuf(streambuf.get());
|
rdbuf(streambuf.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,30 +70,40 @@ namespace SimpleWeb {
|
||||||
*this << "\r\n";
|
*this << "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// send_queue_mutex must be locked here
|
||||||
void send_from_queue() {
|
void send_from_queue() {
|
||||||
auto self = this->shared_from_this();
|
auto self = this->shared_from_this();
|
||||||
strand.post([self]() {
|
asio::async_write(*self->session->connection->socket, *send_queue.begin()->first, [self](const error_code &ec, std::size_t /*bytes_transferred*/) {
|
||||||
asio::async_write(*self->session->connection->socket, *self->send_queue.begin()->first, self->strand.wrap([self](const error_code &ec, std::size_t /*bytes_transferred*/) {
|
auto lock = self->session->connection->handler_runner->continue_lock();
|
||||||
auto lock = self->session->connection->handler_runner->continue_lock();
|
if(!lock)
|
||||||
if(!lock)
|
return;
|
||||||
return;
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(self->send_queue_mutex);
|
||||||
if(!ec) {
|
if(!ec) {
|
||||||
auto it = self->send_queue.begin();
|
auto it = self->send_queue.begin();
|
||||||
if(it->second)
|
auto callback = std::move(it->second);
|
||||||
it->second(ec);
|
|
||||||
self->send_queue.erase(it);
|
self->send_queue.erase(it);
|
||||||
if(self->send_queue.size() > 0)
|
if(self->send_queue.size() > 0)
|
||||||
self->send_from_queue();
|
self->send_from_queue();
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
if(callback)
|
||||||
|
callback(ec);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// All handlers in the queue is called with ec:
|
// All handlers in the queue is called with ec:
|
||||||
|
std::vector<std::function<void(const error_code &)>> callbacks;
|
||||||
for(auto &pair : self->send_queue) {
|
for(auto &pair : self->send_queue) {
|
||||||
if(pair.second)
|
if(pair.second)
|
||||||
pair.second(ec);
|
callbacks.emplace_back(std::move(pair.second));
|
||||||
}
|
}
|
||||||
self->send_queue.clear();
|
self->send_queue.clear();
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
for(auto &callback : callbacks)
|
||||||
|
callback(ec);
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,12 +133,10 @@ namespace SimpleWeb {
|
||||||
this->streambuf = std::unique_ptr<asio::streambuf>(new asio::streambuf());
|
this->streambuf = std::unique_ptr<asio::streambuf>(new asio::streambuf());
|
||||||
rdbuf(this->streambuf.get());
|
rdbuf(this->streambuf.get());
|
||||||
|
|
||||||
auto self = this->shared_from_this();
|
std::lock_guard<std::mutex> lock(send_queue_mutex);
|
||||||
strand.post([self, streambuf, callback]() {
|
send_queue.emplace_back(streambuf, callback);
|
||||||
self->send_queue.emplace_back(streambuf, callback);
|
if(send_queue.size() == 1)
|
||||||
if(self->send_queue.size() == 1)
|
send_from_queue();
|
||||||
self->send_from_queue();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write directly to stream buffer using std::ostream::write
|
/// Write directly to stream buffer using std::ostream::write
|
||||||
|
|
@ -296,19 +286,23 @@ namespace SimpleWeb {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(socket->get_io_service()));
|
timer = std::unique_ptr<asio::steady_timer>(new asio::steady_timer(get_socket_executor(*socket), std::chrono::seconds(seconds)));
|
||||||
timer->expires_from_now(std::chrono::seconds(seconds));
|
std::weak_ptr<Connection> self_weak(this->shared_from_this()); // To avoid keeping Connection instance alive longer than needed
|
||||||
auto self = this->shared_from_this();
|
timer->async_wait([self_weak](const error_code &ec) {
|
||||||
timer->async_wait([self](const error_code &ec) {
|
if(!ec) {
|
||||||
if(!ec)
|
if(auto self = self_weak.lock())
|
||||||
self->close();
|
self->close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel_timeout() noexcept {
|
void cancel_timeout() noexcept {
|
||||||
if(timer) {
|
if(timer) {
|
||||||
error_code ec;
|
try {
|
||||||
timer->cancel(ec);
|
timer->cancel();
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -380,7 +374,7 @@ namespace SimpleWeb {
|
||||||
std::function<void(std::unique_ptr<socket_type> &, std::shared_ptr<typename ServerBase<socket_type>::Request>)> on_upgrade;
|
std::function<void(std::unique_ptr<socket_type> &, std::shared_ptr<typename ServerBase<socket_type>::Request>)> on_upgrade;
|
||||||
|
|
||||||
/// If you have your own asio::io_service, store its pointer here before running start().
|
/// If you have your own asio::io_service, store its pointer here before running start().
|
||||||
std::shared_ptr<asio::io_service> io_service;
|
std::shared_ptr<io_context> io_service;
|
||||||
|
|
||||||
/// If you know the server port in advance, use start() instead.
|
/// If you know the server port in advance, use start() instead.
|
||||||
/// Returns assigned port. If io_service is not set, an internal io_service is created instead.
|
/// Returns assigned port. If io_service is not set, an internal io_service is created instead.
|
||||||
|
|
@ -388,12 +382,12 @@ namespace SimpleWeb {
|
||||||
unsigned short bind() {
|
unsigned short bind() {
|
||||||
asio::ip::tcp::endpoint endpoint;
|
asio::ip::tcp::endpoint endpoint;
|
||||||
if(config.address.size() > 0)
|
if(config.address.size() > 0)
|
||||||
endpoint = asio::ip::tcp::endpoint(asio::ip::address::from_string(config.address), config.port);
|
endpoint = asio::ip::tcp::endpoint(make_address(config.address), config.port);
|
||||||
else
|
else
|
||||||
endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v6(), config.port);
|
endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v6(), config.port);
|
||||||
|
|
||||||
if(!io_service) {
|
if(!io_service) {
|
||||||
io_service = std::make_shared<asio::io_service>();
|
io_service = std::make_shared<io_context>();
|
||||||
internal_io_service = true;
|
internal_io_service = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,7 +418,7 @@ namespace SimpleWeb {
|
||||||
|
|
||||||
if(internal_io_service) {
|
if(internal_io_service) {
|
||||||
if(io_service->stopped())
|
if(io_service->stopped())
|
||||||
io_service->reset();
|
restart(*io_service);
|
||||||
|
|
||||||
// If thread_pool_size>1, start m_io_service.run() in (thread_pool_size-1) threads for thread-pooling
|
// If thread_pool_size>1, start m_io_service.run() in (thread_pool_size-1) threads for thread-pooling
|
||||||
threads.clear();
|
threads.clear();
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#ifndef USE_STANDALONE_ASIO
|
|
||||||
namespace asio = boost::asio;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;
|
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;
|
||||||
using HttpClient = SimpleWeb::Client<SimpleWeb::HTTP>;
|
using HttpClient = SimpleWeb::Client<SimpleWeb::HTTP>;
|
||||||
|
|
||||||
|
|
@ -315,12 +311,33 @@ int main() {
|
||||||
for(auto &thread : threads)
|
for(auto &thread : threads)
|
||||||
thread.join();
|
thread.join();
|
||||||
ASSERT(client.connections.size() == 100);
|
ASSERT(client.connections.size() == 100);
|
||||||
client.io_service->reset();
|
SimpleWeb::restart(*client.io_service);
|
||||||
client.io_service->run();
|
client.io_service->run();
|
||||||
ASSERT(client.connections.size() == 1);
|
ASSERT(client.connections.size() == 1);
|
||||||
for(auto call : calls)
|
for(auto call : calls)
|
||||||
ASSERT(call);
|
ASSERT(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test concurrent requests from different clients
|
||||||
|
{
|
||||||
|
vector<int> calls(10, 0);
|
||||||
|
vector<thread> threads;
|
||||||
|
for(size_t c = 0; c < 10; ++c) {
|
||||||
|
threads.emplace_back([c, &calls] {
|
||||||
|
HttpClient client("localhost:8080");
|
||||||
|
client.request("POST", "/string", "A string", [c, &calls](shared_ptr<HttpClient::Response> response, const SimpleWeb::error_code &ec) {
|
||||||
|
ASSERT(!ec);
|
||||||
|
ASSERT(response->content.string() == "A string");
|
||||||
|
calls[c] = 1;
|
||||||
|
});
|
||||||
|
client.io_service->run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for(auto &thread : threads)
|
||||||
|
thread.join();
|
||||||
|
for(auto call : calls)
|
||||||
|
ASSERT(call);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test concurrent synchronous request calls
|
// Test concurrent synchronous request calls
|
||||||
|
|
@ -390,7 +407,7 @@ int main() {
|
||||||
|
|
||||||
// Test Client client's stop()
|
// Test Client client's stop()
|
||||||
for(size_t c = 0; c < 40; ++c) {
|
for(size_t c = 0; c < 40; ++c) {
|
||||||
auto io_service = make_shared<asio::io_service>();
|
auto io_service = make_shared<SimpleWeb::io_context>();
|
||||||
bool call = false;
|
bool call = false;
|
||||||
HttpClient client("localhost:8080");
|
HttpClient client("localhost:8080");
|
||||||
client.io_service = io_service;
|
client.io_service = io_service;
|
||||||
|
|
@ -410,7 +427,7 @@ int main() {
|
||||||
|
|
||||||
// Test Client destructor that should cancel the client's request
|
// Test Client destructor that should cancel the client's request
|
||||||
for(size_t c = 0; c < 40; ++c) {
|
for(size_t c = 0; c < 40; ++c) {
|
||||||
auto io_service = make_shared<asio::io_service>();
|
auto io_service = make_shared<SimpleWeb::io_context>();
|
||||||
{
|
{
|
||||||
HttpClient client("localhost:8080");
|
HttpClient client("localhost:8080");
|
||||||
client.io_service = io_service;
|
client.io_service = io_service;
|
||||||
|
|
@ -431,7 +448,7 @@ int main() {
|
||||||
|
|
||||||
// Test server destructor
|
// Test server destructor
|
||||||
{
|
{
|
||||||
auto io_service = make_shared<asio::io_service>();
|
auto io_service = make_shared<SimpleWeb::io_context>();
|
||||||
bool call = false;
|
bool call = false;
|
||||||
bool client_catch = false;
|
bool client_catch = false;
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ int main() {
|
||||||
ASSERT(fields_result1 == fields_result2 && fields_result1 == fields);
|
ASSERT(fields_result1 == fields_result2 && fields_result1 == fields);
|
||||||
|
|
||||||
auto serverTest = make_shared<ServerTest>();
|
auto serverTest = make_shared<ServerTest>();
|
||||||
serverTest->io_service = std::make_shared<asio::io_service>();
|
serverTest->io_service = std::make_shared<io_context>();
|
||||||
|
|
||||||
serverTest->parse_request_test();
|
serverTest->parse_request_test();
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ int main() {
|
||||||
clientTest2->parse_response_header_test();
|
clientTest2->parse_response_header_test();
|
||||||
|
|
||||||
|
|
||||||
asio::io_service io_service;
|
io_context io_service;
|
||||||
asio::ip::tcp::socket socket(io_service);
|
asio::ip::tcp::socket socket(io_service);
|
||||||
SimpleWeb::Server<HTTP>::Request request(static_cast<size_t>(-1), nullptr);
|
SimpleWeb::Server<HTTP>::Request request(static_cast<size_t>(-1), nullptr);
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue