fix crash
This commit is contained in:
@@ -84,46 +84,55 @@ void apply_common_socket_properties(boost::asio::ip::tcp::socket &sock) {
|
||||
}
|
||||
|
||||
template <class op_t>
|
||||
void run_with_deadline(boost::asio::io_context &io_ctx,
|
||||
boost::asio::ip::tcp::socket &sock, op_t &&operation,
|
||||
static void run_with_deadline(boost::asio::io_context &io_ctx,
|
||||
boost::asio::ip::tcp::socket &sock,
|
||||
op_t &&operation,
|
||||
std::chrono::milliseconds deadline,
|
||||
std::string_view event_name,
|
||||
std::string_view function_name) {
|
||||
const std::string &event_name,
|
||||
const std::string &function_name) {
|
||||
deadline = std::max(deadline, std::chrono::milliseconds{250});
|
||||
|
||||
bool done = false;
|
||||
bool timed_out = false;
|
||||
struct request_state final {
|
||||
std::atomic<bool> done{false};
|
||||
std::atomic<bool> timed_out{false};
|
||||
boost::system::error_code err;
|
||||
};
|
||||
auto state = std::make_shared<request_state>();
|
||||
|
||||
boost::asio::steady_timer timer{io_ctx};
|
||||
timer.expires_after(deadline);
|
||||
timer.async_wait([&done, &sock, &timed_out](auto &&err_) {
|
||||
if (not err_ && not done) {
|
||||
timed_out = true;
|
||||
sock.cancel();
|
||||
|
||||
timer.async_wait([state, &sock](auto &&err) {
|
||||
if (not err && not state->done) {
|
||||
state->timed_out = true;
|
||||
boost::system::error_code ignored_ec;
|
||||
[[maybe_unused]] auto res = sock.cancel(ignored_ec);
|
||||
}
|
||||
});
|
||||
|
||||
boost::system::error_code err{};
|
||||
operation([&done, &err](auto &&err_) {
|
||||
err = err_;
|
||||
done = true;
|
||||
operation([state](auto &&err) {
|
||||
state->err = err;
|
||||
state->done = true;
|
||||
});
|
||||
|
||||
io_ctx.restart();
|
||||
while (not done) {
|
||||
while (not state->done && not state->timed_out) {
|
||||
io_ctx.run_one();
|
||||
}
|
||||
|
||||
timer.cancel();
|
||||
|
||||
if (timed_out) {
|
||||
io_ctx.poll();
|
||||
|
||||
if (state->timed_out) {
|
||||
repertory::event_system::instance().raise<repertory::packet_client_timeout>(
|
||||
std::string(event_name), std::string(function_name));
|
||||
throw std::runtime_error(std::string(event_name) + " timed-out");
|
||||
throw std::runtime_error(event_name + " timed-out");
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw std::runtime_error(std::string(event_name) + " failed|err|" +
|
||||
err.message());
|
||||
if (state->err) {
|
||||
throw std::runtime_error(event_name + " failed|err|" +
|
||||
state->err.message());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +149,7 @@ void connect_with_deadline(
|
||||
boost::asio::async_connect(
|
||||
sock, endpoints, [handler](auto &&err, auto &&) { handler(err); });
|
||||
},
|
||||
deadline, "connect", function_name);
|
||||
deadline, "connect", std::string{function_name});
|
||||
}
|
||||
|
||||
void read_exact_with_deadline(boost::asio::io_context &io_ctx,
|
||||
@@ -167,7 +176,7 @@ void read_exact_with_deadline(boost::asio::io_context &io_ctx,
|
||||
handler(err);
|
||||
});
|
||||
},
|
||||
deadline, "read", function_name);
|
||||
deadline, "read", std::string{function_name});
|
||||
|
||||
if (bytes_read == 0U) {
|
||||
throw std::runtime_error("0 bytes read");
|
||||
@@ -200,7 +209,7 @@ void write_all_with_deadline(boost::asio::io_context &io_ctx,
|
||||
handler(err);
|
||||
});
|
||||
},
|
||||
deadline, "write", function_name);
|
||||
deadline, "write", std::string{function_name});
|
||||
|
||||
if (bytes_written == 0U) {
|
||||
throw std::runtime_error("0 bytes written");
|
||||
|
@@ -58,10 +58,11 @@ packet_client::~packet_client() {
|
||||
|
||||
void packet_client::close(client &cli) noexcept {
|
||||
boost::system::error_code err1;
|
||||
auto res = cli.socket.shutdown(boost::asio::socket_base::shutdown_both, err1);
|
||||
[[maybe_unused]] auto res =
|
||||
cli.socket.shutdown(boost::asio::socket_base::shutdown_both, err1);
|
||||
|
||||
boost::system::error_code err2;
|
||||
res = cli.socket.close(err2);
|
||||
[[maybe_unused]] auto res2 = cli.socket.close(err2);
|
||||
}
|
||||
|
||||
void packet_client::close_all() {
|
||||
@@ -244,8 +245,12 @@ auto packet_client::read_packet(client &cli, boost::asio::io_context &ctx,
|
||||
std::memcpy(&to_read, buffer.data(), sizeof(to_read));
|
||||
boost::endian::big_to_native_inplace(to_read);
|
||||
|
||||
if (to_read == 0U || to_read > comm::max_packet_bytes) {
|
||||
return utils::from_api_error(api_error::comm_error);
|
||||
if (to_read > comm::max_packet_bytes) {
|
||||
throw std::runtime_error(fmt::format("packet too large|size|{}", to_read));
|
||||
}
|
||||
|
||||
if (to_read < utils::encryption::encryption_header_size) {
|
||||
throw std::runtime_error(fmt::format("packet too small|size|{}", to_read));
|
||||
}
|
||||
|
||||
buffer.resize(to_read);
|
||||
|
@@ -289,6 +289,11 @@ void packet_server::read_packet(std::shared_ptr<connection> conn,
|
||||
fmt::format("packet too large|size|{}", data_size));
|
||||
}
|
||||
|
||||
if (data_size < utils::encryption::encryption_header_size) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("packet too small|size|{}", data_size));
|
||||
}
|
||||
|
||||
auto should_send_response = true;
|
||||
auto response = std::make_shared<packet>();
|
||||
conn->buffer.resize(data_size);
|
||||
|
Reference in New Issue
Block a user