~ubuntu-branches/ubuntu/wily/libtorrent/wily-proposed

« back to all changes in this revision

Viewing changes to debian/patches/libtorrent-0.12.6-ipv6-07.patch

  • Committer: Bazaar Package Importer
  • Author(s): Rogério Brito
  • Date: 2011-03-20 01:06:18 UTC
  • mfrom: (1.1.13 upstream) (4.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110320010618-g3wyylccqzqko73c
Tags: 0.12.7-5
* Use Steinar's "real" patch for IPv6. Addresses #490277, #618275,
  and Closes: #617791.
* Adapt libtorrent-0.12.6-ipv6-07.patch. It FTBFS otherwise.
* Add proper attibution to the IPv6 patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Description: Implement IPv6 for libtorrent
 
2
Author: "Steinar H. Gunderson" <sesse@debian.org>
 
3
Reviewed-By: Rogério Theodoro de Brito <rbrito@ime.usp.br>
 
4
Last-Updated: 2011-03-20
 
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
@@ -205,6 +205,28 @@
 
357
   mutable signal_chunk_type   m_signalChunkFailed;
 
358
 };
 
359
 
 
360
+#ifdef RAK_USE_INET6
 
361
+struct SocketAddressCompact6 {
 
362
+  SocketAddressCompact6() {}
 
363
+  SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {}
 
364
+  SocketAddressCompact6(const rak::socket_address_inet6* sa) : addr(sa->address()), port(sa->port_n()) {}
 
365
+
 
366
+  operator rak::socket_address () const {
 
367
+    rak::socket_address sa;
 
368
+    sa.sa_inet6()->clear();
 
369
+    sa.sa_inet6()->set_port_n(port);
 
370
+    sa.sa_inet6()->set_address(addr);
 
371
+
 
372
+    return sa;
 
373
+  }
 
374
+
 
375
+  in6_addr addr;
 
376
+  uint16_t port;
 
377
+
 
378
+  const char*         c_str() const { return reinterpret_cast<const char*>(this); }
 
379
+} __attribute__ ((packed));
 
380
+#endif
 
381
+
 
382
 }
 
383
 
 
384
 #endif
 
385
--- a/src/net/address_list.cc
 
386
+++ b/src/net/address_list.cc
 
387
@@ -40,6 +40,7 @@
 
388
 #include <rak/functional.h>
 
389
 
 
390
 #include "address_list.h"
 
391
+#include "torrent/download_info.h"
 
392
 
 
393
 namespace torrent {
 
394
 
 
395
@@ -92,4 +93,16 @@
 
396
   }
 
397
 }
 
398
 
 
399
+#ifdef RAK_USE_INET6
 
400
+void
 
401
+AddressList::parse_address_compact_ipv6(const std::string& s) {
 
402
+  if (sizeof(const SocketAddressCompact6) != 18)
 
403
+    throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size.");
 
404
+
 
405
+  std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()),
 
406
+            reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)),
 
407
+            std::back_inserter(*this));
 
408
+}
 
409
+#endif
 
410
+
 
411
 }
 
412
--- a/src/net/address_list.h
 
413
+++ b/src/net/address_list.h
 
414
@@ -54,6 +54,9 @@
 
415
 
 
416
   void                        parse_address_compact(raw_string s);
 
417
   void                        parse_address_compact(const std::string& s);
 
418
+#ifdef RAK_USE_INET6
 
419
+  void                        parse_address_compact_ipv6(const std::string& s);
 
420
+#endif
 
421
 
 
422
 private:
 
423
   static rak::socket_address  parse_address(const Object& b);
 
424
--- /dev/null
 
425
+++ b/src/net/local_addr.cc
 
426
@@ -0,0 +1,336 @@
 
427
+// libTorrent - BitTorrent library
 
428
+// Copyright (C) 2005-2007, Jari Sundell
 
429
+//
 
430
+// This program is free software; you can redistribute it and/or modify
 
431
+// it under the terms of the GNU General Public License as published by
 
432
+// the Free Software Foundation; either version 2 of the License, or
 
433
+// (at your option) any later version.
 
434
+// 
 
435
+// This program is distributed in the hope that it will be useful,
 
436
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
437
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
438
+// GNU General Public License for more details.
 
439
+// 
 
440
+// You should have received a copy of the GNU General Public License
 
441
+// along with this program; if not, write to the Free Software
 
442
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
443
+//
 
444
+// In addition, as a special exception, the copyright holders give
 
445
+// permission to link the code of portions of this program with the
 
446
+// OpenSSL library under certain conditions as described in each
 
447
+// individual source file, and distribute linked combinations
 
448
+// including the two.
 
449
+//
 
