From 2ab7460cbca4a0e8d5c33e71610de2e620eecc8c Mon Sep 17 00:00:00 2001 From: Jari Sundell Date: Mon, 31 Mar 2025 18:26:07 +0200 Subject: [PATCH] Fix SCGI threading and added missing header. --- src/command_local.cc | 8 +- src/rpc/command_map.cc | 36 --------- src/rpc/parse_commands.cc | 52 ++----------- src/rpc/rpc_manager.cc | 3 + src/rpc/scgi.cc | 31 +------- src/rpc/scgi.h | 49 +----------- src/rpc/scgi_task.cc | 156 ++++++++++++++++++++++++-------------- src/rpc/scgi_task.h | 55 +++----------- test/Makefile.am | 3 +- 9 files changed, 135 insertions(+), 258 deletions(-) diff --git a/src/command_local.cc b/src/command_local.cc index fa46e544..a66c03cf 100644 --- a/src/command_local.cc +++ b/src/command_local.cc @@ -220,9 +220,11 @@ initialize_command_local() { CMD2_VAR_LIST ("file.prioritize_toc.first"); CMD2_VAR_LIST ("file.prioritize_toc.last"); - CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager)); - CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2)); - CMD2_VAR_BOOL ("system.files.session.fdatasync", true); + CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager)); + CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2)); + // CMD2_ANY ("system.files.advise_random.hashing", std::bind(&FM_t::advise_random_hashing, fileManager)); + // CMD2_ANY_VALUE_V ("system.files.advise_random.hashing.set", std::bind(&FM_t::set_advise_random_hashing, fileManager, std::placeholders::_2)); + CMD2_VAR_BOOL ("system.files.session.fdatasync", true); CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager)); CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager)); diff --git a/src/rpc/command_map.cc b/src/rpc/command_map.cc index f79cfa5b..32a3a212 100644 --- a/src/rpc/command_map.cc +++ b/src/rpc/command_map.cc @@ -1,39 +1,3 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #include "config.h" #include diff --git a/src/rpc/parse_commands.cc b/src/rpc/parse_commands.cc index d5fecb80..93bd65c8 100644 --- a/src/rpc/parse_commands.cc +++ b/src/rpc/parse_commands.cc @@ -1,39 +1,3 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #include "config.h" #include @@ -43,8 +7,8 @@ #include #include -#include "parse.h" -#include "parse_commands.h" +#include "rpc/parse.h" +#include "rpc/parse_commands.h" #include "rpc/rpc_manager.h" namespace rpc { @@ -128,12 +92,12 @@ parse_command(target_type target, const char* first, const char* last) { if (first == last || *first == '#') return std::make_pair(torrent::Object(), first); - + char key[128]; first = parse_command_name(first, last, key, key + 128); first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); }); - + if (first == last || *first != '=') throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'."); @@ -144,7 +108,7 @@ parse_command(target_type target, const char* first, const char* last) { // the whitespace at the end. This ensures us that the caller // doesn't need to do this nor check for junk at the end. first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); }); - + if (first != last) { if (!command_map_is_newline(*first)) throw torrent::input_error("Junk at end of input."); @@ -189,7 +153,7 @@ parse_command_file(const std::string& path) { while (file.good() && !file.getline(buffer + getCount, 4096 - getCount).fail()) { - + if (file.gcount() == 0) throw torrent::internal_error("parse_command_file(...) file.gcount() == 0."); int lineLength = file.gcount() - 1; @@ -198,7 +162,7 @@ parse_command_file(const std::string& path) { // that the last would also be included in option line. if (file.eof() && file.get() != '\n') lineLength++; - + int escaped = parse_count_escaped(buffer + getCount, buffer + getCount + lineLength); lineNumber++; @@ -206,7 +170,7 @@ parse_command_file(const std::string& path) { if (getCount == 4096 - 1) throw torrent::input_error("Exceeded max line length."); - + if (escaped & 0x1) { // Remove the escape characters and continue reading. getCount -= escaped; diff --git a/src/rpc/rpc_manager.cc b/src/rpc/rpc_manager.cc index 13a13d6a..62085711 100644 --- a/src/rpc/rpc_manager.cc +++ b/src/rpc/rpc_manager.cc @@ -100,8 +100,10 @@ bool RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) { switch (type) { case RPCType::XML: + // TODO: 'network.rpc.use_xmlrpc' should be a bool in RpcManager, not a command variable. if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) { return m_xmlrpc.process(in_buffer, length, callback); + } else { const std::string response = "faultCode-501faultStringXML-RPC not supported"; return callback(response.c_str(), response.size()); @@ -111,6 +113,7 @@ RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_r case RPCType::JSON: if (rpc::call_command_value("network.rpc.use_jsonrpc")) { return m_jsonrpc.process(in_buffer, length, callback); + } else { const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}"; return callback(response.c_str(), response.size()); diff --git a/src/rpc/scgi.cc b/src/rpc/scgi.cc index 1c073c39..0d0f80e3 100644 --- a/src/rpc/scgi.cc +++ b/src/rpc/scgi.cc @@ -1,6 +1,5 @@ #include "config.h" -#include "rpc/scgi_task.h" #include #include #include @@ -9,12 +8,12 @@ #include #include -#include "utils/socket_fd.h" - #include "control.h" #include "globals.h" -#include "scgi.h" -#include "parse_commands.h" +#include "rpc/scgi_task.h" +#include "utils/socket_fd.h" + +#include "rpc/scgi.h" namespace rpc { @@ -110,7 +109,6 @@ SCgi::event_read() { SCgiTask* task = std::find_if(m_task, m_task + max_tasks, std::mem_fn(&SCgiTask::is_available)); if (task == m_task + max_tasks) { - // Ergh... just closing for now. fd.close(); continue; } @@ -129,25 +127,4 @@ SCgi::event_error() { throw torrent::internal_error("SCGI listener port received an error event."); } -bool -SCgi::receive_call(SCgiTask* task, const char* buffer, uint32_t length) { - bool result = false; - - torrent::utils::Thread::acquire_global_lock(); - torrent::main_thread()->interrupt(); - - switch (task->content_type()) { - case rpc::SCgiTask::ContentType::JSON: - result = rpc.process(RpcManager::RPCType::JSON, buffer, length, [task](const char* b, uint32_t l) { return task->receive_write(b, l); }); - break; - case rpc::SCgiTask::ContentType::XML: - result = rpc.process(RpcManager::RPCType::XML, buffer, length, [task](const char* b, uint32_t l) { return task->receive_write(b, l); }); - break; - - } - torrent::utils::Thread::release_global_lock(); - - return result; -} - } diff --git a/src/rpc/scgi.h b/src/rpc/scgi.h index 82df3733..69b01b34 100644 --- a/src/rpc/scgi.h +++ b/src/rpc/scgi.h @@ -1,46 +1,11 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #ifndef RTORRENT_RPC_SCGI_H #define RTORRENT_RPC_SCGI_H #include #include -#include "scgi_task.h" +#include "rpc/scgi_task.h" +#include "utils/socket_fd.h" namespace utils { class SocketFd; @@ -48,17 +13,14 @@ namespace utils { namespace rpc { -class lt_cacheline_aligned SCgi : public torrent::Event { +class SCgi : public torrent::Event { public: - typedef std::function slot_write; - static const int max_tasks = 100; - // Global lock: SCgi() : m_logFd(-1) {} virtual ~SCgi(); - const char* type_name() const { return "scgi"; } + virtual const char* type_name() const { return "scgi"; } void open_port(void* sa, unsigned int length, bool dontRoute); void open_named(const std::string& filename); @@ -71,13 +33,10 @@ public: int log_fd() const { return m_logFd; } void set_log_fd(int fd) { m_logFd = fd; } - // Thread local: virtual void event_read(); virtual void event_write(); virtual void event_error(); - bool receive_call(SCgiTask* task, const char* buffer, uint32_t length); - utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } private: diff --git a/src/rpc/scgi_task.cc b/src/rpc/scgi_task.cc index 12e87e4a..55f9bb4f 100644 --- a/src/rpc/scgi_task.cc +++ b/src/rpc/scgi_task.cc @@ -8,26 +8,22 @@ #include #include #include +#include #include - -#include "utils/socket_fd.h" +#include #include "control.h" #include "globals.h" #include "scgi.h" - -// Test: -// #include "core/manager.h" -// #include - -// static rak::timer scgiTimer; +#include "rpc/parse_commands.h" +#include "utils/socket_fd.h" namespace rpc { // If bufferSize is zero then memcpy won't do anything. inline void SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) { - char* tmp = rak::cacheline_allocator::alloc_size(size); + char* tmp = new char[size]; std::memcpy(tmp, buffer, bufferSize); ::free(m_buffer); @@ -36,17 +32,16 @@ SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) void SCgiTask::open(SCgi* parent, int fd) { - m_parent = parent; - m_fileDesc = fd; - m_buffer = rak::cacheline_allocator::alloc_size((m_bufferSize = default_buffer_size) + 1); - m_position = m_buffer; - m_body = NULL; + m_parent = parent; + m_fileDesc = fd; + m_buffer = new char[default_buffer_size + 1]; + m_buffer_size = default_buffer_size; + m_position = m_buffer; + m_body = NULL; - worker_thread->poll()->open(this); - worker_thread->poll()->insert_read(this); - worker_thread->poll()->insert_error(this); - -// scgiTimer = rak::timer::current(); + torrent::thread_self->poll()->open(this); + torrent::thread_self->poll()->insert_read(this); + torrent::thread_self->poll()->insert_error(this); } void @@ -54,26 +49,26 @@ SCgiTask::close() { if (!get_fd().is_valid()) return; - worker_thread->poll()->remove_read(this); - worker_thread->poll()->remove_write(this); - worker_thread->poll()->remove_error(this); - worker_thread->poll()->close(this); + torrent::main_thread()->cancel_callback_and_wait(this); + torrent::thread_self->cancel_callback(this); + + torrent::thread_self->poll()->remove_read(this); + torrent::thread_self->poll()->remove_write(this); + torrent::thread_self->poll()->remove_error(this); + torrent::thread_self->poll()->close(this); get_fd().close(); get_fd().clear(); - ::free(m_buffer); - m_buffer = NULL; + auto lock = std::lock_guard(m_result_mutex); - // Test -// char buffer[512]; -// sprintf(buffer, "SCgi system call processed: %i", (int)(rak::timer::current() - scgiTimer).usec()); -// control->core()->push_log(std::string(buffer)); + delete[] m_buffer; + m_buffer = NULL; } void SCgiTask::event_read() { - int bytes = ::recv(m_fileDesc, m_position, m_bufferSize - (m_position - m_buffer), 0); + int bytes = ::recv(m_fileDesc, m_position, m_buffer_size - (m_position - m_buffer), 0); if (bytes <= 0) { if (bytes == 0 || !rak::error_number::current().is_blocked_momentary()) @@ -119,17 +114,21 @@ SCgiTask::event_read() { while (current < header_end) { char* key = current; char* key_end = static_cast(std::memchr(current, '\0', header_end - current)); + if (!key_end) goto event_read_failed; current = key_end + 1; + if (current >= header_end) goto event_read_failed; char* value = current; char* value_end = static_cast(std::memchr(current, '\0', header_end - current)); + if (!value_end) goto event_read_failed; + current = value_end + 1; if (strcmp(key, "CONTENT_LENGTH") == 0) { @@ -164,45 +163,41 @@ SCgiTask::event_read() { goto event_read_failed; } - if ((unsigned int)(content_length + header_size) < m_bufferSize) { - m_bufferSize = content_length + header_size; + if ((unsigned int)(content_length + header_size) < m_buffer_size) { + m_buffer_size = content_length + header_size; } else if ((unsigned int)content_length <= default_buffer_size) { - m_bufferSize = content_length; + m_buffer_size = content_length; std::memmove(m_buffer, m_body, std::distance(m_body, m_position)); m_position = m_buffer + std::distance(m_body, m_position); m_body = m_buffer; } else { - realloc_buffer((m_bufferSize = content_length) + 1, m_body, std::distance(m_body, m_position)); + realloc_buffer((m_buffer_size = content_length) + 1, m_body, std::distance(m_body, m_position)); m_position = m_buffer + std::distance(m_body, m_position); m_body = m_buffer; } } - if ((unsigned int)std::distance(m_buffer, m_position) != m_bufferSize) + if ((unsigned int)std::distance(m_buffer, m_position) != m_buffer_size) return; - worker_thread->poll()->remove_read(this); - worker_thread->poll()->insert_write(this); + torrent::thread_self->poll()->remove_read(this); if (m_parent->log_fd() >= 0) { int __UNUSED result; // Clean up logging, this is just plain ugly... // write(m_logFd, "\n---\n", sizeof("\n---\n")); - result = write(m_parent->log_fd(), m_buffer, m_bufferSize); + result = write(m_parent->log_fd(), m_buffer, m_buffer_size); result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n")); } - lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_bufferSize - std::distance(m_buffer, m_body), "scgi", "RPC read.", 0); - - // Close if the call failed, else stay open to write back data. - if (!m_parent->receive_call(this, m_body, m_bufferSize - std::distance(m_buffer, m_body))) - close(); + lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_buffer_size - std::distance(m_buffer, m_body), "scgi", "RPC read.", 0); + receive_call(m_body, m_buffer_size - std::distance(m_buffer, m_body)); return; event_read_failed: @@ -215,9 +210,9 @@ SCgiTask::event_write() { // Apple and Solaris do not support MSG_NOSIGNAL, // so disable this fix until we find a better solution #if defined(__APPLE__) || defined(__sun__) - int bytes = ::send(m_fileDesc, m_position, m_bufferSize, 0); + int bytes = ::send(m_fileDesc, m_position, m_buffer_size, 0); #else - int bytes = ::send(m_fileDesc, m_position, m_bufferSize, MSG_NOSIGNAL); + int bytes = ::send(m_fileDesc, m_position, m_buffer_size, MSG_NOSIGNAL); #endif if (bytes == -1) { @@ -228,9 +223,9 @@ SCgiTask::event_write() { } m_position += bytes; - m_bufferSize -= bytes; + m_buffer_size -= bytes; - if (bytes == 0 || m_bufferSize == 0) + if (bytes == 0 || m_buffer_size == 0) return close(); } @@ -239,13 +234,61 @@ SCgiTask::event_error() { close(); } -bool +void +SCgiTask::receive_call(const char* buffer, uint32_t length) { + // TODO: Rewrite RpcManager.process to pass the result buffer instead of having to copy it. + + auto scgi_thread = torrent::thread_self; + + auto result_callback = [this, scgi_thread](const char* b, uint32_t l) { + receive_write(b, l); + + scgi_thread->callback(this, [this]() { + // Only need to lock once here as a memory barrier. + m_result_mutex.lock(); + m_result_mutex.unlock(); + + torrent::thread_self->poll()->insert_write(this); + }); + }; + + auto lock = std::lock_guard(m_result_mutex); + + switch (content_type()) { + case rpc::SCgiTask::ContentType::JSON: + torrent::main_thread()->callback(this, [buffer, length, result_callback]() { + rpc.process(RpcManager::RPCType::JSON, buffer, length, + [result_callback](const char* b, uint32_t l) { + result_callback(b, l); + return true; + }); + }); + break; + + case rpc::SCgiTask::ContentType::XML: + torrent::main_thread()->callback(this, [buffer, length, result_callback]() { + rpc.process(RpcManager::RPCType::XML, buffer, length, + [result_callback](const char* b, uint32_t l) { + result_callback(b, l); + return true; + }); + }); + break; + + default: + throw torrent::internal_error("SCgiTask::receive_call(...) received bad input."); + } +} + +void SCgiTask::receive_write(const char* buffer, uint32_t length) { if (buffer == NULL || length > (100 << 20)) throw torrent::internal_error("SCgiTask::receive_write(...) received bad input."); + auto lock = std::lock_guard(m_result_mutex); + // Need to cast due to a bug in MacOSX gcc-4.0.1. - if (length + 256 > std::max(m_bufferSize, (unsigned int)default_buffer_size)) + if (length + 256 > std::max(m_buffer_size, (unsigned int)default_buffer_size)) realloc_buffer(length + 256, NULL, 0); const auto header = m_content_type == ContentType::JSON @@ -253,25 +296,20 @@ SCgiTask::receive_write(const char* buffer, uint32_t length) { : "Status: 200 OK\r\nContent-Type: text/xml\r\nContent-Length: %i\r\n\r\n"; // Who ever bothers to check the return value? - int headerSize = sprintf(m_buffer, header, length); + int headerSize = snprintf(m_buffer, m_buffer_size, header, length); m_position = m_buffer; - m_bufferSize = length + headerSize; + m_buffer_size = length + headerSize; std::memcpy(m_buffer + headerSize, buffer, length); if (m_parent->log_fd() >= 0) { - int __UNUSED result; - // Clean up logging, this is just plain ugly... - // write(m_logFd, "\n---\n", sizeof("\n---\n")); - result = write(m_parent->log_fd(), m_buffer, m_bufferSize); + int result [[maybe_unused]]; + result = write(m_parent->log_fd(), m_buffer, m_buffer_size); result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n")); } - lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer, m_bufferSize, "scgi", "RPC write.", 0); - - event_write(); - return true; + lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer, m_buffer_size, "scgi", "RPC write.", 0); } } // namespace rpc diff --git a/src/rpc/scgi_task.h b/src/rpc/scgi_task.h index 3aeeb85b..57116f31 100644 --- a/src/rpc/scgi_task.h +++ b/src/rpc/scgi_task.h @@ -1,42 +1,8 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #ifndef RTORRENT_RPC_SCGI_TASK_H #define RTORRENT_RPC_SCGI_TASK_H +#include +#include #include namespace utils { @@ -69,20 +35,23 @@ public: virtual void event_write(); virtual void event_error(); - bool receive_write(const char* buffer, uint32_t length); - - utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } + utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } private: inline void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize); + void receive_call(const char* buffer, uint32_t length); + void receive_write(const char* buffer, uint32_t length); + SCgi* m_parent; - char* m_buffer; - char* m_position; - char* m_body; + std::mutex m_result_mutex; - unsigned int m_bufferSize; + char* m_buffer{nullptr}; + char* m_position{nullptr}; + char* m_body{nullptr}; + + unsigned int m_buffer_size{0}; ContentType m_content_type{ XML }; }; diff --git a/test/Makefile.am b/test/Makefile.am index fff7df4d..6f06cb4c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -17,7 +17,8 @@ rtorrent_Test_Common = \ helpers/progress_listener.cc \ helpers/progress_listener.h \ helpers/protectors.cc \ - helpers/protectors.h + helpers/protectors.h \ + helpers/utils.h rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \ rpc/command_test.cc \