olifre

Untitled

Jul 20th, 2014
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.21 KB | None | 0 0
  1. Description: Implement IPv6 for libtorrent
  2. Author: "Steinar H. Gunderson" <[email protected]>
  3. Reviewed-By: Rogério Theodoro de Brito <[email protected]>
  4. Last-Updated: 2011-10-13
  5.  
  6. --- a/rak/socket_address.h
  7. +++ b/rak/socket_address.h
  8. @@ -145,7 +145,7 @@
  9. };
  10. };
  11.  
  12. -// Remeber to set the AF_INET.
  13. +// Remember to set the AF_INET.
  14.  
  15. class socket_address_inet {
  16. public:
  17. @@ -184,6 +184,10 @@
  18.  
  19. const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
  20. const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
  21. +
  22. +#ifdef RAK_USE_INET6
  23. + socket_address_inet6 to_mapped_address() const;
  24. +#endif
  25.  
  26. bool operator == (const socket_address_inet& rhs) const;
  27. bool operator < (const socket_address_inet& rhs) const;
  28. @@ -192,6 +196,52 @@
  29. struct sockaddr_in m_sockaddr;
  30. };
  31.  
  32. +#ifdef RAK_USE_INET6
  33. +// Remember to set the AF_INET6.
  34. +
  35. +class socket_address_inet6 {
  36. +public:
  37. + bool is_any() const { return is_port_any() && is_address_any(); }
  38. + bool is_valid() const { return !is_port_any() && !is_address_any(); }
  39. + bool is_port_any() const { return port() == 0; }
  40. + bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
  41. +
  42. + void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
  43. +
  44. + uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
  45. + uint16_t port_n() const { return m_sockaddr.sin6_port; }
  46. + void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
  47. + void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
  48. +
  49. + in6_addr address() const { return m_sockaddr.sin6_addr; }
  50. + std::string address_str() const;
  51. + bool address_c_str(char* buf, socklen_t size) const;
  52. +
  53. + void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
  54. + bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
  55. + bool set_address_c_str(const char* a);
  56. +
  57. + void set_address_any() { set_port(0); set_address(in6addr_any); }
  58. +
  59. + sa_family_t family() const { return m_sockaddr.sin6_family; }
  60. + void set_family() { m_sockaddr.sin6_family = AF_INET6; }
  61. +
  62. + sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
  63. + sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
  64. +
  65. + const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
  66. + const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
  67. +
  68. + socket_address normalize_address() const;
  69. +
  70. + bool operator == (const socket_address_inet6& rhs) const;
  71. + bool operator < (const socket_address_inet6& rhs) const;
  72. +
  73. +private:
  74. + struct sockaddr_in6 m_sockaddr;
  75. +};
  76. +#endif
  77. +
  78. // Unique key for the address, excluding port numbers etc.
  79. class socket_address_key {
  80. public:
  81. @@ -241,8 +291,10 @@
  82. switch (family()) {
  83. case af_inet:
  84. return sa_inet()->is_valid();
  85. -// case af_inet6:
  86. -// return sa_inet6().is_valid();
  87. +#ifdef RAK_USE_INET6
  88. + case af_inet6:
  89. + return sa_inet6()->is_valid();
  90. +#endif
  91. default:
  92. return false;
  93. }
  94. @@ -253,6 +305,10 @@
  95. switch (family()) {
  96. case af_inet:
  97. return !sa_inet()->is_address_any();
  98. +#ifdef RAK_USE_INET6
  99. + case af_inet6:
  100. + return !sa_inet6()->is_address_any();
  101. +#endif
  102. default:
  103. return false;
  104. }
  105. @@ -263,6 +319,10 @@
  106. switch (family()) {
  107. case af_inet:
  108. return sa_inet()->is_address_any();
  109. +#ifdef RAK_USE_INET6
  110. + case af_inet6:
  111. + return sa_inet6()->is_address_any();
  112. +#endif
  113. default:
  114. return true;
  115. }
  116. @@ -273,6 +333,10 @@
  117. switch (family()) {
  118. case af_inet:
  119. return sa_inet()->port();
  120. +#ifdef RAK_USE_INET6
  121. + case af_inet6:
  122. + return sa_inet6()->port();
  123. +#endif
  124. default:
  125. return 0;
  126. }
  127. @@ -283,6 +347,10 @@
  128. switch (family()) {
  129. case af_inet:
  130. return sa_inet()->set_port(p);
  131. +#ifdef RAK_USE_INET6
  132. + case af_inet6:
  133. + return sa_inet6()->set_port(p);
  134. +#endif
  135. default:
  136. break;
  137. }
  138. @@ -293,6 +361,10 @@
  139. switch (family()) {
  140. case af_inet:
  141. return sa_inet()->address_str();
  142. +#ifdef RAK_USE_INET6
  143. + case af_inet6:
  144. + return sa_inet6()->address_str();
  145. +#endif
  146. default:
  147. return std::string();
  148. }
  149. @@ -303,6 +375,10 @@
  150. switch (family()) {
  151. case af_inet:
  152. return sa_inet()->address_c_str(buf, size);
  153. +#ifdef RAK_USE_INET6
  154. + case af_inet6:
  155. + return sa_inet6()->address_c_str(buf, size);
  156. +#endif
  157. default:
  158. return false;
  159. }
  160. @@ -314,6 +390,12 @@
  161. sa_inet()->set_family();
  162. return true;
  163.  
  164. +#ifdef RAK_USE_INET6
  165. + } else if (sa_inet6()->set_address_c_str(a)) {
  166. + sa_inet6()->set_family();
  167. + return true;
  168. +#endif
  169. +
  170. } else {
  171. return false;
  172. }
  173. @@ -325,6 +407,10 @@
  174. switch(family()) {
  175. case af_inet:
  176. return sizeof(sockaddr_in);
  177. +#ifdef RAK_USE_INET6
  178. + case af_inet6:
  179. + return sizeof(sockaddr_in6);
  180. +#endif
  181. default:
  182. return 0;
  183. }
  184. @@ -349,8 +435,10 @@
  185. switch (family()) {
  186. case af_inet:
  187. return *sa_inet() == *rhs.sa_inet();
  188. -// case af_inet6:
  189. -// return *sa_inet6() == *rhs.sa_inet6();
  190. +#ifdef RAK_USE_INET6
  191. + case af_inet6:
  192. + return *sa_inet6() == *rhs.sa_inet6();
  193. +#endif
  194. default:
  195. throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
  196. }
  197. @@ -364,8 +452,10 @@
  198. switch (family()) {
  199. case af_inet:
  200. return *sa_inet() < *rhs.sa_inet();
  201. -// case af_inet6:
  202. -// return *sa_inet6() < *rhs.sa_inet6();
  203. +#ifdef RAK_USE_INET6
  204. + case af_inet6:
  205. + return *sa_inet6() < *rhs.sa_inet6();
  206. +#endif
  207. default:
  208. throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
  209. }
  210. @@ -391,6 +481,23 @@
  211. return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
  212. }
  213.  
  214. +#ifdef RAK_USE_INET6
  215. +inline socket_address_inet6
  216. +socket_address_inet::to_mapped_address() const {
  217. + uint32_t addr32[4];
  218. + addr32[0] = 0;
  219. + addr32[1] = 0;
  220. + addr32[2] = htonl(0xffff);
  221. + addr32[3] = m_sockaddr.sin_addr.s_addr;
  222. +
  223. + socket_address_inet6 sa;
  224. + sa.clear();
  225. + sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
  226. + sa.set_port_n(m_sockaddr.sin_port);
  227. + return sa;
  228. +}
  229. +#endif
  230. +
  231. inline bool
  232. socket_address_inet::operator == (const socket_address_inet& rhs) const {
  233. return
  234. @@ -406,6 +513,59 @@
  235. m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
  236. }
  237.  
  238. +#ifdef RAK_USE_INET6
  239. +
  240. +inline std::string
  241. +socket_address_inet6::address_str() const {
  242. + char buf[INET6_ADDRSTRLEN];
  243. +
  244. + if (!address_c_str(buf, INET6_ADDRSTRLEN))
  245. + return std::string();
  246. +
  247. + return std::string(buf);
  248. +}
  249. +
  250. +inline bool
  251. +socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
  252. + return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
  253. +}
  254. +
  255. +inline bool
  256. +socket_address_inet6::set_address_c_str(const char* a) {
  257. + return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
  258. +}
  259. +
  260. +inline socket_address
  261. +socket_address_inet6::normalize_address() const {
  262. + const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
  263. + if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
  264. + socket_address addr4;
  265. + addr4.sa_inet()->set_family();
  266. + addr4.sa_inet()->set_address_n(addr32[3]);
  267. + addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
  268. + return addr4;
  269. + }
  270. + return *reinterpret_cast<const socket_address*>(this);
  271. +}
  272. +
  273. +inline bool
  274. +socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
  275. + return
  276. + memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
  277. + m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
  278. +}
  279. +
  280. +inline bool
  281. +socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
  282. + int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
  283. + return
  284. + addr_comp < 0 ||
  285. + (addr_comp == 0 ||
  286. + m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
  287. +}
  288. +
  289. +#endif
  290. +
  291. }
  292.  
  293. #endif
  294. --- a/src/dht/dht_node.cc
  295. +++ b/src/dht/dht_node.cc
  296. @@ -54,8 +54,15 @@
  297. m_recentlyInactive(0),
  298. m_bucket(NULL) {
  299.  
  300. +#ifdef RAK_USE_INET6
  301. + if (sa->family() != rak::socket_address::af_inet &&
  302. + (sa->family() != rak::socket_address::af_inet6 ||
  303. + !sa->sa_inet6()->is_any()))
  304. + throw resource_error("Address not af_inet or in6addr_any");
  305. +#else
  306. if (sa->family() != rak::socket_address::af_inet)
  307. throw resource_error("Address not af_inet");
  308. +#endif
  309. }
  310.  
  311. DhtNode::DhtNode(const std::string& id, const Object& cache) :
  312. @@ -84,8 +91,20 @@
  313.  
  314. Object*
  315. DhtNode::store_cache(Object* container) const {
  316. - container->insert_key("i", m_socketAddress.sa_inet()->address_h());
  317. - container->insert_key("p", m_socketAddress.sa_inet()->port());
  318. +#ifdef RAK_USE_INET6
  319. + if (m_socketAddress.family() == rak::socket_address::af_inet6) {
  320. + // Currently, all we support is in6addr_any (checked in the constructor),
  321. + // which is effectively equivalent to this. Note that we need to specify
  322. + // int64_t explicitly here because a zero constant is special in C++ and
  323. + // thus we need an explicit match.
  324. + container->insert_key("i", int64_t(0));
  325. + container->insert_key("p", m_socketAddress.sa_inet6()->port());
  326. + } else
  327. +#endif
  328. + {
  329. + container->insert_key("i", m_socketAddress.sa_inet()->address_h());
  330. + container->insert_key("p", m_socketAddress.sa_inet()->port());
  331. + }
  332. container->insert_key("t", m_lastSeen);
  333. return container;
  334. }
  335. --- a/src/dht/dht_server.cc
  336. +++ b/src/dht/dht_server.cc
  337. @@ -700,6 +700,16 @@
  338. if (read < 0)
  339. break;
  340.  
  341. +#ifdef RAK_USE_INET6
  342. + // We can currently only process mapped-IPv4 addresses, not real IPv6.
  343. + // Translate them to an af_inet socket_address.
  344. + if (sa.family() == rak::socket_address::af_inet6)
  345. + sa = sa.sa_inet6()->normalize_address();
  346. +#endif
  347. +
  348. + if (sa.family() != rak::socket_address::af_inet)
  349. + continue;
  350. +
  351. total += read;
  352.  
  353. // If it's not a valid bencode dictionary at all, it's probably not a DHT
  354. --- a/src/torrent/download_info.h
  355. +++ b/src/torrent/download_info.h
  356. @@ -45,6 +45,8 @@
  357. #include <torrent/rate.h>
  358. #include <torrent/hash_string.h>
  359.  
  360. +#include <rak/socket_address.h>
  361. +
  362. namespace torrent {
  363.  
  364. class FileList;
  365. @@ -204,6 +206,28 @@
  366. mutable signal_chunk_type m_signalChunkFailed;
  367. };
  368.  
  369. +#ifdef RAK_USE_INET6
  370. +struct SocketAddressCompact6 {
  371. + SocketAddressCompact6() {}
  372. + SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {}
  373. + SocketAddressCompact6(const rak::socket_address_inet6* sa) : addr(sa->address()), port(sa->port_n()) {}
  374. +
  375. + operator rak::socket_address () const {
  376. + rak::socket_address sa;
  377. + sa.sa_inet6()->clear();
  378. + sa.sa_inet6()->set_port_n(port);
  379. + sa.sa_inet6()->set_address(addr);
  380. +
  381. + return sa;
  382. + }
  383. +
  384. + in6_addr addr;
  385. + uint16_t port;
  386. +
  387. + const char* c_str() const { return reinterpret_cast<const char*>(this); }
  388. +} __attribute__ ((packed));
  389. +#endif
  390. +
  391. }
  392.  
  393. #endif
  394. --- a/src/net/address_list.cc
  395. +++ b/src/net/address_list.cc
  396. @@ -40,6 +40,7 @@
  397. #include <rak/functional.h>
  398.  
  399. #include "address_list.h"
  400. +#include "torrent/download_info.h"
  401.  
  402. namespace torrent {
  403.  
  404. @@ -92,4 +93,16 @@
  405. }
  406. }
  407.  
  408. +#ifdef RAK_USE_INET6
  409. +void
  410. +AddressList::parse_address_compact_ipv6(const std::string& s) {
  411. + if (sizeof(const SocketAddressCompact6) != 18)
  412. + throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size.");
  413. +
  414. + std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()),
  415. + reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)),
  416. + std::back_inserter(*this));
  417. +}
  418. +#endif
  419. +
  420. }
  421. --- a/src/net/address_list.h
  422. +++ b/src/net/address_list.h
  423. @@ -54,6 +54,9 @@
  424.  
  425. void parse_address_compact(raw_string s);
  426. void parse_address_compact(const std::string& s);
  427. +#ifdef RAK_USE_INET6
  428. + void parse_address_compact_ipv6(const std::string& s);
  429. +#endif
  430.  
  431. private:
  432. static rak::socket_address parse_address(const Object& b);
  433. --- /dev/null
  434. +++ b/src/net/local_addr.cc
  435. @@ -0,0 +1,336 @@
  436. +// libTorrent - BitTorrent library
  437. +// Copyright (C) 2005-2007, Jari Sundell
  438. +//
  439. +// This program is free software; you can redistribute it and/or modify
  440. +// it under the terms of the GNU General Public License as published by
  441. +// the Free Software Foundation; either version 2 of the License, or
  442. +// (at your option) any later version.
  443. +//
  444. +// This program is distributed in the hope that it will be useful,
  445. +// but WITHOUT ANY WARRANTY; without even the implied warranty of
  446. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  447. +// GNU General Public License for more details.
  448. +//
  449. +// You should have received a copy of the GNU General Public License
  450. +// along with this program; if not, write to the Free Software
  451. +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  452. +//
  453. +// In addition, as a special exception, the copyright holders give
  454. +// permission to link the code of portions of this program with the
  455. +// OpenSSL library under certain conditions as described in each
  456. +// individual source file, and distribute linked combinations
  457. +// including the two.
  458. +//
  459. +// You must obey the GNU General Public License in all respects for
  460. +// all of the code used other than OpenSSL. If you modify file(s)
  461. +// with this exception, you may extend this exception to your version
  462. +// of the file(s), but you are not obligated to do so. If you do not
  463. +// wish to do so, delete this exception statement from your version.
  464. +// If you delete this exception statement from all source files in the
  465. +// program, then also delete it here.
  466. +//
  467. +// Contact: Jari Sundell <[email protected]>
  468. +//
  469. +// Skomakerveien 33
  470. +// 3185 Skoppum, NORWAY
  471. +
  472. +#include "config.h"
  473. +
  474. +#include <stdio.h>
  475. +#include <ifaddrs.h>
  476. +#include <rak/socket_address.h>
  477. +#include <sys/types.h>
  478. +#include <errno.h>
  479. +
  480. +#ifdef __linux__
  481. +#include <linux/netlink.h>
  482. +#include <linux/rtnetlink.h>
  483. +#endif
  484. +
  485. +#include "torrent/exceptions.h"
  486. +#include "socket_fd.h"
  487. +#include "local_addr.h"
  488. +
  489. +namespace torrent {
  490. +namespace {
  491. +
  492. +// IPv4 priority, from highest to lowest:
  493. +//
  494. +// 1. Everything else (global address)
  495. +// 2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24)
  496. +// 3. Empty/INADDR_ANY (0.0.0.0)
  497. +// 4. Link-local address (169.254.0.0/16)
  498. +// 5. Localhost (127.0.0.0/8)
  499. +int get_priority_ipv4(const in_addr& addr) {
  500. + if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x7f000000U)) {
  501. + return 5;
  502. + }
  503. + if (addr.s_addr == htonl(0)) {
  504. + return 4;
  505. + }
  506. + if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) {
  507. + return 3;
  508. + }
  509. + if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
  510. + (addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) ||
  511. + (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {
  512. + return 2;
  513. + }
  514. + return 1;
  515. +}
  516. +
  517. +#ifdef RAK_USE_INET6
  518. +// IPv6 priority, from highest to lowest:
  519. +//
  520. +// 1. Global address (2000::/16 not in 6to4 or Teredo)
  521. +// 2. 6to4 (2002::/16)
  522. +// 3. Teredo (2001::/32)
  523. +// 4. Empty/INADDR_ANY (::)
  524. +// 5. Everything else (link-local, ULA, etc.)
  525. +int get_priority_ipv6(const in6_addr& addr) {
  526. + const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(addr.s6_addr);
  527. + if (addr32[0] == htonl(0) &&
  528. + addr32[1] == htonl(0) &&
  529. + addr32[2] == htonl(0) &&
  530. + addr32[3] == htonl(0)) {
  531. + return 4;
  532. + }
  533. + if (addr32[0] == htonl(0x20010000)) {
  534. + return 3;
  535. + }
  536. + if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) {
  537. + return 2;
  538. + }
  539. + if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) {
  540. + return 1;
  541. + }
  542. + return 5;
  543. +}
  544. +#endif
  545. +
  546. +int get_priority(const rak::socket_address& addr) {
  547. + switch (addr.family()) {
  548. + case AF_INET:
  549. + return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr);
  550. +#ifdef RAK_USE_INET6
  551. + case AF_INET6:
  552. + return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr);
  553. +#endif
  554. + default:
  555. + throw torrent::internal_error("Unknown address family given to compare");
  556. + }
  557. +}
  558. +
  559. +}
  560. +
  561. +#ifdef __linux__
  562. +
  563. +// Linux-specific implementation that understands how to filter away
  564. +// understands how to filter away secondary addresses.
  565. +bool get_local_address(sa_family_t family, rak::socket_address *address) {
  566. + ifaddrs *ifaddrs;
  567. + if (getifaddrs(&ifaddrs)) {
  568. + return false;
  569. + }
  570. +
  571. + rak::socket_address best_addr;
  572. + switch (family) {
  573. + case AF_INET:
  574. + best_addr.sa_inet()->clear();
  575. + break;
  576. +#ifdef RAK_USE_INET6
  577. + case AF_INET6:
  578. + best_addr.sa_inet6()->clear();
  579. + break;
  580. +#endif
  581. + default:
  582. + throw torrent::internal_error("Unknown address family given to get_local_address");
  583. + }
  584. +
  585. + // The bottom bit of the priority is used to hold if the address is
  586. + // a secondary address (e.g. with IPv6 privacy extensions) or not;
  587. + // secondary addresses have lower priority (higher number).
  588. + int best_addr_pri = get_priority(best_addr) * 2;
  589. +
  590. + // Get all the addresses via Linux' netlink interface.
  591. + int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  592. + if (fd == -1) {
  593. + return false;
  594. + }
  595. +
  596. + struct sockaddr_nl nladdr;
  597. + memset(&nladdr, 0, sizeof(nladdr));
  598. + nladdr.nl_family = AF_NETLINK;
  599. + if (::bind(fd, (sockaddr *)&nladdr, sizeof(nladdr))) {
  600. + ::close(fd);
  601. + return false;
  602. + }
  603. +
  604. + const int seq_no = 1;
  605. + struct {
  606. + nlmsghdr nh;
  607. + rtgenmsg g;
  608. + } req;
  609. + memset(&req, 0, sizeof(req));
  610. +
  611. + req.nh.nlmsg_len = sizeof(req);
  612. + req.nh.nlmsg_type = RTM_GETADDR;
  613. + req.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
  614. + req.nh.nlmsg_pid = getpid();
  615. + req.nh.nlmsg_seq = seq_no;
  616. + req.g.rtgen_family = AF_UNSPEC;
  617. +
  618. + int ret;
  619. + do {
  620. + ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr));
  621. + } while (ret == -1 && errno == EINTR);
  622. +
  623. + if (ret == -1) {
  624. + ::close(fd);
  625. + return false;
  626. + }
  627. +
  628. + bool done = false;
  629. + do {
  630. + char buf[4096];
  631. + socklen_t len = sizeof(nladdr);
  632. + do {
  633. + ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len);
  634. + } while (ret == -1 && errno == EINTR);
  635. +
  636. + if (ret < 0) {
  637. + ::close(fd);
  638. + return false;
  639. + }
  640. +
  641. + for (const nlmsghdr *nlmsg = (const nlmsghdr *)buf;
  642. + NLMSG_OK(nlmsg, ret);
  643. + nlmsg = NLMSG_NEXT(nlmsg, ret)) {
  644. + if (nlmsg->nlmsg_seq != seq_no)
  645. + continue;
  646. + if (nlmsg->nlmsg_type == NLMSG_DONE) {
  647. + done = true;
  648. + break;
  649. + }
  650. + if (nlmsg->nlmsg_type == NLMSG_ERROR) {
  651. + ::close(fd);
  652. + return false;
  653. + }
  654. + if (nlmsg->nlmsg_type != RTM_NEWADDR)
  655. + continue;
  656. +
  657. + const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg);
  658. +
  659. + if (ifa->ifa_family != family)
  660. + continue;
  661. +
  662. +#ifdef IFA_F_OPTIMISTIC
  663. + if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0)
  664. + continue;
  665. +#endif
  666. +#ifdef IFA_F_DADFAILED
  667. + if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0)
  668. + continue;
  669. +#endif
  670. +#ifdef IFA_F_DEPRECATED
  671. + if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0)
  672. + continue;
  673. +#endif
  674. +#ifdef IFA_F_TENTATIVE
  675. + if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0)
  676. + continue;
  677. +#endif
  678. +
  679. + // Since there can be point-to-point links on the machine, we need to keep
  680. + // track of the addresses we've seen for this interface; if we see both
  681. + // IFA_LOCAL and IFA_ADDRESS for an interface, keep only the IFA_LOCAL.
  682. + rak::socket_address this_addr;
  683. + bool seen_addr = false;
  684. + int plen = IFA_PAYLOAD(nlmsg);
  685. + for (const rtattr *rta = IFA_RTA(ifa);
  686. + RTA_OK(rta, plen);
  687. + rta = RTA_NEXT(rta, plen)) {
  688. + if (rta->rta_type != IFA_LOCAL &&
  689. + rta->rta_type != IFA_ADDRESS) {
  690. + continue;
  691. + }
  692. + if (rta->rta_type == IFA_ADDRESS && seen_addr) {
  693. + continue;
  694. + }
  695. + seen_addr = true;
  696. + switch (ifa->ifa_family) {
  697. + case AF_INET:
  698. + this_addr.sa_inet()->clear();
  699. + this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta));
  700. + break;
  701. +#ifdef RAK_USE_INET6
  702. + case AF_INET6:
  703. + this_addr.sa_inet6()->clear();
  704. + this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta));
  705. + break;
  706. +#endif
  707. + }
  708. + }
  709. + if (!seen_addr)
  710. + continue;
  711. +
  712. + int this_addr_pri = get_priority(this_addr) * 2;
  713. + if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) {
  714. + ++this_addr_pri;
  715. + }
  716. +
  717. + if (this_addr_pri < best_addr_pri) {
  718. + best_addr = this_addr;
  719. + best_addr_pri = this_addr_pri;
  720. + }
  721. + }
  722. + } while (!done);
  723. +
  724. + ::close(fd);
  725. + if (!best_addr.is_address_any()) {
  726. + *address = best_addr;
  727. + return true;
  728. + } else {
  729. + return false;
  730. + }
  731. +}
  732. +
  733. +#else
  734. +
  735. +// Generic POSIX variant.
  736. +bool get_local_address(sa_family_t family, rak::socket_address *address) {
  737. + SocketFd sock;
  738. + if (!sock.open_datagram()) {
  739. + return false;
  740. + }
  741. +
  742. + rak::socket_address dummy_dest;
  743. + dummy_dest.clear();
  744. +
  745. + switch (family) {
  746. + case rak::socket_address::af_inet:
  747. + dummy_dest.set_address_c_str("4.0.0.0");
  748. + break;
  749. +#ifdef RAK_USE_INET6
  750. + case rak::socket_address::af_inet6:
  751. + dummy_dest.set_address_c_str("2001:700::");
  752. + break;
  753. +#endif
  754. + default:
  755. + throw internal_error("Unknown address family");
  756. + }
  757. + dummy_dest.set_port(80);
  758. +
  759. + if (!sock.connect(dummy_dest)) {
  760. + sock.close();
  761. + return false;
  762. + }
  763. +
  764. + bool ret = sock.getsockname(address);
  765. + sock.close();
  766. + return ret;
  767. +}
  768. +
  769. +#endif
  770. +
  771. +}
  772. --- /dev/null
  773. +++ b/src/net/local_addr.h
  774. @@ -0,0 +1,64 @@
  775. +// libTorrent - BitTorrent library
  776. +// Copyright (C) 2005-2007, Jari Sundell
  777. +//
  778. +// This program is free software; you can redistribute it and/or modify
  779. +// it under the terms of the GNU General Public License as published by
  780. +// the Free Software Foundation; either version 2 of the License, or
  781. +// (at your option) any later version.
  782. +//
  783. +// This program is distributed in the hope that it will be useful,
  784. +// but WITHOUT ANY WARRANTY; without even the implied warranty of
  785. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  786. +// GNU General Public License for more details.
  787. +//
  788. +// You should have received a copy of the GNU General Public License
  789. +// along with this program; if not, write to the Free Software
  790. +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  791. +//
  792. +// In addition, as a special exception, the copyright holders give
  793. +// permission to link the code of portions of this program with the
  794. +// OpenSSL library under certain conditions as described in each
  795. +// individual source file, and distribute linked combinations
  796. +// including the two.
  797. +//
  798. +// You must obey the GNU General Public License in all respects for
  799. +// all of the code used other than OpenSSL. If you modify file(s)
  800. +// with this exception, you may extend this exception to your version
  801. +// of the file(s), but you are not obligated to do so. If you do not
  802. +// wish to do so, delete this exception statement from your version.
  803. +// If you delete this exception statement from all source files in the
  804. +// program, then also delete it here.
  805. +//
  806. +// Contact: Jari Sundell <[email protected]>
  807. +//
  808. +// Skomakerveien 33
  809. +// 3185 Skoppum, NORWAY
  810. +
  811. +// A routine to get a local IP address that can be presented to a tracker.
  812. +// (Does not use UPnP etc., so will not understand NAT.)
  813. +// On a machine with multiple network cards, address selection can be a
  814. +// complex process, and in general what's selected is a source/destination
  815. +// address pair. However, this routine will give an approximation that will
  816. +// be good enough for most purposes and users.
  817. +
  818. +#ifndef LIBTORRENT_NET_LOCAL_ADDR_H
  819. +#define LIBTORRENT_NET_LOCAL_ADDR_H
  820. +
  821. +#include <unistd.h>
  822. +
  823. +namespace rak {
  824. + class socket_address;
  825. +}
  826. +
  827. +namespace torrent {
  828. +
  829. +// Note: family must currently be rak::af_inet or rak::af_inet6
  830. +// (rak::af_unspec won't do); anything else will throw an exception.
  831. +// Returns false if no address of the given family could be found,
  832. +// either because there are none, or because something went wrong in
  833. +// the process (e.g., no free file descriptors).
  834. +bool get_local_address(sa_family_t family, rak::socket_address *address);
  835. +
  836. +}
  837. +
  838. +#endif /* LIBTORRENT_NET_LOCAL_ADDR_H */
  839. --- a/src/net/Makefile.am
  840. +++ b/src/net/Makefile.am
  841. @@ -4,6 +4,8 @@
  842. address_list.cc \
  843. address_list.h \
  844. data_buffer.h \
  845. + local_addr.cc \
  846. + local_addr.h \
  847. listen.cc \
  848. listen.h \
  849. protocol_buffer.h \
  850. --- a/src/net/Makefile.in
  851. +++ b/src/net/Makefile.in
  852. @@ -54,9 +54,9 @@
  853. CONFIG_CLEAN_VPATH_FILES =
  854. LTLIBRARIES = $(noinst_LTLIBRARIES)
  855. libsub_net_la_LIBADD =
  856. -am_libsub_net_la_OBJECTS = address_list.lo listen.lo socket_base.lo \
  857. - socket_datagram.lo socket_fd.lo socket_set.lo socket_stream.lo \
  858. - throttle_internal.lo throttle_list.lo
  859. +am_libsub_net_la_OBJECTS = address_list.lo local_addr.lo listen.lo \
  860. + socket_base.lo socket_datagram.lo socket_fd.lo socket_set.lo \
  861. + socket_stream.lo throttle_internal.lo throttle_list.lo
  862. libsub_net_la_OBJECTS = $(am_libsub_net_la_OBJECTS)
  863. DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
  864. depcomp = $(SHELL) $(top_srcdir)/depcomp
  865. @@ -223,6 +223,8 @@
  866. address_list.cc \
  867. address_list.h \
  868. data_buffer.h \
  869. + local_addr.cc \
  870. + local_addr.h \
  871. listen.cc \
  872. listen.h \
  873. protocol_buffer.h \
  874. @@ -297,6 +299,7 @@
  875.  
  876. @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_list.Plo@am__quote@
  877. @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listen.Plo@am__quote@
  878. +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_addr.Plo@am__quote@
  879. @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_base.Plo@am__quote@
  880. @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_datagram.Plo@am__quote@
  881. @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Plo@am__quote@
  882. --- a/src/net/socket_datagram.cc
  883. +++ b/src/net/socket_datagram.cc
  884. @@ -73,7 +73,13 @@
  885. int r;
  886.  
  887. if (sa != NULL) {
  888. - r = ::sendto(m_fileDesc, buffer, length, 0, sa->sa_inet()->c_sockaddr(), sizeof(rak::socket_address_inet));
  889. +#ifdef RAK_USE_INET6
  890. + if (m_ipv6_socket && sa->family() == rak::socket_address::pf_inet) {
  891. + rak::socket_address_inet6 sa_mapped = sa->sa_inet()->to_mapped_address();
  892. + r = ::sendto(m_fileDesc, buffer, length, 0, sa_mapped.c_sockaddr(), sizeof(rak::socket_address_inet6));
  893. + } else
  894. +#endif
  895. + r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length());
  896. } else {
  897. r = ::send(m_fileDesc, buffer, length, 0);
  898. }
  899. --- a/src/net/socket_fd.cc
  900. +++ b/src/net/socket_fd.cc
  901. @@ -70,6 +70,11 @@
  902. check_valid();
  903. int opt = p;
  904.  
  905. +#ifdef RAK_USE_INET6
  906. + if (m_ipv6_socket)
  907. + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
  908. + else
  909. +#endif
  910. return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
  911. }
  912.  
  913. @@ -112,12 +117,36 @@
  914.  
  915. bool
  916. SocketFd::open_stream() {
  917. +#ifdef RAK_USE_INET6
  918. + m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
  919. + if (m_fd == -1) {
  920. + m_ipv6_socket = false;
  921. + return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
  922. + }
  923. + m_ipv6_socket = true;
  924. +
  925. + int zero = 0;
  926. + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
  927. +#else
  928. return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
  929. +#endif
  930. }
  931.  
  932. bool
  933. SocketFd::open_datagram() {
  934. +#ifdef RAK_USE_INET6
  935. + m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
  936. + if (m_fd == -1) {
  937. + m_ipv6_socket = false;
  938. + return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
  939. + }
  940. + m_ipv6_socket = true;
  941. +
  942. + int zero = 0;
  943. + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
  944. +#else
  945. return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
  946. +#endif
  947. }
  948.  
  949. bool
  950. @@ -135,6 +164,12 @@
  951. SocketFd::bind(const rak::socket_address& sa) {
  952. check_valid();
  953.  
  954. +#ifdef RAK_USE_INET6
  955. + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
  956. + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
  957. + return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
  958. + }
  959. +#endif
  960. return !::bind(m_fd, sa.c_sockaddr(), sa.length());
  961. }
  962.  
  963. @@ -142,6 +177,12 @@
  964. SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
  965. check_valid();
  966.  
  967. +#ifdef RAK_USE_INET6
  968. + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
  969. + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
  970. + return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
  971. + }
  972. +#endif
  973. return !::bind(m_fd, sa.c_sockaddr(), length);
  974. }
  975.  
  976. @@ -149,10 +190,34 @@
  977. SocketFd::connect(const rak::socket_address& sa) {
  978. check_valid();
  979.  
  980. +#ifdef RAK_USE_INET6
  981. + if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
  982. + rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
  983. + return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
  984. + }
  985. +#endif
  986. return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
  987. }
  988.  
  989. bool
  990. +SocketFd::getsockname(rak::socket_address *sa) {
  991. + check_valid();
  992. +
  993. + socklen_t len = sizeof(rak::socket_address);
  994. + if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
  995. + return false;
  996. + }
  997. +
  998. +#ifdef RAK_USE_INET6
  999. + if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
  1000. + *sa = sa->sa_inet6()->normalize_address();
  1001. + }
  1002. +#endif
  1003. +
  1004. + return true;
  1005. +}
  1006. +
  1007. +bool
  1008. SocketFd::listen(int size) {
  1009. check_valid();
  1010.  
  1011. @@ -164,7 +229,18 @@
  1012. check_valid();
  1013. socklen_t len = sizeof(rak::socket_address);
  1014.  
  1015. +#ifdef RAK_USE_INET6
  1016. + if (sa == NULL) {
  1017. + return SocketFd(::accept(m_fd, NULL, &len));
  1018. + }
  1019. + int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
  1020. + if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
  1021. + *sa = sa->sa_inet6()->normalize_address();
  1022. + }
  1023. + return SocketFd(fd);
  1024. +#else
  1025. return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len));
  1026. +#endif
  1027. }
  1028.  
  1029. // unsigned int
  1030. --- a/src/net/socket_fd.h
  1031. +++ b/src/net/socket_fd.h
  1032. @@ -77,6 +77,7 @@
  1033. bool bind(const rak::socket_address& sa);
  1034. bool bind(const rak::socket_address& sa, unsigned int length);
  1035. bool connect(const rak::socket_address& sa);
  1036. + bool getsockname(rak::socket_address* sa);
  1037.  
  1038. bool listen(int size);
  1039. SocketFd accept(rak::socket_address* sa);
  1040. @@ -88,6 +89,9 @@
  1041. inline void check_valid() const;
  1042.  
  1043. int m_fd;
  1044. +#ifdef RAK_USE_INET6
  1045. + bool m_ipv6_socket;
  1046. +#endif
  1047. };
  1048.  
  1049. }
  1050. --- a/src/torrent/connection_manager.cc
  1051. +++ b/src/torrent/connection_manager.cc
  1052. @@ -80,13 +80,18 @@
  1053. m_slotResolver(&resolve_host) {
  1054.  
  1055. m_bindAddress = (new rak::socket_address())->c_sockaddr();
  1056. - rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
  1057. -
  1058. m_localAddress = (new rak::socket_address())->c_sockaddr();
  1059. - rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
  1060. -
  1061. m_proxyAddress = (new rak::socket_address())->c_sockaddr();
  1062. +
  1063. +#ifdef RAK_USE_INET6
  1064. + rak::socket_address::cast_from(m_bindAddress)->sa_inet6()->clear();
  1065. + rak::socket_address::cast_from(m_localAddress)->sa_inet6()->clear();
  1066. + rak::socket_address::cast_from(m_proxyAddress)->sa_inet6()->clear();
  1067. +#else
  1068. + rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
  1069. + rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
  1070. rak::socket_address::cast_from(m_proxyAddress)->sa_inet()->clear();
  1071. +#endif
  1072. }
  1073.  
  1074. ConnectionManager::~ConnectionManager() {
  1075. @@ -125,8 +130,10 @@
  1076. ConnectionManager::set_bind_address(const sockaddr* sa) {
  1077. const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
  1078.  
  1079. +#ifndef RAK_USE_INET6
  1080. if (rsa->family() != rak::socket_address::af_inet)
  1081. throw input_error("Tried to set a bind address that is not an af_inet address.");
  1082. +#endif
  1083.  
  1084. rak::socket_address::cast_from(m_bindAddress)->copy(*rsa, rsa->length());
  1085. }
  1086. @@ -135,8 +142,10 @@
  1087. ConnectionManager::set_local_address(const sockaddr* sa) {
  1088. const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
  1089.  
  1090. +#ifndef RAK_USE_INET6
  1091. if (rsa->family() != rak::socket_address::af_inet)
  1092. throw input_error("Tried to set a local address that is not an af_inet address.");
  1093. +#endif
  1094.  
  1095. rak::socket_address::cast_from(m_localAddress)->copy(*rsa, rsa->length());
  1096. }
  1097. @@ -145,8 +154,10 @@
  1098. ConnectionManager::set_proxy_address(const sockaddr* sa) {
  1099. const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
  1100.  
  1101. +#ifndef RAK_USE_INET6
  1102. if (rsa->family() != rak::socket_address::af_inet)
  1103. throw input_error("Tried to set a proxy address that is not an af_inet address.");
  1104. +#endif
  1105.  
  1106. rak::socket_address::cast_from(m_proxyAddress)->copy(*rsa, rsa->length());
  1107. }
  1108. --- a/src/torrent/event.h
  1109. +++ b/src/torrent/event.h
  1110. @@ -57,6 +57,10 @@
  1111.  
  1112. protected:
  1113. int m_fileDesc;
  1114. +
  1115. +#ifdef RAK_USE_INET6
  1116. + bool m_ipv6_socket;
  1117. +#endif
  1118. };
  1119.  
  1120. }
  1121. --- a/src/torrent/peer/peer_list.cc
  1122. +++ b/src/torrent/peer/peer_list.cc
  1123. @@ -67,15 +67,23 @@
  1124. // humans.
  1125. return sa1->sa_inet()->address_h() < sa2->sa_inet()->address_h();
  1126.  
  1127. +#ifdef RAK_USE_INET6
  1128. + else {
  1129. + const in6_addr addr1 = sa1->sa_inet6()->address();
  1130. + const in6_addr addr2 = sa2->sa_inet6()->address();
  1131. + return memcmp(&addr1, &addr2, sizeof(in6_addr)) < 0;
  1132. + }
  1133. +#else
  1134. else
  1135. - // When we implement INET6 handling, embed the ipv4 address in
  1136. - // the ipv6 address.
  1137. throw internal_error("socket_address_key(...) tried to compare an invalid family type.");
  1138. +#endif
  1139. +
  1140. }
  1141.  
  1142. inline bool
  1143. socket_address_key::is_comparable(const sockaddr* sa) {
  1144. - return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet;
  1145. + return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet ||
  1146. + rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet6;
  1147. }
  1148.  
  1149. struct peer_list_equal_port : public std::binary_function<PeerList::reference, uint16_t, bool> {
  1150. --- a/src/tracker/tracker_http.cc
  1151. +++ b/src/tracker/tracker_http.cc
  1152. @@ -42,6 +42,7 @@
  1153. #include <rak/string_manip.h>
  1154.  
  1155. #include "net/address_list.h"
  1156. +#include "net/local_addr.h"
  1157. #include "torrent/connection_manager.h"
  1158. #include "torrent/download_info.h"
  1159. #include "torrent/exceptions.h"
  1160. @@ -114,9 +115,16 @@
  1161.  
  1162. const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
  1163.  
  1164. - if (localAddress->family() == rak::socket_address::af_inet &&
  1165. - !localAddress->sa_inet()->is_address_any())
  1166. + if (!localAddress->is_address_any())
  1167. s << "&ip=" << localAddress->address_str();
  1168. +
  1169. +#ifdef RAK_USE_INET6
  1170. + if (localAddress->is_address_any() || localAddress->family() != rak::socket_address::pf_inet6) {
  1171. + rak::socket_address local_v6;
  1172. + if (get_local_address(rak::socket_address::af_inet6, &local_v6))
  1173. + s << "&ipv6=" << rak::copy_escape_html(local_v6.address_str());
  1174. + }
  1175. +#endif
  1176.  
  1177. if (info->is_compact())
  1178. s << "&compact=1";
  1179. @@ -220,18 +228,34 @@
  1180.  
  1181. AddressList l;
  1182.  
  1183. - try {
  1184. - // Due to some trackers sending the wrong type when no peers are
  1185. - // available, don't bork on it.
  1186. - if (b.get_key("peers").is_string())
  1187. - l.parse_address_compact(b.get_key_string("peers"));
  1188. + if (!b.has_key("peers")
  1189. +#ifdef RAK_USE_INET6
  1190. + && !b.has_key("peers6")
  1191. +#endif
  1192. + ) {
  1193. + return receive_failed("No peers returned");
  1194. + }
  1195.  
  1196. - else if (b.get_key("peers").is_list())
  1197. - l.parse_address_normal(b.get_key_list("peers"));
  1198. + if (b.has_key("peers")) {
  1199. + try {
  1200. + // Due to some trackers sending the wrong type when no peers are
  1201. + // available, don't bork on it.
  1202. + if (b.get_key("peers").is_string())
  1203. + l.parse_address_compact(b.get_key_string("peers"));
  1204. +
  1205. + else if (b.get_key("peers").is_list())
  1206. + l.parse_address_normal(b.get_key_list("peers"));
  1207. +
  1208. + } catch (bencode_error& e) {
  1209. + return receive_failed(e.what());
  1210. + }
  1211. + }
  1212.  
  1213. - } catch (bencode_error& e) {
  1214. - return receive_failed(e.what());
  1215. +#ifdef RAK_USE_INET6
  1216. + if (b.has_key("peers6")) {
  1217. + l.parse_address_compact_ipv6(b.get_key_string("peers6"));
  1218. }
  1219. +#endif
  1220.  
  1221. close();
  1222. m_parent->receive_success(this, &l);
  1223. --- a/src/tracker/tracker_udp.cc
  1224. +++ b/src/tracker/tracker_udp.cc
  1225. @@ -273,11 +273,18 @@
  1226.  
  1227. const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
  1228.  
  1229. - // This code assumes we're have a inet address.
  1230. +#ifdef RAK_USE_INET6
  1231. + uint32_t local_addr = 0;
  1232. + if (localAddress->family() == rak::socket_address::af_inet)
  1233. + local_addr = localAddress->sa_inet()->address_n();
  1234. +#else
  1235. if (localAddress->family() != rak::socket_address::af_inet)
  1236. throw internal_error("TrackerUdp::prepare_announce_input() info->local_address() not of family AF_INET.");
  1237. +
  1238. + uint32_t local_addr = localAddress->sa_inet()->address_n();
  1239. +#endif
  1240.  
  1241. - m_writeBuffer->write_32_n(localAddress->sa_inet()->address_n());
  1242. + m_writeBuffer->write_32_n(local_addr);
  1243. m_writeBuffer->write_32(m_parent->key());
  1244. m_writeBuffer->write_32(m_parent->numwant());
  1245. m_writeBuffer->write_16(manager->connection_manager()->listen_port());
Advertisement
Add Comment
Please, Sign In to add comment