450
+// You must obey the GNU General Public License in all respects for
 
451
+// all of the code used other than OpenSSL.  If you modify file(s)
 
452
+// with this exception, you may extend this exception to your version
 
453
+// of the file(s), but you are not obligated to do so.  If you do not
 
454
+// wish to do so, delete this exception statement from your version.
 
455
+// If you delete this exception statement from all source files in the
 
456
+// program, then also delete it here.
 
457
+//
 
458
+// Contact:  Jari Sundell <jaris@ifi.uio.no>
 
459
+//
 
460
+//           Skomakerveien 33
 
461
+//           3185 Skoppum, NORWAY
 
462
+
 
463
+#include "config.h"
 
464
+
 
465
+#include <stdio.h>
 
466
+#include <ifaddrs.h>
 
467
+#include <rak/socket_address.h>
 
468
+#include <sys/types.h>
 
469
+#include <errno.h>
 
470
+
 
471
+#ifdef __linux__
 
472
+#include <linux/netlink.h>
 
473
+#include <linux/rtnetlink.h>
 
474
+#endif
 
475
+
 
476
+#include "torrent/exceptions.h"
 
477
+#include "socket_fd.h"
 
478
+#include "local_addr.h"
 
479
+
 
480
+namespace torrent {
 
481
+namespace {
 
482
+
 
483
+// IPv4 priority, from highest to lowest:
 
484
+//
 
485
+//   1. Everything else (global address)
 
486
+//   2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24)
 
487
+//   3. Empty/INADDR_ANY (0.0.0.0)
 
488
+//   4. Link-local address (169.254.0.0/16)
 
489
+//   5. Localhost (127.0.0.0/8)
 
490
+int get_priority_ipv4(const in_addr& addr) {
 
491
+  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x7f000000U)) {
 
492
+    return 5;
 
493
+  }
 
494
+  if (addr.s_addr == htonl(0)) {
 
495
+    return 4;
 
496
+  }
 
497
+  if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) {
 
498
+    return 3;
 
499
+  }
 
500
+  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
 
501
+      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) ||
 
502
+      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {
 
503
+    return 2;
 
504
+  }
 
505
+  return 1;
 
506
+}
 
507
+
 
508
+#ifdef RAK_USE_INET6
 
509
+// IPv6 priority, from highest to lowest:
 
510
+//
 
511
+//  1. Global address (2000::/16 not in 6to4 or Teredo)
 
512
+//  2. 6to4 (2002::/16)
 
513
+//  3. Teredo (2001::/32)
 
514
+//  4. Empty/INADDR_ANY (::)
 
515
+//  5. Everything else (link-local, ULA, etc.)
 
516
+int get_priority_ipv6(const in6_addr& addr) {
 
517
+  const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(addr.s6_addr);
 
518
+  if (addr32[0] == htonl(0) &&
 
519
+      addr32[1] == htonl(0) &&
 
520
+      addr32[2] == htonl(0) &&
 
521
+      addr32[3] == htonl(0)) {
 
522
+    return 4;
 
523
+  }
 
524
+  if (addr32[0] == htonl(0x20010000)) {
 
525
+    return 3;
 
526
+  }
 
527
+  if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) {
 
528
+    return 2;
 
529
+  }
 
530
+  if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) {
 
531
+    return 1;
 
532
+  }
 
533
+  return 5;
 
534
+}
 
535
+#endif
 
536
+
 
537
+int get_priority(const rak::socket_address& addr) {
 
538
+  switch (addr.family()) {
 
539
+  case AF_INET:
 
540
+    return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr);
 
541
+#ifdef RAK_USE_INET6
 
542
+  case AF_INET6:
 
543
+    return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr);
 
544
+#endif
 
545
+  default:
 
546
+    throw torrent::internal_error("Unknown address family given to compare");
 
547
+  }
 
548
+}
 
549
+
 
550
+}
 
551
+
 
552
+#ifdef __linux__
 
553
+
 
554
+// Linux-specific implementation that understands how to filter away
 
555
+// understands how to filter away secondary addresses.
 
