From 13dc0c942a4eea1e2d6c157bad3e566c539a1cec Mon Sep 17 00:00:00 2001 From: rakshasa Date: Wed, 23 May 2007 21:47:11 +0000 Subject: [PATCH] * Allow binding of the SCGI socket to a specific address, and added "scgi_dont_route" variable. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@908 e378c898-3ddf-0310-93e7-cc216c733640 --- src/command_network.cc | 33 ++++++++++++++++++++------------- src/rpc/scgi.cc | 16 +++++++--------- src/rpc/scgi.h | 6 +++--- src/rpc/scgi_task.cc | 2 +- src/utils/socket_fd.cc | 18 ++++++++++++++++++ src/utils/socket_fd.h | 3 +++ 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/command_network.cc b/src/command_network.cc index aa2c02f0..9211244c 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -178,7 +178,7 @@ apply_fast_cgi(const std::string& arg) { void apply_scgi(const std::string& arg, int type) { - if (control->fast_cgi() != NULL) + if (control->scgi() != NULL) throw torrent::input_error("SCGI already enabled."); if (control->xmlrpc() == NULL) @@ -187,35 +187,37 @@ apply_scgi(const std::string& arg, int type) { // Fix this... control->set_scgi(new rpc::SCgi); + rak::address_info* ai = NULL; + rak::socket_address sa; + rak::socket_address* saPtr; + try { - int port; + int port, err; char dummy; char address[1024]; switch (type) { case 1: if (std::sscanf(arg.c_str(), ":%i%c", &port, &dummy) == 1) { - if (port <= 0 || port >= (1 << 16)) - throw torrent::input_error("Invalid port number."); - - control->scgi()->open_port(port); + sa.sa_inet()->clear(); + saPtr = &sa; } else if (std::sscanf(arg.c_str(), "%1023[^:]:%i%c", address, &port, &dummy) == 2) { - if (port <= 0 || port >= (1 << 16)) - throw torrent::input_error("Invalid port number."); - - int err; - rak::address_info* ai; - if ((err = rak::address_info::get_address_info(address, PF_INET, SOCK_STREAM, &ai)) != 0) throw torrent::input_error("Could not bind address: " + std::string(rak::address_info::strerror(err)) + "."); - control->scgi()->open(ai->address()->c_sockaddr(), ai->address()->length()); + saPtr = ai->address(); } else { throw torrent::input_error("Could not parse address."); } + if (port <= 0 || port >= (1 << 16)) + throw torrent::input_error("Invalid port number."); + + saPtr->set_port(port); + control->scgi()->open_port(saPtr, saPtr->length(), control->variable()->call_command_value("get_scgi_dont_route")); + break; case 2: @@ -224,7 +226,11 @@ apply_scgi(const std::string& arg, int type) { break; } + rak::address_info::free_address_info(ai); + } catch (torrent::local_error& e) { + rak::address_info::free_address_info(ai); + throw torrent::input_error(e.what()); } @@ -289,6 +295,7 @@ initialize_command_network() { ADD_COMMAND_STRING_UN("fast_cgi", std::ptr_fun(&apply_fast_cgi)); ADD_COMMAND_STRING_UN("scgi_port", rak::bind2nd(std::ptr_fun(&apply_scgi), 1)); ADD_COMMAND_STRING_UN("scgi_local", rak::bind2nd(std::ptr_fun(&apply_scgi), 2)); + ADD_VARIABLE_BOOL("scgi_dont_route", false); ADD_COMMAND_VALUE_TRI("hash_read_ahead", std::ptr_fun(&apply_hash_read_ahead), rak::ptr_fun(torrent::hash_read_ahead)); ADD_COMMAND_VALUE_TRI("hash_interval", std::ptr_fun(&apply_hash_interval), rak::ptr_fun(torrent::hash_interval)); diff --git a/src/rpc/scgi.cc b/src/rpc/scgi.cc index d7c25f7f..7d97b577 100644 --- a/src/rpc/scgi.cc +++ b/src/rpc/scgi.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include #include @@ -71,15 +72,12 @@ SCgi::~SCgi() { } void -SCgi::open_port(uint16_t port) { - rak::socket_address sa; - sa.sa_inet()->clear(); - sa.sa_inet()->set_port(port); +SCgi::open_port(void* sa, unsigned int length, bool dontRoute) { + if (!get_fd().open_stream() || + (dontRoute && !get_fd().set_dont_route(true))) + throw torrent::resource_error("Could not open socket for listening: " + std::string(rak::error_number::current().c_str())); - if (!get_fd().open_stream()) - throw torrent::resource_error("Could not open socket for listening."); - - open(sa.c_sockaddr(), sa.length()); + open(sa, length); } void @@ -107,7 +105,7 @@ SCgi::open(void* sa, unsigned int length) { !get_fd().set_reuse_address(true) || !get_fd().bind(*reinterpret_cast(sa), length) || !get_fd().listen(max_tasks)) - throw torrent::resource_error("Could not prepare socket for listening."); + throw torrent::resource_error("Could not prepare socket for listening: " + std::string(rak::error_number::current().c_str())); torrent::connection_manager()->inc_socket_count(); diff --git a/src/rpc/scgi.h b/src/rpc/scgi.h index 07f52570..2130f1ea 100644 --- a/src/rpc/scgi.h +++ b/src/rpc/scgi.h @@ -59,9 +59,7 @@ public: SCgi() {} virtual ~SCgi(); - void open(void* sa, unsigned int length); - - void open_port(uint16_t port); + void open_port(void* sa, unsigned int length, bool dontRoute); void open_named(const std::string& filename); const std::string path() const { return m_path; } @@ -77,6 +75,8 @@ public: utils::SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } private: + void open(void* sa, unsigned int length); + std::string m_path; slot_process m_slotProcess; SCgiTask m_task[max_tasks]; diff --git a/src/rpc/scgi_task.cc b/src/rpc/scgi_task.cc index afd1e292..9a986f85 100644 --- a/src/rpc/scgi_task.cc +++ b/src/rpc/scgi_task.cc @@ -67,7 +67,7 @@ SCgiTask::open(SCgi* parent, int fd) { control->poll()->insert_read(this); control->poll()->insert_error(this); - scgiTimer = rak::timer::current(); +// scgiTimer = rak::timer::current(); } void diff --git a/src/utils/socket_fd.cc b/src/utils/socket_fd.cc index 8319a345..0d4b853a 100644 --- a/src/utils/socket_fd.cc +++ b/src/utils/socket_fd.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,23 @@ SocketFd::set_reuse_address(bool 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; +// strncpy(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(); diff --git a/src/utils/socket_fd.h b/src/utils/socket_fd.h index 2d72336f..ff43c82c 100644 --- a/src/utils/socket_fd.h +++ b/src/utils/socket_fd.h @@ -59,6 +59,9 @@ public: 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);