mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-18 15:16:17 +00:00
Remove obsolete SocketFd class.
This commit is contained in:
@@ -172,8 +172,6 @@ libsub_root_a_SOURCES = \
|
|||||||
utils/list_focus.h \
|
utils/list_focus.h \
|
||||||
utils/lockfile.cc \
|
utils/lockfile.cc \
|
||||||
utils/lockfile.h \
|
utils/lockfile.h \
|
||||||
utils/socket_fd.cc \
|
|
||||||
utils/socket_fd.h \
|
|
||||||
\
|
\
|
||||||
command_download.cc \
|
command_download.cc \
|
||||||
command_dynamic.cc \
|
command_dynamic.cc \
|
||||||
|
|||||||
+51
-43
@@ -1,6 +1,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <torrent/connection_manager.h>
|
#include <torrent/connection_manager.h>
|
||||||
#include <torrent/torrent.h>
|
#include <torrent/torrent.h>
|
||||||
@@ -12,7 +13,6 @@
|
|||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "rpc/scgi_task.h"
|
#include "rpc/scgi_task.h"
|
||||||
#include "utils/socket_fd.h"
|
|
||||||
|
|
||||||
// TODO: Figure out why moving this to the top causes a build error.
|
// TODO: Figure out why moving this to the top causes a build error.
|
||||||
#include "rpc/scgi.h"
|
#include "rpc/scgi.h"
|
||||||
@@ -20,30 +20,26 @@
|
|||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
SCgi::~SCgi() {
|
SCgi::~SCgi() {
|
||||||
if (!get_fd().is_valid())
|
assert(!is_open() && "SCgi::~SCgi() called while open");
|
||||||
return;
|
|
||||||
|
|
||||||
for (SCgiTask* itr = m_task, *last = m_task + max_tasks; itr != last; ++itr)
|
|
||||||
if (itr->is_open())
|
|
||||||
itr->close();
|
|
||||||
|
|
||||||
deactivate();
|
|
||||||
torrent::connection_manager()->dec_socket_count();
|
|
||||||
|
|
||||||
get_fd().close();
|
|
||||||
get_fd().clear();
|
|
||||||
|
|
||||||
if (!m_path.empty())
|
|
||||||
::unlink(m_path.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgi::open_port(void* sa, unsigned int length, bool dontRoute) {
|
SCgi::open_port(sockaddr* sa, unsigned int length, bool dont_route) {
|
||||||
if (!get_fd().open_stream() ||
|
int fd = torrent::fd_open_family(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address,
|
||||||
(dontRoute && !get_fd().set_dont_route(true)))
|
reinterpret_cast<sockaddr*>(sa)->sa_family);
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
||||||
|
|
||||||
open(sa, length);
|
if (dont_route && !torrent::fd_set_dont_route(fd, true)) {
|
||||||
|
torrent::fd_close(fd);
|
||||||
|
throw torrent::resource_error("Could not set socket option IP_DONTROUTE: " + std::string(std::strerror(errno)));
|
||||||
|
}
|
||||||
|
|
||||||
|
set_file_descriptor(fd);
|
||||||
|
open(reinterpret_cast<sockaddr*>(sa), length);
|
||||||
|
|
||||||
|
torrent::connection_manager()->inc_socket_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -51,45 +47,42 @@ SCgi::open_named(const std::string& filename) {
|
|||||||
if (filename.empty() || filename.size() > 4096)
|
if (filename.empty() || filename.size() > 4096)
|
||||||
throw torrent::resource_error("Invalid filename length.");
|
throw torrent::resource_error("Invalid filename length.");
|
||||||
|
|
||||||
auto buffer = std::make_unique<char[]>(sizeof(sockaddr_un) + filename.size());
|
auto buffer = std::make_unique<char[]>(sizeof(sockaddr_un) + filename.size() + 1);
|
||||||
|
|
||||||
sockaddr_un* sa = reinterpret_cast<sockaddr_un*>(buffer.get());
|
sockaddr_un* sa = reinterpret_cast<sockaddr_un*>(buffer.get());
|
||||||
|
|
||||||
#ifdef __sun__
|
|
||||||
sa->sun_family = AF_UNIX;
|
|
||||||
#else
|
|
||||||
sa->sun_family = AF_LOCAL;
|
sa->sun_family = AF_LOCAL;
|
||||||
#endif
|
|
||||||
|
|
||||||
std::memcpy(sa->sun_path, filename.c_str(), filename.size() + 1);
|
std::memcpy(sa->sun_path, filename.c_str(), filename.size() + 1);
|
||||||
|
|
||||||
if (!get_fd().open_local())
|
int fd = torrent::fd_open_local(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address);
|
||||||
throw torrent::resource_error("Could not open socket for listening.");
|
|
||||||
|
if (fd == -1)
|
||||||
|
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
||||||
|
|
||||||
|
set_file_descriptor(fd);
|
||||||
|
open(reinterpret_cast<sockaddr*>(sa), offsetof(struct sockaddr_un, sun_path) + filename.size() + 1);
|
||||||
|
|
||||||
|
torrent::connection_manager()->inc_socket_count();
|
||||||
|
|
||||||
open(sa, offsetof(struct sockaddr_un, sun_path) + filename.size() + 1);
|
|
||||||
m_path = filename;
|
m_path = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgi::open(void* sa, unsigned int length) {
|
SCgi::open(sockaddr* sa, unsigned int length) {
|
||||||
try {
|
try {
|
||||||
if (!get_fd().set_nonblock() ||
|
if (::bind(file_descriptor(), sa, length) == -1)
|
||||||
!get_fd().set_reuse_address(true) ||
|
throw torrent::resource_error("Could not bind socket for listening: " + std::string(std::strerror(errno)));
|
||||||
!get_fd().bind_sa(reinterpret_cast<sockaddr*>(sa), length) ||
|
|
||||||
!get_fd().listen(max_tasks))
|
if (!torrent::fd_listen(file_descriptor(), max_tasks))
|
||||||
throw torrent::resource_error("Could not prepare socket for listening: " + std::string(std::strerror(errno)));
|
throw torrent::resource_error("Could not prepare socket for listening: " + std::string(std::strerror(errno)));
|
||||||
|
|
||||||
torrent::connection_manager()->inc_socket_count();
|
|
||||||
|
|
||||||
} catch (torrent::resource_error& e) {
|
} catch (torrent::resource_error& e) {
|
||||||
get_fd().close();
|
torrent::fd_close(file_descriptor());
|
||||||
get_fd().clear();
|
set_file_descriptor(-1);
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Verify this is run in correct thread, also only ever call poll methods from thread_self.
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgi::activate() {
|
SCgi::activate() {
|
||||||
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
||||||
@@ -100,16 +93,31 @@ SCgi::activate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgi::deactivate() {
|
SCgi::stop() {
|
||||||
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
||||||
|
|
||||||
|
if (!is_open())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (SCgiTask* itr = m_task, *last = m_task + max_tasks; itr != last; ++itr)
|
||||||
|
if (itr->is_open())
|
||||||
|
itr->close();
|
||||||
|
|
||||||
torrent::this_thread::poll()->remove_and_close(this);
|
torrent::this_thread::poll()->remove_and_close(this);
|
||||||
|
|
||||||
|
torrent::fd_close(file_descriptor());
|
||||||
|
set_file_descriptor(-1);
|
||||||
|
|
||||||
|
torrent::connection_manager()->dec_socket_count();
|
||||||
|
|
||||||
|
if (!m_path.empty())
|
||||||
|
::unlink(m_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgi::event_read() {
|
SCgi::event_read() {
|
||||||
while (true) {
|
while (true) {
|
||||||
int fd = torrent::fd_accept(get_fd().get_fd());
|
int fd = torrent::fd_accept(file_descriptor());
|
||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
|
|||||||
+4
-10
@@ -5,11 +5,6 @@
|
|||||||
#include <torrent/event.h>
|
#include <torrent/event.h>
|
||||||
|
|
||||||
#include "rpc/scgi_task.h"
|
#include "rpc/scgi_task.h"
|
||||||
#include "utils/socket_fd.h"
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class SocketFd;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
@@ -21,11 +16,12 @@ public:
|
|||||||
|
|
||||||
const char* type_name() const override { return "scgi"; }
|
const char* type_name() const override { return "scgi"; }
|
||||||
|
|
||||||
void open_port(void* sa, unsigned int length, bool dontRoute);
|
void open_port(sockaddr* sa, unsigned int length, bool dont_route);
|
||||||
void open_named(const std::string& filename);
|
void open_named(const std::string& filename);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
const std::string& path() const { return m_path; }
|
const std::string& path() const { return m_path; }
|
||||||
|
|
||||||
@@ -36,10 +32,8 @@ public:
|
|||||||
void event_write() override;
|
void event_write() override;
|
||||||
void event_error() override;
|
void event_error() override;
|
||||||
|
|
||||||
utils::SocketFd& get_fd() { return *reinterpret_cast<utils::SocketFd*>(&m_fileDesc); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void open(void* sa, unsigned int length);
|
void open(sockaddr* sa, unsigned int length);
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
int m_logFd{-1};
|
int m_logFd{-1};
|
||||||
|
|||||||
+33
-37
@@ -3,11 +3,13 @@
|
|||||||
#include "rpc/scgi_task.h"
|
#include "rpc/scgi_task.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <torrent/exceptions.h>
|
#include <torrent/exceptions.h>
|
||||||
#include <torrent/torrent.h>
|
#include <torrent/torrent.h>
|
||||||
|
#include <torrent/net/fd.h>
|
||||||
#include <torrent/net/poll.h>
|
#include <torrent/net/poll.h>
|
||||||
#include <torrent/utils/log.h>
|
#include <torrent/utils/log.h>
|
||||||
#include <torrent/utils/thread.h>
|
#include <torrent/utils/thread.h>
|
||||||
@@ -16,7 +18,6 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "scgi.h"
|
#include "scgi.h"
|
||||||
#include "rpc/parse_commands.h"
|
#include "rpc/parse_commands.h"
|
||||||
#include "utils/socket_fd.h"
|
|
||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
@@ -24,10 +25,12 @@ void
|
|||||||
SCgiTask::open(SCgi* parent, int fd) {
|
SCgiTask::open(SCgi* parent, int fd) {
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
m_fileDesc = fd;
|
m_fileDesc = fd;
|
||||||
m_buffer = new char[default_buffer_size + 1];
|
|
||||||
|
m_buffer.reset(new char[default_buffer_size + 1]);
|
||||||
|
|
||||||
m_buffer_size = default_buffer_size;
|
m_buffer_size = default_buffer_size;
|
||||||
m_position = m_buffer;
|
m_position = m_buffer.get();
|
||||||
m_body = NULL;
|
m_body = nullptr;
|
||||||
|
|
||||||
torrent::this_thread::poll()->open(this);
|
torrent::this_thread::poll()->open(this);
|
||||||
torrent::this_thread::poll()->insert_read(this);
|
torrent::this_thread::poll()->insert_read(this);
|
||||||
@@ -36,7 +39,7 @@ SCgiTask::open(SCgi* parent, int fd) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
SCgiTask::close() {
|
SCgiTask::close() {
|
||||||
if (!get_fd().is_valid())
|
if (!is_open())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
torrent::main_thread::thread()->cancel_callback_and_wait(this);
|
torrent::main_thread::thread()->cancel_callback_and_wait(this);
|
||||||
@@ -44,18 +47,17 @@ SCgiTask::close() {
|
|||||||
|
|
||||||
torrent::this_thread::poll()->remove_and_close(this);
|
torrent::this_thread::poll()->remove_and_close(this);
|
||||||
|
|
||||||
get_fd().close();
|
torrent::fd_close(file_descriptor());
|
||||||
get_fd().clear();
|
set_file_descriptor(-1);
|
||||||
|
|
||||||
auto lock = std::lock_guard<std::mutex>(m_result_mutex);
|
auto lock = std::lock_guard<std::mutex>(m_result_mutex);
|
||||||
|
|
||||||
delete[] m_buffer;
|
m_buffer = nullptr;
|
||||||
m_buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SCgiTask::event_read() {
|
SCgiTask::event_read() {
|
||||||
int bytes = ::recv(m_fileDesc, m_position, m_buffer_size - (m_position - m_buffer), 0);
|
int bytes = ::recv(m_fileDesc, m_position, m_buffer_size - (m_position - m_buffer.get()), 0);
|
||||||
|
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
if (bytes == 0 || !(errno == EAGAIN || errno == EINTR))
|
if (bytes == 0 || !(errno == EAGAIN || errno == EINTR))
|
||||||
@@ -73,14 +75,14 @@ SCgiTask::event_read() {
|
|||||||
// receive all the data we need the first time.
|
// receive all the data we need the first time.
|
||||||
char* current;
|
char* current;
|
||||||
|
|
||||||
int header_size = strtol(m_buffer, ¤t, 0);
|
int header_size = strtol(m_buffer.get(), ¤t, 0);
|
||||||
|
|
||||||
if (current == m_position)
|
if (current == m_position)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the request doesn't start with an integer or if it didn't
|
// If the request doesn't start with an integer or if it didn't
|
||||||
// end in ':', then close the connection.
|
// end in ':', then close the connection.
|
||||||
if (current == m_buffer || *current != ':' || header_size < 17 || header_size > max_header_size)
|
if (current == m_buffer.get() || *current != ':' || header_size < 17 || header_size > max_header_size)
|
||||||
goto event_read_failed;
|
goto event_read_failed;
|
||||||
|
|
||||||
if (std::distance(++current, m_position) < header_size + 1)
|
if (std::distance(++current, m_position) < header_size + 1)
|
||||||
@@ -135,7 +137,7 @@ SCgiTask::event_read() {
|
|||||||
goto event_read_failed;
|
goto event_read_failed;
|
||||||
|
|
||||||
m_body = current + 1;
|
m_body = current + 1;
|
||||||
header_size = std::distance(m_buffer, m_body);
|
header_size = std::distance(m_buffer.get(), m_body);
|
||||||
|
|
||||||
if (!detect_content_type(content_type))
|
if (!detect_content_type(content_type))
|
||||||
goto event_read_failed;
|
goto event_read_failed;
|
||||||
@@ -146,19 +148,19 @@ SCgiTask::event_read() {
|
|||||||
} else if ((unsigned int)content_length <= default_buffer_size) {
|
} else if ((unsigned int)content_length <= default_buffer_size) {
|
||||||
m_buffer_size = content_length;
|
m_buffer_size = content_length;
|
||||||
|
|
||||||
std::memmove(m_buffer, m_body, std::distance(m_body, m_position));
|
std::memmove(m_buffer.get(), m_body, std::distance(m_body, m_position));
|
||||||
m_position = m_buffer + std::distance(m_body, m_position);
|
m_position = m_buffer.get() + std::distance(m_body, m_position);
|
||||||
m_body = m_buffer;
|
m_body = m_buffer.get();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
realloc_buffer((m_buffer_size = 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_position = m_buffer.get() + std::distance(m_body, m_position);
|
||||||
m_body = m_buffer;
|
m_body = m_buffer.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((unsigned int)std::distance(m_buffer, m_position) != m_buffer_size)
|
if ((unsigned int)std::distance(m_buffer.get(), m_position) != m_buffer_size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
torrent::this_thread::poll()->remove_read(this);
|
torrent::this_thread::poll()->remove_read(this);
|
||||||
@@ -168,13 +170,13 @@ SCgiTask::event_read() {
|
|||||||
|
|
||||||
// Clean up logging, this is just plain ugly...
|
// Clean up logging, this is just plain ugly...
|
||||||
// write(m_logFd, "\n---\n", sizeof("\n---\n"));
|
// write(m_logFd, "\n---\n", sizeof("\n---\n"));
|
||||||
result = write(m_parent->log_fd(), m_buffer, m_buffer_size);
|
result = ::write(m_parent->log_fd(), m_buffer.get(), m_buffer_size);
|
||||||
result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
result = ::write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_buffer_size - std::distance(m_buffer, m_body), "scgi", "RPC read.", 0);
|
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_buffer_size - std::distance(m_buffer.get(), m_body), "scgi", "RPC read.", 0);
|
||||||
|
|
||||||
receive_call(m_body, m_buffer_size - std::distance(m_buffer, m_body));
|
receive_call(m_body, m_buffer_size - std::distance(m_buffer.get(), m_body));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event_read_failed:
|
event_read_failed:
|
||||||
@@ -184,13 +186,7 @@ event_read_failed:
|
|||||||
|
|
||||||
void
|
void
|
||||||
SCgiTask::event_write() {
|
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_buffer_size, 0);
|
|
||||||
#else
|
|
||||||
int bytes = ::send(m_fileDesc, m_position, m_buffer_size, MSG_NOSIGNAL);
|
int bytes = ::send(m_fileDesc, m_position, m_buffer_size, MSG_NOSIGNAL);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bytes == -1) {
|
if (bytes == -1) {
|
||||||
if (!(errno == EAGAIN || errno == EINTR))
|
if (!(errno == EAGAIN || errno == EINTR))
|
||||||
@@ -248,11 +244,11 @@ SCgiTask::detect_content_type(const std::string& content_type) {
|
|||||||
// If bufferSize is zero then memcpy won't do anything.
|
// If bufferSize is zero then memcpy won't do anything.
|
||||||
void
|
void
|
||||||
SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) {
|
SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) {
|
||||||
char* tmp = new char[size];
|
auto tmp = new char[size];
|
||||||
|
|
||||||
std::memcpy(tmp, buffer, bufferSize);
|
std::memcpy(tmp, buffer, bufferSize);
|
||||||
::free(m_buffer);
|
|
||||||
m_buffer = tmp;
|
m_buffer.reset(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -317,20 +313,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";
|
: "Status: 200 OK\r\nContent-Type: text/xml\r\nContent-Length: %i\r\n\r\n";
|
||||||
|
|
||||||
// Who ever bothers to check the return value?
|
// Who ever bothers to check the return value?
|
||||||
int headerSize = snprintf(m_buffer, m_buffer_size, header, length);
|
int headerSize = snprintf(m_buffer.get(), m_buffer_size, header, length);
|
||||||
|
|
||||||
m_position = m_buffer;
|
m_position = m_buffer.get();
|
||||||
m_buffer_size = length + headerSize;
|
m_buffer_size = length + headerSize;
|
||||||
|
|
||||||
std::memcpy(m_buffer + headerSize, buffer, length);
|
std::memcpy(m_buffer.get() + headerSize, buffer, length);
|
||||||
|
|
||||||
if (m_parent->log_fd() >= 0) {
|
if (m_parent->log_fd() >= 0) {
|
||||||
[[maybe_unused]] int result;
|
[[maybe_unused]] int result;
|
||||||
result = write(m_parent->log_fd(), m_buffer, m_buffer_size);
|
result = write(m_parent->log_fd(), m_buffer.get(), m_buffer_size);
|
||||||
result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer, m_buffer_size, "scgi", "RPC write.", 0);
|
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer.get(), m_buffer_size, "scgi", "RPC write.", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rpc
|
} // namespace rpc
|
||||||
|
|||||||
+4
-10
@@ -5,10 +5,6 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <torrent/event.h>
|
#include <torrent/event.h>
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
class SocketFd;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
class SCgi;
|
class SCgi;
|
||||||
@@ -37,8 +33,6 @@ public:
|
|||||||
void event_write() override;
|
void event_write() override;
|
||||||
void event_error() override;
|
void event_error() override;
|
||||||
|
|
||||||
utils::SocketFd& get_fd() { return *reinterpret_cast<utils::SocketFd*>(&m_fileDesc); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool detect_content_type(const std::string& content_type);
|
bool detect_content_type(const std::string& content_type);
|
||||||
void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize);
|
void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize);
|
||||||
@@ -46,13 +40,13 @@ private:
|
|||||||
void receive_call(const char* buffer, uint32_t length);
|
void receive_call(const char* buffer, uint32_t length);
|
||||||
void receive_write(const char* buffer, uint32_t length);
|
void receive_write(const char* buffer, uint32_t length);
|
||||||
|
|
||||||
SCgi* m_parent;
|
SCgi* m_parent{};
|
||||||
|
|
||||||
std::mutex m_result_mutex;
|
std::mutex m_result_mutex;
|
||||||
|
|
||||||
char* m_buffer{nullptr};
|
std::unique_ptr<char[]> m_buffer;
|
||||||
char* m_position{nullptr};
|
char* m_position{};
|
||||||
char* m_body{nullptr};
|
char* m_body{};
|
||||||
|
|
||||||
unsigned int m_buffer_size{0};
|
unsigned int m_buffer_size{0};
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ ThreadScgi::thread_scgi() {
|
|||||||
void
|
void
|
||||||
ThreadScgi::cleanup_thread() {
|
ThreadScgi::cleanup_thread() {
|
||||||
if (m_scgi != nullptr)
|
if (m_scgi != nullptr)
|
||||||
m_scgi.load()->deactivate();
|
m_scgi.load()->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc::SCgi*
|
rpc::SCgi*
|
||||||
@@ -49,6 +49,8 @@ ThreadScgi::scgi() {
|
|||||||
return m_scgi;
|
return m_scgi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Disable changing SCGI once set?
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ThreadScgi::set_scgi(rpc::SCgi* scgi) {
|
ThreadScgi::set_scgi(rpc::SCgi* scgi) {
|
||||||
rpc::SCgi* expected = nullptr;
|
rpc::SCgi* expected = nullptr;
|
||||||
@@ -59,7 +61,7 @@ ThreadScgi::set_scgi(rpc::SCgi* scgi) {
|
|||||||
change_rpc_log();
|
change_rpc_log();
|
||||||
|
|
||||||
callback(nullptr, [this]() {
|
callback(nullptr, [this]() {
|
||||||
if (m_scgi == NULL)
|
if (m_scgi == nullptr)
|
||||||
throw torrent::internal_error("Tried to start SCGI but object was not present.");
|
throw torrent::internal_error("Tried to start SCGI but object was not present.");
|
||||||
|
|
||||||
m_scgi.load()->activate();
|
m_scgi.load()->activate();
|
||||||
@@ -78,7 +80,7 @@ ThreadScgi::set_rpc_log(const std::string& filename) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
ThreadScgi::change_rpc_log() {
|
ThreadScgi::change_rpc_log() {
|
||||||
if (scgi() == NULL)
|
if (scgi() == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (scgi()->log_fd() != -1) {
|
if (scgi()->log_fd() != -1) {
|
||||||
|
|||||||
@@ -1,159 +0,0 @@
|
|||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/in_systm.h>
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <torrent/exceptions.h>
|
|
||||||
#include <torrent/net/socket_address.h>
|
|
||||||
|
|
||||||
#include "socket_fd.h"
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
|
|
||||||
inline void
|
|
||||||
SocketFd::check_valid() const {
|
|
||||||
if (!is_valid())
|
|
||||||
throw torrent::internal_error("SocketFd function called on an invalid fd.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_nonblock() {
|
|
||||||
check_valid();
|
|
||||||
|
|
||||||
return fcntl(m_fd, F_SETFL, O_NONBLOCK) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_priority(priority_type p) {
|
|
||||||
check_valid();
|
|
||||||
int opt = p;
|
|
||||||
|
|
||||||
if (m_ipv6_socket)
|
|
||||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
|
|
||||||
else
|
|
||||||
return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_reuse_address(bool state) {
|
|
||||||
check_valid();
|
|
||||||
int opt = state;
|
|
||||||
|
|
||||||
return setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_dont_route(bool state) {
|
|
||||||
check_valid();
|
|
||||||
int opt = state;
|
|
||||||
|
|
||||||
return setsockopt(m_fd, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// bool
|
|
||||||
// SocketFd::set_bind_to_device(const char* device) {
|
|
||||||
// check_valid();
|
|
||||||
// struct ifreq ifr;
|
|
||||||
// strlcpy(ifr.ifr_name, device, IFNAMSIZ);
|
|
||||||
|
|
||||||
// return setsockopt(m_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_send_buffer_size(uint32_t s) {
|
|
||||||
check_valid();
|
|
||||||
int opt = s;
|
|
||||||
|
|
||||||
return setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::set_receive_buffer_size(uint32_t s) {
|
|
||||||
check_valid();
|
|
||||||
int opt = s;
|
|
||||||
|
|
||||||
return setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
SocketFd::get_error() const {
|
|
||||||
check_valid();
|
|
||||||
|
|
||||||
int err;
|
|
||||||
socklen_t length = sizeof(err);
|
|
||||||
|
|
||||||
if (getsockopt(m_fd, SOL_SOCKET, SO_ERROR, &err, &length) == -1)
|
|
||||||
throw torrent::internal_error("SocketFd::get_error() could not get error");
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::open_stream() {
|
|
||||||
m_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
|
|
||||||
if (m_fd == -1) {
|
|
||||||
m_ipv6_socket = false;
|
|
||||||
return (m_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ipv6_socket = true;
|
|
||||||
|
|
||||||
int zero = 0;
|
|
||||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::open_datagram() {
|
|
||||||
m_fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
|
||||||
if (m_fd == -1) {
|
|
||||||
m_ipv6_socket = false;
|
|
||||||
return (m_fd = socket(AF_INET, SOCK_DGRAM, 0)) != -1;
|
|
||||||
}
|
|
||||||
m_ipv6_socket = true;
|
|
||||||
|
|
||||||
int zero = 0;
|
|
||||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::open_local() {
|
|
||||||
return (m_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SocketFd::close() {
|
|
||||||
if (::close(m_fd) && errno == EBADF)
|
|
||||||
throw torrent::internal_error("SocketFd::close() called on an invalid file descriptor");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::bind_sa(const sockaddr* sa, unsigned int length) {
|
|
||||||
check_valid();
|
|
||||||
|
|
||||||
if (m_ipv6_socket && sa->sa_family == AF_INET) {
|
|
||||||
if (length < sizeof(sockaddr_in))
|
|
||||||
throw torrent::input_error("SocketFd::bind_sa: invalid sockaddr length for AF_INET");
|
|
||||||
|
|
||||||
auto mapped_sa = torrent::sin6_to_v4mapped_in(reinterpret_cast<const sockaddr_in*>(sa));
|
|
||||||
return !::bind(m_fd, reinterpret_cast<const sockaddr*>(mapped_sa.get()), sizeof(sockaddr_in6));
|
|
||||||
}
|
|
||||||
|
|
||||||
return !::bind(m_fd, sa, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
SocketFd::listen(int size) {
|
|
||||||
check_valid();
|
|
||||||
|
|
||||||
return !::listen(m_fd, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#ifndef RTORRENT_UTILS_SOCKET_FD_H
|
|
||||||
#define RTORRENT_UTILS_SOCKET_FD_H
|
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
|
|
||||||
class SocketFd {
|
|
||||||
public:
|
|
||||||
typedef uint8_t priority_type;
|
|
||||||
|
|
||||||
SocketFd() : m_fd(-1) {}
|
|
||||||
explicit SocketFd(int fd) : m_fd(fd) {}
|
|
||||||
|
|
||||||
bool is_valid() const { return m_fd >= 0; }
|
|
||||||
|
|
||||||
int get_fd() const { return m_fd; }
|
|
||||||
void set_fd(int fd) { m_fd = fd; }
|
|
||||||
|
|
||||||
bool set_nonblock();
|
|
||||||
bool set_reuse_address(bool state);
|
|
||||||
bool set_dont_route(bool state);
|
|
||||||
|
|
||||||
bool set_bind_to_device(const char* device);
|
|
||||||
|
|
||||||
bool set_priority(priority_type p);
|
|
||||||
|
|
||||||
bool set_send_buffer_size(uint32_t s);
|
|
||||||
bool set_receive_buffer_size(uint32_t s);
|
|
||||||
|
|
||||||
int get_error() const;
|
|
||||||
|
|
||||||
bool open_stream();
|
|
||||||
bool open_datagram();
|
|
||||||
bool open_local();
|
|
||||||
void close();
|
|
||||||
|
|
||||||
void clear() { m_fd = -1; }
|
|
||||||
|
|
||||||
bool bind_sa(const sockaddr* sa, unsigned int length);
|
|
||||||
|
|
||||||
bool listen(int size);
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline void check_valid() const;
|
|
||||||
|
|
||||||
int m_fd;
|
|
||||||
bool m_ipv6_socket;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user