556
+bool get_local_address(sa_family_t family, rak::socket_address *address) {
 
557
+  ifaddrs *ifaddrs;
 
558
+  if (getifaddrs(&ifaddrs)) {
 
559
+    return false;
 
560
+  }
 
561
+
 
562
+  rak::socket_address best_addr;
 
563
+  switch (family) {
 
564
+  case AF_INET:
 
565
+    best_addr.sa_inet()->clear();
 
566
+    break;
 
567
+#ifdef RAK_USE_INET6
 
568
+  case AF_INET6:
 
569
+    best_addr.sa_inet6()->clear();
 
570
+    break;
 
571
+#endif
 
572
+  default:
 
573
+    throw torrent::internal_error("Unknown address family given to get_local_address");
 
574
+  }
 
575
+
 
576
+  // The bottom bit of the priority is used to hold if the address is 
 
577
+  // a secondary address (e.g. with IPv6 privacy extensions) or not;
 
578
+  // secondary addresses have lower priority (higher number).
 
579
+  int best_addr_pri = get_priority(best_addr) * 2;
 
580
+
 
581
+  // Get all the addresses via Linux' netlink interface.
 
582
+  int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
 
583
+  if (fd == -1) {
 
584
+    return false;
 
585
+  }
 
586
+
 
587
+  struct sockaddr_nl nladdr;
 
588
+  memset(&nladdr, 0, sizeof(nladdr));
 
589
+  nladdr.nl_family = AF_NETLINK;
 
590
+  if (::bind(fd, (sockaddr *)&nladdr, sizeof(nladdr))) {
 
591
+    ::close(fd);
 
592
+    return false;
 
593
+  }
 
594
+
 
595
+  const int seq_no = 1;
 
596
+  struct {
 
597
+    nlmsghdr nh;
 
598
+    rtgenmsg g;
 
599
+  } req;
 
600
+  memset(&req, 0, sizeof(req));
 
601
+
 
602
+  req.nh.nlmsg_len = sizeof(req);
 
603
+  req.nh.nlmsg_type = RTM_GETADDR;
 
604
+  req.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
 
605
+  req.nh.nlmsg_pid = getpid();
 
606
+  req.nh.nlmsg_seq = seq_no;
 
607
+  req.g.rtgen_family = AF_UNSPEC;
 
608
+
 
609
+  int ret;
 
610
+  do {
 
611
+    ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr));
 
612
+  } while (ret == -1 && errno == EINTR);
 
613
+
 
614
+  if (ret == -1) {
 
615
+    ::close(fd);
 
616
+    return false;
 
617
+  }
 
618
+
 
619
+  bool done = false;
 
620
+  do {
 
621
+    char buf[4096];
 
622
+    socklen_t len = sizeof(nladdr);
 
623
+    do {
 
624
+      ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len);
 
625
+    } while (ret == -1 && errno == EINTR);
 
626
+
 
627
+    if (ret < 0) {
 
628
+      ::close(fd);
 
629
+      return false;
 
630
+    }
 
631
+
 
632
+    for (const nlmsghdr *nlmsg = (const nlmsghdr *)buf;
 
633
+         NLMSG_OK(nlmsg, ret);
 
634
+         nlmsg = NLMSG_NEXT(nlmsg, ret)) {
 
635
+      if (nlmsg->nlmsg_seq != seq_no)
 
636
+        continue;
 
637
+      if (nlmsg->nlmsg_type == NLMSG_DONE) {
 
638
+        done = true;
 
639
+        break;
 
640
+      }
 
641
+      if (nlmsg->nlmsg_type == NLMSG_ERROR) {
 
642
+        ::close(fd);
 
643
+        return false;
 
644
+      }
 
645
+      if (nlmsg->nlmsg_type != RTM_NEWADDR)
 
646
+        continue;
 
647
+
 
648
+      const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg);
 
649
+
 
650
+      if (ifa->ifa_family != family)
 
651
+        continue; 
 
652
+
 
653
+#ifdef IFA_F_OPTIMISTIC
 
654
+      if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0)
 
655
+        continue;
 
656
+#endif
 
657
+#ifdef IFA_F_DADFAILED
 
658
+      if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0)
 
659
+        continue;
 
660
+#endif
 
661
+#ifdef IFA_F_DEPRECATED
 
662
+      if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0)
 
663
+        continue;
 
664
+#endif
 
665
+#ifdef IFA_F_TENTATIVE
 
666
+      if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0)
 
667
+        continue;
 
668
+#endif
 
669
+  
 
670
+      // Since there can be point-to-point links on the machine, we need to keep
 
671
+      // track of the addresses we've seen for this interface; if we see both
 
672
+      // IFA_LOCAL and IFA_ADDRESS for an interface, keep only the IFA_LOCAL.
 
673
+      rak::socket_address this_addr;
 
674
+      bool seen_addr = false;
 
675
+      int plen = IFA_PAYLOAD(nlmsg);
 
