Ticket #1111: libtorrent-0.12.7-ipv6-08.patch

File libtorrent-0.12.7-ipv6-08.patch, 40.3 KB (added by anonymous, 13 months ago)
  • rak/socket_address.h

    diff -Nur libtorrent-0.12.7.orig/rak/socket_address.h libtorrent-0.12.7/rak/socket_address.h
    old new  
    145145  }; 
    146146}; 
    147147 
    148 // Remeber to set the AF_INET. 
     148// Remember to set the AF_INET. 
    149149 
    150150class socket_address_inet { 
    151151public: 
     
    184184 
    185185  const sockaddr*     c_sockaddr() const                      { return reinterpret_cast<const sockaddr*>(&m_sockaddr); } 
    186186  const sockaddr_in*  c_sockaddr_inet() const                 { return &m_sockaddr; } 
     187   
     188#ifdef RAK_USE_INET6 
     189  socket_address_inet6 to_mapped_address() const; 
     190#endif 
    187191 
    188192  bool                operator == (const socket_address_inet& rhs) const; 
    189193  bool                operator < (const socket_address_inet& rhs) const; 
     
    192196  struct sockaddr_in  m_sockaddr; 
    193197}; 
    194198 
     199#ifdef RAK_USE_INET6 
     200// Remember to set the AF_INET6. 
     201 
     202class socket_address_inet6 { 
     203public: 
     204  bool                is_any() const                          { return is_port_any() && is_address_any(); } 
     205  bool                is_valid() const                        { return !is_port_any() && !is_address_any(); } 
     206  bool                is_port_any() const                     { return port() == 0; } 
     207  bool                is_address_any() const                  { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; } 
     208 
     209  void                clear()                                 { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); } 
     210 
     211  uint16_t            port() const                            { return ntohs(m_sockaddr.sin6_port); } 
     212  uint16_t            port_n() const                          { return m_sockaddr.sin6_port; } 
     213  void                set_port(uint16_t p)                    { m_sockaddr.sin6_port = htons(p); } 
     214  void                set_port_n(uint16_t p)                  { m_sockaddr.sin6_port = p; } 
     215 
     216  in6_addr            address() const                         { return m_sockaddr.sin6_addr; } 
     217  std::string         address_str() const; 
     218  bool                address_c_str(char* buf, socklen_t size) const; 
     219 
     220  void                set_address(in6_addr a)                 { m_sockaddr.sin6_addr = a; } 
     221  bool                set_address_str(const std::string& a)   { return set_address_c_str(a.c_str()); } 
     222  bool                set_address_c_str(const char* a); 
     223 
     224  void                set_address_any()                       { set_port(0); set_address(in6addr_any); } 
     225 
     226  sa_family_t         family() const                          { return m_sockaddr.sin6_family; } 
     227  void                set_family()                            { m_sockaddr.sin6_family = AF_INET6; } 
     228 
     229  sockaddr*           c_sockaddr()                            { return reinterpret_cast<sockaddr*>(&m_sockaddr); } 
     230  sockaddr_in6*       c_sockaddr_inet6()                      { return &m_sockaddr; } 
     231 
     232  const sockaddr*     c_sockaddr() const                      { return reinterpret_cast<const sockaddr*>(&m_sockaddr); } 
     233  const sockaddr_in6* c_sockaddr_inet6() const                { return &m_sockaddr; } 
     234 
     235  socket_address      normalize_address() const; 
     236 
     237  bool                operator == (const socket_address_inet6& rhs) const; 
     238  bool                operator < (const socket_address_inet6& rhs) const; 
     239 
     240private: 
     241  struct sockaddr_in6 m_sockaddr; 
     242}; 
     243#endif 
     244 
    195245// Unique key for the address, excluding port numbers etc. 
    196246class socket_address_key { 
    197247public: 
     
    241291  switch (family()) { 
    242292  case af_inet: 
    243293    return sa_inet()->is_valid(); 
    244 //   case af_inet6: 
    245 //     return sa_inet6().is_valid(); 
     294#ifdef RAK_USE_INET6 
     295  case af_inet6: 
     296    return sa_inet6()->is_valid(); 
     297#endif 
    246298  default: 
    247299    return false; 
    248300  } 
     
    253305  switch (family()) { 
    254306  case af_inet: 
    255307    return !sa_inet()->is_address_any(); 
     308#ifdef RAK_USE_INET6 
     309  case af_inet6: 
     310    return !sa_inet6()->is_address_any(); 
     311#endif 
    256312  default: 
    257313    return false; 
    258314  } 
     
    263319  switch (family()) { 
    264320  case af_inet: 
    265321    return sa_inet()->is_address_any(); 
     322#ifdef RAK_USE_INET6 
     323  case af_inet6: 
     324    return sa_inet6()->is_address_any(); 
     325#endif 
    266326  default: 
    267327    return true; 
    268328  } 
     
    273333  switch (family()) { 
    274334  case af_inet: 
    275335    return sa_inet()->port(); 
     336#ifdef RAK_USE_INET6 
     337  case af_inet6: 
     338    return sa_inet6()->port(); 
     339#endif 
    276340  default: 
    277341    return 0; 
    278342  } 
     
    283347  switch (family()) { 
    284348  case af_inet: 
    285349    return sa_inet()->set_port(p); 
     350#ifdef RAK_USE_INET6 
     351  case af_inet6: 
     352    return sa_inet6()->set_port(p); 
     353#endif 
    286354  default: 
    287355    break; 
    288356  } 
     
    293361  switch (family()) { 
    294362  case af_inet: 
    295363    return sa_inet()->address_str(); 
     364#ifdef RAK_USE_INET6 
     365  case af_inet6: 
     366    return sa_inet6()->address_str(); 
     367#endif 
    296368  default: 
    297369    return std::string(); 
    298370  } 
     
    303375  switch (family()) { 
    304376  case af_inet: 
    305377    return sa_inet()->address_c_str(buf, size); 
     378#ifdef RAK_USE_INET6 
     379  case af_inet6: 
     380    return sa_inet6()->address_c_str(buf, size); 
     381#endif 
    306382  default: 
    307383    return false; 
    308384  } 
     
    314390    sa_inet()->set_family(); 
    315391    return true; 
    316392 
     393#ifdef RAK_USE_INET6 
     394  } else if (sa_inet6()->set_address_c_str(a)) { 
     395    sa_inet6()->set_family(); 
     396    return true; 
     397#endif 
     398 
    317399  } else { 
    318400    return false; 
    319401  } 
     
    325407  switch(family()) { 
    326408  case af_inet: 
    327409    return sizeof(sockaddr_in); 
     410#ifdef RAK_USE_INET6 
     411  case af_inet6: 
     412    return sizeof(sockaddr_in6); 
     413#endif 
    328414  default: 
    329415    return 0; 
    330416  }       
     
    349435  switch (family()) { 
    350436  case af_inet: 
    351437    return *sa_inet() == *rhs.sa_inet(); 
    352 //   case af_inet6: 
    353 //     return *sa_inet6() == *rhs.sa_inet6(); 
     438#ifdef RAK_USE_INET6 
     439  case af_inet6: 
     440    return *sa_inet6() == *rhs.sa_inet6(); 
     441#endif 
    354442  default: 
    355443    throw std::logic_error("socket_address::operator == (rhs) invalid type comparison."); 
    356444  } 
     
    364452  switch (family()) { 
    365453  case af_inet: 
    366454    return *sa_inet() < *rhs.sa_inet(); 
    367 //   case af_inet6: 
    368 //     return *sa_inet6() < *rhs.sa_inet6(); 
     455#ifdef RAK_USE_INET6 
     456  case af_inet6: 
     457    return *sa_inet6() < *rhs.sa_inet6(); 
     458#endif 
    369459  default: 
    370460    throw std::logic_error("socket_address::operator < (rhs) invalid type comparison."); 
    371461  } 
     
    391481  return inet_pton(AF_INET, a, &m_sockaddr.sin_addr); 
    392482} 
    393483 
     484#ifdef RAK_USE_INET6 
     485inline socket_address_inet6 
     486socket_address_inet::to_mapped_address() const { 
     487  uint32_t addr32[4]; 
     488  addr32[0] = 0; 
     489  addr32[1] = 0; 
     490  addr32[2] = htonl(0xffff); 
     491  addr32[3] = m_sockaddr.sin_addr.s_addr; 
     492   
     493  socket_address_inet6 sa; 
     494  sa.clear(); 
     495  sa.set_address(*reinterpret_cast<in6_addr *>(addr32)); 
     496  sa.set_port_n(m_sockaddr.sin_port); 
     497  return sa; 
     498} 
     499#endif 
     500 
    394501inline bool 
    395502socket_address_inet::operator == (const socket_address_inet& rhs) const { 
    396503  return 
     
    406513     m_sockaddr.sin_port < rhs.m_sockaddr.sin_port); 
    407514} 
    408515 
     516#ifdef RAK_USE_INET6 
     517 
     518inline std::string 
     519socket_address_inet6::address_str() const { 
     520  char buf[INET6_ADDRSTRLEN]; 
     521 
     522  if (!address_c_str(buf, INET6_ADDRSTRLEN)) 
     523    return std::string(); 
     524 
     525  return std::string(buf); 
     526} 
     527 
     528inline bool 
     529socket_address_inet6::address_c_str(char* buf, socklen_t size) const { 
     530  return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size); 
     531} 
     532 
     533inline bool 
     534socket_address_inet6::set_address_c_str(const char* a) { 
     535  return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr); 
     536} 
     537 
     538inline socket_address 
     539socket_address_inet6::normalize_address() const { 
     540  const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr); 
     541  if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) { 
     542    socket_address addr4; 
     543    addr4.sa_inet()->set_family(); 
     544    addr4.sa_inet()->set_address_n(addr32[3]); 
     545    addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port); 
     546    return addr4; 
     547  } 
     548  return *reinterpret_cast<const socket_address*>(this); 
     549} 
     550 
     551inline bool 
     552socket_address_inet6::operator == (const socket_address_inet6& rhs) const { 
     553  return 
     554    memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 && 
     555    m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port; 
     556} 
     557 
     558inline bool 
     559socket_address_inet6::operator < (const socket_address_inet6& rhs) const { 
     560  int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)); 
     561  return 
     562    addr_comp < 0 || 
     563    (addr_comp == 0 || 
     564     m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port); 
     565} 
     566 
     567#endif 
     568 
    409569} 
    410570 
    411571#endif 
  • src/dht/dht_server.cc

    @@ -54,8 +54,15@@
       m_recentlyInactive(0),
       m_bucket(NULL) {
     
    +#ifdef RAK_USE_INET6
    +  if (sa->family() != rak::socket_address::af_inet &&
    +      (sa->family() != rak::socket_address::af_inet6 ||
    +       !sa->sa_inet6()->is_any()))
    +    throw resource_error("Addres not af_inet or in6addr_any");
    +#else
       if (sa->family() != rak::socket_address::af_inet)
         throw resource_error("Address not af_inet");
    +#endif
     }
     
     DhtNode::DhtNode(const std::string& id, const Object& cache) :
    @@ -84,8 +91,20 @@
     
     Object*
     DhtNode::store_cache(Object* container) const {
    -  container->insert_key("i", m_socketAddress.sa_inet()->address_h());
    -  container->insert_key("p", m_socketAddress.sa_inet()->port());
    +#ifdef RAK_USE_INET6
    +  if (m_socketAddress.family() == rak::socket_address::af_inet6) {
    +    // Currently, all we support is in6addr_any (checked in the constructor),
    +    // which is effectively equivalent to this. Note that we need to specify
    +    // int64_t explicitly here because a zero constant is special in C++ and
    +    // thus we need an explicit match.
    +    container->insert_key("i", int64_t(0));
    +    container->insert_key("p", m_socketAddress.sa_inet6()->port());
    +  } else 
    +#endif
    +  {
    +    container->insert_key("i", m_socketAddress.sa_inet()->address_h());
    +    container->insert_key("p", m_socketAddress.sa_inet()->port());
    +  }
       container->insert_key("t", m_lastSeen);
       return container;
     }
    diff -Nur libtorrent-0.12.7.orig/src/dht/dht_server.cc libtorrent-0.12.7/src/dht/dht_server.cc
    old new  
    700700      if (read < 0) 
    701701        break; 
    702702 
     703#ifdef RAK_USE_INET6 
     704      // We can currently only process mapped-IPv4 addresses, not real IPv6. 
     705      // Translate them to an af_inet socket_address. 
     706      if (sa.family() == rak::socket_address::af_inet6) 
     707        sa = sa.sa_inet6()->normalize_address(); 
     708#endif 
     709 
     710      if (sa.family() != rak::socket_address::af_inet) 
     711        continue; 
     712 
    703713      total += read; 
    704714 
    705715      // If it's not a valid bencode dictionary at all, it's probably not a DHT 
  • src/net/address_list.h

    diff -Nur libtorrent-0.12.7.orig/src/net/address_list.h libtorrent-0.12.7/src/net/address_list.h
    old new  
    5454 
    5555  void                        parse_address_compact(raw_string s); 
    5656  void                        parse_address_compact(const std::string& s); 
     57#ifdef RAK_USE_INET6 
     58  void                        parse_address_compact_ipv6(const std::string& s); 
     59#endif 
    5760 
    5861private: 
    5962  static rak::socket_address  parse_address(const Object& b); 
     
    9999  const char*         c_str() const { return reinterpret_cast<const char*>(this); } 
    100100} __attribute__ ((packed)); 
    101101 
     102#ifdef RAK_USE_INET6 
     103struct SocketAddressCompact6 { 
     104  SocketAddressCompact6() {} 
     105  SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {} 
     106  SocketAddressCompact6(const rak::socket_address_inet6* sa) : addr(sa->address()), port(sa->port_n()) {} 
     107 
     108  operator rak::socket_address () const { 
     109    rak::socket_address sa; 
     110    sa.sa_inet6()->clear(); 
     111    sa.sa_inet6()->set_port_n(port); 
     112    sa.sa_inet6()->set_address(addr); 
     113 
     114    return sa; 
     115  } 
     116 
     117  in6_addr addr; 
     118  uint16_t port; 
     119 
     120  const char*         c_str() const { return reinterpret_cast<const char*>(this); } 
     121} __attribute__ ((packed)); 
     122#endif 
     123 
    102124} 
    103125 
    104126#endif 
  • src/net/address_list.cc

    diff -Nur libtorrent-0.12.7.orig/src/net/address_list.cc libtorrent-0.12.7/src/net/address_list.cc
    old new  
    7777            std::back_inserter(*this)); 
    7878} 
    7979 
     80#ifdef RAK_USE_INET6 
     81void 
     82AddressList::parse_address_compact_ipv6(const std::string& s) { 
     83  if (sizeof(const SocketAddressCompact6) != 18) 
     84    throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size."); 
     85 
     86  std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()), 
     87            reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)), 
     88            std::back_inserter(*this)); 
     89} 
     90#endif 
     91 
    8092void 
    8193AddressList::parse_address_bencode(raw_list s) { 
    8294  if (sizeof(const SocketAddressCompact) != 6) 
  • src/net/local_addr.cc

    diff -Nur libtorrent-0.12.7.orig/src/net/local_addr.cc libtorrent-0.12.7/src/net/local_addr.cc
    old new  
     1// libTorrent - BitTorrent library 
     2// Copyright (C) 2005-2007, Jari Sundell 
     3// 
     4// This program is free software; you can redistribute it and/or modify 
     5// it under the terms of the GNU General Public License as published by 
     6// the Free Software Foundation; either version 2 of the License, or 
     7// (at your option) any later version. 
     8//  
     9// This program is distributed in the hope that it will be useful, 
     10// but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12// GNU General Public License for more details. 
     13//  
     14// You should have received a copy of the GNU General Public License 
     15// along with this program; if not, write to the Free Software 
     16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     17// 
     18// In addition, as a special exception, the copyright holders give 
     19// permission to link the code of portions of this program with the 
     20// OpenSSL library under certain conditions as described in each 
     21// individual source file, and distribute linked combinations 
     22// including the two. 
     23// 
     24// You must obey the GNU General Public License in all respects for 
     25// all of the code used other than OpenSSL.  If you modify file(s) 
     26// with this exception, you may extend this exception to your version 
     27// of the file(s), but you are not obligated to do so.  If you do not 
     28// wish to do so, delete this exception statement from your version. 
     29// If you delete this exception statement from all source files in the 
     30// program, then also delete it here. 
     31// 
     32// Contact:  Jari Sundell <jaris@ifi.uio.no> 
     33// 
     34//           Skomakerveien 33 
     35//           3185 Skoppum, NORWAY 
     36 
     37#include "config.h" 
     38 
     39#include <stdio.h> 
     40#include <ifaddrs.h> 
     41#include <rak/socket_address.h> 
     42#include <sys/types.h> 
     43#include <errno.h> 
     44 
     45#ifdef __linux__ 
     46#include <linux/netlink.h> 
     47#include <linux/rtnetlink.h> 
     48#endif 
     49 
     50#include "torrent/exceptions.h" 
     51#include "socket_fd.h" 
     52#include "local_addr.h" 
     53 
     54namespace torrent { 
     55namespace { 
     56 
     57// IPv4 priority, from highest to lowest: 
     58// 
     59//   1. Everything else (global address) 
     60//   2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24) 
     61//   3. Empty/INADDR_ANY (0.0.0.0) 
     62//   4. Link-local address (169.254.0.0/16) 
     63//   5. Localhost (127.0.0.0/8) 
     64int get_priority_ipv4(const in_addr& addr) { 
     65  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x7f000000U)) { 
     66    return 5; 
     67  } 
     68  if (addr.s_addr == htonl(0)) { 
     69    return 4; 
     70  } 
     71  if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) { 
     72    return 3; 
     73  } 
     74  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) || 
     75      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) || 
     76      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) { 
     77    return 2; 
     78  } 
     79  return 1; 
     80} 
     81 
     82#ifdef RAK_USE_INET6 
     83// IPv6 priority, from highest to lowest: 
     84// 
     85//  1. Global address (2000::/16 not in 6to4 or Teredo) 
     86//  2. 6to4 (2002::/16) 
     87//  3. Teredo (2001::/32) 
     88//  4. Empty/INADDR_ANY (::) 
     89//  5. Everything else (link-local, ULA, etc.) 
     90int get_priority_ipv6(const in6_addr& addr) { 
     91  const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(addr.s6_addr); 
     92  if (addr32[0] == htonl(0) && 
     93      addr32[1] == htonl(0) && 
     94      addr32[2] == htonl(0) && 
     95      addr32[3] == htonl(0)) { 
     96    return 4; 
     97  } 
     98  if (addr32[0] == htonl(0x20010000)) { 
     99    return 3; 
     100  } 
     101  if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) { 
     102    return 2; 
     103  } 
     104  if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) { 
     105    return 1; 
     106  } 
     107  return 5; 
     108} 
     109#endif 
     110 
     111int get_priority(const rak::socket_address& addr) { 
     112  switch (addr.family()) { 
     113  case AF_INET: 
     114    return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr); 
     115#ifdef RAK_USE_INET6 
     116  case AF_INET6: 
     117    return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr); 
     118#endif 
     119  default: 
     120    throw torrent::internal_error("Unknown address family given to compare"); 
     121  } 
     122} 
     123 
     124} 
     125 
     126#ifdef __linux__ 
     127 
     128// Linux-specific implementation that understands how to filter away 
     129// understands how to filter away secondary addresses. 
     130bool get_local_address(sa_family_t family, rak::socket_address *address) { 
     131  ifaddrs *ifaddrs; 
     132  if (getifaddrs(&ifaddrs)) { 
     133    return false; 
     134  } 
     135 
     136  rak::socket_address best_addr; 
     137  switch (family) { 
     138  case AF_INET: 
     139    best_addr.sa_inet()->clear(); 
     140    break; 
     141#ifdef RAK_USE_INET6 
     142  case AF_INET6: 
     143    best_addr.sa_inet6()->clear(); 
     144    break; 
     145#endif 
     146  default: 
     147    throw torrent::internal_error("Unknown address family given to get_local_address"); 
     148  } 
     149 
     150  // The bottom bit of the priority is used to hold if the address is  
     151  // a secondary address (e.g. with IPv6 privacy extensions) or not; 
     152  // secondary addresses have lower priority (higher number). 
     153  int best_addr_pri = get_priority(best_addr) * 2; 
     154 
     155  // Get all the addresses via Linux' netlink interface. 
     156  int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 
     157  if (fd == -1) { 
     158    return false; 
     159  } 
     160 
     161  struct sockaddr_nl nladdr; 
     162  memset(&nladdr, 0, sizeof(nladdr)); 
     163  nladdr.nl_family = AF_NETLINK; 
     164  if (::bind(fd, (sockaddr *)&nladdr, sizeof(nladdr))) { 
     165    ::close(fd); 
     166    return false; 
     167  } 
     168 
     169  const int seq_no = 1; 
     170  struct { 
     171    nlmsghdr nh; 
     172    rtgenmsg g; 
     173  } req; 
     174  memset(&req, 0, sizeof(req)); 
     175 
     176  req.nh.nlmsg_len = sizeof(req); 
     177  req.nh.nlmsg_type = RTM_GETADDR; 
     178  req.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; 
     179  req.nh.nlmsg_pid = getpid(); 
     180  req.nh.nlmsg_seq = seq_no; 
     181  req.g.rtgen_family = AF_UNSPEC; 
     182 
     183  int ret; 
     184  do { 
     185    ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr)); 
     186  } while (ret == -1 && errno == EINTR); 
     187 
     188  if (ret == -1) { 
     189    ::close(fd); 
     190    return false; 
     191  } 
     192 
     193  bool done = false; 
     194  do { 
     195    char buf[4096]; 
     196    socklen_t len = sizeof(nladdr); 
     197    do { 
     198      ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len); 
     199    } while (ret == -1 && errno == EINTR); 
     200 
     201    if (ret < 0) { 
     202      ::close(fd); 
     203      return false; 
     204    } 
     205 
     206    for (const nlmsghdr *nlmsg = (const nlmsghdr *)buf; 
     207         NLMSG_OK(nlmsg, ret); 
     208         nlmsg = NLMSG_NEXT(nlmsg, ret)) { 
     209      if (nlmsg->nlmsg_seq != seq_no) 
     210        continue; 
     211      if (nlmsg->nlmsg_type == NLMSG_DONE) { 
     212        done = true; 
     213        break; 
     214      } 
     215      if (nlmsg->nlmsg_type == NLMSG_ERROR) { 
     216        ::close(fd); 
     217        return false; 
     218      } 
     219      if (nlmsg->nlmsg_type != RTM_NEWADDR) 
     220        continue; 
     221 
     222      const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg); 
     223 
     224      if (ifa->ifa_family != family) 
     225        continue;  
     226 
     227#ifdef IFA_F_OPTIMISTIC 
     228      if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0) 
     229        continue; 
     230#endif 
     231#ifdef IFA_F_DADFAILED 
     232      if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0) 
     233        continue; 
     234#endif 
     235#ifdef IFA_F_DEPRECATED 
     236      if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0) 
     237        continue; 
     238#endif 
     239#ifdef IFA_F_TENTATIVE 
     240      if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0) 
     241        continue; 
     242#endif 
     243   
     244      // Since there can be point-to-point links on the machine, we need to keep 
     245      // track of the addresses we've seen for this interface; if we see both 
     246      // IFA_LOCAL and IFA_ADDRESS for an interface, keep only the IFA_LOCAL. 
     247      rak::socket_address this_addr; 
     248      bool seen_addr = false; 
     249      int plen = IFA_PAYLOAD(nlmsg); 
     250      for (const rtattr *rta = IFA_RTA(ifa); 
     251           RTA_OK(rta, plen); 
     252           rta = RTA_NEXT(rta, plen)) { 
     253        if (rta->rta_type != IFA_LOCAL && 
     254            rta->rta_type != IFA_ADDRESS) { 
     255          continue; 
     256        } 
     257        if (rta->rta_type == IFA_ADDRESS && seen_addr) { 
     258          continue; 
     259        } 
     260        seen_addr = true; 
     261        switch (ifa->ifa_family) { 
     262        case AF_INET: 
     263          this_addr.sa_inet()->clear(); 
     264          this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta)); 
     265          break; 
     266#ifdef RAK_USE_INET6 
     267        case AF_INET6: 
     268          this_addr.sa_inet6()->clear(); 
     269          this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta)); 
     270          break; 
     271#endif 
     272        } 
     273      } 
     274      if (!seen_addr) 
     275        continue; 
     276        
     277      int this_addr_pri = get_priority(this_addr) * 2; 
     278      if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) { 
     279        ++this_addr_pri; 
     280      } 
     281 
     282      if (this_addr_pri < best_addr_pri) { 
     283        best_addr = this_addr; 
     284        best_addr_pri = this_addr_pri; 
     285      } 
     286    } 
     287  } while (!done); 
     288 
     289  ::close(fd); 
     290  if (!best_addr.is_address_any()) { 
     291    *address = best_addr; 
     292    return true; 
     293  } else { 
     294    return false; 
     295  }  
     296} 
     297 
     298#else 
     299 
     300// Generic POSIX variant. 
     301bool get_local_address(sa_family_t family, rak::socket_address *address) { 
     302  SocketFd sock; 
     303  if (!sock.open_datagram()) { 
     304    return false; 
     305  } 
     306 
     307  rak::socket_address dummy_dest; 
     308  dummy_dest.clear(); 
     309 
     310  switch (family) { 
     311  case rak::socket_address::af_inet: 
     312    dummy_dest.set_address_c_str("4.0.0.0");  
     313    break; 
     314#ifdef RAK_USE_INET6 
     315  case rak::socket_address::af_inet6: 
     316    dummy_dest.set_address_c_str("2001:700::");  
     317    break; 
     318#endif 
     319  default: 
     320    throw internal_error("Unknown address family"); 
     321  } 
     322  dummy_dest.set_port(80); 
     323 
     324  if (!sock.connect(dummy_dest)) { 
     325    sock.close(); 
     326    return false; 
     327  } 
     328 
     329  bool ret = sock.getsockname(address); 
     330  sock.close(); 
     331  return ret; 
     332} 
     333 
     334#endif 
     335 
     336} 
  • src/net/local_addr.h

    diff -Nur libtorrent-0.12.7.orig/src/net/local_addr.h libtorrent-0.12.7/src/net/local_addr.h
    old new  
     1// libTorrent - BitTorrent library 
     2// Copyright (C) 2005-2007, Jari Sundell 
     3// 
     4// This program is free software; you can redistribute it and/or modify 
     5// it under the terms of the GNU General Public License as published by 
     6// the Free Software Foundation; either version 2 of the License, or 
     7// (at your option) any later version. 
     8//  
     9// This program is distributed in the hope that it will be useful, 
     10// but WITHOUT ANY WARRANTY; without even the implied warranty of 
     11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     12// GNU General Public License for more details. 
     13//  
     14// You should have received a copy of the GNU General Public License 
     15// along with this program; if not, write to the Free Software 
     16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     17// 
     18// In addition, as a special exception, the copyright holders give 
     19// permission to link the code of portions of this program with the 
     20// OpenSSL library under certain conditions as described in each 
     21// individual source file, and distribute linked combinations 
     22// including the two. 
     23// 
     24// You must obey the GNU General Public License in all respects for 
     25// all of the code used other than OpenSSL.  If you modify file(s) 
     26// with this exception, you may extend this exception to your version 
     27// of the file(s), but you are not obligated to do so.  If you do not 
     28// wish to do so, delete this exception statement from your version. 
     29// If you delete this exception statement from all source files in the 
     30// program, then also delete it here. 
     31// 
     32// Contact:  Jari Sundell <jaris@ifi.uio.no> 
     33// 
     34//           Skomakerveien 33 
     35//           3185 Skoppum, NORWAY 
     36 
     37// A routine to get a local IP address that can be presented to a tracker. 
     38// (Does not use UPnP etc., so will not understand NAT.) 
     39// On a machine with multiple network cards, address selection can be a 
     40// complex process, and in general what's selected is a source/destination 
     41// address pair. However, this routine will give an approximation that will 
     42// be good enough for most purposes and users. 
     43 
     44#ifndef LIBTORRENT_NET_LOCAL_ADDR_H 
     45#define LIBTORRENT_NET_LOCAL_ADDR_H 
     46 
     47#include <unistd.h> 
     48 
     49namespace rak { 
     50  class socket_address; 
     51} 
     52 
     53namespace torrent { 
     54 
     55// Note: family must currently be rak::af_inet or rak::af_inet6 
     56// (rak::af_unspec won't do); anything else will throw an exception. 
     57// Returns false if no address of the given family could be found, 
     58// either because there are none, or because something went wrong in 
     59// the process (e.g., no free file descriptors). 
     60bool get_local_address(sa_family_t family, rak::socket_address *address); 
     61 
     62} 
     63 
     64#endif /* LIBTORRENT_NET_LOCAL_ADDR_H */ 
  • src/net/Makefile.am

    diff -Nur libtorrent-0.12.7.orig/src/net/Makefile.am libtorrent-0.12.7/src/net/Makefile.am
    old new  
    44        address_list.cc \ 
    55        address_list.h \ 
    66        data_buffer.h \ 
     7        local_addr.cc \ 
     8        local_addr.h \ 
    79        listen.cc \ 
    810        listen.h \ 
    911        protocol_buffer.h \ 
  • src/net/Makefile.in

    diff -Nur libtorrent-0.12.7.orig/src/net/Makefile.in libtorrent-0.12.7/src/net/Makefile.in
    old new  
    5454CONFIG_CLEAN_VPATH_FILES = 
    5555LTLIBRARIES = $(noinst_LTLIBRARIES) 
    5656libsub_net_la_LIBADD = 
    57 am_libsub_net_la_OBJECTS = address_list.lo listen.lo socket_base.lo \ 
    58         socket_datagram.lo socket_fd.lo socket_set.lo socket_stream.lo \ 
    59         throttle_internal.lo throttle_list.lo 
     57am_libsub_net_la_OBJECTS = address_list.lo local_addr.lo listen.lo \ 
     58        socket_base.lo socket_datagram.lo socket_fd.lo socket_set.lo \ 
     59        socket_stream.lo throttle_internal.lo throttle_list.lo 
    6060libsub_net_la_OBJECTS = $(am_libsub_net_la_OBJECTS) 
    6161DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 
    6262depcomp = $(SHELL) $(top_srcdir)/depcomp 
     
    220220        address_list.cc \ 
    221221        address_list.h \ 
    222222        data_buffer.h \ 
     223        local_addr.cc \ 
     224        local_addr.h \ 
    223225        listen.cc \ 
    224226        listen.h \ 
    225227        protocol_buffer.h \ 
     
    294296 
    295297@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_list.Plo@am__quote@ 
    296298@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listen.Plo@am__quote@ 
     299@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_addr.Plo@am__quote@ 
    297300@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_base.Plo@am__quote@ 
    298301@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_datagram.Plo@am__quote@ 
    299302@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Plo@am__quote@ 
  • src/net/socket_datagram.cc

    diff -Nur libtorrent-0.12.7.orig/src/net/socket_datagram.cc libtorrent-0.12.7/src/net/socket_datagram.cc
    old new  
    7373  int r; 
    7474 
    7575  if (sa != NULL) { 
    76     r = ::sendto(m_fileDesc, buffer, length, 0, sa->sa_inet()->c_sockaddr(), sizeof(rak::socket_address_inet)); 
     76#ifdef RAK_USE_INET6 
     77    if (m_ipv6_socket && sa->family() == rak::socket_address::pf_inet) { 
     78      rak::socket_address_inet6 sa_mapped = sa->sa_inet()->to_mapped_address(); 
     79      r = ::sendto(m_fileDesc, buffer, length, 0, sa_mapped.c_sockaddr(), sizeof(rak::socket_address_inet6)); 
     80    } else 
     81#endif 
     82    r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length()); 
    7783  } else { 
    7884    r = ::send(m_fileDesc, buffer, length, 0); 
    7985  } 
  • src/net/socket_fd.cc

    diff -Nur libtorrent-0.12.7.orig/src/net/socket_fd.cc libtorrent-0.12.7/src/net/socket_fd.cc
    old new  
    7070  check_valid(); 
    7171  int opt = p; 
    7272 
     73#ifdef RAK_USE_INET6 
     74  if (m_ipv6_socket) 
     75    return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0; 
     76  else 
     77#endif 
    7378  return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0; 
    7479} 
    7580 
     
    112117 
    113118bool 
    114119SocketFd::open_stream() { 
     120#ifdef RAK_USE_INET6 
     121  m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP); 
     122  if (m_fd == -1) { 
     123    m_ipv6_socket = false; 
     124    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1; 
     125  } 
     126  m_ipv6_socket = true; 
     127 
     128  int zero = 0; 
     129  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1; 
     130#else 
    115131  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1; 
     132#endif 
    116133} 
    117134 
    118135bool 
    119136SocketFd::open_datagram() { 
     137#ifdef RAK_USE_INET6 
     138  m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0); 
     139  if (m_fd == -1) { 
     140    m_ipv6_socket = false; 
     141    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1; 
     142  } 
     143  m_ipv6_socket = true; 
     144 
     145  int zero = 0; 
     146  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1; 
     147#else 
    120148  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1; 
     149#endif 
    121150} 
    122151 
    123152bool 
     
    135164SocketFd::bind(const rak::socket_address& sa) { 
    136165  check_valid(); 
    137166 
     167#ifdef RAK_USE_INET6 
     168  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 
     169    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 
     170    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)); 
     171  } 
     172#endif 
    138173  return !::bind(m_fd, sa.c_sockaddr(), sa.length()); 
    139174} 
    140175 
     
    142177SocketFd::bind(const rak::socket_address& sa, unsigned int length) { 
    143178  check_valid(); 
    144179 
     180#ifdef RAK_USE_INET6 
     181  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 
     182    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 
     183    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)); 
     184  } 
     185#endif 
    145186  return !::bind(m_fd, sa.c_sockaddr(), length); 
    146187} 
    147188 
     
    149190SocketFd::connect(const rak::socket_address& sa) { 
    150191  check_valid(); 
    151192 
     193#ifdef RAK_USE_INET6 
     194  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 
     195    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 
     196    return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS; 
     197  } 
     198#endif 
    152199  return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS; 
    153200} 
    154201 
    155202bool 
     203SocketFd::getsockname(rak::socket_address *sa) { 
     204  check_valid(); 
     205 
     206  socklen_t len = sizeof(rak::socket_address); 
     207  if (::getsockname(m_fd, sa->c_sockaddr(), &len)) { 
     208    return false; 
     209  } 
     210 
     211#ifdef RAK_USE_INET6 
     212  if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) { 
     213    *sa = sa->sa_inet6()->normalize_address(); 
     214  } 
     215#endif 
     216 
     217  return true; 
     218} 
     219 
     220bool 
    156221SocketFd::listen(int size) { 
    157222  check_valid(); 
    158223 
     
    164229  check_valid(); 
    165230  socklen_t len = sizeof(rak::socket_address); 
    166231 
     232#ifdef RAK_USE_INET6 
     233  if (sa == NULL) { 
     234    return SocketFd(::accept(m_fd, NULL, &len)); 
     235  } 
     236  int fd = ::accept(m_fd, sa->c_sockaddr(), &len); 
     237  if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) { 
     238    *sa = sa->sa_inet6()->normalize_address(); 
     239  } 
     240  return SocketFd(fd); 
     241#else 
    167242  return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len)); 
     243#endif 
    168244} 
    169245 
    170246// unsigned int 
  • src/net/socket_fd.h

    diff -Nur libtorrent-0.12.7.orig/src/net/socket_fd.h libtorrent-0.12.7/src/net/socket_fd.h
    old new  
    7777  bool                bind(const rak::socket_address& sa); 
    7878  bool                bind(const rak::socket_address& sa, unsigned int length); 
    7979  bool                connect(const rak::socket_address& sa); 
     80  bool                getsockname(rak::socket_address* sa); 
    8081 
    8182  bool                listen(int size); 
    8283  SocketFd            accept(rak::socket_address* sa); 
     
    8889  inline void         check_valid() const; 
    8990 
    9091  int                 m_fd; 
     92#ifdef RAK_USE_INET6 
     93  bool                m_ipv6_socket; 
     94#endif 
    9195}; 
    9296 
    9397} 
  • src/torrent/connection_manager.cc

    diff -Nur libtorrent-0.12.7.orig/src/torrent/connection_manager.cc libtorrent-0.12.7/src/torrent/connection_manager.cc
    old new  
    8080  m_slotResolver(&resolve_host) { 
    8181 
    8282  m_bindAddress = (new rak::socket_address())->c_sockaddr(); 
    83   rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear(); 
    84  
    8583  m_localAddress = (new rak::socket_address())->c_sockaddr(); 
    86   rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear(); 
    87  
    8884  m_proxyAddress = (new rak::socket_address())->c_sockaddr(); 
     85 
     86#ifdef RAK_USE_INET6 
     87  rak::socket_address::cast_from(m_bindAddress)->sa_inet6()->clear(); 
     88  rak::socket_address::cast_from(m_localAddress)->sa_inet6()->clear(); 
     89  rak::socket_address::cast_from(m_proxyAddress)->sa_inet6()->clear(); 
     90#else 
     91  rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear(); 
     92  rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear(); 
    8993  rak::socket_address::cast_from(m_proxyAddress)->sa_inet()->clear(); 
     94#endif 
    9095} 
    9196 
    9297ConnectionManager::~ConnectionManager() { 
     
    125130ConnectionManager::set_bind_address(const sockaddr* sa) { 
    126131  const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 
    127132 
     133#ifndef RAK_USE_INET6 
    128134  if (rsa->family() != rak::socket_address::af_inet) 
    129135    throw input_error("Tried to set a bind address that is not an af_inet address."); 
     136#endif 
    130137 
    131138  rak::socket_address::cast_from(m_bindAddress)->copy(*rsa, rsa->length()); 
    132139} 
     
    135142ConnectionManager::set_local_address(const sockaddr* sa) { 
    136143  const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 
    137144 
     145#ifndef RAK_USE_INET6 
    138146  if (rsa->family() != rak::socket_address::af_inet) 
    139147    throw input_error("Tried to set a local address that is not an af_inet address."); 
     148#endif 
    140149 
    141150  rak::socket_address::cast_from(m_localAddress)->copy(*rsa, rsa->length()); 
    142151} 
     
    145154ConnectionManager::set_proxy_address(const sockaddr* sa) { 
    146155  const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 
    147156 
     157#ifndef RAK_USE_INET6 
    148158  if (rsa->family() != rak::socket_address::af_inet) 
    149159    throw input_error("Tried to set a proxy address that is not an af_inet address."); 
     160#endif 
    150161 
    151162  rak::socket_address::cast_from(m_proxyAddress)->copy(*rsa, rsa->length()); 
    152163} 
  • src/torrent/event.h

    diff -Nur libtorrent-0.12.7.orig/src/torrent/event.h libtorrent-0.12.7/src/torrent/event.h
    old new  
    5757 
    5858protected: 
    5959  int                 m_fileDesc; 
     60 
     61#ifdef RAK_USE_INET6 
     62  bool                m_ipv6_socket; 
     63#endif 
    6064}; 
    6165 
    6266} 
  • src/torrent/peer/peer_list.cc

    diff -Nur libtorrent-0.12.7.orig/src/torrent/peer/peer_list.cc libtorrent-0.12.7/src/torrent/peer/peer_list.cc
    old new  
    6565    // humans. 
    6666    return sa1->sa_inet()->address_h() < sa2->sa_inet()->address_h(); 
    6767 
     68#ifdef RAK_USE_INET6 
     69  else { 
     70    const in6_addr addr1 = sa1->sa_inet6()->address(); 
     71    const in6_addr addr2 = sa2->sa_inet6()->address(); 
     72    return memcmp(&addr1, &addr2, sizeof(in6_addr)) < 0; 
     73  } 
     74#else 
    6875  else 
    69     // When we implement INET6 handling, embed the ipv4 address in 
    70     // the ipv6 address. 
    7176    throw internal_error("socket_address_key(...) tried to compare an invalid family type."); 
     77#endif 
     78 
    7279} 
    7380 
    7481inline bool 
    7582socket_address_key::is_comparable(const sockaddr* sa) { 
    76   return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet; 
     83  return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet || 
     84    rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet6; 
    7785} 
    7886 
    7987struct peer_list_equal_port : public std::binary_function<PeerList::reference, uint16_t, bool> { 
  • src/tracker/tracker_http.cc

    diff -Nur libtorrent-0.12.7.orig/src/tracker/tracker_http.cc libtorrent-0.12.7/src/tracker/tracker_http.cc
    old new  
    4242#include <rak/string_manip.h> 
    4343 
    4444#include "net/address_list.h" 
     45#include "net/local_addr.h" 
    4546#include "torrent/connection_manager.h" 
    4647#include "torrent/download_info.h" 
    4748#include "torrent/exceptions.h" 
     
    114115 
    115116  const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address()); 
    116117 
    117   if (localAddress->family() == rak::socket_address::af_inet && 
    118       !localAddress->sa_inet()->is_address_any()) 
     118  if (!localAddress->is_address_any()) 
    119119    s << "&ip=" << localAddress->address_str(); 
     120   
     121#ifdef RAK_USE_INET6 
     122  if (localAddress->is_address_any() || localAddress->family() != rak::socket_address::pf_inet6) { 
     123    rak::socket_address local_v6; 
     124    if (get_local_address(rak::socket_address::af_inet6, &local_v6)) 
     125      s << "&ipv6=" << rak::copy_escape_html(local_v6.address_str()); 
     126  } 
     127#endif 
    120128 
    121129  if (info->is_compact()) 
    122130    s << "&compact=1"; 
     
    220228 
    221229  AddressList l; 
    222230 
    223   try { 
    224     // Due to some trackers sending the wrong type when no peers are 
    225     // available, don't bork on it. 
    226     if (b.get_key("peers").is_string()) 
    227       l.parse_address_compact(b.get_key_string("peers")); 
     231  if (!b.has_key("peers") 
     232#ifdef RAK_USE_INET6 
     233      && !b.has_key("peers6") 
     234#endif 
     235  ) { 
     236    return receive_failed("No peers returned"); 
     237  } 
    228238 
    229     else if (b.get_key("peers").is_list()) 
    230       l.parse_address_normal(b.get_key_list("peers")); 
     239  if (b.has_key("peers")) { 
     240    try { 
     241      // Due to some trackers sending the wrong type when no peers are 
     242      // available, don't bork on it. 
     243      if (b.get_key("peers").is_string()) 
     244        l.parse_address_compact(b.get_key_string("peers")); 
     245 
     246      else if (b.get_key("peers").is_list()) 
     247        l.parse_address_normal(b.get_key_list("peers")); 
     248 
     249    } catch (bencode_error& e) { 
     250      return receive_failed(e.what()); 
     251    } 
     252  } 
    231253 
    232   } catch (bencode_error& e) { 
    233     return receive_failed(e.what()); 
     254#ifdef RAK_USE_INET6 
     255  if (b.has_key("peers6")) { 
     256    l.parse_address_compact_ipv6(b.get_key_string("peers6")); 
    234257  } 
     258#endif 
    235259 
    236260  close(); 
    237261  m_parent->receive_success(this, &l); 
  • src/tracker/tracker_udp.cc

    diff -Nur libtorrent-0.12.7.orig/src/tracker/tracker_udp.cc libtorrent-0.12.7/src/tracker/tracker_udp.cc
    old new  
    273273 
    274274  const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address()); 
    275275 
    276   // This code assumes we're have a inet address. 
     276#ifdef RAK_USE_INET6 
     277  uint32_t local_addr = 0; 
     278  if (localAddress->family() == rak::socket_address::af_inet) 
     279    local_addr = localAddress->sa_inet()->address_n(); 
     280#else 
    277281  if (localAddress->family() != rak::socket_address::af_inet) 
    278282    throw internal_error("TrackerUdp::prepare_announce_input() info->local_address() not of family AF_INET."); 
     283   
     284  uint32_t local_addr = localAddress->sa_inet()->address_n(); 
     285#endif 
    279286 
    280   m_writeBuffer->write_32_n(localAddress->sa_inet()->address_n()); 
     287  m_writeBuffer->write_32_n(local_addr); 
    281288  m_writeBuffer->write_32(m_parent->key()); 
    282289  m_writeBuffer->write_32(m_parent->numwant()); 
    283290  m_writeBuffer->write_16(manager->connection_manager()->listen_port());