Changeset 9549
- Timestamp:
- Nov 24, 2009, 1:59:51 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/announcer.c
r9533 r9549 1651 1651 while(( tor = tr_torrentNext( announcer->session, tor ))) { 1652 1652 if( tor->dhtAnnounceAt <= now ) { 1653 int rc = 1; 1654 if( tor->isRunning && tr_torrentAllowsDHT(tor) ) 1655 rc = tr_dhtAnnounce(tor, 1); 1656 if(rc == 0) 1657 /* The DHT is not ready yet. Try again soon. */ 1658 tor->dhtAnnounceAt = now + 5 + tr_cryptoWeakRandInt( 5 ); 1659 else 1660 /* We should announce at least once every 30 minutes. */ 1661 tor->dhtAnnounceAt = now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 ); 1653 if( tor->isRunning && tr_torrentAllowsDHT(tor) ) { 1654 int rc; 1655 rc = tr_dhtAnnounce(tor, AF_INET, 1); 1656 if(rc == 0) 1657 /* The DHT is not ready yet. Try again soon. */ 1658 tor->dhtAnnounceAt = now + 5 + tr_cryptoWeakRandInt( 5 ); 1659 else 1660 /* We should announce at least once every 30 minutes. */ 1661 tor->dhtAnnounceAt = 1662 now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 ); 1663 } 1664 } 1665 1666 if( tor->dhtAnnounce6At <= now ) { 1667 if( tor->isRunning && tr_torrentAllowsDHT(tor) ) { 1668 int rc; 1669 rc = tr_dhtAnnounce(tor, AF_INET6, 1); 1670 if(rc == 0) 1671 tor->dhtAnnounce6At = now + 5 + tr_cryptoWeakRandInt( 5 ); 1672 else 1673 tor->dhtAnnounce6At = 1674 now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 ); 1675 } 1662 1676 } 1663 1677 } -
trunk/libtransmission/peer-msgs.c
r9540 r9549 2129 2129 2130 2130 if(tr_peerIoSupportsDHT(peer->io)) { 2131 /* We don't have an IPv6 DHT yet. 2132 * According to BEP-32, we can't send PORT over IPv6. */ 2131 /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */ 2133 2132 const struct tr_address *addr = tr_peerIoGetAddress( peer->io, NULL ); 2134 if( addr->type == TR_AF_INET ) {2133 if( addr->type == TR_AF_INET || tr_globalIPv6() ) { 2135 2134 protocolSendPort( m, tr_dhtPort( torrent->session ) ); 2136 2135 } -
trunk/libtransmission/torrent.c
r9540 r9549 1320 1320 tr_announcerTorrentStarted( tor ); 1321 1321 tor->dhtAnnounceAt = now + tr_cryptoWeakRandInt( 20 ); 1322 tor->dhtAnnounce6At = now + tr_cryptoWeakRandInt( 20 ); 1322 1323 tr_peerMgrStartTorrent( tor ); 1323 1324 } -
trunk/libtransmission/torrent.h
r9540 r9549 182 182 183 183 time_t dhtAnnounceAt; 184 time_t dhtAnnounce6At; 184 185 tr_bool dhtAnnounceInProgress; 186 tr_bool dhtAnnounce6InProgress; 185 187 186 188 uint64_t downloadedCur; -
trunk/libtransmission/tr-dht.c
r9522 r9549 31 31 #include <sys/types.h> 32 32 #include <sys/socket.h> /* socket(), bind() */ 33 #include <netdb.h> 33 34 #include <unistd.h> /* close() */ 34 35 … … 51 52 #include "version.h" 52 53 53 static int dht_socket ;54 static struct event dht_event ;54 static int dht_socket = -1, dht6_socket = -1; 55 static struct event dht_event, dht6_event; 55 56 static tr_port dht_port; 56 57 static unsigned char myid[20]; … … 62 63 tr_session *session; 63 64 uint8_t *nodes; 64 size_t len; 65 uint8_t *nodes6; 66 size_t len, len6; 65 67 }; 68 69 static int 70 bootstrap_done( tr_session *session, int af ) 71 { 72 int status; 73 74 if(af == 0) 75 return 76 bootstrap_done(session, AF_INET) && 77 bootstrap_done(session, AF_INET6); 78 79 status = tr_dhtStatus(session, af, NULL); 80 return status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED; 81 } 82 83 static void 84 nap( int roughly ) 85 { 86 struct timeval tv; 87 tr_timevalSet( &tv, roughly / 2 + tr_cryptoWeakRandInt( roughly ), 88 tr_cryptoWeakRandInt( 1000000 ) ); 89 select( 0, NULL, NULL, NULL, &tv ); 90 } 91 92 static int 93 bootstrap_af(tr_session *session) 94 { 95 if( bootstrap_done(session, AF_INET6) ) 96 return AF_INET; 97 else if ( bootstrap_done(session, AF_INET) ) 98 return AF_INET6; 99 else 100 return 0; 101 } 102 103 static void 104 bootstrap_from_name( const char *name, short int port, int af ) 105 { 106 struct addrinfo hints, *info, *infop; 107 char pp[10]; 108 int rc; 109 110 memset(&hints, 0, sizeof(hints)); 111 hints.ai_socktype = SOCK_DGRAM; 112 hints.ai_family = af; 113 /* No, just passing p + 1 to gai won't work. */ 114 snprintf(pp, 10, "%d", port); 115 116 rc = getaddrinfo(name, pp, &hints, &info); 117 if(rc != 0) { 118 tr_nerr("DHT", "%s:%s: %s", name, pp, gai_strerror(rc)); 119 return; 120 } 121 122 infop = info; 123 while(infop) { 124 dht_ping_node(infop->ai_addr, infop->ai_addrlen); 125 126 nap(15); 127 128 if(bootstrap_done(session, af)) 129 break; 130 infop = infop->ai_next; 131 } 132 freeaddrinfo(info); 133 } 66 134 67 135 static void … … 69 137 { 70 138 struct bootstrap_closure *cl = closure; 71 size_t i; 139 int i; 140 int num = cl->len / 6, num6 = cl->len6 / 18; 72 141 73 142 if(session != cl->session) 74 143 return; 75 144 76 for(i = 0; i < cl->len; i += 6) 77 { 78 struct timeval tv; 79 tr_port port; 80 struct tr_address addr; 81 int status; 82 83 memset(&addr, 0, sizeof(addr)); 84 addr.type = TR_AF_INET; 85 memcpy(&addr.addr.addr4, &cl->nodes[i], 4); 86 memcpy(&port, &cl->nodes[i + 4], 2); 87 port = ntohs(port); 88 /* There's no race here -- if we uninit between the test and the 89 AddNode, the AddNode will be ignored. */ 90 status = tr_dhtStatus(cl->session, NULL); 91 if(status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED) 145 if(cl->len > 0) 146 tr_ninf( "DHT", "Bootstrapping from %d nodes", num ); 147 148 if(cl->len6 > 0) 149 tr_ninf( "DHT", "Bootstrapping from %d IPv6 nodes", num6 ); 150 151 152 for(i = 0; i < MAX(num, num6); i++) { 153 if( i < num && !bootstrap_done(cl->session, AF_INET) ) { 154 tr_port port; 155 struct tr_address addr; 156 157 memset(&addr, 0, sizeof(addr)); 158 addr.type = TR_AF_INET; 159 memcpy(&addr.addr.addr4, &cl->nodes[i * 6], 4); 160 memcpy(&port, &cl->nodes[i * 6 + 4], 2); 161 port = ntohs(port); 162 tr_dhtAddNode(cl->session, &addr, port, 1); 163 } 164 if( i < num6 && !bootstrap_done(cl->session, AF_INET6) ) { 165 tr_port port; 166 struct tr_address addr; 167 168 memset(&addr, 0, sizeof(addr)); 169 addr.type = TR_AF_INET6; 170 memcpy(&addr.addr.addr6, &cl->nodes6[i * 18], 16); 171 memcpy(&port, &cl->nodes6[i * 18 + 16], 2); 172 port = ntohs(port); 173 tr_dhtAddNode(cl->session, &addr, port, 1); 174 } 175 176 /* Our DHT code is able to take up to 9 nodes in a row without 177 dropping any. After that, it takes some time to split buckets. 178 So ping the first 8 nodes quickly, then slow down. */ 179 if(i < 8) 180 nap(2); 181 else 182 nap(15); 183 184 if(bootstrap_done( session, 0 )) 92 185 break; 93 tr_dhtAddNode(cl->session, &addr, port, 1); 94 tr_timevalSet( &tv, 2 + tr_cryptoWeakRandInt( 5 ), tr_cryptoWeakRandInt( 1000000 ) ); 95 select( 0, NULL, NULL, NULL, &tv ); 96 } 97 tr_free( cl->nodes ); 186 } 187 188 if(!bootstrap_done(cl->session, 0)) { 189 char *bootstrap_file; 190 FILE *f = NULL; 191 192 bootstrap_file = 193 tr_buildPath(cl->session->configDir, "dht.bootstrap", NULL); 194 195 if(bootstrap_file) 196 f = fopen(bootstrap_file, "r"); 197 if(f) { 198 tr_ninf("DHT", "Attempting manual bootstrap"); 199 while(1) { 200 char buf[201]; 201 char *p; 202 int port = 0; 203 204 p = fgets(buf, 200, f); 205 if( p == NULL ) 206 break; 207 208 p = memchr(buf, ' ', strlen(buf)); 209 if(p != NULL) 210 port = atoi(p + 1); 211 if(p == NULL || port <= 0 || port >= 0x10000) { 212 tr_nerr("DHT", "Couldn't parse %s", buf); 213 continue; 214 } 215 216 *p = '\0'; 217 218 bootstrap_from_name( buf, port, bootstrap_af(session) ); 219 220 if(bootstrap_done(cl->session, 0)) 221 break; 222 } 223 } 224 } 225 226 /* We really don't want to abuse our bootstrap nodes. 227 Be glacially slow. */ 228 if(!bootstrap_done(cl->session, 0)) 229 nap(30); 230 231 if(!bootstrap_done(cl->session, 0)) { 232 tr_ninf("DHT", "Attempting bootstrap from dht.transmissionbt.com"); 233 bootstrap_from_name( "dht.transmissionbt.com", 6881, 234 bootstrap_af(session) ); 235 } 236 237 if( cl->nodes ) 238 tr_free( cl->nodes ); 239 if( cl->nodes6 ) 240 tr_free( cl->nodes6 ); 98 241 tr_free( closure ); 99 242 tr_ndbg( "DHT", "Finished bootstrapping" ); 100 243 } 101 244 245 /* BEP-32 has a rather nice explanation of why we need to bind to one 246 IPv6 address, if I may say so myself. */ 247 248 static int 249 rebind_ipv6(int force) 250 { 251 struct sockaddr_in6 sin6; 252 const unsigned char *ipv6 = tr_globalIPv6(); 253 static unsigned char *last_bound = NULL; 254 int rc; 255 256 if(dht6_socket < 0) 257 return 0; 258 259 if(!force && 260 ((ipv6 == NULL && last_bound == NULL) || 261 (ipv6 != NULL && last_bound != NULL && 262 memcmp(ipv6, last_bound, 16) == 0))) 263 return 0; 264 265 memset(&sin6, 0, sizeof(sin6)); 266 sin6.sin6_family = AF_INET6; 267 if(ipv6) 268 memcpy(&sin6.sin6_addr, ipv6, 16); 269 sin6.sin6_port = htons(dht_port); 270 rc = bind(dht6_socket, (struct sockaddr*)&sin6, sizeof(sin6)); 271 272 if(last_bound) 273 free(last_bound); 274 last_bound = NULL; 275 276 if(rc >= 0 && ipv6) { 277 last_bound = malloc(16); 278 if(last_bound) 279 memcpy(last_bound, ipv6, 16); 280 } 281 return rc; 282 } 283 102 284 int 103 tr_dhtInit(tr_session *ss, tr_address * tr_addr)285 tr_dhtInit(tr_session *ss, const tr_address * tr_addr) 104 286 { 105 287 struct sockaddr_in sin; … … 108 290 tr_bool have_id = FALSE; 109 291 char * dat_file; 110 uint8_t * nodes = NULL ;292 uint8_t * nodes = NULL, * nodes6 = NULL; 111 293 const uint8_t * raw; 112 size_t len ;294 size_t len, len6; 113 295 char v[5]; 296 struct bootstrap_closure * cl; 114 297 115 298 if( session ) /* already initialized */ … … 128 311 memset(&sin, 0, sizeof(sin)); 129 312 sin.sin_family = AF_INET; 130 memcpy(& (sin.sin_addr), &(tr_addr->addr.addr4), sizeof (struct in_addr));313 memcpy(&sin.sin_addr, &tr_addr->addr.addr4, sizeof (struct in_addr)); 131 314 sin.sin_port = htons(dht_port); 132 315 rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin)); … … 134 317 goto fail; 135 318 319 if(tr_globalIPv6()) { 320 dht6_socket = socket(PF_INET6, SOCK_DGRAM, 0); 321 if(dht6_socket < 0) 322 goto fail; 323 324 rebind_ipv6(1); 325 326 } 327 136 328 if( getenv( "TR_DHT_VERBOSE" ) != NULL ) 137 329 dht_debug = stderr; … … 141 333 tr_free( dat_file ); 142 334 if(rc == 0) { 143 if(( have_id = tr_bencDictFindRaw( &benc, "id", &raw, &len ) && len==20 )) 335 have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len); 336 if( have_id && len==20 ) 144 337 memcpy( myid, raw, len ); 145 if( tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) { 146 nodes = tr_memdup( raw, len ); 147 tr_ninf( "DHT", "Bootstrapping from %d old nodes", (int)(len/6) ); 338 if( dht_socket >= 0 && 339 tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) { 340 nodes = tr_memdup( raw, len ); 341 } 342 if( dht6_socket > 0 && 343 tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) { 344 nodes6 = tr_memdup( raw, len6 ); 148 345 } 149 346 tr_bencFree( &benc ); 150 347 } 348 349 if(nodes == NULL) 350 len = 0; 351 if(nodes6 == NULL) 352 len6 = 0; 151 353 152 354 if( have_id ) … … 163 365 v[2] = (SVN_REVISION_NUM >> 8) & 0xFF; 164 366 v[3] = SVN_REVISION_NUM & 0xFF; 165 rc = dht_init( dht_socket, myid, (const unsigned char*)v );367 rc = dht_init( dht_socket, dht6_socket, myid, (const unsigned char*)v ); 166 368 if(rc < 0) 167 369 goto fail; … … 169 371 session = ss; 170 372 171 if(nodes) {172 struct bootstrap_closure * cl = tr_new( struct bootstrap_closure, 1 );173 cl->session = session;174 cl->nodes = nodes;175 176 tr_threadNew( dht_bootstrap, cl );177 }373 cl = tr_new( struct bootstrap_closure, 1 ); 374 cl->session = session; 375 cl->nodes = nodes; 376 cl->nodes6 = nodes6; 377 cl->len = len; 378 cl->len6 = len6; 379 tr_threadNew( dht_bootstrap, cl ); 178 380 179 381 event_set( &dht_event, dht_socket, EV_READ, event_callback, NULL ); 382 event_set( &dht6_event, dht6_socket, EV_READ, event_callback, NULL ); 180 383 tr_timerAdd( &dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) ); 384 tr_timerAdd( &dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) ); 181 385 182 386 tr_ndbg( "DHT", "DHT initialized" ); … … 188 392 const int save = errno; 189 393 close(dht_socket); 190 dht_socket = -1; 394 if( dht6_socket >= 0 ) 395 close(dht6_socket); 396 dht_socket = dht6_socket = -1; 191 397 session = NULL; 192 398 tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", save ); … … 206 412 207 413 event_del(&dht_event); 414 event_del(&dht6_event); 208 415 209 416 /* Since we only save known good nodes, avoid erasing older data if we 210 417 don't know enough nodes. */ 211 if(tr_dhtStatus(ss, NULL) < TR_DHT_FIREWALLED)418 if(tr_dhtStatus(ss, AF_INET, NULL) < TR_DHT_FIREWALLED) 212 419 tr_ninf( "DHT", "Not saving nodes, DHT not ready" ); 213 420 else { 214 421 tr_benc benc; 215 422 struct sockaddr_in sins[300]; 216 char compact[300 * 6]; 423 struct sockaddr_in6 sins6[300]; 424 char compact[300 * 6], compact6[300 * 18]; 217 425 char *dat_file; 218 int i; 219 int n = dht_get_nodes(sins, 300); 220 int j = 0; 221 222 tr_ninf( "DHT", "Saving %d nodes", n ); 223 for( i=0; i<n; ++i ) { 426 int i, j, num = 300, num6 = 300; 427 int n = dht_get_nodes(sins, &num, sins6, &num6); 428 429 tr_ninf( "DHT", "Saving %d (%d + %d) nodes", n, num, num6 ); 430 431 j = 0; 432 for( i=0; i<num; ++i ) { 224 433 memcpy( compact + j, &sins[i].sin_addr, 4 ); 225 434 memcpy( compact + j + 4, &sins[i].sin_port, 2 ); 226 435 j += 6; 227 436 } 228 tr_bencInitDict( &benc, 2 ); 437 j = 0; 438 for( i=0; i<num6; ++i ) { 439 memcpy( compact6 + j, &sins6[i].sin6_addr, 16 ); 440 memcpy( compact6 + j + 16, &sins6[i].sin6_port, 2 ); 441 j += 18; 442 } 443 tr_bencInitDict( &benc, 3 ); 229 444 tr_bencDictAddRaw( &benc, "id", myid, 20 ); 230 tr_bencDictAddRaw( &benc, "nodes", compact, j ); 445 if(num > 0) 446 tr_bencDictAddRaw( &benc, "nodes", compact, num * 6 ); 447 if(num6 > 0) 448 tr_bencDictAddRaw( &benc, "nodes6", compact6, num6 * 18 ); 231 449 dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL ); 232 450 tr_bencToFile( &benc, TR_FMT_BENC, dat_file ); … … 235 453 } 236 454 237 dht_uninit( dht_socket, 0);455 dht_uninit( 1 ); 238 456 tr_netCloseSocket( dht_socket ); 457 if(dht6_socket > 0) 458 tr_netCloseSocket( dht6_socket ); 239 459 240 460 tr_ndbg("DHT", "Done uninitializing DHT"); … … 244 464 245 465 tr_bool 246 tr_dhtEnabled( consttr_session * ss )466 tr_dhtEnabled( tr_session * ss ) 247 467 { 248 468 return ss && ( ss == session ); … … 251 471 struct getstatus_closure 252 472 { 473 int af; 253 474 sig_atomic_t status; 254 475 sig_atomic_t count; … … 256 477 257 478 static void 258 getstatus( void * cl osure)259 { 260 struct getstatus_closure * ret = closure;479 getstatus( void * cl ) 480 { 481 struct getstatus_closure * closure = cl; 261 482 int good, dubious, incoming; 262 483 263 dht_nodes( &good, &dubious, NULL, &incoming );264 265 ret->count = good + dubious;484 dht_nodes( closure->af, &good, &dubious, NULL, &incoming ); 485 486 closure->count = good + dubious; 266 487 267 488 if( good < 4 || good + dubious <= 8 ) 268 ret->status = TR_DHT_BROKEN;489 closure->status = TR_DHT_BROKEN; 269 490 else if( good < 40 ) 270 ret->status = TR_DHT_POOR;491 closure->status = TR_DHT_POOR; 271 492 else if( incoming < 8 ) 272 ret->status = TR_DHT_FIREWALLED;493 closure->status = TR_DHT_FIREWALLED; 273 494 else 274 ret->status = TR_DHT_GOOD;495 closure->status = TR_DHT_GOOD; 275 496 } 276 497 277 498 int 278 tr_dhtStatus( tr_session * ss, int * nodes_return )279 { 280 struct getstatus_closure ret = { -1, -1 };499 tr_dhtStatus( tr_session * ss, int af, int * nodes_return ) 500 { 501 struct getstatus_closure closure = { af, -1, -1 }; 281 502 282 503 if( !tr_dhtEnabled( ss ) ) 283 504 return TR_DHT_STOPPED; 284 505 285 tr_runInEventThread( ss, getstatus, &ret ); 286 while( ret.status < 0 ) 506 if(dht_socket < 0 && dht6_socket < 0) 507 return TR_DHT_STOPPED; 508 509 if(af == AF_INET && dht_socket < 0) 510 return TR_DHT_STOPPED; 511 512 if(af == AF_INET6 && dht6_socket < 0) 513 return TR_DHT_STOPPED; 514 515 tr_runInEventThread( ss, getstatus, &closure ); 516 while( closure.status < 0 ) 287 517 tr_wait( 10 /*msec*/ ); 288 518 289 519 if( nodes_return ) 290 *nodes_return = ret.count;291 292 return ret.status;520 *nodes_return = closure.count; 521 522 return closure.status; 293 523 } 294 524 295 525 tr_port 296 tr_dhtPort( consttr_session *ss )526 tr_dhtPort( tr_session *ss ) 297 527 { 298 528 return tr_dhtEnabled( ss ) ? dht_port : 0; … … 305 535 tr_bool bootstrap ) 306 536 { 307 struct sockaddr_in sin;537 int af = address->type == TR_AF_INET ? AF_INET : AF_INET6; 308 538 309 539 if( !tr_dhtEnabled( ss ) ) 310 540 return 0; 311 541 312 if( address->type != TR_AF_INET )313 return 0;314 315 542 /* Since we don't want to abuse our bootstrap nodes, 316 543 * we don't ping them if the DHT is in a good state. */ 544 317 545 if(bootstrap) { 318 if(tr_dhtStatus(ss, NULL) >= TR_DHT_FIREWALLED)546 if(tr_dhtStatus(ss, af, NULL) >= TR_DHT_FIREWALLED) 319 547 return 0; 320 548 } 321 549 322 memset(&sin, 0, sizeof(sin)); 323 sin.sin_family = AF_INET; 324 memcpy(&sin.sin_addr, &address->addr.addr4, 4); 325 sin.sin_port = htons(port); 326 dht_ping_node(dht_socket, &sin); 327 328 return 1; 550 if( address->type == TR_AF_INET ) { 551 struct sockaddr_in sin; 552 memset(&sin, 0, sizeof(sin)); 553 sin.sin_family = AF_INET; 554 memcpy(&sin.sin_addr, &address->addr.addr4, 4); 555 sin.sin_port = htons(port); 556 dht_ping_node((struct sockaddr*)&sin, sizeof(sin)); 557 return 1; 558 } else if( address->type == TR_AF_INET6 ) { 559 struct sockaddr_in6 sin6; 560 memset(&sin6, 0, sizeof(sin6)); 561 sin6.sin6_family = AF_INET6; 562 memcpy(&sin6.sin6_addr, &address->addr.addr6, 16); 563 sin6.sin6_port = htons(port); 564 dht_ping_node((struct sockaddr*)&sin6, sizeof(sin6)); 565 return 1; 566 } 567 568 return 0; 329 569 } 330 570 … … 346 586 unsigned char *info_hash, void *data, size_t data_len ) 347 587 { 348 if( event == DHT_EVENT_VALUES ) 349 { 588 if( event == DHT_EVENT_VALUES || event == DHT_EVENT_VALUES6 ) { 350 589 tr_torrent *tor; 351 590 tr_globalLock( session ); … … 354 593 { 355 594 size_t i, n; 356 tr_pex * pex = tr_peerMgrCompactToPex(data, data_len, NULL, 0, &n); 595 tr_pex * pex; 596 if( event == DHT_EVENT_VALUES ) 597 pex = tr_peerMgrCompactToPex(data, data_len, NULL, 0, &n); 598 else 599 pex = tr_peerMgrCompact6ToPex(data, data_len, NULL, 0, &n); 357 600 for( i=0; i<n; ++i ) 358 601 tr_peerMgrAddPex( tor, TR_PEER_FROM_DHT, pex+i ); 359 602 tr_free(pex); 360 tr_torinf(tor, "Learned %d peers from DHT", (int)n); 603 tr_torinf(tor, "Learned %d%s peers from DHT", 604 (int)n, 605 event == DHT_EVENT_VALUES6 ? " IPv6" : ""); 361 606 } 362 607 tr_globalUnlock( session ); 363 } 364 else if( event == DHT_EVENT_SEARCH_DONE ) 365 { 608 } else if( event == DHT_EVENT_SEARCH_DONE || 609 event == DHT_EVENT_SEARCH_DONE6) { 366 610 tr_torrent * tor = tr_torrentFindFromHash( session, info_hash ); 367 611 if( tor ) { 368 tr_torinf(tor, "DHT announce done"); 369 tor->dhtAnnounceInProgress = 0; 612 if( event == DHT_EVENT_SEARCH_DONE ) { 613 tr_torinf(tor, "DHT announce done"); 614 tor->dhtAnnounceInProgress = 0; 615 } else { 616 tr_torinf(tor, "IPv6 DHT announce done"); 617 tor->dhtAnnounce6InProgress = 0; 618 } 370 619 } 371 620 } … … 373 622 374 623 int 375 tr_dhtAnnounce(tr_torrent *tor, tr_bool announce)376 { 377 int rc, status, numnodes ;624 tr_dhtAnnounce(tr_torrent *tor, int af, tr_bool announce) 625 { 626 int rc, status, numnodes, ret = 0; 378 627 379 628 if( !tr_torrentAllowsDHT( tor ) ) 380 629 return -1; 381 630 382 status = tr_dhtStatus( tor->session, &numnodes ); 383 if(status < TR_DHT_POOR ) { 384 tr_tordbg(tor, "DHT not ready (%s, %d nodes)", 631 status = tr_dhtStatus( tor->session, af, &numnodes ); 632 if(status >= TR_DHT_POOR ) { 633 rc = dht_search( tor->info.hash, 634 announce ? tr_sessionGetPeerPort(session) : 0, 635 af, callback, NULL); 636 if( rc >= 1 ) { 637 tr_torinf(tor, "Starting%s DHT announce (%s, %d nodes)", 638 af == AF_INET6 ? " IPv6" : "", 639 tr_dhtPrintableStatus(status), numnodes); 640 if(af == AF_INET) 641 tor->dhtAnnounceInProgress = TRUE; 642 else 643 tor->dhtAnnounce6InProgress = TRUE; 644 ret = 1; 645 } else { 646 tr_torerr(tor, "%sDHT announce failed, errno = %d (%s, %d nodes)", 647 af == AF_INET6 ? "IPv6 " : "", 648 errno, tr_dhtPrintableStatus(status), numnodes); 649 } 650 } else { 651 tr_tordbg(tor, "%sDHT not ready (%s, %d nodes)", 652 af == AF_INET6 ? "IPv6 " : "", 385 653 tr_dhtPrintableStatus(status), numnodes); 386 return 0; 387 } 388 389 rc = dht_search( dht_socket, tor->info.hash, 390 announce ? tr_sessionGetPeerPort(session) : 0, 391 callback, NULL); 392 393 if( rc >= 1 ) { 394 tr_torinf(tor, "Starting DHT announce (%s, %d nodes)", 395 tr_dhtPrintableStatus(status), numnodes); 396 tor->dhtAnnounceInProgress = TRUE; 397 } else { 398 tr_torerr(tor, "DHT announce failed, errno = %d (%s, %d nodes)", 399 errno, tr_dhtPrintableStatus(status), numnodes); 400 } 401 402 return 1; 654 } 655 656 return ret; 403 657 } 404 658 … … 406 660 event_callback(int s, short type, void *ignore UNUSED ) 407 661 { 662 struct event *event = (s == dht_socket) ? &dht_event : &dht6_event; 408 663 time_t tosleep; 409 410 if( dht_periodic(s, type == EV_READ, &tosleep, callback, NULL) < 0 ) { 664 static int count = 0; 665 666 if( dht_periodic( type == EV_READ, &tosleep, callback, NULL) < 0 ) { 411 667 if(errno == EINTR) { 412 668 tosleep = 0; … … 419 675 } 420 676 677 /* Only do this once in a while. Counting rather than measuring time 678 avoids a system call. */ 679 count++; 680 if(count >= 128) { 681 rebind_ipv6(0); 682 count = 0; 683 } 684 421 685 /* Being slightly late is fine, 422 686 and has the added benefit of adding some jitter. */ 423 tr_timerAdd( &dht_event, tosleep, tr_cryptoWeakRandInt( 1000000 ) );687 tr_timerAdd( event, tosleep, tr_cryptoWeakRandInt( 1000000 ) ); 424 688 } 425 689 -
trunk/libtransmission/tr-dht.h
r9434 r9549 27 27 #define TR_DHT_GOOD 4 28 28 29 int tr_dhtInit( tr_session *, tr_address * );29 int tr_dhtInit( tr_session *, const tr_address * ); 30 30 void tr_dhtUninit( tr_session * ); 31 tr_bool tr_dhtEnabled( consttr_session * );32 tr_port tr_dhtPort ( consttr_session * );33 int tr_dhtStatus( tr_session *, int * setme_nodeCount );31 tr_bool tr_dhtEnabled( tr_session * ); 32 tr_port tr_dhtPort ( tr_session * ); 33 int tr_dhtStatus( tr_session *, int af, int * setme_nodeCount ); 34 34 const char *tr_dhtPrintableStatus(int status); 35 35 int tr_dhtAddNode( tr_session *, const tr_address *, tr_port, tr_bool bootstrap ); 36 int tr_dhtAnnounce( tr_torrent *, tr_bool announce );36 int tr_dhtAnnounce( tr_torrent *, int af, tr_bool announce ); -
trunk/third-party/dht/CHANGES
r9323 r9549 1 22 November 2009: dht-0.11 2 3 * Implemented IPv6 support (BEP-32). 4 * Fixed a bug which could cause us to never mark a search as finished. 5 * Fixed a bug that could cause us to send incomplete lists in response to 6 find_nodes. 7 * Limit the number of hashes that we're willing to track. 8 * Made bucket maintenance slightly more aggressive. 9 * Produce on-the-wire error messages to give a hint to the other side. 10 * Added a bunch of options to dht-example to make it useful as 11 a bootstrap node. 12 * Send version "JC\0\0" when using dht-example. 13 1 14 18 October 2009: dht-0.10 2 15 -
trunk/third-party/dht/README
r9145 r9549 20 20 21 21 This must be called before using the library. You pass it a bound IPv4 22 datagram socket, and your node id, a 20-octet array that should be globally 23 unique. 22 datagram socket, a bound IPv6 datagram socket, and your node id, a 20-octet 23 array that should be globally unique. 24 25 If you're on a multi-homed host, you should bind the sockets to one of your 26 addresses. 24 27 25 28 Node ids must be well distributed, so you cannot just use your Bittorrent … … 28 31 idea to keep the id stable, so you may want to store it in stable storage 29 32 at client shutdown. 33 30 34 31 35 * dht_uninit … … 148 152 149 153 The callback function is called with 5 arguments. Closure is simply the 150 value that you passed to dht_periodic. Event is one of DHT_EVENT_VALUES, 151 which indicates that we have new values, or DHT_EVENT_SEARCH_DONE, which 152 indicates that a search has completed. In either case, info_hash is set to 153 the info-hash of the search. 154 value that you passed to dht_periodic. Event is one of DHT_EVENT_VALUES or 155 DHT_EVENT_VALUES6, which indicates that we have new values, or 156 DHT_EVENT_SEARCH_DONE or DHT_EVENT_SEARCH_DONE6, which indicates that 157 a search has completed. In either case, info_hash is set to the info-hash 158 of the search. 154 159 155 160 In the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact'' 156 format -- 6 bytes per node, 4 for the IP address and 2 for the port. It's 157 length in bytes is in data_len. 161 format -- 6 or 18 bytes per node. Its length in bytes is in data_len. 158 162 159 163 * dht_hash … … 187 191 keep both pieces. 188 192 189 IPv6 support is deliberately not included: designing a double-stack190 distributed hash table raises some tricky issues, and doing it naively may191 break connectivity for everyone.192 193 193 194 Juliusz Chroboczek -
trunk/third-party/dht/dht-example.c
r9323 r9549 21 21 22 22 #define MAX_BOOTSTRAP_NODES 20 23 static struct sockaddr_ inbootstrap_nodes[MAX_BOOTSTRAP_NODES];23 static struct sockaddr_storage bootstrap_nodes[MAX_BOOTSTRAP_NODES]; 24 24 static int num_bootstrap_nodes = 0; 25 25 … … 93 93 { 94 94 int i, rc, fd; 95 int s , port;95 int s = -1, s6 = -1, port; 96 96 int have_id = 0; 97 97 unsigned char myid[20]; 98 98 time_t tosleep = 0; 99 char *id_file = "dht-example.id"; 100 int opt; 101 int quiet = 0, ipv4 = 1, ipv6 = 1; 102 struct sockaddr_in sin; 103 struct sockaddr_in6 sin6; 104 105 memset(&sin, 0, sizeof(sin)); 106 sin.sin_family = AF_INET; 107 108 memset(&sin6, 0, sizeof(sin6)); 109 sin6.sin6_family = AF_INET6; 110 111 112 113 while(1) { 114 opt = getopt(argc, argv, "q46b:i:"); 115 if(opt < 0) 116 break; 117 118 switch(opt) { 119 case 'q': quiet = 1; break; 120 case '4': ipv6 = 0; break; 121 case '6': ipv4 = 0; break; 122 case 'b': { 123 char buf[16]; 124 int rc; 125 rc = inet_pton(AF_INET, optarg, buf); 126 if(rc == 1) { 127 memcpy(&sin.sin_addr, buf, 4); 128 break; 129 } 130 rc = inet_pton(AF_INET6, optarg, buf); 131 if(rc == 1) { 132 memcpy(&sin6.sin6_addr, buf, 16); 133 break; 134 } 135 goto usage; 136 } 137 break; 138 case 'i': 139 id_file = optarg; 140 break; 141 default: 142 goto usage; 143 } 144 } 99 145 100 146 /* Ids need to be distributed evenly, so you cannot just use your 101 147 bittorrent id. Either generate it randomly, or take the SHA-1 of 102 148 something. */ 103 fd = open( "dht-example.id", O_RDONLY);149 fd = open(id_file, O_RDONLY); 104 150 if(fd >= 0) { 105 151 rc = read(fd, myid, 20); … … 109 155 } 110 156 157 fd = open("/dev/urandom", O_RDONLY); 158 if(fd < 0) { 159 perror("open(random)"); 160 exit(1); 161 } 162 111 163 if(!have_id) { 112 fd = open("/dev/urandom", O_RDONLY); 113 if(fd < 0) { 114 perror("open(random)"); 115 exit(1); 116 } 164 int ofd; 165 117 166 rc = read(fd, myid, 20); 118 167 if(rc < 0) { … … 123 172 close(fd); 124 173 125 fd = open("dht-example.id", O_WRONLY | O_CREAT | O_TRUNC, 0666);126 if( fd >= 0) {127 rc = write( fd, myid, 20);174 ofd = open(id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); 175 if(ofd >= 0) { 176 rc = write(ofd, myid, 20); 128 177 if(rc < 20) 129 unlink("dht-example.id"); 130 close(fd); 131 } 132 } 178 unlink(id_file); 179 close(ofd); 180 } 181 } 182 183 { 184 unsigned seed; 185 read(fd, &seed, sizeof(seed)); 186 srandom(seed); 187 } 188 189 close(fd); 133 190 134 191 if(argc < 2) 135 192 goto usage; 136 193 137 i = 1;194 i = optind; 138 195 139 196 if(argc < i + 1) … … 147 204 struct addrinfo hints, *info, *infop; 148 205 memset(&hints, 0, sizeof(hints)); 149 hints.ai_family = AF_INET;150 206 hints.ai_socktype = SOCK_DGRAM; 151 rc = getaddrinfo(argv[i], NULL, &hints, &info); 207 if(!ipv6) 208 hints.ai_family = AF_INET; 209 else if(!ipv4) 210 hints.ai_family = AF_INET6; 211 else 212 hints.ai_family = 0; 213 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info); 152 214 if(rc != 0) { 153 215 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc)); … … 161 223 infop = info; 162 224 while(infop) { 163 if(infop->ai_addr->sa_family == AF_INET) { 164 struct sockaddr_in sin; 165 memcpy(&sin, infop->ai_addr, infop->ai_addrlen); 166 sin.sin_port = htons(atoi(argv[i])); 167 bootstrap_nodes[num_bootstrap_nodes] = sin; 168 num_bootstrap_nodes++; 169 } 225 memcpy(&bootstrap_nodes[num_bootstrap_nodes], 226 infop->ai_addr, infop->ai_addrlen); 170 227 infop = infop->ai_next; 228 num_bootstrap_nodes++; 171 229 } 172 230 freeaddrinfo(info); … … 177 235 /* If you set dht_debug to a stream, every action taken by the DHT will 178 236 be logged. */ 179 dht_debug = stdout; 180 181 /* We need an IPv4 socket, bound to a stable port. Rumour has it that 182 uTorrent works better when it is the same as your Bittorrent port. */ 183 s = socket(PF_INET, SOCK_DGRAM, 0); 184 if(s < 0) { 185 perror("socket"); 237 if(!quiet) 238 dht_debug = stdout; 239 240 /* We need an IPv4 and an IPv6 socket, bound to a stable port. Rumour 241 has it that uTorrent works better when it is the same as your 242 Bittorrent port. */ 243 if(ipv4) { 244 s = socket(PF_INET, SOCK_DGRAM, 0); 245 if(s < 0) { 246 perror("socket(IPv4)"); 247 } 248 } 249 250 if(ipv6) { 251 s6 = socket(PF_INET6, SOCK_DGRAM, 0); 252 if(s6 < 0) { 253 perror("socket(IPv6)"); 254 } 255 } 256 257 if(s < 0 && s6 < 0) { 258 fprintf(stderr, "Eek!"); 186 259 exit(1); 187 260 } 188 261 189 { 190 struct sockaddr_in sin; 191 memset(&sin, 0, sizeof(sin)); 192 sin.sin_family = AF_INET; 262 263 if(s >= 0) { 193 264 sin.sin_port = htons(port); 194 265 rc = bind(s, (struct sockaddr*)&sin, sizeof(sin)); 195 266 if(rc < 0) { 196 perror("bind ");267 perror("bind(IPv4)"); 197 268 exit(1); 198 269 } 199 270 } 200 271 272 if(s6 >= 0) { 273 int rc; 274 int val = 1; 275 276 rc = setsockopt(s6, IPPROTO_IPV6, IPV6_V6ONLY, 277 (char *)&val, sizeof(val)); 278 if(rc < 0) { 279 perror("setsockopt(IPV6_V6ONLY)"); 280 exit(1); 281 } 282 283 /* BEP-32 mandates that we should bind this socket to one of our 284 global IPv6 addresses. In this simple example, this only 285 happens if the user used the -b flag. */ 286 287 sin6.sin6_port = htons(port); 288 rc = bind(s6, (struct sockaddr*)&sin6, sizeof(sin6)); 289 if(rc < 0) { 290 perror("bind(IPv6)"); 291 exit(1); 292 } 293 } 294 201 295 /* Init the dht. This sets the socket into non-blocking mode. */ 202 rc = dht_init(s, myid, NULL);296 rc = dht_init(s, s6, myid, (unsigned char*)"JC\0\0"); 203 297 if(rc < 0) { 204 298 perror("dht_init"); … … 218 312 dht_insert_node. If the ids are incorrect, the DHT will recover. */ 219 313 for(i = 0; i < num_bootstrap_nodes; i++) { 220 dht_ping_node(s, &bootstrap_nodes[i]); 314 dht_ping_node((struct sockaddr*)&bootstrap_nodes[i], 315 sizeof(bootstrap_nodes[i])); 221 316 usleep(random() % 100000); 222 317 } … … 229 324 230 325 FD_ZERO(&readfds); 231 FD_SET(s, &readfds); 232 rc = select(s + 1, &readfds, NULL, NULL, &tv); 326 if(s >= 0) 327 FD_SET(s, &readfds); 328 if(s6 >= 0) 329 FD_SET(s6, &readfds); 330 rc = select(s > s6 ? s + 1 : s6 + 1, &readfds, NULL, NULL, &tv); 233 331 if(rc < 0) { 234 332 if(errno != EINTR) { … … 241 339 break; 242 340 243 rc = dht_periodic( s,rc > 0, &tosleep, callback, NULL);341 rc = dht_periodic(rc > 0, &tosleep, callback, NULL); 244 342 if(rc < 0) { 245 343 if(errno == EINTR) { … … 254 352 255 353 /* This is how you trigger a search for a torrent hash. If port 256 (the third argument) is non-zero, it also performs an announce.354 (the second argument) is non-zero, it also performs an announce. 257 355 Since peers expire announced data after 30 minutes, it's a good 258 356 idea to reannounce every 28 minutes or so. */ 259 357 if(searching) { 260 dht_search(s, hash, 0, callback, NULL); 358 if(s >= 0) 359 dht_search(hash, 0, AF_INET, callback, NULL); 360 if(s6 >= 0) 361 dht_search(hash, 0, AF_INET6, callback, NULL); 261 362 searching = 0; 262 363 } … … 270 371 271 372 { 272 struct sockaddr_in sins[500]; 373 struct sockaddr_in sin[500]; 374 struct sockaddr_in6 sin6[500]; 375 int num = 500, num6 = 500; 273 376 int i; 274 i = dht_get_nodes(sin s, 500);275 printf("Found %d good nodes.\n", i);276 } 277 278 dht_uninit( s,1);377 i = dht_get_nodes(sin, &num, sin6, &num6); 378 printf("Found %d (%d + %d) good nodes.\n", i, num, num6); 379 } 380 381 dht_uninit(1); 279 382 return 0; 280 383 281 384 usage: 282 fprintf(stderr, "Foo!\n"); 385 printf("Usage: dht-example [-q] [-4] [-6] [-i filename] [-b address]...\n" 386 " port [address port]...\n"); 283 387 exit(1); 284 388 } -
trunk/third-party/dht/dht.c
r9524 r9549 58 58 59 59 /* We set sin_family to 0 to mark unused slots. */ 60 #if AF_INET == 0 60 #if AF_INET == 0 || AF_INET6 == 0 61 61 #error You lose 62 62 #endif … … 81 81 struct node { 82 82 unsigned char id[20]; 83 struct sockaddr_in sin; 83 struct sockaddr_storage ss; 84 int sslen; 84 85 time_t time; /* time of last message received */ 85 86 time_t reply_time; /* time of last correct reply received */ … … 90 91 91 92 struct bucket { 93 int af; 92 94 unsigned char first[20]; 93 95 int count; /* number of nodes */ 94 96 int time; /* time of last reply in this bucket */ 95 97 struct node *nodes; 96 struct sockaddr_in cached; /* the address of a likely candidate */ 98 struct sockaddr_storage cached; /* the address of a likely candidate */ 99 int cachedlen; 97 100 struct bucket *next; 98 101 }; … … 100 103 struct search_node { 101 104 unsigned char id[20]; 102 struct sockaddr_in sin; 105 struct sockaddr_storage ss; 106 int sslen; 103 107 time_t request_time; /* the time of the last unanswered request */ 104 108 time_t reply_time; /* the time of the last reply */ … … 117 121 struct search { 118 122 unsigned short tid; 123 int af; 119 124 time_t step_time; /* the time of the last search_step */ 120 125 unsigned char id[20]; … … 128 133 struct peer { 129 134 time_t time; 130 unsigned char ip[4]; 135 unsigned char ip[16]; 136 unsigned short len; 131 137 unsigned short port; 132 138 }; … … 137 143 #endif 138 144 145 /* The maximum number of hashes we're willing to track. */ 146 #ifndef DHT_MAX_HASHES 147 #define DHT_MAX_HASHES 16384 148 #endif 149 139 150 /* The maximum number of searches we keep data about. */ 140 151 #ifndef DHT_MAX_SEARCHES … … 149 160 struct storage { 150 161 unsigned char id[20]; 151 int numpeers; 152 int maxpeers; 162 int numpeers, maxpeers; 153 163 struct peer *peers; 154 164 struct storage *next; 155 165 }; 156 166 157 static int send_ping( int s,struct sockaddr *sa, int salen,167 static int send_ping(struct sockaddr *sa, int salen, 158 168 const unsigned char *tid, int tid_len); 159 static int send_pong( int s,struct sockaddr *sa, int salen,169 static int send_pong(struct sockaddr *sa, int salen, 160 170 const unsigned char *tid, int tid_len); 161 static int send_find_node( int s,struct sockaddr *sa, int salen,171 static int send_find_node(struct sockaddr *sa, int salen, 162 172 const unsigned char *tid, int tid_len, 163 const unsigned char *target, int confirm);164 static int send_nodes_peers( int s,struct sockaddr *sa, int salen,173 const unsigned char *target, int want, int confirm); 174 static int send_nodes_peers(struct sockaddr *sa, int salen, 165 175 const unsigned char *tid, int tid_len, 166 176 const unsigned char *nodes, int nodes_len, 167 struct peer *peers1, int numpeers1,168 struct peer *peers2, int numpeers2,177 const unsigned char *nodes6, int nodes6_len, 178 int af, struct storage *st, 169 179 const unsigned char *token, int token_len); 170 static int send_closest_nodes( int s,struct sockaddr *sa, int salen,180 static int send_closest_nodes(struct sockaddr *sa, int salen, 171 181 const unsigned char *tid, int tid_len, 172 const unsigned char *id, 173 struct peer *peers1, int numpeers1, 174 struct peer *peers2, int numpeers2, 182 const unsigned char *id, int want, 183 int af, struct storage *st, 175 184 const unsigned char *token, int token_len); 176 static int send_get_peers( int s,struct sockaddr *sa, int salen,185 static int send_get_peers(struct sockaddr *sa, int salen, 177 186 unsigned char *tid, int tid_len, 178 unsigned char *infohash, int confirm);179 static int send_announce_peer( int s,struct sockaddr *sa, int salen,187 unsigned char *infohash, int want, int confirm); 188 static int send_announce_peer(struct sockaddr *sa, int salen, 180 189 unsigned char *tid, int tid_len, 181 190 unsigned char *infohas, unsigned short port, 182 191 unsigned char *token, int token_len, int confirm); 183 int send_peer_announced(int s, struct sockaddr *sa, int salen, 184 unsigned char *tid, int tid_len); 185 186 #define REPLY 0 187 #define PING 1 188 #define FIND_NODE 2 189 #define GET_PEERS 3 190 #define ANNOUNCE_PEER 4 192 static int send_peer_announced(struct sockaddr *sa, int salen, 193 unsigned char *tid, int tid_len); 194 static int send_error(struct sockaddr *sa, int salen, 195 unsigned char *tid, int tid_len, 196 int code, const char *message); 197 198 #define ERROR 0 199 #define REPLY 1 200 #define PING 2 201 #define FIND_NODE 3 202 #define GET_PEERS 4 203 #define ANNOUNCE_PEER 5 204 205 #define WANT4 1 206 #define WANT6 2 207 191 208 static int parse_message(const unsigned char *buf, int buflen, 192 209 unsigned char *tid_return, int *tid_len, … … 197 214 unsigned char *token_return, int *token_len, 198 215 unsigned char *nodes_return, int *nodes_len, 199 const unsigned char *values_return, int *values_len); 216 unsigned char *nodes6_return, int *nodes6_len, 217 unsigned char *values_return, int *values_len, 218 unsigned char *values6_return, int *values6_len, 219 int *want_return); 200 220 201 221 static const unsigned char zeroes[20] = {0}; … … 205 225 0xFF, 0xFF, 0xFF, 0xFF 206 226 }; 227 228 static int dht_socket = -1; 229 static int dht_socket6 = -1; 230 207 231 static time_t search_time; 208 232 static time_t confirm_nodes_time; … … 216 240 217 241 static struct bucket *buckets = NULL; 242 static struct bucket *buckets6 = NULL; 218 243 static struct storage *storage; 244 static int numstorage; 219 245 220 246 static struct search *searches = NULL; … … 227 253 #define DHT_MAX_BLACKLISTED 10 228 254 #endif 229 static struct sockaddr_ inblacklist[DHT_MAX_BLACKLISTED];255 static struct sockaddr_storage blacklist[DHT_MAX_BLACKLISTED]; 230 256 int next_blacklisted; 231 257 232 258 static struct timeval now; 233 static time_t mybucket_grow_time ;259 static time_t mybucket_grow_time, mybucket6_grow_time; 234 260 static time_t expire_stuff_time; 235 261 … … 356 382 357 383 static struct bucket * 358 find_bucket(unsigned const char *id) 359 { 360 struct bucket *b = buckets; 384 find_bucket(unsigned const char *id, int af) 385 { 386 struct bucket *b = af == AF_INET ? buckets : buckets6; 387 388 if(b == NULL) 389 return NULL; 361 390 362 391 while(1) { … … 372 401 previous_bucket(struct bucket *b) 373 402 { 374 struct bucket *p = b uckets;403 struct bucket *p = b->af == AF_INET ? buckets : buckets6; 375 404 376 405 if(b == p) … … 388 417 /* Every bucket contains an unordered list of nodes. */ 389 418 static struct node * 390 find_node(const unsigned char *id )391 { 392 struct bucket *b = find_bucket(id );419 find_node(const unsigned char *id, int af) 420 { 421 struct bucket *b = find_bucket(id, af); 393 422 struct node *n; 394 423 395 424 if(b == NULL) 396 425 return NULL; 426 397 427 n = b->nodes; 398 428 while(n) { … … 459 489 id_return[i] = random() & 0xFF; 460 490 return 1; 461 } 491 } 462 492 463 493 /* Insert a new node into a bucket. */ … … 465 495 insert_node(struct node *node) 466 496 { 467 struct bucket *b = find_bucket(node->id); 497 struct bucket *b = find_bucket(node->id, node->ss.ss_family); 498 499 if(b == NULL) 500 return NULL; 468 501 469 502 node->next = b->nodes; … … 509 542 /* Every bucket caches the address of a likely node. Ping it. */ 510 543 static int 511 send_cached_ping(int s, struct bucket *b) 512 { 544 send_cached_ping(struct bucket *b) 545 { 546 unsigned char tid[4]; 513 547 int rc; 514 548 /* We set family to 0 when there's no cached node. */ 515 if(b->cached.sin_family == AF_INET) { 516 unsigned char tid[4]; 517 debugf("Sending ping to cached node.\n"); 518 make_tid(tid, "pn", 0); 519 rc = send_ping(s, (struct sockaddr*)&b->cached, 520 sizeof(struct sockaddr_in), 521 tid, 4); 522 b->cached.sin_family = 0; 523 return rc; 524 } 525 return 0; 549 if(b->cached.ss_family == 0) 550 return 0; 551 552 debugf("Sending ping to cached node.\n"); 553 make_tid(tid, "pn", 0); 554 rc = send_ping((struct sockaddr*)&b->cached, b->cachedlen, tid, 4); 555 b->cached.ss_family = 0; 556 b->cachedlen = 0; 557 return rc; 526 558 } 527 559 528 560 /* Split a bucket into two equal parts. */ 529 561 static struct bucket * 530 split_bucket( int s,struct bucket *b)562 split_bucket(struct bucket *b) 531 563 { 532 564 struct bucket *new; … … 543 575 return NULL; 544 576 545 send_cached_ping(s, b); 577 new->af = b->af; 578 579 send_cached_ping(b); 546 580 547 581 memcpy(new->first, new_id, 20); … … 564 598 /* Called whenever we send a request to a node. */ 565 599 static void 566 pinged( int s,struct node *n, struct bucket *b)600 pinged(struct node *n, struct bucket *b) 567 601 { 568 602 n->pinged++; 569 603 n->pinged_time = now.tv_sec; 570 604 if(n->pinged >= 3) 571 send_cached_ping( s, b ? b : find_bucket(n->id));605 send_cached_ping(b ? b : find_bucket(n->id, n->ss.ss_family)); 572 606 } 573 607 … … 575 609 the node sent a message, 2 if it sent us a reply. */ 576 610 static struct node * 577 new_node(int s, const unsigned char *id, struct sockaddr_in *sin, 578 int confirm) 579 { 580 struct bucket *b = find_bucket(id); 611 new_node(const unsigned char *id, struct sockaddr *sa, int salen, int confirm) 612 { 613 struct bucket *b = find_bucket(id, sa->sa_family); 581 614 struct node *n; 582 int mybucket = in_bucket(myid, b); 615 int mybucket, split; 616 617 if(b == NULL) 618 return NULL; 583 619 584 620 if(id_cmp(id, myid) == 0) 585 621 return NULL; 622 623 mybucket = in_bucket(myid, b); 586 624 587 625 if(confirm == 2) … … 593 631 if(confirm || n->time < now.tv_sec - 15 * 60) { 594 632 /* Known node. Update stuff. */ 595 n->sin = *sin;633 memcpy((struct sockaddr*)&n->ss, sa, salen); 596 634 if(confirm) 597 635 n->time = now.tv_sec; … … 612 650 if(n->pinged >= 3 && n->pinged_time < now.tv_sec - 15) { 613 651 memcpy(n->id, id, 20); 614 n->sin = *sin;652 memcpy((struct sockaddr*)&n->ss, sa, salen); 615 653 n->time = confirm ? now.tv_sec : 0; 616 654 n->reply_time = confirm >= 2 ? now.tv_sec : 0; 617 655 n->pinged_time = 0; 618 656 n->pinged = 0; 619 if(mybucket) 620 mybucket_grow_time = now.tv_sec; 657 if(mybucket) { 658 if(sa->sa_family == AF_INET) 659 mybucket_grow_time = now.tv_sec; 660 else 661 mybucket6_grow_time = now.tv_sec; 662 } 621 663 return n; 622 664 } … … 639 681 debugf("Sending ping to dubious node.\n"); 640 682 make_tid(tid, "pn", 0); 641 send_ping(s, 642 (struct sockaddr*)&n->sin, 643 sizeof(struct sockaddr_in), 683 send_ping((struct sockaddr*)&n->ss, n->sslen, 644 684 tid, 4); 645 685 n->pinged++; … … 651 691 } 652 692 653 /* If there's only one bucket, split even if there remain doubtful 654 nodes. This violates the spec, but it speeds up bootstrapping. */ 655 if(mybucket && (!dubious || buckets->next == NULL)) { 693 split = 0; 694 if(mybucket) { 695 if(!dubious) 696 split = 1; 697 /* If there's only one bucket, split eagerly. This is 698 incorrect unless there's more than 8 nodes in the DHT. */ 699 else if(b->af == AF_INET && buckets->next == NULL) 700 split = 1; 701 else if(b->af == AF_INET6 && buckets6->next == NULL) 702 split = 1; 703 } 704 705 if(split) { 656 706 debugf("Splitting.\n"); 657 b = split_bucket(s, b); 658 mybucket_grow_time = now.tv_sec; 659 return new_node(s, id, sin, confirm); 707 b = split_bucket(b); 708 if(sa->sa_family == AF_INET) 709 mybucket_grow_time = now.tv_sec; 710 else 711 mybucket6_grow_time = now.tv_sec; 712 return new_node(id, sa, salen, confirm); 660 713 } 661 714 662 715 /* No space for this node. Cache it away for later. */ 663 if(confirm || b->cached.sin_family == 0) 664 b->cached = *sin; 716 if(confirm || b->cached.ss_family == 0) { 717 memcpy(&b->cached, sa, salen); 718 b->cachedlen = salen; 719 } 665 720 666 721 return NULL; … … 672 727 return NULL; 673 728 memcpy(n->id, id, 20); 674 n->sin = *sin; 729 memcpy(&n->ss, sa, salen); 730 n->sslen = salen; 675 731 n->time = confirm ? now.tv_sec : 0; 676 732 n->reply_time = confirm >= 2 ? now.tv_sec : 0; … … 678 734 b->nodes = n; 679 735 b->count++; 680 if(mybucket) 681 mybucket_grow_time = now.tv_sec; 736 if(mybucket) { 737 if(sa->sa_family == AF_INET) 738 mybucket_grow_time = now.tv_sec; 739 else 740 mybucket6_grow_time = now.tv_sec; 741 } 682 742 return n; 683 743 } … … 687 747 recover as soon as we find better ones. */ 688 748 static int 689 expire_buckets(int s) 690 { 691 struct bucket *b = buckets; 692 749 expire_buckets(struct bucket *b) 750 { 693 751 while(b) { 694 752 struct node *n, *p; … … 716 774 717 775 if(changed) 718 send_cached_ping( s,b);776 send_cached_ping(b); 719 777 720 778 b = b->next; … … 730 788 731 789 static struct search * 732 find_search(unsigned short tid )790 find_search(unsigned short tid, int af) 733 791 { 734 792 struct search *sr = searches; 735 793 while(sr) { 736 if(sr->tid == tid )794 if(sr->tid == tid && sr->af == af) 737 795 return sr; 738 796 sr = sr->next; … … 746 804 747 805 static int 748 insert_search_node(unsigned char *id, struct sockaddr_in *sin, 806 insert_search_node(unsigned char *id, 807 struct sockaddr *sa, int salen, 749 808 struct search *sr, int replied, 750 809 unsigned char *token, int token_len) … … 752 811 struct search_node *n; 753 812 int i, j; 813 814 if(sa->sa_family != sr->af) { 815 debugf("Attempted to insert node in the wrong family.\n"); 816 return 0; 817 } 754 818 755 819 for(i = 0; i < sr->numnodes; i++) { … … 778 842 779 843 found: 780 n->sin = *sin; 844 memcpy(&n->ss, sa, salen); 845 n->sslen = salen; 781 846 782 847 if(replied) { … … 830 895 /* This must always return 0 or 1, never -1, not even on failure (see below). */ 831 896 static int 832 search_send_get_peers( int s,struct search *sr, struct search_node *n)897 search_send_get_peers(struct search *sr, struct search_node *n) 833 898 { 834 899 struct node *node; … … 850 915 debugf("Sending get_peers.\n"); 851 916 make_tid(tid, "gp", sr->tid); 852 send_get_peers(s, (struct sockaddr*)&n->sin, 853 sizeof(struct sockaddr_in), tid, 4, sr->id, 917 send_get_peers((struct sockaddr*)&n->ss, n->sslen, tid, 4, sr->id, -1, 854 918 n->reply_time >= now.tv_sec - 15); 855 919 n->pinged++; … … 857 921 /* If the node happens to be in our main routing table, mark it 858 922 as pinged. */ 859 node = find_node(n->id );860 if(node) pinged( s,node, NULL);923 node = find_node(n->id, n->ss.ss_family); 924 if(node) pinged(node, NULL); 861 925 return 1; 862 926 } … … 865 929 further requests. */ 866 930 static void 867 search_step( int s,struct search *sr, dht_callback *callback, void *closure)931 search_step(struct search *sr, dht_callback *callback, void *closure) 868 932 { 869 933 int i, j; … … 905 969 debugf("Sending announce_peer.\n"); 906 970 make_tid(tid, "ap", sr->tid); 907 send_announce_peer(s, 908 (struct sockaddr*)&n->sin, 909 sizeof(struct sockaddr_in), 971 send_announce_peer((struct sockaddr*)&n->ss, 972 sizeof(struct sockaddr_storage), 910 973 tid, 4, sr->id, sr->port, 911 974 n->token, n->token_len, … … 913 976 n->pinged++; 914 977 n->request_time = now.tv_sec; 915 node = find_node(n->id );916 if(node) pinged( s,node, NULL);978 node = find_node(n->id, n->ss.ss_family); 979 if(node) pinged(node, NULL); 917 980 } 918 981 j++; … … 930 993 j = 0; 931 994 for(i = 0; i < sr->numnodes; i++) { 932 j += search_send_get_peers(s , sr, &sr->nodes[i]);995 j += search_send_get_peers(sr, &sr->nodes[i]); 933 996 if(j >= 3) 934 997 break; … … 940 1003 sr->done = 1; 941 1004 if(callback) 942 (*callback)(closure, DHT_EVENT_SEARCH_DONE, sr->id, NULL, 0); 1005 (*callback)(closure, 1006 sr->af == AF_INET ? 1007 DHT_EVENT_SEARCH_DONE : DHT_EVENT_SEARCH_DONE6, 1008 sr->id, NULL, 0); 943 1009 sr->step_time = now.tv_sec; 944 1010 } … … 984 1050 n = b->nodes; 985 1051 while(n) { 986 insert_search_node(n->id, &n->sin, sr, 0, NULL, 0); 1052 insert_search_node(n->id, (struct sockaddr*)&n->ss, n->sslen, 1053 sr, 0, NULL, 0); 987 1054 n = n->next; 988 1055 } … … 991 1058 /* Start a search. If port is non-zero, perform an announce when the 992 1059 search is complete. */ 993 int 994 dht_search( int s, const unsigned char *id, int port,1060 int 1061 dht_search(const unsigned char *id, int port, int af, 995 1062 dht_callback *callback, void *closure) 996 1063 { 997 1064 struct search *sr; 998 struct bucket *b; 1065 struct bucket *b = find_bucket(id, af); 1066 1067 if(b == NULL) { 1068 errno = EAFNOSUPPORT; 1069 return -1; 1070 } 999 1071 1000 1072 sr = searches; 1001 1073 while(sr) { 1002 if( id_cmp(sr->id, id) == 0)1074 if(sr->af == af && id_cmp(sr->id, id) == 0) 1003 1075 break; 1004 1076 sr = sr->next; … … 1030 1102 return -1; 1031 1103 } 1104 sr->af = af; 1032 1105 sr->tid = search_id++; 1033 1106 sr->step_time = 0; … … 1039 1112 sr->port = port; 1040 1113 1041 b = find_bucket(id);1042 1114 insert_search_bucket(b, sr); 1043 1115 … … 1050 1122 } 1051 1123 if(sr->numnodes < SEARCH_NODES) 1052 insert_search_bucket(find_bucket(myid ), sr);1053 1054 search_step(s , sr, callback, closure);1124 insert_search_bucket(find_bucket(myid, af), sr); 1125 1126 search_step(sr, callback, closure); 1055 1127 search_time = now.tv_sec; 1056 1128 return 1; … … 1074 1146 1075 1147 static int 1076 storage_store(const unsigned char *id, const unsigned char *ip, 1077 unsigned short port) 1078 { 1079 int i; 1148 storage_store(const unsigned char *id, struct sockaddr *sa) 1149 { 1150 int i, len; 1080 1151 struct storage *st = storage; 1152 unsigned char *ip; 1153 unsigned short port; 1081 1154 1082 1155 st = find_storage(id); 1083 1156 1084 1157 if(st == NULL) { 1158 if(numstorage >= DHT_MAX_HASHES) 1159 return -1; 1085 1160 st = calloc(1, sizeof(struct storage)); 1086 1161 if(st == NULL) return -1; … … 1088 1163 st->next = storage; 1089 1164 storage = st; 1165 numstorage++; 1166 } 1167 1168 if(sa->sa_family == AF_INET) { 1169 struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1170 ip = (unsigned char*)&sin->sin_addr; 1171 len = 4; 1172 port = ntohs(sin->sin_port); 1173 } else if(sa->sa_family == AF_INET6) { 1174 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1175 ip = (unsigned char*)&sin6->sin6_addr; 1176 len = 16; 1177 port = ntohs(sin6->sin6_port); 1090 1178 } 1091 1179 1092 1180 for(i = 0; i < st->numpeers; i++) { 1093 if(st->peers[i].port == port && memcmp(st->peers[i].ip, ip, 4) == 0) 1181 if(st->peers[i].port == port && st->peers[i].len == len && 1182 memcmp(st->peers[i].ip, ip, len) == 0) 1094 1183 break; 1095 1184 } 1185 1096 1186 if(i < st->numpeers) { 1097 1187 /* Already there, only need to refresh */ … … 1104 1194 struct peer *new_peers; 1105 1195 int n; 1106 if(st->maxpeers > DHT_MAX_PEERS / 2)1196 if(st->maxpeers >= DHT_MAX_PEERS) 1107 1197 return 0; 1108 1198 n = st->maxpeers == 0 ? 2 : 2 * st->maxpeers; 1199 n = MIN(n, DHT_MAX_PEERS); 1109 1200 new_peers = realloc(st->peers, n * sizeof(struct peer)); 1110 1201 if(new_peers == NULL) … … 1115 1206 p = &st->peers[st->numpeers++]; 1116 1207 p->time = now.tv_sec; 1117 memcpy(p->ip, ip, 4); 1208 p->len = len; 1209 memcpy(p->ip, ip, len); 1118 1210 p->port = port; 1119 1211 return 1; … … 1148 1240 else 1149 1241 st = storage; 1242 numstorage--; 1243 if(numstorage < 0) { 1244 debugf("Eek... numstorage became negative.\n"); 1245 numstorage = 0; 1246 } 1150 1247 } else { 1151 1248 previous = st; … … 1158 1255 /* We've just found out that a node is buggy. */ 1159 1256 static void 1160 broken_node( int s, const unsigned char *id, struct sockaddr_in *sin)1257 broken_node(const unsigned char *id, struct sockaddr *sa, int salen) 1161 1258 { 1162 1259 int i; … … 1168 1265 struct search *sr; 1169 1266 /* Make the node easy to discard. */ 1170 n = find_node(id );1267 n = find_node(id, sa->sa_family); 1171 1268 if(n) { 1172 1269 n->pinged = 3; 1173 pinged( s,n, NULL);1270 pinged(n, NULL); 1174 1271 } 1175 1272 /* Discard it from any searches in progress. */ … … 1183 1280 } 1184 1281 /* And make sure we don't hear from it again. */ 1185 blacklist[next_blacklisted] = *sin;1282 memcpy(&blacklist[next_blacklisted], sa, salen); 1186 1283 next_blacklisted = (next_blacklisted + 1) % DHT_MAX_BLACKLISTED; 1187 1284 } … … 1208 1305 1209 1306 static void 1210 make_token(const unsigned char *ipv4, unsigned short port, int old, 1211 unsigned char *token_return) 1212 { 1307 make_token(struct sockaddr *sa, int old, unsigned char *token_return) 1308 { 1309 void *ip; 1310 int iplen; 1311 unsigned short port; 1312 1313 if(sa->sa_family == AF_INET) { 1314 struct sockaddr_in *sin = (struct sockaddr_in*)sa; 1315 ip = &sin->sin_addr; 1316 iplen = 4; 1317 port = htons(sin->sin_port); 1318 } else if(sa->sa_family == AF_INET6) { 1319 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; 1320 ip = &sin6->sin6_addr; 1321 iplen = 16; 1322 port = htons(sin6->sin6_port); 1323 } else { 1324 abort(); 1325 } 1326 1213 1327 dht_hash(token_return, TOKEN_SIZE, 1214 1328 old ? oldsecret : secret, sizeof(secret), 1215 ipv4, 4, 1216 (unsigned char*)&port, 2); 1329 ip, iplen, (unsigned char*)&port, 2); 1217 1330 } 1218 1331 static int 1219 token_match(unsigned char *token, int token_len, 1220 const unsigned char *ipv4, unsigned short port) 1332 token_match(unsigned char *token, int token_len, struct sockaddr *sa) 1221 1333 { 1222 1334 unsigned char t[TOKEN_SIZE]; 1223 1335 if(token_len != TOKEN_SIZE) 1224 1336 return 0; 1225 make_token( ipv4, port, 0, t);1337 make_token(sa, 0, t); 1226 1338 if(memcmp(t, token, TOKEN_SIZE) == 0) 1227 1339 return 1; 1228 make_token( ipv4, port, 1, t);1340 make_token(sa, 1, t); 1229 1341 if(memcmp(t, token, TOKEN_SIZE) == 0) 1230 1342 return 1; … … 1233 1345 1234 1346 int 1235 dht_nodes(int *good_return, int *dubious_return, int *cached_return,1347 dht_nodes(int af, int *good_return, int *dubious_return, int *cached_return, 1236 1348 int *incoming_return) 1237 1349 { 1238 1350 int good = 0, dubious = 0, cached = 0, incoming = 0; 1239 struct bucket *b = buckets; 1351 struct bucket *b = af == AF_INET ? buckets : buckets6; 1352 1240 1353 while(b) { 1241 1354 struct node *n = b->nodes; … … 1250 1363 n = n->next; 1251 1364 } 1252 if(b->cached.s in_family == AF_INET)1365 if(b->cached.ss_family > 0) 1253 1366 cached++; 1254 1367 b = b->next; … … 1264 1377 return good + dubious; 1265 1378 } 1266 1379 1380 static void 1381 dump_bucket(FILE *f, struct bucket *b) 1382 { 1383 struct node *n = b->nodes; 1384 fprintf(f, "Bucket "); 1385 print_hex(f, b->first, 20); 1386 fprintf(f, " count %d age %d%s%s:\n", 1387 b->count, (int)(now.tv_sec - b->time), 1388 in_bucket(myid, b) ? " (mine)" : "", 1389 b->cached.ss_family ? " (cached)" : ""); 1390 while(n) { 1391 char buf[512]; 1392 unsigned short port; 1393 fprintf(f, " Node "); 1394 print_hex(f, n->id, 20); 1395 if(n->ss.ss_family == AF_INET) { 1396 struct sockaddr_in *sin = (struct sockaddr_in*)&n->ss; 1397 inet_ntop(AF_INET, &sin->sin_addr, buf, 512); 1398 port = ntohs(sin->sin_port); 1399 } else if(n->ss.ss_family == AF_INET6) { 1400 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&n->ss; 1401 inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 512); 1402 port = ntohs(sin6->sin6_port); 1403 } else { 1404 snprintf(buf, 512, "unknown(%d)", n->ss.ss_family); 1405 port = 0; 1406 } 1407 1408 if(n->ss.ss_family == AF_INET6) 1409 fprintf(f, " [%s]:%d ", buf, port); 1410 else 1411 fprintf(f, " %s:%d ", buf, port); 1412 if(n->time != n->reply_time) 1413 fprintf(f, "age %ld, %ld", 1414 (long)(now.tv_sec - n->time), 1415 (long)(now.tv_sec - n->reply_time)); 1416 else 1417 fprintf(f, "age %ld", (long)(now.tv_sec - n->time)); 1418 if(n->pinged) 1419 fprintf(f, " (%d)", n->pinged); 1420 if(node_good(n)) 1421 fprintf(f, " (good)"); 1422 fprintf(f, "\n"); 1423 n = n->next; 1424 } 1425 1426 } 1267 1427 1268 1428 void … … 1270 1430 { 1271 1431 int i; 1272 struct bucket *b = buckets;1432 struct bucket *b; 1273 1433 struct storage *st = storage; 1274 1434 struct search *sr = searches; … … 1277 1437 print_hex(f, myid, 20); 1278 1438 fprintf(f, "\n"); 1439 1440 b = buckets; 1279 1441 while(b) { 1280 struct node *n = b->nodes; 1281 fprintf(f, "Bucket "); 1282 print_hex(f, b->first, 20); 1283 fprintf(f, " count %d age %d%s%s:\n", 1284 b->count, (int)(now.tv_sec - b->time), 1285 in_bucket(myid, b) ? " (mine)" : "", 1286 b->cached.sin_family ? " (cached)" : ""); 1287 while(n) { 1288 char buf[512]; 1289 fprintf(f, " Node "); 1290 print_hex(f, n->id, 20); 1291 inet_ntop(AF_INET, &n->sin.sin_addr, buf, 512); 1292 fprintf(f, " %s:%d ", buf, ntohs(n->sin.sin_port)); 1293 if(n->time != n->reply_time) 1294 fprintf(f, "age %ld, %ld", 1295 (long)(now.tv_sec - n->time), 1296 (long)(now.tv_sec - n->reply_time)); 1297 else 1298 fprintf(f, "age %ld", (long)(now.tv_sec - n->time)); 1299 if(n->pinged) 1300 fprintf(f, " (%d)", n->pinged); 1301 if(node_good(n)) 1302 fprintf(f, " (good)"); 1303 fprintf(f, "\n"); 1304 n = n->next; 1305 } 1442 dump_bucket(f, b); 1306 1443 b = b->next; 1307 1444 } 1445 1446 fprintf(f, "\n"); 1447 1448 b = buckets6; 1449 while(b) { 1450 dump_bucket(f, b); 1451 b = b->next; 1452 } 1453 1308 1454 while(sr) { 1309 fprintf(f, "\nSearch id");1455 fprintf(f, "\nSearch%s id ", sr->af == AF_INET6 ? " (IPv6)" : ""); 1310 1456 print_hex(f, sr->id, 20); 1311 1457 fprintf(f, " age %d%s\n", (int)(now.tv_sec - sr->step_time), … … 1322 1468 fprintf(f, " (%d)", n->pinged); 1323 1469 fprintf(f, "%s%s.\n", 1324 find_node(n->id) ? " (known)" : "",1325 n->replied ? " (replied)" : "");1470 find_node(n->id, AF_INET) ? " (known)" : "", 1471 n->replied ? " (replied)" : ""); 1326 1472 } 1327 1473 sr = sr->next; 1328 1474 } 1329 1475 1330 1331 1476 while(st) { 1332 1477 fprintf(f, "\nStorage "); … … 1334 1479 fprintf(f, " %d/%d nodes:", st->numpeers, st->maxpeers); 1335 1480 for(i = 0; i < st->numpeers; i++) { 1336 char buf[20]; 1337 inet_ntop(AF_INET, st->peers[i].ip, buf, 20); 1481 char buf[100]; 1482 if(st->peers[i].len == 4) { 1483 inet_ntop(AF_INET, st->peers[i].ip, buf, 100); 1484 } else if(st->peers[i].len == 16) { 1485 buf[0] = '['; 1486 inet_ntop(AF_INET6, st->peers[i].ip, buf + 1, 98); 1487 strcat(buf, "]"); 1488 } else { 1489 strcpy(buf, "???"); 1490 } 1338 1491 fprintf(f, " %s:%u (%ld)", 1339 1492 buf, st->peers[i].port, … … 1342 1495 st = st->next; 1343 1496 } 1344 1497 1345 1498 fprintf(f, "\n\n"); 1346 1499 fflush(f); … … 1348 1501 1349 1502 int 1350 dht_init(int s, const unsigned char *id, const unsigned char *v)1503 dht_init(int s, int s6, const unsigned char *id, const unsigned char *v) 1351 1504 { 1352 1505 int rc; 1353 1506 1354 if( buckets) {1507 if(dht_socket >= 0 || dht_socket6 >= 0 || buckets || buckets6) { 1355 1508 errno = EBUSY; 1356 1509 return -1; 1357 1510 } 1358 1511 1359 buckets = calloc(sizeof(struct bucket), 1);1360 if(buckets == NULL)1361 return -1;1362 1363 1512 searches = NULL; 1364 1513 numsearches = 0; 1365 1514 1366 1515 storage = NULL; 1367 1368 rc = fcntl(s, F_GETFL, 0); 1369 if(rc < 0) 1370 goto fail; 1371 1372 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK)); 1373 if(rc < 0) 1374 goto fail; 1516 numstorage = 0; 1517 1518 if(s >= 0) { 1519 buckets = calloc(sizeof(struct bucket), 1); 1520 if(buckets == NULL) 1521 return -1; 1522 buckets->af = AF_INET; 1523 1524 rc = fcntl(s, F_GETFL, 0); 1525 if(rc < 0) 1526 goto fail; 1527 1528 rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK)); 1529 if(rc < 0) 1530 goto fail; 1531 } 1532 1533 if(s6 >= 0) { 1534 buckets6 = calloc(sizeof(struct bucket), 1); 1535 if(buckets6 == NULL) 1536 return -1; 1537 buckets6->af = AF_INET6; 1538 1539 rc = fcntl(s6, F_GETFL, 0); 1540 if(rc < 0) 1541 goto fail; 1542 1543 rc = fcntl(s6, F_SETFL, (rc | O_NONBLOCK)); 1544 if(rc < 0) 1545 goto fail; 1546 } 1375 1547 1376 1548 memcpy(myid, id, 20); … … 1386 1558 1387 1559 mybucket_grow_time = now.tv_sec; 1560 mybucket6_grow_time = now.tv_sec; 1388 1561 confirm_nodes_time = now.tv_sec + random() % 3; 1389 1562 … … 1401 1574 goto fail; 1402 1575 1403 expire_buckets(s); 1576 dht_socket = s; 1577 dht_socket6 = s6; 1578 1579 expire_buckets(buckets); 1580 expire_buckets(buckets6); 1404 1581 1405 1582 return 1; … … 1412 1589 1413 1590 int 1414 dht_uninit(int s, int dofree) 1415 { 1591 dht_uninit(int dofree) 1592 { 1593 if(dht_socket < 0) { 1594 errno = EINVAL; 1595 return -1; 1596 } 1597 1416 1598 if(!dofree) 1417 1599 return 1; … … 1462 1644 } 1463 1645 1646 static int 1647 neighbourhood_maintenance(int af) 1648 { 1649 unsigned char id[20]; 1650 struct bucket *b = find_bucket(myid, af); 1651 struct bucket *q; 1652 struct node *n; 1653 1654 if(b == NULL) 1655 return -1; 1656 1657 memcpy(id, myid, 20); 1658 id[19] = random() & 0xFF; 1659 q = b; 1660 if(q->next && (q->count == 0 || (random() & 7) == 0)) 1661 q = b->next; 1662 if(q->count == 0 || (random() & 7) == 0) { 1663 struct bucket *r; 1664 r = previous_bucket(b); 1665 if(r && r->count > 0) 1666 q = r; 1667 } 1668 1669 if(q) { 1670 int want = dht_socket >= 0 && dht_socket6 >= 0 ? (WANT4 | WANT6) : -1; 1671 n = random_node(q); 1672 if(n) { 1673 unsigned char tid[4]; 1674 debugf("Sending find_node for%s neighborhood maintenance.\n", 1675 af == AF_INET6 ? " IPv6" : ""); 1676 make_tid(tid, "fn", 0); 1677 send_find_node((struct sockaddr*)&n->ss, n->sslen, 1678 tid, 4, id, want, 1679 n->reply_time >= now.tv_sec - 15); 1680 pinged(n, q); 1681 } 1682 } 1683 return 1; 1684 } 1685 1686 static int 1687 bucket_maintenance(int af) 1688 { 1689 struct bucket *b; 1690 1691 b = af == AF_INET ? buckets : buckets6; 1692 1693 while(b) { 1694 struct bucket *q; 1695 if(b->time < now.tv_sec - 600) { 1696 /* This bucket hasn't seen any positive confirmation for a long 1697 time. Pick a random id in this bucket's range, and send 1698 a request to a random node. */ 1699 unsigned char id[20]; 1700 struct node *n; 1701 int rc; 1702 1703 rc = bucket_random(b, id); 1704 if(rc < 0) 1705 memcpy(id, b->first, 20); 1706 1707 q = b; 1708 /* If the bucket is empty, we try to fill it from a neighbour. 1709 We also sometimes do it gratuitiously to recover from 1710 buckets full of broken nodes. */ 1711 if(q->next && (q->count == 0 || (random() & 7) == 0)) 1712 q = b->next; 1713 if(q->count == 0 || (random() & 7) == 0) { 1714 struct bucket *r; 1715 r = previous_bucket(b); 1716 if(r && r->count > 0) 1717 q = r; 1718 } 1719 1720 if(q) { 1721 n = random_node(q); 1722 if(n) { 1723 unsigned char tid[4]; 1724 int want = -1; 1725 1726 if(dht_socket >= 0 && dht_socket6 >= 0) { 1727 struct bucket *otherbucket; 1728 otherbucket = 1729 find_bucket(id, af == AF_INET ? AF_INET6 : AF_INET); 1730 if(otherbucket && otherbucket->count < 8) 1731 /* The corresponding bucket in the other family 1732 is emptyish -- querying both is useful. */ 1733 want = WANT4 | WANT6; 1734 else if(random() % 37 == 0) 1735 /* Most of the time, this just adds overhead. 1736 However, it might help stitch back one of 1737 the DHTs after a network collapse, so query 1738 both, but only very occasionally. */ 1739 want = WANT4 | WANT6; 1740 } 1741 1742 debugf("Sending find_node for%s bucket maintenance.\n", 1743 af == AF_INET6 ? " IPv6" : ""); 1744 make_tid(tid, "fn", 0); 1745 send_find_node((struct sockaddr*)&n->ss, n->sslen, 1746 tid, 4, id, want, 1747 n->reply_time >= now.tv_sec - 15); 1748 pinged(n, q); 1749 /* In order to avoid sending queries back-to-back, 1750 give up for now and reschedule us soon. */ 1751 return 1; 1752 } 1753 } 1754 } 1755 b = b->next; 1756 } 1757 return 0; 1758 } 1759 1464 1760 int 1465 dht_periodic(int s, intavailable, time_t *tosleep,1761 dht_periodic(int available, time_t *tosleep, 1466 1762 dht_callback *callback, void *closure) 1467 1763 { 1764 int i; 1765 1468 1766 gettimeofday(&now, NULL); 1469 1767 1470 1768 if(available) { 1471 int rc, i,message;1769 int rc, message; 1472 1770 unsigned char tid[16], id[20], info_hash[20], target[20]; 1473 unsigned char buf[1536], nodes[256], token[128];1771 unsigned char buf[1536], nodes[256], nodes6[1024], token[128]; 1474 1772 int tid_len = 16, token_len = 128; 1475 int nodes_len = 256 ;1773 int nodes_len = 256, nodes6_len = 1024; 1476 1774 unsigned short port; 1477 unsigned char values[2048]; 1478 int values_len = 2048; 1479 struct sockaddr_in source; 1480 socklen_t source_len = sizeof(struct sockaddr_in); 1775 unsigned char values[2048], values6[2048]; 1776 int values_len = 2048, values6_len = 2048; 1777 int want, want4, want6; 1778 struct sockaddr_storage source_storage; 1779 struct sockaddr *source = (struct sockaddr*)&source_storage; 1780 socklen_t sourcelen = sizeof(source_storage); 1481 1781 unsigned short ttid; 1482 1782 1483 rc = recvfrom(s, buf, 1536, 0, 1484 (struct sockaddr*)&source, &source_len); 1485 if(rc < 0) { 1486 if(errno == EAGAIN) 1487 goto dontread; 1488 else 1489 return rc; 1490 } 1491 1492 if(source_len != sizeof(struct sockaddr_in)) { 1493 /* Hmm... somebody gave us an IPv6 socket. */ 1494 errno = EINVAL; 1495 return -1; 1496 } 1783 rc = -1; 1784 if(dht_socket >= 0) { 1785 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen); 1786 if(rc < 0 && errno != EAGAIN) { 1787 return rc; 1788 } 1789 } 1790 if(dht_socket6 >= 0 && rc < 0) { 1791 rc = recvfrom(dht_socket6, buf, 1536, 0, 1792 source, &sourcelen); 1793 if(rc < 0 && errno != EAGAIN) { 1794 return rc; 1795 } 1796 } 1797 1798 if(rc < 0 || sourcelen > sizeof(struct sockaddr_storage)) 1799 goto dontread; 1497 1800 1498 1801 for(i = 0; i < DHT_MAX_BLACKLISTED; i++) { 1499 if(blacklist[i].sin_family == AF_INET && 1500 blacklist[i].sin_port == source.sin_port && 1501 memcmp(&blacklist[i].sin_addr, &source.sin_addr, 4) == 0) { 1802 if(memcmp(&blacklist[i], source, sourcelen) == 0) { 1502 1803 debugf("Received packet from blacklisted node.\n"); 1503 1804 goto dontread; … … 1518 1819 message = parse_message(buf, rc, tid, &tid_len, id, info_hash, 1519 1820 target, &port, token, &token_len, 1520 nodes, &nodes_len, values, &values_len); 1521 if(id_cmp(id, zeroes) == 0) { 1522 debugf("Message with no id: "); 1821 nodes, &nodes_len, nodes6, &nodes6_len, 1822 values, &values_len, values6, &values6_len, 1823 &want); 1824 1825 if(message < 0 || message == ERROR || id_cmp(id, zeroes) == 0) { 1826 debugf("Unparseable message: "); 1523 1827 debug_printable(buf, rc); 1524 1828 debugf("\n"); … … 1537 1841 goto dontread; 1538 1842 } 1843 } 1844 1845 if(want > 0) { 1846 want4 = (want & WANT4); 1847 want6 = (want & WANT6); 1848 } else { 1849 want4 = source->sa_family == AF_INET; 1850 want6 = source->sa_family == AF_INET6; 1539 1851 } 1540 1852 … … 1548 1860 time-out all our searches that go through this node. 1549 1861 Kill it. */ 1550 broken_node( s, id, &source);1862 broken_node(id, source, sourcelen); 1551 1863 goto dontread; 1552 1864 } 1553 1865 if(tid_match(tid, "pn", NULL)) { 1554 1866 debugf("Pong!\n"); 1555 new_node( s, id, &source, 2);1867 new_node(id, source, sourcelen, 2); 1556 1868 } else if(tid_match(tid, "fn", NULL) || 1557 1869 tid_match(tid, "gp", NULL)) { … … 1560 1872 if(tid_match(tid, "gp", &ttid)) { 1561 1873 gp = 1; 1562 sr = find_search(ttid );1874 sr = find_search(ttid, source->sa_family); 1563 1875 } 1564 debugf("Nodes found (%d )%s!\n", nodes_len / 26,1876 debugf("Nodes found (%d+%d)%s!\n", nodes_len/26, nodes6_len/38, 1565 1877 gp ? " for get_peers" : ""); 1566 if(nodes_len % 26 != 0 ) {1878 if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) { 1567 1879 debugf("Unexpected length for node info!\n"); 1568 broken_node( s, id, &source);1880 broken_node(id, source, sourcelen); 1569 1881 } else if(gp && sr == NULL) { 1570 1882 debugf("Unknown search!\n"); 1571 new_node( s, id, &source, 1);1883 new_node(id, source, sourcelen, 1); 1572 1884 } else { 1573 1885 int i; 1574 new_node( s, id, &source, 2);1886 new_node(id, source, sourcelen, 2); 1575 1887 for(i = 0; i < nodes_len / 26; i++) { 1576 1888 unsigned char *ni = nodes + i * 26; … … 1582 1894 memcpy(&sin.sin_addr, ni + 20, 4); 1583 1895 memcpy(&sin.sin_port, ni + 24, 2); 1584 new_node(s, ni, &sin, 0); 1585 if(sr) { 1586 insert_search_node(ni, &sin, sr, 0, NULL, 0); 1896 new_node(ni, (struct sockaddr*)&sin, sizeof(sin), 0); 1897 if(sr && sr->af == AF_INET) { 1898 insert_search_node(ni, 1899 (struct sockaddr*)&sin, 1900 sizeof(sin), 1901 sr, 0, NULL, 0); 1902 } 1903 } 1904 for(i = 0; i < nodes6_len / 38; i++) { 1905 unsigned char *ni = nodes6 + i * 38; 1906 struct sockaddr_in6 sin6; 1907 if(id_cmp(ni, myid) == 0) 1908 continue; 1909 memset(&sin6, 0, sizeof(sin6)); 1910 sin6.sin6_family = AF_INET6; 1911 memcpy(&sin6.sin6_addr, ni + 20, 16); 1912 memcpy(&sin6.sin6_port, ni + 36, 2); 1913 new_node(ni, (struct sockaddr*)&sin6, sizeof(sin6), 0); 1914 if(sr && sr->af == AF_INET6) { 1915 insert_search_node(ni, 1916 (struct sockaddr*)&sin6, 1917 sizeof(sin6), 1918 sr, 0, NULL, 0); 1587 1919 } 1588 1920 } … … 1591 1923 requests in flight has decreased. Let's push 1592 1924 another request. */ 1593 search_send_get_peers(s , sr, NULL);1925 search_send_get_peers(sr, NULL); 1594 1926 } 1595 1927 if(sr) { 1596 insert_search_node(id, &source, sr,1928 insert_search_node(id, source, sourcelen, sr, 1597 1929 1, token, token_len); 1598 if(values_len > 0) { 1599 debugf("Got values (%d)!\n", values_len / 6); 1930 if(values_len > 0 || values6_len > 0) { 1931 debugf("Got values (%d+%d)!\n", 1932 values_len / 6, values6_len / 18); 1600 1933 if(callback) { 1601 (*callback)(closure, DHT_EVENT_VALUES, 1602 sr->id, (void*)values, values_len); 1934 if(values_len > 0) 1935 (*callback)(closure, DHT_EVENT_VALUES, sr->id, 1936 (void*)values, values_len); 1937 1938 if(values6_len > 0) 1939 (*callback)(closure, DHT_EVENT_VALUES6, sr->id, 1940 (void*)values6, values6_len); 1603 1941 } 1604 1942 } … … 1607 1945 struct search *sr; 1608 1946 debugf("Got reply to announce_peer.\n"); 1609 sr = find_search(ttid );1947 sr = find_search(ttid, source->sa_family); 1610 1948 if(!sr) { 1611 1949 debugf("Unknown search!\n"); 1612 new_node( s, id, &source, 1);1950 new_node(id, source, sourcelen, 1); 1613 1951 } else { 1614 1952 int i; 1615 new_node( s, id, &source, 2);1953 new_node(id, source, sourcelen, 2); 1616 1954 for(i = 0; i < sr->numnodes; i++) 1617 1955 if(id_cmp(sr->nodes[i].id, id) == 0) { … … 1623 1961 } 1624 1962 /* See comment for gp above. */ 1625 search_send_get_peers(s , sr, NULL);1963 search_send_get_peers(sr, NULL); 1626 1964 } 1627 1965 } else { … … 1633 1971 case PING: 1634 1972 debugf("Ping (%d)!\n", tid_len); 1635 new_node( s, id, &source, 1);1973 new_node(id, source, sourcelen, 1); 1636 1974 debugf("Sending pong.\n"); 1637 send_pong(s, (struct sockaddr*)&source, sizeof(source), 1638 tid, tid_len); 1975 send_pong(source, sourcelen, tid, tid_len); 1639 1976 break; 1640 1977 case FIND_NODE: 1641 1978 debugf("Find node!\n"); 1642 new_node( s, id, &source, 1);1643 debugf("Sending closest nodes .\n");1644 send_closest_nodes(s , (struct sockaddr*)&source, sizeof(source),1645 tid, tid_len, target, 1646 NULL, 0, NULL, 0, NULL, 0);1979 new_node(id, source, sourcelen, 1); 1980 debugf("Sending closest nodes (%d).\n", want); 1981 send_closest_nodes(source, sourcelen, 1982 tid, tid_len, target, want, 1983 0, NULL, NULL, 0); 1647 1984 break; 1648 1985 case GET_PEERS: 1649 1986 debugf("Get_peers!\n"); 1650 new_node( s, id, &source, 1);1987 new_node(id, source, sourcelen, 1); 1651 1988 if(id_cmp(info_hash, zeroes) == 0) { 1652 1989 debugf("Eek! Got get_peers with no info_hash.\n"); 1990 send_error(source, sourcelen, tid, tid_len, 1991 203, "Get_peers with no info_hash"); 1653 1992 break; 1654 1993 } else { 1655 1994 struct storage *st = find_storage(info_hash); 1656 1995 unsigned char token[TOKEN_SIZE]; 1657 make_token((unsigned char*)&source.sin_addr, 1658 ntohs(source.sin_port), 1659 0, token); 1996 make_token(source, 0, token); 1660 1997 if(st && st->numpeers > 0) { 1661 int i0, n0, n1; 1662 i0 = random() % st->numpeers; 1663 /* We treat peers as a circular list, and choose 50 1664 peers starting at i0. */ 1665 n0 = MIN(st->numpeers - i0, 50); 1666 n1 = n0 >= 50 ? 0 : MIN(50, i0); 1667 debugf("Sending found peers (%d).\n", n0 + n1); 1668 /* According to the spec, we should not be sending any 1669 nodes in this case. However, this avoids breaking 1670 searches if data is stored at the wrong place, and 1671 is also what libtorrent and uTorrent do. */ 1672 send_closest_nodes(s, (struct sockaddr*)&source, 1673 sizeof(source), tid, tid_len, 1674 info_hash, 1675 st->peers + i0, n0, 1676 st->peers, n1, 1677 token, TOKEN_SIZE); 1998 debugf("Sending found%s peers.\n", 1999 source->sa_family == AF_INET6 ? " IPv6" : ""); 2000 send_closest_nodes(source, sourcelen, 2001 tid, tid_len, 2002 info_hash, want, 2003 source->sa_family, st, 2004 token, TOKEN_SIZE); 1678 2005 } else { 1679 2006 debugf("Sending nodes for get_peers.\n"); 1680 send_closest_nodes(s, (struct sockaddr*)&source, 1681 sizeof(source), 1682 tid, tid_len, info_hash, 1683 NULL, 0, NULL, 0, 1684 token, TOKEN_SIZE); 2007 send_closest_nodes(source, sourcelen, 2008 tid, tid_len, info_hash, want, 2009 0, NULL, token, TOKEN_SIZE); 1685 2010 } 1686 2011 } … … 1688 2013 case ANNOUNCE_PEER: 1689 2014 debugf("Announce peer!\n"); 1690 new_node( s, id, &source, 1);2015 new_node(id, source, sourcelen, 1); 1691 2016 if(id_cmp(info_hash, zeroes) == 0) { 1692 2017 debugf("Announce_peer with no info_hash.\n"); 2018 send_error(source, sourcelen, tid, tid_len, 2019 203, "Announce_peer with no info_hash"); 1693 2020 break; 1694 2021 } 1695 if(!token_match(token, token_len, 1696 (unsigned char*)&source.sin_addr, 1697 ntohs(source.sin_port))) { 2022 if(!token_match(token, token_len, source)) { 1698 2023 debugf("Incorrect token for announce_peer.\n"); 2024 send_error(source, sourcelen, tid, tid_len, 2025 203, "Announce_peer with wrong token"); 1699 2026 break; 1700 2027 } 1701 2028 if(port == 0) { 1702 2029 debugf("Announce_peer with forbidden port %d.\n", port); 2030 send_error(source, sourcelen, tid, tid_len, 2031 203, "Announce_peer with forbidden port number"); 1703 2032 break; 1704 2033 } 1705 storage_store(info_hash, 1706 (unsigned char*)&source.sin_addr, port); 2034 storage_store(info_hash, source); 2035 /* Note that if storage_store failed, we lie to the requestor. 2036 This is to prevent them from backtracking, and hence 2037 polluting the DHT. */ 1707 2038 debugf("Sending peer announced.\n"); 1708 send_peer_announced(s, (struct sockaddr*)&source, 1709 sizeof(source), tid, tid_len); 2039 send_peer_announced(source, sourcelen, tid, tid_len); 1710 2040 } 1711 2041 } … … 1716 2046 1717 2047 if(now.tv_sec >= expire_stuff_time) { 1718 expire_buckets(s); 2048 expire_buckets(buckets); 2049 expire_buckets(buckets6); 1719 2050 expire_storage(); 1720 2051 expire_searches(); … … 1726 2057 while(sr) { 1727 2058 if(!sr->done && sr->step_time + 5 <= now.tv_sec) { 1728 search_step(s , sr, callback, closure);2059 search_step(sr, callback, closure); 1729 2060 } 1730 2061 sr = sr->next; 1731 2062 } 1732 2063 1733 2064 search_time = 0; 1734 2065 … … 1745 2076 1746 2077 if(now.tv_sec >= confirm_nodes_time) { 1747 struct bucket *b;1748 2078 int soon = 0; 1749 b = buckets; 1750 while(!soon && b) { 1751 struct bucket *q; 1752 if(b->time < now.tv_sec - 900) { 1753 /* This bucket hasn't seen any activity for a long 1754 time. Pick a random id in this bucket's range, and 1755 send a request to a random node. */ 1756 unsigned char id[20]; 1757 struct node *n; 1758 int rc; 1759 1760 rc = bucket_random(b, id); 1761 if(rc < 0) 1762 memcpy(id, b->first, 20); 1763 1764 q = b; 1765 /* If the bucket is empty, we try to fill it from 1766 a neighbour. We also sometimes do it gratuitiously 1767 to recover from buckets full of broken nodes. */ 1768 if(q->next && (q->count == 0 || random() % 7 == 0)) 1769 q = b->next; 1770 if(q->count == 0 || random() % 7 == 0) { 1771 struct bucket *r; 1772 r = previous_bucket(b); 1773 if(r && r->count > 0) 1774 q = r; 1775 } 1776 1777 if(q) { 1778 n = random_node(q); 1779 if(n) { 1780 unsigned char tid[4]; 1781 debugf("Sending find_node " 1782 "for bucket maintenance.\n"); 1783 make_tid(tid, "fn", 0); 1784 send_find_node(s, (struct sockaddr*)&n->sin, 1785 sizeof(struct sockaddr_in), 1786 tid, 4, id, 1787 n->reply_time >= now.tv_sec - 15); 1788 pinged(s, n, q); 1789 /* In order to avoid sending queries back-to-back, 1790 give up for now and reschedule us soon. */ 1791 soon = 1; 1792 } 1793 } 1794 } 1795 b = b->next; 1796 } 1797 1798 if(!soon && mybucket_grow_time >= now.tv_sec - 150) { 1799 /* We've seen updates to our own bucket recently. Try to 1800 improve our neighbourship. */ 1801 unsigned char id[20]; 1802 struct bucket *b, *q; 1803 struct node *n; 1804 1805 memcpy(id, myid, 20); 1806 id[19] = random() % 0xFF; 1807 b = find_bucket(myid); 1808 q = b; 1809 if(q->next && (q->count == 0 || random() % 7 == 0)) 1810 q = b->next; 1811 if(q->count == 0 || random() % 7 == 0) { 1812 struct bucket *r; 1813 r = previous_bucket(b); 1814 if(r && r->count > 0) 1815 q = r; 1816 } 1817 1818 if(q) { 1819 n = random_node(q); 1820 if(n) { 1821 unsigned char tid[4]; 1822 debugf("Sending find_node " 1823 "for neighborhood maintenance.\n"); 1824 make_tid(tid, "fn", 0); 1825 send_find_node(s, (struct sockaddr*)&n->sin, 1826 sizeof(struct sockaddr_in), 1827 tid, 4, id, 1828 n->reply_time >= now.tv_sec - 15); 1829 pinged(s, n, q); 1830 } 1831 } 1832 soon = 1; 1833 } 1834 1835 /* In order to maintain all buckets' age within 900 seconds, worst 1836 case is roughly 40 seconds, assuming the table is 22 bits deep. 2079 2080 soon |= bucket_maintenance(AF_INET); 2081 soon |= bucket_maintenance(AF_INET6); 2082 2083 if(!soon) { 2084 if(mybucket_grow_time >= now.tv_sec - 150) 2085 soon |= neighbourhood_maintenance(AF_INET); 2086 if(mybucket6_grow_time >= now.tv_sec - 150) 2087 soon |= neighbourhood_maintenance(AF_INET6); 2088 } 2089 2090 /* In order to maintain all buckets' age within 600 seconds, worst 2091 case is roughly 27 seconds, assuming the table is 22 bits deep. 1837 2092 We want to keep a margin for neighborhood maintenance, so keep 1838 this within 30seconds. */2093 this within 25 seconds. */ 1839 2094 if(soon) 1840 confirm_nodes_time = now.tv_sec + 10+ random() % 20;2095 confirm_nodes_time = now.tv_sec + 5 + random() % 20; 1841 2096 else 1842 2097 confirm_nodes_time = now.tv_sec + 60 + random() % 120; … … 1854 2109 *tosleep = search_time - now.tv_sec; 1855 2110 } 1856 1857 return find_bucket(myid)->count > 2;2111 2112 return 1; 1858 2113 } 1859 2114 1860 2115 int 1861 dht_get_nodes(struct sockaddr_in *sins, int num) 1862 { 1863 int i; 2116 dht_get_nodes(struct sockaddr_in *sin, int *num, 2117 struct sockaddr_in6 *sin6, int *num6) 2118 { 2119 int i, j; 1864 2120 struct bucket *b; 1865 2121 struct node *n; … … 1869 2125 /* For restoring to work without discarding too many nodes, the list 1870 2126 must start with the contents of our bucket. */ 1871 b = find_bucket(myid); 2127 b = find_bucket(myid, AF_INET); 2128 if(b == NULL) 2129 goto no_ipv4; 2130 1872 2131 n = b->nodes; 1873 while(n && i < num) {2132 while(n && i < *num) { 1874 2133 if(node_good(n)) { 1875 sin s[i] = n->sin;2134 sin[i] = *(struct sockaddr_in*)&n->ss; 1876 2135 i++; 1877 2136 } … … 1880 2139 1881 2140 b = buckets; 1882 while(b && i < num) {2141 while(b && i < *num) { 1883 2142 if(!in_bucket(myid, b)) { 1884 2143 n = b->nodes; 1885 while(n && i < num) {2144 while(n && i < *num) { 1886 2145 if(node_good(n)) { 1887 sin s[i] = n->sin;2146 sin[i] = *(struct sockaddr_in*)&n->ss; 1888 2147 i++; 1889 2148 } … … 1893 2152 b = b->next; 1894 2153 } 1895 return i; 2154 2155 no_ipv4: 2156 2157 j = 0; 2158 2159 b = find_bucket(myid, AF_INET6); 2160 if(b == NULL) 2161 goto no_ipv6; 2162 2163 n = b->nodes; 2164 while(n && j < *num6) { 2165 if(node_good(n)) { 2166 sin6[j] = *(struct sockaddr_in6*)&n->ss; 2167 j++; 2168 } 2169 n = n->next; 2170 } 2171 2172 b = buckets6; 2173 while(b && j < *num6) { 2174 if(!in_bucket(myid, b)) { 2175 n = b->nodes; 2176 while(n && j < *num6) { 2177 if(node_good(n)) { 2178 sin6[j] = *(struct sockaddr_in6*)&n->ss; 2179 j++; 2180 } 2181 n = n->next; 2182 } 2183 } 2184 b = b->next; 2185 } 2186 2187 no_ipv6: 2188 2189 *num = i; 2190 *num6 = j; 2191 return i + j; 1896 2192 } 1897 2193 1898 2194 int 1899 dht_insert_node( int s, const unsigned char *id, struct sockaddr_in *sin)2195 dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen) 1900 2196 { 1901 2197 struct node *n; 1902 n = new_node(s, id, sin, 0); 2198 2199 if(sa->sa_family != AF_INET) { 2200 errno = EAFNOSUPPORT; 2201 return -1; 2202 } 2203 2204 n = new_node(id, (struct sockaddr*)sa, salen, 0); 1903 2205 return !!n; 1904 2206 } 1905 2207 1906 2208 int 1907 dht_ping_node( int s, struct sockaddr_in *sin)2209 dht_ping_node(struct sockaddr *sa, int salen) 1908 2210 { 1909 2211 unsigned char tid[4]; 2212 1910 2213 debugf("Sending ping.\n"); 1911 2214 make_tid(tid, "pn", 0); 1912 return send_ping(s, (struct sockaddr*)sin, sizeof(struct sockaddr_in), 1913 tid, 4); 2215 return send_ping(sa, salen, tid, 4); 1914 2216 } 1915 2217 … … 1934 2236 } 1935 2237 2238 static int 2239 dht_send(const void *buf, size_t len, int flags, 2240 const struct sockaddr *sa, int salen) 2241 { 2242 int s; 2243 2244 if(salen == 0) 2245 abort(); 2246 2247 if(sa->sa_family == AF_INET) 2248 s = dht_socket; 2249 else if(sa->sa_family == AF_INET6) 2250 s = dht_socket6; 2251 else 2252 s = -1; 2253 2254 if(s < 0) { 2255 errno = EAFNOSUPPORT; 2256 return -1; 2257 } 2258 2259 return sendto(s, buf, len, flags, sa, salen); 2260 } 2261 1936 2262 int 1937 send_ping( int s,struct sockaddr *sa, int salen,2263 send_ping(struct sockaddr *sa, int salen, 1938 2264 const unsigned char *tid, int tid_len) 1939 2265 { … … 1947 2273 ADD_V(buf, i, 512); 1948 2274 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512); 1949 return sendto(s,buf, i, 0, sa, salen);2275 return dht_send(buf, i, 0, sa, salen); 1950 2276 1951 2277 fail: … … 1955 2281 1956 2282 int 1957 send_pong( int s,struct sockaddr *sa, int salen,2283 send_pong(struct sockaddr *sa, int salen, 1958 2284 const unsigned char *tid, int tid_len) 1959 2285 { … … 1966 2292 ADD_V(buf, i, 512); 1967 2293 rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512); 1968 return sendto(s,buf, i, 0, sa, salen);2294 return dht_send(buf, i, 0, sa, salen); 1969 2295 1970 2296 fail: … … 1974 2300 1975 2301 int 1976 send_find_node( int s,struct sockaddr *sa, int salen,2302 send_find_node(struct sockaddr *sa, int salen, 1977 2303 const unsigned char *tid, int tid_len, 1978 const unsigned char *target, int confirm)2304 const unsigned char *target, int want, int confirm) 1979 2305 { 1980 2306 char buf[512]; … … 1984 2310 rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512); 1985 2311 COPY(buf, i, target, 20, 512); 2312 if(want > 0) { 2313 rc = snprintf(buf + i, 512 - i, "4:wantl%s%se", 2314 (want & WANT4) ? "2:n4" : "", 2315 (want & WANT6) ? "2:n6" : ""); 2316 INC(i, rc, 512); 2317 } 1986 2318 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len); 1987 2319 INC(i, rc, 512); … … 1989 2321 ADD_V(buf, i, 512); 1990 2322 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512); 1991 return sendto(s,buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);2323 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen); 1992 2324 1993 2325 fail: … … 1997 2329 1998 2330 int 1999 send_nodes_peers( int s,struct sockaddr *sa, int salen,2331 send_nodes_peers(struct sockaddr *sa, int salen, 2000 2332 const unsigned char *tid, int tid_len, 2001 2333 const unsigned char *nodes, int nodes_len, 2002 struct peer *peers1, int numpeers1,2003 struct peer *peers2, int numpeers2,2334 const unsigned char *nodes6, int nodes6_len, 2335 int af, struct storage *st, 2004 2336 const unsigned char *token, int token_len) 2005 2337 { 2006 2338 char buf[2048]; 2007 int i = 0, rc, j; 2339 int i = 0, rc, j0, j, k, len; 2340 2008 2341 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048); 2009 2342 COPY(buf, i, myid, 20, 2048); … … 2018 2351 COPY(buf, i, nodes, nodes_len, 2048); 2019 2352 } 2020 for(j = 0; j < numpeers1; j++) { 2021 unsigned short swapped = htons(peers1[j].port); 2022 rc = snprintf(buf + i, 2048 - i, "6:"); INC(i, rc, 2048); 2023 COPY(buf, i, peers1[j].ip, 4, 2048); 2024 COPY(buf, i, &swapped, 2, 2048); 2025 } 2026 for(j = 0; j < numpeers2; j++) { 2027 unsigned short swapped = htons(peers2[j].port); 2028 rc = snprintf(buf + i, 2048 - i, "6:"); INC(i, rc, 2048); 2029 COPY(buf, i, peers2[j].ip, 4, 2048); 2030 COPY(buf, i, &swapped, 2, 2048); 2031 } 2353 if(nodes6_len > 0) { 2354 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len); 2355 INC(i, rc, 2048); 2356 COPY(buf, i, nodes6, nodes6_len, 2048); 2357 } 2358 2359 if(st && st->numpeers > 0) { 2360 /* We treat the storage as a circular list, and serve a randomly 2361 chosen slice. In order to make sure we fit within 1024 octets, 2362 we limit ourselves to 50 peers. */ 2363 2364 len = af == AF_INET ? 4 : 16; 2365 j0 = random() % st->numpeers; 2366 j = j0; 2367 k = 0; 2368 2369 rc = snprintf(buf + i, 2048 - i, "6:valuesl"); INC(i, rc, 2048); 2370 do { 2371 if(st->peers[j].len == len) { 2372 unsigned short swapped; 2373 swapped = htons(st->peers[j].port); 2374 rc = snprintf(buf + i, 2048 - i, "%d:", len + 2); 2375 INC(i, rc, 2048); 2376 COPY(buf, i, st->peers[j].ip, len, 2048); 2377 COPY(buf, i, &swapped, 2, 2048); 2378 k++; 2379 } 2380 j = (j + 1) % st->numpeers; 2381 } while(j != j0 && k < 50); 2382 rc = snprintf(buf + i, 2048 - i, "e"); INC(i, rc, 2048); 2383 } 2384 2032 2385 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048); 2033 2386 COPY(buf, i, tid, tid_len, 2048); … … 2035 2388 rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048); 2036 2389 2037 return sendto(s,buf, i, 0, sa, salen);2390 return dht_send(buf, i, 0, sa, salen); 2038 2391 2039 2392 fail: … … 2046 2399 const unsigned char *id, struct node *n) 2047 2400 { 2048 int i; 2401 int i, size; 2402 2403 if(n->ss.ss_family == AF_INET) 2404 size = 26; 2405 else if(n->ss.ss_family == AF_INET6) 2406 size = 38; 2407 else 2408 abort(); 2409 2049 2410 for(i = 0; i< numnodes; i++) { 2050 if(id_cmp(n odes + 26 * i, id) == 0)2411 if(id_cmp(n->id, nodes + size * i) == 0) 2051 2412 return numnodes; 2052 if(xorcmp(n->id, nodes + 26* i, id) < 0)2413 if(xorcmp(n->id, nodes + size * i, id) < 0) 2053 2414 break; 2054 2415 } … … 2061 2422 2062 2423 if(i < numnodes - 1) 2063 memmove(nodes + 26 * (i + 1), nodes + 26 * i, 26 * (numnodes - i - 1)); 2064 2065 memcpy(nodes + 26 * i, n->id, 20); 2066 memcpy(nodes + 26 * i + 20, &n->sin.sin_addr, 4); 2067 memcpy(nodes + 26 * i + 24, &n->sin.sin_port, 2); 2424 memmove(nodes + size * (i + 1), nodes + size * i, 2425 size * (numnodes - i - 1)); 2426 2427 if(n->ss.ss_family == AF_INET) { 2428 struct sockaddr_in *sin = (struct sockaddr_in*)&n->ss; 2429 memcpy(nodes + size * i, n->id, 20); 2430 memcpy(nodes + size * i + 20, &sin->sin_addr, 4); 2431 memcpy(nodes + size * i + 24, &sin->sin_port, 2); 2432 } else if(n->ss.ss_family == AF_INET6) { 2433 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&n->ss; 2434 memcpy(nodes + size * i, n->id, 20); 2435 memcpy(nodes + size * i + 20, &sin6->sin6_addr, 16); 2436 memcpy(nodes + size * i + 36, &sin6->sin6_port, 2); 2437 } else { 2438 abort(); 2439 } 2068 2440 2069 2441 return numnodes; … … 2084 2456 2085 2457 int 2086 send_closest_nodes( int s,struct sockaddr *sa, int salen,2458 send_closest_nodes(struct sockaddr *sa, int salen, 2087 2459 const unsigned char *tid, int tid_len, 2088 const unsigned char *id, 2089 struct peer *peers1, int numpeers1, 2090 struct peer *peers2, int numpeers2, 2460 const unsigned char *id, int want, 2461 int af, struct storage *st, 2091 2462 const unsigned char *token, int token_len) 2092 2463 { 2093 2464 unsigned char nodes[8 * 26]; 2094 int numnodes = 0; 2465 unsigned char nodes6[8 * 38]; 2466 int numnodes = 0, numnodes6 = 0; 2095 2467 struct bucket *b; 2096 2468 2097 b = find_bucket(id); 2098 numnodes = buffer_closest_nodes(nodes, numnodes, id, b); 2099 if(b->next) 2100 numnodes = buffer_closest_nodes(nodes, numnodes, id, b->next); 2101 b = previous_bucket(b); 2102 if(b) 2103 numnodes = buffer_closest_nodes(nodes, numnodes, id, b); 2104 2105 return send_nodes_peers(s, sa, salen, tid, tid_len, 2469 if(want < 0) 2470 want = sa->sa_family == AF_INET ? WANT4 : WANT6; 2471 2472 if((want & WANT4)) { 2473 b = find_bucket(id, AF_INET); 2474 if(b) { 2475 numnodes = buffer_closest_nodes(nodes, numnodes, id, b); 2476 if(b->next) 2477 numnodes = buffer_closest_nodes(nodes, numnodes, id, b->next); 2478 b = previous_bucket(b); 2479 if(b) 2480 numnodes = buffer_closest_nodes(nodes, numnodes, id, b); 2481 } 2482 } 2483 2484 if((want & WANT6)) { 2485 b = find_bucket(id, AF_INET6); 2486 if(b) { 2487 numnodes6 = buffer_closest_nodes(nodes6, numnodes6, id, b); 2488 if(b->next) 2489 numnodes6 = 2490 buffer_closest_nodes(nodes6, numnodes6, id, b->next); 2491 b = previous_bucket(b); 2492 if(b) 2493 numnodes6 = buffer_closest_nodes(nodes6, numnodes6, id, b); 2494 } 2495 } 2496 debugf(" (%d+%d nodes.)\n", numnodes, numnodes6); 2497 2498 return send_nodes_peers(sa, salen, tid, tid_len, 2106 2499 nodes, numnodes * 26, 2107 peers1, numpeers1, peers2, numpeers2,2108 token, token_len);2500 nodes6, numnodes6 * 38, 2501 af, st, token, token_len); 2109 2502 } 2110 2503 2111 2504 int 2112 send_get_peers( int s,struct sockaddr *sa, int salen,2505 send_get_peers(struct sockaddr *sa, int salen, 2113 2506 unsigned char *tid, int tid_len, unsigned char *infohash, 2114 int confirm)2507 int want, int confirm) 2115 2508 { 2116 2509 char buf[512]; … … 2121 2514 rc = snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512); 2122 2515 COPY(buf, i, infohash, 20, 512); 2516 if(want > 0) { 2517 rc = snprintf(buf + i, 512 - i, "4:wantl%s%se", 2518 (want & WANT4) ? "2:n4" : "", 2519 (want & WANT6) ? "2:n6" : ""); 2520 INC(i, rc, 512); 2521 } 2123 2522 rc = snprintf(buf + i, 512 - i, "e1:q9:get_peers1:t%d:", tid_len); 2124 2523 INC(i, rc, 512); … … 2126 2525 ADD_V(buf, i, 512); 2127 2526 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512); 2128 return sendto(s,buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);2527 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen); 2129 2528 2130 2529 fail: … … 2134 2533 2135 2534 int 2136 send_announce_peer( int s,struct sockaddr *sa, int salen,2535 send_announce_peer(struct sockaddr *sa, int salen, 2137 2536 unsigned char *tid, int tid_len, 2138 2537 unsigned char *infohash, unsigned short port, … … 2156 2555 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512); 2157 2556 2158 return sendto(s,buf, i, confirm ? 0 : MSG_CONFIRM, sa, salen);2557 return dht_send(buf, i, confirm ? 0 : MSG_CONFIRM, sa, salen); 2159 2558 2160 2559 fail: … … 2163 2562 } 2164 2563 2165 int2166 send_peer_announced( int s,struct sockaddr *sa, int salen,2564 static int 2565 send_peer_announced(struct sockaddr *sa, int salen, 2167 2566 unsigned char *tid, int tid_len) 2168 2567 { … … 2175 2574 INC(i, rc, 512); 2176 2575 COPY(buf, i, tid, tid_len, 512); 2177 ADD_V(buf, i, 2048); 2178 rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048); 2179 return sendto(s, buf, i, 0, sa, salen); 2576 ADD_V(buf, i, 512); 2577 rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512); 2578 return dht_send(buf, i, 0, sa, salen); 2579 2580 fail: 2581 errno = ENOSPC; 2582 return -1; 2583 } 2584 2585 static int 2586 send_error(struct sockaddr *sa, int salen, 2587 unsigned char *tid, int tid_len, 2588 int code, const char *message) 2589 { 2590 char buf[512]; 2591 int i = 0, rc; 2592 2593 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", 2594 code, (int)strlen(message)); 2595 INC(i, rc, 512); 2596 COPY(buf, i, message, (int)strlen(message), 512); 2597 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512); 2598 COPY(buf, i, tid, tid_len, 512); 2599 ADD_V(buf, i, 512); 2600 rc = snprintf(buf + i, 512 - i, "1:y1:ee"); INC(i, rc, 512); 2601 return dht_send(buf, i, 0, sa, salen); 2180 2602 2181 2603 fail: … … 2217 2639 unsigned char *token_return, int *token_len, 2218 2640 unsigned char *nodes_return, int *nodes_len, 2219 const unsigned char *values_return, int *values_len) 2641 unsigned char *nodes6_return, int *nodes6_len, 2642 unsigned char *values_return, int *values_len, 2643 unsigned char *values6_return, int *values6_len, 2644 int *want_return) 2220 2645 { 2221 2646 const unsigned char *p; … … 2293 2718 *token_len = 0; 2294 2719 } 2295 2296 if(nodes_ return) {2720 2721 if(nodes_len) { 2297 2722 p = memmem(buf, buflen, "5:nodes", 7); 2298 2723 if(p) { … … 2310 2735 } 2311 2736 2312 if(values_return) { 2737 if(nodes6_len) { 2738 p = memmem(buf, buflen, "6:nodes6", 8); 2739 if(p) { 2740 long l; 2741 char *q; 2742 l = strtol((char*)p + 8, &q, 10); 2743 if(q && *q == ':' && l > 0 && l < *nodes6_len) { 2744 CHECK(q + 1, l); 2745 memcpy(nodes6_return, q + 1, l); 2746 *nodes6_len = l; 2747 } else 2748 *nodes6_len = 0; 2749 } else 2750 *nodes6_len = 0; 2751 } 2752 2753 if(values_len || values6_len) { 2313 2754 p = memmem(buf, buflen, "6:valuesl", 9); 2314 2755 if(p) { 2315 2756 int i = p - buf + 9; 2316 int j = 0 ;2757 int j = 0, j6 = 0; 2317 2758 while(1) { 2318 2759 long l; … … 2321 2762 if(q && *q == ':' && l > 0) { 2322 2763 CHECK(q + 1, l); 2323 if(j + l > *values_len) 2324 break; 2325 i = q + 1 + l - (char*)buf; 2326 /* BEP 32 allows heterogeneous values -- ignore IPv6 */ 2327 if(l != 6) { 2328 debugf("Received weird value -- %d bytes.\n", 2329 (int)l); 2330 continue; 2764 if(l == 6) { 2765 if(j + l > *values_len) 2766 continue; 2767 i = q + 1 + l - (char*)buf; 2768 memcpy((char*)values_return + j, q + 1, l); 2769 j += l; 2770 } else if(l == 18) { 2771 if(j6 + l > *values6_len) 2772 continue; 2773 i = q + 1 + l - (char*)buf; 2774 memcpy((char*)values6_return + j6, q + 1, l); 2775 j6 += l; 2776 } else { 2777 debugf("Received weird value -- %d bytes.\n", (int)l); 2778 i = q + 1 + l - (char*)buf; 2331 2779 } 2332 memcpy((char*)values_return + j, q + 1, l);2333 j += l;2334 2780 } else { 2335 2781 break; … … 2338 2784 if(i >= buflen || buf[i] != 'e') 2339 2785 debugf("eek... unexpected end for values.\n"); 2340 *values_len = j; 2786 if(values_len) 2787 *values_len = j; 2788 if(values6_len) 2789 *values6_len = j6; 2341 2790 } else { 2342 2791 *values_len = 0; 2792 *values6_len = 0; 2793 } 2794 } 2795 2796 if(want_return) { 2797 p = memmem(buf, buflen, "4:wantl", 7); 2798 if(p) { 2799 int i = p - buf + 7; 2800 *want_return = 0; 2801 while(buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' && 2802 i + 2 + buf[i] - '0' < buflen) { 2803 CHECK(buf + i + 2, buf[i] - '0'); 2804 if(buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0) 2805 *want_return |= WANT4; 2806 else if(buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0) 2807 *want_return |= WANT6; 2808 else 2809 debugf("eek... unexpected want flag (%c)\n", buf[i]); 2810 i += 2 + buf[i] - '0'; 2811 } 2812 if(i >= buflen || buf[i] != 'e') 2813 debugf("eek... unexpected end for want.\n"); 2814 } else { 2815 *want_return = -1; 2343 2816 } 2344 2817 } 2345 2818 2346 2819 #undef CHECK 2347 2820 2348 2821 if(memmem(buf, buflen, "1:y1:r", 6)) 2349 2822 return REPLY; 2823 if(memmem(buf, buflen, "1:y1:e", 6)) 2824 return ERROR; 2350 2825 if(!memmem(buf, buflen, "1:y1:q", 6)) 2351 2826 return -1; -
trunk/third-party/dht/dht.h
r8440 r9549 28 28 #define DHT_EVENT_NONE 0 29 29 #define DHT_EVENT_VALUES 1 30 #define DHT_EVENT_SEARCH_DONE 2 30 #define DHT_EVENT_VALUES6 2 31 #define DHT_EVENT_SEARCH_DONE 3 32 #define DHT_EVENT_SEARCH_DONE6 4 31 33 32 34 extern FILE *dht_debug; 33 35 34 int dht_init(int s, const unsigned char *id, const unsigned char *v);35 int dht_insert_node( int s, const unsigned char *id, struct sockaddr_in *sin);36 int dht_ping_node( int s, struct sockaddr_in *sin);37 int dht_periodic(int s, intavailable, time_t *tosleep,36 int dht_init(int s, int s6, const unsigned char *id, const unsigned char *v); 37 int dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen); 38 int dht_ping_node(struct sockaddr *sa, int salen); 39 int dht_periodic(int available, time_t *tosleep, 38 40 dht_callback *callback, void *closure); 39 int dht_search( int s, const unsigned char *id, int port,41 int dht_search(const unsigned char *id, int port, int af, 40 42 dht_callback *callback, void *closure); 41 int dht_nodes(int *good_return, int *dubious_return, int *cached_return, 43 int dht_nodes(int af, 44 int *good_return, int *dubious_return, int *cached_return, 42 45 int *incoming_return); 43 46 void dht_dump_tables(FILE *f); 44 int dht_get_nodes(struct sockaddr_in *sins, int num); 45 int dht_uninit(int s, int dofree); 47 int dht_get_nodes(struct sockaddr_in *sin, int *num, 48 struct sockaddr_in6 *sin6, int *num6); 49 int dht_uninit(int dofree); 46 50 47 51 /* This must be provided by the user. */
Note: See TracChangeset
for help on using the changeset viewer.