676
+      for (const rtattr *rta = IFA_RTA(ifa);
 
677
+           RTA_OK(rta, plen);
 
678
+          rta = RTA_NEXT(rta, plen)) {
 
679
+        if (rta->rta_type != IFA_LOCAL &&
 
680
+            rta->rta_type != IFA_ADDRESS) {
 
681
+          continue;
 
682
+        }
 
683
+        if (rta->rta_type == IFA_ADDRESS && seen_addr) {
 
684
+          continue;
 
685
+        }
 
686
+        seen_addr = true;
 
687
+        switch (ifa->ifa_family) {
 
688
+        case AF_INET:
 
689
+          this_addr.sa_inet()->clear();
 
690
+          this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta));
 
691
+          break;
 
692
+#ifdef RAK_USE_INET6
 
693
+        case AF_INET6:
 
694
+          this_addr.sa_inet6()->clear();
 
695
+          this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta));
 
696
+          break;
 
697
+#endif
 
698
+        }
 
699
+      }
 
700
+      if (!seen_addr)
 
701
+        continue;
 
702
+       
 
703
+      int this_addr_pri = get_priority(this_addr) * 2;
 
704
+      if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) {
 
705
+        ++this_addr_pri;
 
706
+      }
 
707
+
 
708
+      if (this_addr_pri < best_addr_pri) {
 
709
+        best_addr = this_addr;
 
710
+        best_addr_pri = this_addr_pri;
 
711
+      }
 
712
+    }
 
713
+  } while (!done);
 
714
+
 
715
+  ::close(fd);
 
716
+  if (!best_addr.is_address_any()) {
 
717
+    *address = best_addr;
 
718
+    return true;
 
719
+  } else {
 
720
+    return false;
 
721
+  } 
 
722
+}
 
723
+
 
724
+#else
 
725
+
 
726
+// Generic POSIX variant.
 
727
+bool get_local_address(sa_family_t family, rak::socket_address *address) {
 
728
+  SocketFd sock;
 
729
+  if (!sock.open_datagram()) {
 
730
+    return false;
 
731
+  }
 
732
+
 
733
+  rak::socket_address dummy_dest;
 
734
+  dummy_dest.clear();
 
735
+
 
736
+  switch (family) {
 
737
+  case rak::socket_address::af_inet:
 
738
+    dummy_dest.set_address_c_str("4.0.0.0"); 
 
739
+    break;
 
740
+#ifdef RAK_USE_INET6
 
741
+  case rak::socket_address::af_inet6:
 
742
+    dummy_dest.set_address_c_str("2001:700::"); 
 
743
+    break;
 
744
+#endif
 
745
+  default:
 
746
+    throw internal_error("Unknown address family");
 
747
+  }
 
748
+  dummy_dest.set_port(80);
 
749
+
 
750
+  if (!sock.connect(dummy_dest)) {
 
751
+    sock.close();
 
752
+    return false;
 
753
+  }
 
754
+
 
755
+  bool ret = sock.getsockname(address);
 
756
+  sock.close();
 
757
+  return ret;
 
758
+}
 
759
+
 
760
+#endif
 
761
+
 
762
+}
 
763
--- /dev/null
 
764
+++ b/src/net/local_addr.h
 
765
@@ -0,0 +1,64 @@
 
766
+// libTorrent - BitTorrent library
 
767
+// Copyright (C) 2005-2007, Jari Sundell
 
768
+//
 
769
+// This program is free software; you can redistribute it and/or modify
 
770
+// it under the terms of the GNU General Public License as published by
 
771
+// the Free Software Foundation; either version 2 of the License, or
 
772
+// (at your option) any later version.
 
773
+// 
 
774
+// This program is distributed in the hope that it will be useful,
 
775
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
776
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
777
+// GNU General Public License for more details.
 
778
+// 
 
779
+// You should have received a copy of the GNU General Public License
 
780
+// along with this program; if not, write to the Free Software
 
781
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
782
+//
 
783
+// In addition, as a special exception, the copyright holders give
 
784
+// permission to link the code of portions of this program with the
 
785
+// OpenSSL library under certain conditions as described in each
 
786
+// individual source file, and distribute linked combinations
 
787
+// including the two.
 
788
+//
 
789
+// You must obey the GNU General Public License in all respects for
 
790
+// all of the code used other than OpenSSL.  If you modify file(s)
 
791
+// with this exception, you may extend this exception to your version
 
792
+// of the file(s), but you are not obligated to do so.  If you do not
 
793
+// wish to do so, delete this exception statement from your version.
 
794
+// If you delete this exception statement from all source files in the
 
795
+// program, then also delete it here.
 
796
+//
 
797
+// Contact:  Jari Sundell <jaris@ifi.uio.no>
 
798
+//
 
799
+//           Skomakerveien 33
 
800
+//           3185 Skoppum, NORWAY
 
801
+
 
802
+// A routine to get a local IP address that can be presented to a tracker.
 
803
+// (Does not use UPnP etc., so will not understand NAT.)
 
