Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Description: Enable support for IPv6. Closes: #490277.
- Author: Steinar H. Gunderson <[email protected]>
- Reviewed-By: Rogério Theodoro de Brito <[email protected]>
- Bug-Debian: http://bugs.debian.org/490277
- Origin: http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6.patch
- Last-Update: 2011-03-20
- --- a/rak/socket_address.h
- +++ b/rak/socket_address.h
- @@ -145,7 +145,7 @@
- };
- };
- -// Remeber to set the AF_INET.
- +// Remember to set the AF_INET.
- class socket_address_inet {
- public:
- @@ -184,6 +184,10 @@
- const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
- const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
- +
- +#ifdef RAK_USE_INET6
- + socket_address_inet6 to_mapped_address() const;
- +#endif
- bool operator == (const socket_address_inet& rhs) const;
- bool operator < (const socket_address_inet& rhs) const;
- @@ -192,6 +196,52 @@
- struct sockaddr_in m_sockaddr;
- };
- +#ifdef RAK_USE_INET6
- +// Remember to set the AF_INET6.
- +
- +class socket_address_inet6 {
- +public:
- + bool is_any() const { return is_port_any() && is_address_any(); }
- + bool is_valid() const { return !is_port_any() && !is_address_any(); }
- + bool is_port_any() const { return port() == 0; }
- + bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
- +
- + void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
- +
- + uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
- + uint16_t port_n() const { return m_sockaddr.sin6_port; }
- + void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
- + void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
- +
- + in6_addr address() const { return m_sockaddr.sin6_addr; }
- + std::string address_str() const;
- + bool address_c_str(char* buf, socklen_t size) const;
- +
- + void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
- + bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
- + bool set_address_c_str(const char* a);
- +
- + void set_address_any() { set_port(0); set_address(in6addr_any); }
- +
- + sa_family_t family() const { return m_sockaddr.sin6_family; }
- + void set_family() { m_sockaddr.sin6_family = AF_INET6; }
- +
- + sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
- + sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
- +
- + const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
- + const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
- +
- + socket_address normalize_address() const;
- +
- + bool operator == (const socket_address_inet6& rhs) const;
- + bool operator < (const socket_address_inet6& rhs) const;
- +
- +private:
- + struct sockaddr_in6 m_sockaddr;
- +};
- +#endif
- +
- // Unique key for the address, excluding port numbers etc.
- class socket_address_key {
- public:
- @@ -241,8 +291,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->is_valid();
- -// case af_inet6:
- -// return sa_inet6().is_valid();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->is_valid();
- +#endif
- default:
- return false;
- }
- @@ -253,6 +305,10 @@
- switch (family()) {
- case af_inet:
- return !sa_inet()->is_address_any();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return !sa_inet6()->is_address_any();
- +#endif
- default:
- return false;
- }
- @@ -263,6 +319,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->is_address_any();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->is_address_any();
- +#endif
- default:
- return true;
- }
- @@ -273,6 +333,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->port();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->port();
- +#endif
- default:
- return 0;
- }
- @@ -283,6 +347,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->set_port(p);
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->set_port(p);
- +#endif
- default:
- break;
- }
- @@ -293,6 +361,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->address_str();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->address_str();
- +#endif
- default:
- return std::string();
- }
- @@ -303,6 +375,10 @@
- switch (family()) {
- case af_inet:
- return sa_inet()->address_c_str(buf, size);
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sa_inet6()->address_c_str(buf, size);
- +#endif
- default:
- return false;
- }
- @@ -314,6 +390,12 @@
- sa_inet()->set_family();
- return true;
- +#ifdef RAK_USE_INET6
- + } else if (sa_inet6()->set_address_c_str(a)) {
- + sa_inet6()->set_family();
- + return true;
- +#endif
- +
- } else {
- return false;
- }
- @@ -325,6 +407,10 @@
- switch(family()) {
- case af_inet:
- return sizeof(sockaddr_in);
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return sizeof(sockaddr_in6);
- +#endif
- default:
- return 0;
- }
- @@ -349,8 +435,10 @@
- switch (family()) {
- case af_inet:
- return *sa_inet() == *rhs.sa_inet();
- -// case af_inet6:
- -// return *sa_inet6() == *rhs.sa_inet6();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return *sa_inet6() == *rhs.sa_inet6();
- +#endif
- default:
- throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
- }
- @@ -364,8 +452,10 @@
- switch (family()) {
- case af_inet:
- return *sa_inet() < *rhs.sa_inet();
- -// case af_inet6:
- -// return *sa_inet6() < *rhs.sa_inet6();
- +#ifdef RAK_USE_INET6
- + case af_inet6:
- + return *sa_inet6() < *rhs.sa_inet6();
- +#endif
- default:
- throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
- }
- @@ -391,6 +481,23 @@
- return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
- }
- +#ifdef RAK_USE_INET6
- +inline socket_address_inet6
- +socket_address_inet::to_mapped_address() const {
- + uint32_t addr32[4];
- + addr32[0] = 0;
- + addr32[1] = 0;
- + addr32[2] = htonl(0xffff);
- + addr32[3] = m_sockaddr.sin_addr.s_addr;
- +
- + socket_address_inet6 sa;
- + sa.clear();
- + sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
- + sa.set_port_n(m_sockaddr.sin_port);
- + return sa;
- +}
- +#endif
- +
- inline bool
- socket_address_inet::operator == (const socket_address_inet& rhs) const {
- return
- @@ -406,6 +513,59 @@
- m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
- }
- +#ifdef RAK_USE_INET6
- +
- +inline std::string
- +socket_address_inet6::address_str() const {
- + char buf[INET6_ADDRSTRLEN];
- +
- + if (!address_c_str(buf, INET6_ADDRSTRLEN))
- + return std::string();
- +
- + return std::string(buf);
- +}
- +
- +inline bool
- +socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
- + return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
- +}
- +
- +inline bool
- +socket_address_inet6::set_address_c_str(const char* a) {
- + return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
- +}
- +
- +inline socket_address
- +socket_address_inet6::normalize_address() const {
- + const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
- + if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
- + socket_address addr4;
- + addr4.sa_inet()->set_family();
- + addr4.sa_inet()->set_address_n(addr32[3]);
- + addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
- + return addr4;
- + }
- + return *reinterpret_cast<const socket_address*>(this);
- +}
- +
- +inline bool
- +socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
- + return
- + memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
- + m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
- +}
- +
- +inline bool
- +socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
- + int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
- + return
- + addr_comp < 0 ||
- + (addr_comp == 0 ||
- + m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
- +}
- +
- +#endif
- +
- }
- #endif
- --- a/src/command_peer.cc
- +++ b/src/command_peer.cc
- @@ -69,7 +69,13 @@
- torrent::Object
- retrieve_p_address(torrent::Peer* peer) {
- - return rak::socket_address::cast_from(peer->peer_info()->socket_address())->address_str();
- + const rak::socket_address *addr = rak::socket_address::cast_from(peer->peer_info()->socket_address());
- +#ifdef RAK_USE_INET6
- + if (addr->family() == rak::socket_address::af_inet6)
- + return "[" + addr->address_str() + "]";
- + else
- +#endif
- + return addr->address_str();
- }
- torrent::Object
- --- a/src/core/curl_get.cc
- +++ b/src/core/curl_get.cc
- @@ -91,8 +91,20 @@
- curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
- curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
- curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
- +
- + // Even when IPv6-enabled, we don't want to use CURL_IPRESOLVE_WHATEVER,
- + // since that will usually prefer connecting over IPv6 to the tracker.
- + // Since it's usually a lot easier to find our global IPv6 address
- + // (if we have one) than our global IPv4 address, we prefer connecting
- + // over IPv4 if we can, so that the tracker will get our IPv4 address
- + // that way. If the resolve fails, CurlStack will call retry_ipv6()
- + // on us and we'll make a second attempt with CURL_IPRESOLVE_V6.
- curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
- +
- curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
- +#ifdef RAK_USE_INET6
- + m_ipv6 = false;
- +#endif
- m_stack->add_get(this);
- }
- @@ -110,6 +122,17 @@
- m_handle = NULL;
- }
- +#ifdef RAK_USE_INET6
- +void
- +CurlGet::retry_ipv6() {
- + CURL* nhandle = curl_easy_duphandle(m_handle);
- + curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
- + curl_easy_cleanup(m_handle);
- + m_handle = nhandle;
- + m_ipv6 = true;
- +}
- +#endif
- +
- void
- CurlGet::receive_timeout() {
- return m_stack->transfer_done(m_handle, "Timed out");
- --- a/src/core/curl_get.h
- +++ b/src/core/curl_get.h
- @@ -56,6 +56,10 @@
- void start();
- void close();
- +#ifdef RAK_USE_INET6
- + bool is_using_ipv6() { return m_ipv6; }
- + void retry_ipv6();
- +#endif
- bool is_busy() const { return m_handle; }
- bool is_active() const { return m_active; }
- @@ -74,6 +78,9 @@
- void receive_timeout();
- bool m_active;
- +#ifdef RAK_USE_INET6
- + bool m_ipv6;
- +#endif
- rak::priority_item m_taskTimeout;
- --- a/src/core/curl_stack.cc
- +++ b/src/core/curl_stack.cc
- @@ -112,6 +112,21 @@
- if (msg->msg != CURLMSG_DONE)
- throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
- +#ifdef RAK_USE_INET6
- + if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
- + iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
- +
- + if (itr == end())
- + throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
- +
- + if (!(*itr)->is_using_ipv6()) {
- + (*itr)->retry_ipv6();
- + if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
- + throw torrent::internal_error("Error calling curl_multi_add_handle.");
- + continue;
- + }
- + } else
- +#endif
- transfer_done(msg->easy_handle, msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
- }
- --- a/src/display/window_peer_list.cc
- +++ b/src/display/window_peer_list.cc
- @@ -68,7 +68,11 @@
- int x = 2;
- int y = 0;
- - m_canvas->print(x, y, "IP"); x += 16;
- +#ifdef RAK_USE_INET6
- + m_canvas->print(x, y, "IP"); x += 25;
- +#else
- + m_canvas->print(x, y, "IP"); x += 16;
- +#endif
- m_canvas->print(x, y, "UP"); x += 7;
- m_canvas->print(x, y, "DOWN"); x += 7;
- m_canvas->print(x, y, "PEER"); x += 7;
- @@ -99,10 +103,21 @@
- x = 0;
- + std::string ip_address = rak::socket_address::cast_from(p->address())->address_str();
- +#ifdef RAK_USE_INET6
- + if (ip_address.size() >= 24) {
- + ip_address.replace(ip_address.begin() + 21, ip_address.end(), "...");
- + }
- +#endif
- +
- m_canvas->print(x, y, "%c %s",
- range.first == *m_focus ? '*' : ' ',
- - rak::socket_address::cast_from(p->address())->address_str().c_str());
- + ip_address.c_str());
- +#ifdef RAK_USE_INET6
- + x += 27;
- +#else
- x += 18;
- +#endif
- m_canvas->print(x, y, "%.1f", (double)p->up_rate()->rate() / 1024); x += 7;
- m_canvas->print(x, y, "%.1f", (double)p->down_rate()->rate() / 1024); x += 7;
- --- a/src/utils/socket_fd.cc
- +++ b/src/utils/socket_fd.cc
- @@ -71,6 +71,11 @@
- check_valid();
- int opt = p;
- +#ifdef RAK_USE_INET6
- + if (m_ipv6_socket)
- + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
- + else
- +#endif
- return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
- }
- @@ -130,12 +135,36 @@
- bool
- SocketFd::open_stream() {
- +#ifdef RAK_USE_INET6
- + m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
- + if (m_fd == -1) {
- + m_ipv6_socket = false;
- + return (m_fd = socket(rak::socket_address::pf_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;
- +#else
- return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
- +#endif
- }
- bool
- SocketFd::open_datagram() {
- +#ifdef RAK_USE_INET6
- + m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
- + if (m_fd == -1) {
- + m_ipv6_socket = false;
- + return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
- + }
- + m_ipv6_socket = true;
- +
- + int zero = 0;
- + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
- +#else
- return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
- +#endif
- }
- bool
- @@ -153,6 +182,12 @@
- SocketFd::bind(const rak::socket_address& sa) {
- check_valid();
- +#ifdef RAK_USE_INET6
- + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
- + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
- + return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
- + }
- +#endif
- return !::bind(m_fd, sa.c_sockaddr(), sa.length());
- }
- @@ -160,6 +195,12 @@
- SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
- check_valid();
- +#ifdef RAK_USE_INET6
- + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
- + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
- + return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
- + }
- +#endif
- return !::bind(m_fd, sa.c_sockaddr(), length);
- }
- @@ -167,10 +208,34 @@
- SocketFd::connect(const rak::socket_address& sa) {
- check_valid();
- +#ifdef RAK_USE_INET6
- + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
- + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
- + return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
- + }
- +#endif
- return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
- }
- bool
- +SocketFd::getsockname(rak::socket_address *sa) {
- + check_valid();
- +
- + socklen_t len = sizeof(rak::socket_address);
- + if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
- + return false;
- + }
- +
- +#ifdef RAK_USE_INET6
- + if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
- + *sa = sa->sa_inet6()->normalize_address();
- + }
- +#endif
- +
- + return true;
- +}
- +
- +bool
- SocketFd::listen(int size) {
- check_valid();
- @@ -182,7 +247,18 @@
- check_valid();
- socklen_t len = sizeof(rak::socket_address);
- +#ifdef RAK_USE_INET6
- + if (sa == NULL) {
- + return SocketFd(::accept(m_fd, NULL, &len));
- + }
- + int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
- + if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
- + *sa = sa->sa_inet6()->normalize_address();
- + }
- + return SocketFd(fd);
- +#else
- return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len));
- +#endif
- }
- // unsigned int
- --- a/src/utils/socket_fd.h
- +++ b/src/utils/socket_fd.h
- @@ -80,6 +80,7 @@
- bool bind(const rak::socket_address& sa);
- bool bind(const rak::socket_address& sa, unsigned int length);
- bool connect(const rak::socket_address& sa);
- + bool getsockname(rak::socket_address* sa);
- bool listen(int size);
- SocketFd accept(rak::socket_address* sa);
- @@ -91,6 +92,9 @@
- inline void check_valid() const;
- int m_fd;
- +#ifdef RAK_USE_INET6
- + bool m_ipv6_socket;
- +#endif
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment