diff --git a/rak/functional.h b/rak/functional.h index 278c942f..82f93d47 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -106,6 +106,27 @@ equal(Type t, Ftor f) { return equal_t(t, f); } +template +struct equal_ptr_t { + typedef bool result_type; + + equal_ptr_t(Type* t, Ftor f) : m_t(t), m_f(f) {} + + template + bool operator () (const Arg& a) { + return *m_t == *m_f(a); + } + + Type* m_t; + Ftor m_f; +}; + +template +inline equal_ptr_t +equal_ptr(Type* t, Ftor f) { + return equal_ptr_t(t, f); +} + template struct not_equal_t { typedef bool result_type; diff --git a/rak/socket_address.h b/rak/socket_address.h index c567ba17..642147c7 100644 --- a/rak/socket_address.h +++ b/rak/socket_address.h @@ -90,6 +90,8 @@ public: bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); } bool set_address_c_str(const char* a); + uint32_t length() const; + socket_address_inet* sa_inet() { return reinterpret_cast(this); } socket_address_inet6* sa_inet6() { return reinterpret_cast(this); } @@ -109,6 +111,9 @@ public: // struct. void copy(const socket_address& src, size_t length); + static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast(sa); } + static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast(sa); } + // The different families will be sorted according to the // sa_family_t's numeric value. bool operator == (const socket_address& rhs) const; @@ -254,6 +259,17 @@ socket_address::set_address_c_str(const char* a) { } } +// Is the zero length really needed, should we require some length? +inline uint32_t +socket_address::length() const { + switch(family()) { + case af_inet: + return sizeof(sockaddr_in); + default: + return 0; + } +} + inline void socket_address::copy(const socket_address& src, size_t length) { length = std::min(length, sizeof(socket_address)); diff --git a/src/core/manager.cc b/src/core/manager.cc index fe7ef906..1703373c 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -277,17 +278,51 @@ Manager::listen_open() { } void -Manager::bind(const std::string& addr) { - if (torrent::listen_port() != 0) { - torrent::listen_close(); - torrent::set_bind_address(addr); - listen_open(); +Manager::set_bind_address(const std::string& addr) { + int err; + rak::address_info* ai; - } else { - torrent::set_bind_address(addr); + if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0) + throw torrent::input_error("Could not set bind address: " + std::string(rak::address_info::strerror(err)) + "."); + + try { + + if (torrent::listen_port() != 0) { + torrent::listen_close(); + torrent::set_bind_address(ai->address()->c_sockaddr()); + listen_open(); + + } else { + torrent::set_bind_address(ai->address()->c_sockaddr()); + } + + rak::address_info::free_address_info(ai); + + m_pollManager->get_http_stack()->set_bind_address(addr); + + } catch (torrent::input_error& e) { + throw e; } +} - m_pollManager->get_http_stack()->set_bind_address(torrent::bind_address()); +void +Manager::set_local_address(const std::string& addr) { + int err; + rak::address_info* ai; + + if ((err = rak::address_info::get_address_info(addr.c_str(), PF_INET, SOCK_STREAM, &ai)) != 0) + throw torrent::input_error("Could not set local address: " + std::string(rak::address_info::strerror(err)) + "."); + + try { + + torrent::set_local_address(ai->address()->c_sockaddr()); + rak::address_info::free_address_info(ai); + + m_pollManager->get_http_stack()->set_bind_address(addr); + + } catch (torrent::input_error& e) { + throw e; + } } void diff --git a/src/core/manager.h b/src/core/manager.h index ad9e9c22..0ed8c329 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -78,7 +78,8 @@ public: void listen_open(); - void bind(const std::string& addr); + void set_bind_address(const std::string& addr); + void set_local_address(const std::string& addr); void shutdown(bool force); diff --git a/src/display/utils.cc b/src/display/utils.cc index 199c9dc6..4faa0222 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -39,12 +39,13 @@ #include #include #include +#include +#include #include #include #include #include "core/download.h" -#include #include "utils.h" @@ -90,6 +91,19 @@ print_ddmmyyyy(char* first, char* last, time_t t) { return print_buffer(first, last, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year)); } +char* +print_address(char* first, char* last, const rak::socket_address* sa) { + if (!sa->address_c_str(first, last - first)) + return first; + + return std::find(first, last, '\0'); +} + +inline char* +print_address(char* first, char* last, const sockaddr* sa) { + return print_address(first, last, rak::socket_address::cast_from(sa)); +} + char* print_download_title(char* first, char* last, core::Download* d) { return print_buffer(first, last, " %s", d->get_download().name().c_str()); @@ -198,17 +212,18 @@ print_status_info(char* first, char* last) { (double)torrent::up_rate()->rate() / 1024.0, (double)torrent::down_rate()->rate() / 1024.0); - first = print_buffer(first, last, " [Listen %s:%u]", - torrent::local_address().c_str(), - (unsigned int)torrent::listen_port()); + first = print_buffer(first, last, " [Listen "); + first = print_address(first, last, torrent::local_address()); + first = print_buffer(first, last, ":%u]", (unsigned int)torrent::listen_port()); if (first > last) throw torrent::internal_error("print_status_info(...) wrote past end of the buffer."); - std::string bindAddress = torrent::bind_address(); - - if (!bindAddress.empty()) - first = print_buffer(first, last, " [Bind %s]", bindAddress.c_str()); + if (!rak::socket_address::cast_from(torrent::bind_address())->is_address_any()) { + first = print_buffer(first, last, " [Bind "); + first = print_address(first, last, torrent::bind_address()); + first = print_buffer(first, last, "]"); + } return first; } diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index 6ee1c231..3f45fa4d 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -37,6 +37,7 @@ #include "config.h" #include +#include #include #include @@ -101,8 +102,11 @@ WindowPeerInfo::redraw() { m_canvas->print(0, y++, "*** Peer Info ***"); - m_canvas->print(0, y++, "DNS: %s:%hu", (*m_focus)->address().c_str(), (*m_focus)->port()); - m_canvas->print(0, y++, "Id: %s" , rak::copy_escape_html((*m_focus)->id()).c_str()); + m_canvas->print(0, y++, "IP: %s:%hu", + rak::socket_address::cast_from((*m_focus)->address())->address_str().c_str(), + rak::socket_address::cast_from((*m_focus)->address())->port()); + + m_canvas->print(0, y++, "ID: %s" , rak::copy_escape_html((*m_focus)->id()).c_str()); char buf[128]; control->client_info()->print(buf, buf + 128, (*m_focus)->id().c_str()); diff --git a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc index bf2cfb36..4acdb767 100644 --- a/src/display/window_peer_list.cc +++ b/src/display/window_peer_list.cc @@ -37,6 +37,7 @@ #include "config.h" #include +#include #include #include "core/download.h" @@ -63,7 +64,7 @@ WindowPeerList::redraw() { int x = 2; int y = 0; - m_canvas->print(x, y, "DNS"); x += 16; + m_canvas->print(x, y, "IP"); x += 16; m_canvas->print(x, y, "UP"); x += 7; m_canvas->print(x, y, "DOWN"); x += 7; m_canvas->print(x, y, "PEER"); x += 7; @@ -95,7 +96,7 @@ WindowPeerList::redraw() { m_canvas->print(x, y, "%c %s", range.first == *m_focus ? '*' : ' ', - p.address().c_str()); + rak::socket_address::cast_from(p.address())->address_str().c_str()); x += 18; m_canvas->print(x, y, "%.1f", (double)p.up_rate()->rate() / 1024); x += 7; diff --git a/src/input/text_input.cc b/src/input/text_input.cc index 26ea8542..1e1b46d0 100644 --- a/src/input/text_input.cc +++ b/src/input/text_input.cc @@ -66,6 +66,7 @@ TextInput::pressed(int key) { } else { switch (key) { case 0x7F: + case 'h' - 'a' + 1: // ^H case KEY_BACKSPACE: if (m_pos != 0) Base::erase(--m_pos, 1); @@ -92,6 +93,23 @@ TextInput::pressed(int key) { break; + case KEY_HOME: + m_pos = 0; + break; + + case KEY_END: + m_pos = size(); + break; + + case 'u' - 'a' + 1: // ^U + Base::erase(0, m_pos); + m_pos = 0; + break; + + case 'k' - 'a' + 1: // ^K + Base::erase(m_pos, size()-m_pos); + break; + case 0x1B: m_alt = true; diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 817e3ffc..0c61d49d 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -166,13 +166,13 @@ initialize_option_handler(Control* c) { variables->insert("session_lock", new utils::VariableAny("yes")); variables->insert("session_on_completion", new utils::VariableAny("yes")); - variables->insert("connection_leech", new utils::VariableAny("leech")); - variables->insert("connection_seed", new utils::VariableAny("seed")); + variables->insert("connection_leech", new utils::VariableAny("leech")); + variables->insert("connection_seed", new utils::VariableAny("seed")); - variables->insert("directory", new utils::VariableAny("./")); - variables->insert("working_directory", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&apply_working_directory))); - variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&torrent::set_local_address))); - variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind))); + variables->insert("directory", new utils::VariableAny("./")); + variables->insert("working_directory", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&apply_working_directory))); + variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::set_bind_address))); + variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::set_local_address))); variables->insert("min_peers", new utils::VariableValue(40)); variables->insert("max_peers", new utils::VariableValue(100));