804
+// On a machine with multiple network cards, address selection can be a
 
805
+// complex process, and in general what's selected is a source/destination
 
806
+// address pair. However, this routine will give an approximation that will
 
807
+// be good enough for most purposes and users.
 
808
+
 
809
+#ifndef LIBTORRENT_NET_LOCAL_ADDR_H
 
810
+#define LIBTORRENT_NET_LOCAL_ADDR_H
 
811
+
 
812
+#include <unistd.h>
 
813
+
 
814
+namespace rak {
 
815
+  class socket_address;
 
816
+}
 
817
+
 
818
+namespace torrent {
 
819
+
 
820
+// Note: family must currently be rak::af_inet or rak::af_inet6
 
821
+// (rak::af_unspec won't do); anything else will throw an exception.
 
822
+// Returns false if no address of the given family could be found,
 
823
+// either because there are none, or because something went wrong in
 
824
+// the process (e.g., no free file descriptors).
 
825
+bool get_local_address(sa_family_t family, rak::socket_address *address);
 
826
+
 
827
+}
 
828
+
 
829
+#endif /* LIBTORRENT_NET_LOCAL_ADDR_H */
 
830
--- a/src/net/Makefile.am
 
831
+++ b/src/net/Makefile.am
 
832
@@ -4,6 +4,8 @@
 
833
        address_list.cc \
 
834
        address_list.h \
 
835
        data_buffer.h \
 
836
+       local_addr.cc \
 
837
+       local_addr.h \
 
838
        listen.cc \
 
839
        listen.h \
 
840
        protocol_buffer.h \
 
841
--- a/src/net/Makefile.in
 
842
+++ b/src/net/Makefile.in
 
843
@@ -54,9 +54,9 @@
 
844
 CONFIG_CLEAN_VPATH_FILES =
 
845
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 
846
 libsub_net_la_LIBADD =
 
847
-am_libsub_net_la_OBJECTS = address_list.lo listen.lo socket_base.lo \
 
848
-       socket_datagram.lo socket_fd.lo socket_set.lo socket_stream.lo \
 
849
-       throttle_internal.lo throttle_list.lo
 
850
+am_libsub_net_la_OBJECTS = address_list.lo local_addr.lo listen.lo \
 
851
+       socket_base.lo socket_datagram.lo socket_fd.lo socket_set.lo \
 
852
+       socket_stream.lo throttle_internal.lo throttle_list.lo
 
853
 libsub_net_la_OBJECTS = $(am_libsub_net_la_OBJECTS)
 
854
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 
855
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 
856
@@ -220,6 +220,8 @@
 
857
        address_list.cc \
 
858
        address_list.h \
 
859
        data_buffer.h \
 
860
+       local_addr.cc \
 
861
+       local_addr.h \
 
862
        listen.cc \
 
863
        listen.h \
 
864
        protocol_buffer.h \
 
865
@@ -294,6 +296,7 @@
 
866
 
 
867
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_list.Plo@am__quote@
 
868
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listen.Plo@am__quote@
 
869
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_addr.Plo@am__quote@
 
870
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_base.Plo@am__quote@
 
871
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_datagram.Plo@am__quote@
 
872
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Plo@am__quote@
 
873
--- a/src/net/socket_datagram.cc
 
874
+++ b/src/net/socket_datagram.cc
 
875
@@ -73,7 +73,13 @@
 
876
   int r;
 
877
 
 
878
   if (sa != NULL) {
 
879
-    r = ::sendto(m_fileDesc, buffer, length, 0, sa->sa_inet()->c_sockaddr(), sizeof(rak::socket_address_inet));
 
880
+#ifdef RAK_USE_INET6
 
881
+    if (m_ipv6_socket && sa->family() == rak::socket_address::pf_inet) {
 
882
+      rak::socket_address_inet6 sa_mapped = sa->sa_inet()->to_mapped_address();
 
883
+      r = ::sendto(m_fileDesc, buffer, length, 0, sa_mapped.c_sockaddr(), sizeof(rak::socket_address_inet6));
 
884
+    } else
 
885
+#endif
 
886
+    r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length());
 
887
   } else {
 
888
     r = ::send(m_fileDesc, buffer, length, 0);
 
889
   }
 
890
--- a/src/net/socket_fd.cc
 
891
+++ b/src/net/socket_fd.cc
 
892
@@ -70,6 +70,11 @@
 
893
   check_valid();
 
894
   int opt = p;
 
895
 
 
896
+#ifdef RAK_USE_INET6
 
897
+  if (m_ipv6_socket)
 
898
+    return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
 
899
+  else
 
900
+#endif
 
901
   return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
 
902
 }
 
903
 
 
904
@@ -112,12 +117,36 @@
 
905
 
 
906
 bool
 
907
 SocketFd::open_stream() {
 
908
+#ifdef RAK_USE_INET6
 
909
+  m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
 
910
+  if (m_fd == -1) {
 
911
+    m_ipv6_socket = false;
 
912
+    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
 
913
+  }
 
914
+  m_ipv6_socket = true;
 
915
+
 
916
+  int zero = 0;
 
917
+  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
 
918
+#else
 
919
   return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
 
920
+#endif
 
921
 }
 
922
 
 
923
 bool
 
924
 SocketFd::open_datagram() {
 
925
+#ifdef RAK_USE_INET6
 
926
+  m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
 
927
+  if (m_fd == -1) {
 
928
+    m_ipv6_socket = false;
 
929
+    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
 
930
+  }
 
931
+  m_ipv6_socket = true;
 
932
+
 
933
+  int zero = 0;
 
934
+  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
 
935
+#else
 
936
   return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
 
937
+#endif
 
938
 }
 
939
 
 
940
 bool
 
941
@@ -135,6 +164,12 @@
 
942
 SocketFd::bind(const rak::socket_address& sa) {
 
943
   check_valid();
 
944
 
 
945
+#ifdef RAK_USE_INET6
 
946
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
 
947
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
 
948
+    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
 
949
+  }
 
950
+#endif
 
951
   return !::bind(m_fd, sa.c_sockaddr(), sa.length());
 
952
 }
 
953
 
 
954
@@ -142,6 +177,12 @@
 
955
 SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
 
956
   check_valid();
 
957
 
 
958
+#ifdef RAK_USE_INET6
 
959
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
 
960
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
 
961
+    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
 
962
+  }
 
963
+#endif
 
964
   return !::bind(m_fd, sa.c_sockaddr(), length);
 
965
 }
 
966
 
 
967
@@ -149,10 +190,34 @@
 
968
 SocketFd::connect(const rak::socket_address& sa) {
 
969
   check_valid();
 
970
 
 
971
+#ifdef RAK_USE_INET6
 
972
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
 
973
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
 
974
+    return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
 
975
+  }
 
976
+#endif
 
977
   return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
 
978
 }
 
979
 
 
980
 bool
 
981
+SocketFd::getsockname(rak::socket_address *sa) {
 
982
+  check_valid();
 
983
+
 
984
+  socklen_t len = sizeof(rak::socket_address);
 
985
+  if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
 
986
+    return false;
 
987
+  }
 
988
+
 
989
+#ifdef RAK_USE_INET6
 
990
+  if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
 
991
+    *sa = sa->sa_inet6()->normalize_address();
 
992
+  }
 
993
+#endif
 
994
+
 
995
+  return true;
 
996
+}
 
997
+
 
998
+bool
 
999
 SocketFd::listen(int size) {
 
1000
   check_valid();
 
1001
 
 
1002
@@ -164,7 +229,18 @@
 
1003
   check_valid();
 
1004
   socklen_t len = sizeof(rak::socket_address);
 
1005
 
 
1006
+#ifdef RAK_USE_INET6
 
1007
+  if (sa == NULL) {
 
1008
+    return SocketFd(::accept(m_fd, NULL, &len));
 
1009
+  }
 
1010
+  int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
 
1011
+  if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
 
1012
+    *sa = sa->sa_inet6()->normalize_address();
 
1013
+  }
 
1014
+  return SocketFd(fd);
 
1015
+#else
 
1016
   return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len));
 
1017
+#endif
 
1018
 }
 
1019
 
 
1020
 // unsigned int
 
1021
--- a/src/net/socket_fd.h
 
1022
+++ b/src/net/socket_fd.h
 
1023
@@ -77,6 +77,7 @@
 
1024
   bool                bind(const rak::socket_address& sa);
 
1025
   bool                bind(const rak::socket_address& sa, unsigned int length);
 
1026
   bool                connect(const rak::socket_address& sa);
 
1027
+  bool                getsockname(rak::socket_address* sa);
 
1028
 
 
1029
   bool                listen(int size);
 
1030
   SocketFd            accept(rak::socket_address* sa);
 
1031
@@ -88,6 +89,9 @@
 
1032
   inline void         check_valid() const;
 
1033
 
 
1034
   int                 m_fd;
 
1035
+#ifdef RAK_USE_INET6
 
1036
+  bool                m_ipv6_socket;
 
1037
+#endif
 
1038
 };
 
1039
 
 
1040
 }
 
1041
--- a/src/torrent/connection_manager.cc
 
1042
+++ b/src/torrent/connection_manager.cc
 
1043
@@ -80,13 +80,18 @@
 
1044
   m_slotResolver(&resolve_host) {
 
1045
 
 
1046
   m_bindAddress = (new rak::socket_address())->c_sockaddr();
 
1047
-  rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
 
1048
-
 
1049
   m_localAddress = (new rak::socket_address())->c_sockaddr();
 
1050
-  rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
 
1051
-
 
1052
   m_proxyAddress = (new rak::socket_address())->c_sockaddr();
 
1053
+
 
1054
+#ifdef RAK_USE_INET6
 
1055
+  rak::socket_address::cast_from(m_bindAddress)->sa_inet6()->clear();
 
1056
+  rak::socket_address::cast_from(m_localAddress)->sa_inet6()->clear();
 
1057
+  rak::socket_address::cast_from(m_proxyAddress)->sa_inet6()->clear();
 
1058
+#else
 
1059
+  rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
 
1060
+  rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
 
1061
   rak::socket_address::cast_from(m_proxyAddress)->sa_inet()->clear();
 
1062
+#endif
 
1063
 }
 
1064
 
 
1065
 ConnectionManager::~ConnectionManager() {
 
1066
@@ -125,8 +130,10 @@
 
1067
 ConnectionManager::set_bind_address(const sockaddr* sa) {
 
1068
   const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
 
1069
 
 
1070
+#ifndef RAK_USE_INET6
 
1071
   if (rsa->family() != rak::socket_address::af_inet)
 
1072
     throw input_error("Tried to set a bind address that is not an af_inet address.");
 
1073
+#endif
 
1074
 
 
1075
   rak::socket_address::cast_from(m_bindAddress)->copy(*rsa, rsa->length());
 
1076
 }
 
1077
@@ -135,8 +142,10 @@
 
1078
 ConnectionManager::set_local_address(const sockaddr* sa) {
 
1079
   const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
 
1080
 
 
1081
+#ifndef RAK_USE_INET6
 
1082
   if (rsa->family() != rak::socket_address::af_inet)
 
1083
     throw input_error("Tried to set a local address that is not an af_inet address.");
 
1084
+#endif
 
1085
 
 
1086
   rak::socket_address::cast_from(m_localAddress)->copy(*rsa, rsa->length());
 
1087
 }
 
1088
@@ -145,8 +154,10 @@
 
1089
 ConnectionManager::set_proxy_address(const sockaddr* sa) {
 
1090
   const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
 
1091
 
 
1092
+#ifndef RAK_USE_INET6
 
1093
   if (rsa->family() != rak::socket_address::af_inet)
 
1094
     throw input_error("Tried to set a proxy address that is not an af_inet address.");
 
1095
+#endif
 
1096
 
 
1097
   rak::socket_address::cast_from(m_proxyAddress)->copy(*rsa, rsa->length());
 
1098
 }
 
1099
--- a/src/torrent/event.h
 
1100
+++ b/src/torrent/event.h
 
1101
@@ -57,6 +57,10 @@
 
1102
 
 
1103
 protected:
 
1104
   int                 m_fileDesc;
 
1105
+
 
1106
+#ifdef RAK_USE_INET6
 
1107
+  bool                m_ipv6_socket;
 
1108
+#endif
 
1109
 };
 
1110
 
 
1111
 }
 
1112
--- a/src/torrent/peer/peer_list.cc
 
1113
+++ b/src/torrent/peer/peer_list.cc
 
1114
@@ -65,15 +65,23 @@
 
1115
     // humans.
 
1116
     return sa1->sa_inet()->address_h() < sa2->sa_inet()->address_h();
 
1117
 
 
1118
+#ifdef RAK_USE_INET6
 
1119
+  else {
 
1120
+    const in6_addr addr1 = sa1->sa_inet6()->address();
 
1121
+    const in6_addr addr2 = sa2->sa_inet6()->address();
 
1122
+    return memcmp(&addr1, &addr2, sizeof(in6_addr)) < 0;
 
1123
+  }
 
1124
+#else
 
1125
   else
 
1126
-    // When we implement INET6 handling, embed the ipv4 address in
 
1127
-    // the ipv6 address.
 
1128
     throw internal_error("socket_address_key(...) tried to compare an invalid family type.");
 
1129
+#endif
 
1130
+
 
1131
 }
 
1132
 
 
1133
 inline bool
 
1134
 socket_address_key::is_comparable(const sockaddr* sa) {
 
1135
-  return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet;
 
1136
+  return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet ||
 
1137
+    rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet6;
 
1138
 }
 
1139
 
 
1140
 struct peer_list_equal_port : public std::binary_function<PeerList::reference, uint16_t, bool> {
 
1141
--- a/src/tracker/tracker_http.cc
 
1142
+++ b/src/tracker/tracker_http.cc
 
1143
@@ -42,6 +42,7 @@
 
1144
 #include <rak/string_manip.h>
 
1145
 
 
1146
 #include "net/address_list.h"
 
1147
+#include "net/local_addr.h"
 
1148
 #include "torrent/connection_manager.h"
 
1149
 #include "torrent/download_info.h"
 
1150
 #include "torrent/exceptions.h"
 
1151
@@ -114,9 +115,16 @@
 
1152
 
 
1153
   const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
 
1154
 
 
1155
-  if (localAddress->family() == rak::socket_address::af_inet &&
 
1156
-      !localAddress->sa_inet()->is_address_any())
 
1157
+  if (!localAddress->is_address_any())
 
1158
     s << "&ip=" << localAddress->address_str();
 
1159
+  
 
1160
+#ifdef RAK_USE_INET6
 
1161
+  if (localAddress->is_address_any() || localAddress->family() != rak::socket_address::pf_inet6) {
 
1162
+    rak::socket_address local_v6;
 
1163
+    if (get_local_address(rak::socket_address::af_inet6, &local_v6))
 
1164
+      s << "&ipv6=" << rak::copy_escape_html(local_v6.address_str());
 
1165
+  }
 
1166
+#endif
 
1167
 
 
1168
   if (info->is_compact())
 
1169
     s << "&compact=1";
 
1170
@@ -220,18 +228,34 @@
 
1171
 
 
1172
   AddressList l;
 
1173
 
 
1174
-  try {
 
1175
-    // Due to some trackers sending the wrong type when no peers are
 
1176
-    // available, don't bork on it.
 
1177
-    if (b.get_key("peers").is_string())
 
1178
-      l.parse_address_compact(b.get_key_string("peers"));
 
1179
+  if (!b.has_key("peers")
 
1180
+#ifdef RAK_USE_INET6
 
1181
+      && !b.has_key("peers6")
 
1182
+#endif
 
1183
+  ) {
 
1184
+    return receive_failed("No peers returned");
 
1185
+  }
 
1186
 
 
1187
-    else if (b.get_key("peers").is_list())
 
1188
-      l.parse_address_normal(b.get_key_list("peers"));
 
1189
+  if (b.has_key("peers")) {
 
1190
+    try {
 
1191
+      // Due to some trackers sending the wrong type when no peers are
 
1192
+      // available, don't bork on it.
 
1193
+      if (b.get_key("peers").is_string())
 
1194
+        l.parse_address_compact(b.get_key_string("peers"));
 
1195
+
 
1196
+      else if (b.get_key("peers").is_list())
 
1197
+        l.parse_address_normal(b.get_key_list("peers"));
 
1198
+
 
1199
+    } catch (bencode_error& e) {
 
1200
+      return receive_failed(e.what());
 
1201
+    }
 
1202
+  }
 
1203
 
 
1204
-  } catch (bencode_error& e) {
 
1205
-    return receive_failed(e.what());
 
1206
+#ifdef RAK_USE_INET6
 
1207
+  if (b.has_key("peers6")) {
 
1208
+    l.parse_address_compact_ipv6(b.get_key_string("peers6"));
 
1209
   }
 
1210
+#endif
 
1211
 
 
1212
   close();
 
1213
   m_parent->receive_success(this, &l);
 
1214
--- a/src/tracker/tracker_udp.cc
 
1215
+++ b/src/tracker/tracker_udp.cc
 
1216
@@ -273,11 +273,18 @@
 
1217
 
 
1218
   const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
 
1219
 
 
1220
-  // This code assumes we're have a inet address.
 
1221
+#ifdef RAK_USE_INET6
 
1222
+  uint32_t local_addr = 0;
 
1223
+  if (localAddress->family() == rak::socket_address::af_inet)
 
1224
+    local_addr = localAddress->sa_inet()->address_n();
 
1225
+#else
 
1226
   if (localAddress->family() != rak::socket_address::af_inet)
 
1227
     throw internal_error("TrackerUdp::prepare_announce_input() info->local_address() not of family AF_INET.");
 
1228
+  
 
1229
+  uint32_t local_addr = localAddress->sa_inet()->address_n();
 
1230
+#endif
 
1231
 
 
1232
-  m_writeBuffer->write_32_n(localAddress->sa_inet()->address_n());
 
1233
+  m_writeBuffer->write_32_n(local_addr);
 
1234
   m_writeBuffer->write_32(m_parent->key());
 
1235
   m_writeBuffer->write_32(m_parent->numwant());
 
1236
   m_writeBuffer->write_16(manager->connection_manager()->listen_port());