diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2024-04-03 22:25:30 +0200 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2024-04-03 22:25:30 +0200 |
| commit | 2afc4893bf802700a1decfff57673cefc861c7e7 (patch) | |
| tree | 9a0817371ac05062dbcf25107fcf5a6481feccc0 | |
| parent | eb8834f7783cb85ae825976425800cd4af711263 (diff) | |
Prepare opentracker for dual stack capabilities
| -rw-r--r-- | ot_clean.c | 63 | ||||
| -rw-r--r-- | ot_fullscrape.c | 24 | ||||
| -rw-r--r-- | ot_http.c | 18 | ||||
| -rw-r--r-- | ot_livesync.c | 12 | ||||
| -rw-r--r-- | ot_mutex.h | 2 | ||||
| -rw-r--r-- | ot_stats.c | 36 | ||||
| -rw-r--r-- | ot_udp.c | 26 | ||||
| -rw-r--r-- | ot_vector.c | 83 | ||||
| -rw-r--r-- | ot_vector.h | 10 | ||||
| -rw-r--r-- | trackerlogic.c | 174 | ||||
| -rw-r--r-- | trackerlogic.h | 54 |
11 files changed, 293 insertions, 209 deletions
| @@ -20,36 +20,36 @@ | |||
| 20 | #include "ot_accesslist.h" | 20 | #include "ot_accesslist.h" |
| 21 | 21 | ||
| 22 | /* Returns amount of removed peers */ | 22 | /* Returns amount of removed peers */ |
| 23 | static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, time_t timedout, int *removed_seeders ) { | 23 | static ssize_t clean_single_bucket( ot_peer *peers, size_t peer_count, size_t peer_size, time_t timedout, int *removed_seeders ) { |
| 24 | ot_peer *last_peer = peers + peer_count, *insert_point; | 24 | ot_peer *last_peer = peers + peer_count * peer_size, *insert_point; |
| 25 | time_t timediff; | ||
| 26 | 25 | ||
| 27 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ | 26 | /* Two scan modes: unless there is one peer removed, just increase ot_peertime */ |
| 28 | while( peers < last_peer ) { | 27 | while( peers < last_peer ) { |
| 29 | if( ( timediff = timedout + OT_PEERTIME( peers ) ) >= OT_PEER_TIMEOUT ) | 28 | time_t timediff = timedout + OT_PEERTIME( peers, peer_size ); |
| 29 | if( timediff >= OT_PEER_TIMEOUT ) | ||
| 30 | break; | 30 | break; |
| 31 | OT_PEERTIME( peers++ ) = timediff; | 31 | OT_PEERTIME( peers, peer_size ) = timediff; |
| 32 | peers += peer_size; | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | /* If we at least remove one peer, we have to copy */ | 35 | /* If we at least remove one peer, we have to copy */ |
| 35 | insert_point = peers; | 36 | for( insert_point = peers; peers < last_peer; peers += peer_size ) { |
| 36 | while( peers < last_peer ) | 37 | time_t timediff = timedout + OT_PEERTIME( peers, peer_size ); |
| 37 | if( ( timediff = timedout + OT_PEERTIME( peers ) ) < OT_PEER_TIMEOUT ) { | 38 | |
| 38 | OT_PEERTIME( peers ) = timediff; | 39 | if( timediff < OT_PEER_TIMEOUT ) { |
| 39 | memcpy( insert_point++, peers++, sizeof(ot_peer)); | 40 | OT_PEERTIME( peers, peer_size ) = timediff; |
| 41 | memcpy( insert_point, peers, peer_size); | ||
| 42 | insert_point += peer_size; | ||
| 40 | } else | 43 | } else |
| 41 | if( OT_PEERFLAG( peers++ ) & PEER_FLAG_SEEDING ) | 44 | if( OT_PEERFLAG_D( peers, peer_size ) & PEER_FLAG_SEEDING ) |
| 42 | (*removed_seeders)++; | 45 | (*removed_seeders)++; |
| 46 | } | ||
| 43 | 47 | ||
| 44 | return peers - insert_point; | 48 | return peers - insert_point; |
| 45 | } | 49 | } |
| 46 | 50 | ||
| 47 | /* Clean a single torrent | 51 | int clean_single_peer_list( ot_peerlist *peer_list, size_t peer_size ) { |
| 48 | return 1 if torrent timed out | 52 | ot_vector *peer_vector = &peer_list->peers; |
| 49 | */ | ||
| 50 | int clean_single_torrent( ot_torrent *torrent ) { | ||
| 51 | ot_peerlist *peer_list = torrent->peer_list; | ||
| 52 | ot_vector *bucket_list = &peer_list->peers; | ||
| 53 | time_t timedout = (time_t)( g_now_minutes - peer_list->base ); | 53 | time_t timedout = (time_t)( g_now_minutes - peer_list->base ); |
| 54 | int num_buckets = 1, removed_seeders = 0; | 54 | int num_buckets = 1, removed_seeders = 0; |
| 55 | 55 | ||
| @@ -69,24 +69,26 @@ int clean_single_torrent( ot_torrent *torrent ) { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { | 71 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { |
| 72 | num_buckets = bucket_list->size; | 72 | num_buckets = peer_vector->size; |
| 73 | bucket_list = (ot_vector *)bucket_list->data; | 73 | peer_vector = (ot_vector *)peer_vector->data; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | while( num_buckets-- ) { | 76 | while( num_buckets-- ) { |
| 77 | size_t removed_peers = clean_single_bucket( bucket_list->data, bucket_list->size, timedout, &removed_seeders ); | 77 | size_t removed_peers = clean_single_bucket( peer_vector->data, peer_vector->size, peer_size, timedout, &removed_seeders ); |
| 78 | peer_list->peer_count -= removed_peers; | 78 | peer_list->peer_count -= removed_peers; |
| 79 | bucket_list->size -= removed_peers; | 79 | peer_vector->size -= removed_peers; |
| 80 | if( bucket_list->size < removed_peers ) | 80 | if( removed_peers ) |
| 81 | vector_fixup_peers( bucket_list ); | 81 | vector_fixup_peers( peer_vector, peer_size ); |
| 82 | ++bucket_list; | 82 | |
| 83 | /* Skip to next bucket, a vector containing peers */ | ||
| 84 | ++peer_vector; | ||
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | peer_list->seed_count -= removed_seeders; | 87 | peer_list->seed_count -= removed_seeders; |
| 86 | 88 | ||
| 87 | /* See, if we need to convert a torrent from simple vector to bucket list */ | 89 | /* See if we need to convert a torrent from simple vector to bucket list */ |
| 88 | if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) ) | 90 | if( ( peer_list->peer_count > OT_PEER_BUCKET_MINCOUNT ) || OT_PEERLIST_HASBUCKETS(peer_list) ) |
| 89 | vector_redistribute_buckets( peer_list ); | 91 | vector_redistribute_buckets( peer_list, peer_size ); |
| 90 | 92 | ||
| 91 | if( peer_list->peer_count ) | 93 | if( peer_list->peer_count ) |
| 92 | peer_list->base = g_now_minutes; | 94 | peer_list->base = g_now_minutes; |
| @@ -96,7 +98,14 @@ int clean_single_torrent( ot_torrent *torrent ) { | |||
| 96 | peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; | 98 | peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; |
| 97 | } | 99 | } |
| 98 | return 0; | 100 | return 0; |
| 101 | } | ||
| 99 | 102 | ||
| 103 | /* Clean a single torrent | ||
| 104 | return 1 if torrent timed out | ||
| 105 | */ | ||
| 106 | int clean_single_torrent( ot_torrent *torrent ) { | ||
| 107 | return clean_single_peer_list( torrent->peer_list6, OT_PEER_SIZE6) * | ||
| 108 | clean_single_peer_list( torrent->peer_list4, OT_PEER_SIZE4); | ||
| 100 | } | 109 | } |
| 101 | 110 | ||
| 102 | /* Clean up all peers in current bucket, remove timedout pools and | 111 | /* Clean up all peers in current bucket, remove timedout pools and |
diff --git a/ot_fullscrape.c b/ot_fullscrape.c index 5d115dc..d7d3518 100644 --- a/ot_fullscrape.c +++ b/ot_fullscrape.c | |||
| @@ -82,7 +82,11 @@ void fullscrape_deliver( int64 sock, ot_tasktype tasktype ) { | |||
| 82 | mutex_workqueue_pushtask( sock, tasktype ); | 82 | mutex_workqueue_pushtask( sock, tasktype ); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_peerlist *peer_list, ot_hash *hash ) { | 85 | static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_torrent *torrent, ot_hash *hash ) { |
| 86 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | ||
| 87 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | ||
| 88 | size_t down_count = torrent->peer_list6->down_count + torrent->peer_list4->down_count; | ||
| 89 | |||
| 86 | switch( mode & TASK_TASK_MASK ) { | 90 | switch( mode & TASK_TASK_MASK ) { |
| 87 | case TASK_FULLSCRAPE: | 91 | case TASK_FULLSCRAPE: |
| 88 | default: | 92 | default: |
| @@ -90,30 +94,30 @@ static char * fullscrape_write_one( ot_tasktype mode, char *r, ot_peerlist *peer | |||
| 90 | *r++='2'; *r++='0'; *r++=':'; | 94 | *r++='2'; *r++='0'; *r++=':'; |
| 91 | memcpy( r, hash, sizeof(ot_hash) ); r += sizeof(ot_hash); | 95 | memcpy( r, hash, sizeof(ot_hash) ); r += sizeof(ot_hash); |
| 92 | /* push rest of the scrape string */ | 96 | /* push rest of the scrape string */ |
| 93 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count ); | 97 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", seed_count, down_count, peer_count-seed_count ); |
| 94 | 98 | ||
| 95 | break; | 99 | break; |
| 96 | case TASK_FULLSCRAPE_TPB_ASCII: | 100 | case TASK_FULLSCRAPE_TPB_ASCII: |
| 97 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); | 101 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); |
| 98 | r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count ); | 102 | r += sprintf( r, ":%zd:%zd\n", seed_count, peer_count-seed_count ); |
| 99 | break; | 103 | break; |
| 100 | case TASK_FULLSCRAPE_TPB_ASCII_PLUS: | 104 | case TASK_FULLSCRAPE_TPB_ASCII_PLUS: |
| 101 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); | 105 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); |
| 102 | r += sprintf( r, ":%zd:%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count, peer_list->down_count ); | 106 | r += sprintf( r, ":%zd:%zd:%zd\n", seed_count, peer_count-seed_count, down_count ); |
| 103 | break; | 107 | break; |
| 104 | case TASK_FULLSCRAPE_TPB_BINARY: | 108 | case TASK_FULLSCRAPE_TPB_BINARY: |
| 105 | memcpy( r, *hash, sizeof(ot_hash) ); r += sizeof(ot_hash); | 109 | memcpy( r, *hash, sizeof(ot_hash) ); r += sizeof(ot_hash); |
| 106 | *(uint32_t*)(r+0) = htonl( (uint32_t) peer_list->seed_count ); | 110 | *(uint32_t*)(r+0) = htonl( (uint32_t) seed_count ); |
| 107 | *(uint32_t*)(r+4) = htonl( (uint32_t)( peer_list->peer_count-peer_list->seed_count) ); | 111 | *(uint32_t*)(r+4) = htonl( (uint32_t)( peer_count-seed_count) ); |
| 108 | r+=8; | 112 | r+=8; |
| 109 | break; | 113 | break; |
| 110 | case TASK_FULLSCRAPE_TPB_URLENCODED: | 114 | case TASK_FULLSCRAPE_TPB_URLENCODED: |
| 111 | r += fmt_urlencoded( r, (char *)*hash, 20 ); | 115 | r += fmt_urlencoded( r, (char *)*hash, 20 ); |
| 112 | r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count ); | 116 | r += sprintf( r, ":%zd:%zd\n", seed_count, peer_count-seed_count ); |
| 113 | break; | 117 | break; |
| 114 | case TASK_FULLSCRAPE_TRACKERSTATE: | 118 | case TASK_FULLSCRAPE_TRACKERSTATE: |
| 115 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); | 119 | to_hex( r, *hash ); r+= 2 * sizeof(ot_hash); |
| 116 | r += sprintf( r, ":%zd:%zd\n", peer_list->base, peer_list->down_count ); | 120 | r += sprintf( r, ":%zd:%zd\n", torrent->peer_list6->base, down_count ); |
| 117 | break; | 121 | break; |
| 118 | } | 122 | } |
| 119 | return r; | 123 | return r; |
| @@ -145,7 +149,7 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas | |||
| 145 | 149 | ||
| 146 | /* For each torrent in this bucket.. */ | 150 | /* For each torrent in this bucket.. */ |
| 147 | for( i=0; i<torrents_list->size; ++i ) { | 151 | for( i=0; i<torrents_list->size; ++i ) { |
| 148 | r = fullscrape_write_one( mode, r, torrents[i].peer_list, &torrents[i].hash ); | 152 | r = fullscrape_write_one( mode, r, torrents+i, &torrents[i].hash ); |
| 149 | 153 | ||
| 150 | if( r > re) { | 154 | if( r > re) { |
| 151 | /* Allocate a fresh output buffer at the end of our buffers list */ | 155 | /* Allocate a fresh output buffer at the end of our buffers list */ |
| @@ -210,7 +214,7 @@ static void fullscrape_make_gzip( int *iovec_entries, struct iovec **iovector, o | |||
| 210 | /* For each torrent in this bucket.. */ | 214 | /* For each torrent in this bucket.. */ |
| 211 | for( i=0; i<torrents_list->size; ++i ) { | 215 | for( i=0; i<torrents_list->size; ++i ) { |
| 212 | char compress_buffer[OT_SCRAPE_MAXENTRYLEN]; | 216 | char compress_buffer[OT_SCRAPE_MAXENTRYLEN]; |
| 213 | r = fullscrape_write_one( mode, compress_buffer, torrents[i].peer_list, &torrents[i].hash ); | 217 | r = fullscrape_write_one( mode, compress_buffer, torrents+i, &torrents[i].hash ); |
| 214 | strm.next_in = (uint8_t*)compress_buffer; | 218 | strm.next_in = (uint8_t*)compress_buffer; |
| 215 | strm.avail_in = r - compress_buffer; | 219 | strm.avail_in = r - compress_buffer; |
| 216 | zres = deflate( &strm, Z_NO_FLUSH ); | 220 | zres = deflate( &strm, Z_NO_FLUSH ); |
| @@ -421,26 +421,18 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, | |||
| 421 | ot_ip6 proxied_ip; | 421 | ot_ip6 proxied_ip; |
| 422 | char *fwd = http_header( ws->request, ws->header_size, "x-forwarded-for" ); | 422 | char *fwd = http_header( ws->request, ws->header_size, "x-forwarded-for" ); |
| 423 | if( fwd && scan_ip6( fwd, proxied_ip ) ) { | 423 | if( fwd && scan_ip6( fwd, proxied_ip ) ) { |
| 424 | /* If proxy reports an ipv6 address but we can only handle v4 (or vice versa), bail out */ | 424 | OT_SETIP( ws->peer, proxied_ip ); |
| 425 | #ifndef WANT_V6 | ||
| 426 | if( !ip6_isv4mapped(proxied_ip) ) | ||
| 427 | #else | ||
| 428 | if( ip6_isv4mapped(proxied_ip) ) | ||
| 429 | #endif | ||
| 430 | HTTPERROR_400_PARAM; | ||
| 431 | |||
| 432 | OT_SETIP( &ws->peer, proxied_ip ); | ||
| 433 | } else | 425 | } else |
| 434 | OT_SETIP( &ws->peer, cookie->ip ); | 426 | OT_SETIP( ws->peer, cookie->ip ); |
| 435 | } else | 427 | } else |
| 436 | #endif | 428 | #endif |
| 437 | OT_SETIP( &ws->peer, cookie->ip ); | 429 | OT_SETIP( ws->peer, cookie->ip ); |
| 438 | 430 | ||
| 439 | ws->peer_id = NULL; | 431 | ws->peer_id = NULL; |
| 440 | ws->hash = NULL; | 432 | ws->hash = NULL; |
| 441 | 433 | ||
| 442 | OT_SETPORT( &ws->peer, &port ); | 434 | OT_SETPORT( ws->peer, &port ); |
| 443 | OT_PEERFLAG( &ws->peer ) = 0; | 435 | OT_PEERFLAG( ws->peer ) = 0; |
| 444 | numwant = 50; | 436 | numwant = 50; |
| 445 | scanon = 1; | 437 | scanon = 1; |
| 446 | 438 | ||
diff --git a/ot_livesync.c b/ot_livesync.c index 75a5f9f..b87fa6d 100644 --- a/ot_livesync.c +++ b/ot_livesync.c | |||
| @@ -127,13 +127,13 @@ static void livesync_handle_peersync( struct ot_workstruct *ws ) { | |||
| 127 | 127 | ||
| 128 | /* Now basic sanity checks have been done on the live sync packet | 128 | /* Now basic sanity checks have been done on the live sync packet |
| 129 | We might add more testing and logging. */ | 129 | We might add more testing and logging. */ |
| 130 | while( off + (ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer ) <= ws->request_size ) { | 130 | while( off + (ssize_t)sizeof( ot_hash ) + OT_PEER_SIZE4 <= ws->request_size ) { |
| 131 | memcpy( &ws->peer, ws->request + off + sizeof(ot_hash), sizeof( ot_peer ) ); | 131 | memcpy( &ws->peer, ws->request + off + sizeof(ot_hash), OT_PEER_SIZE4 ); |
| 132 | ws->hash = (ot_hash*)(ws->request + off); | 132 | ws->hash = (ot_hash*)(ws->request + off); |
| 133 | 133 | ||
| 134 | if( !g_opentracker_running ) return; | 134 | if( !g_opentracker_running ) return; |
| 135 | 135 | ||
| 136 | if( OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED ) | 136 | if( OT_PEERFLAG(ws->peer) & PEER_FLAG_STOPPED ) |
| 137 | remove_peer_from_torrent( FLAG_MCA, ws ); | 137 | remove_peer_from_torrent( FLAG_MCA, ws ); |
| 138 | else | 138 | else |
| 139 | add_peer_to_torrent_and_return_peers( FLAG_MCA, ws, /* amount = */ 0 ); | 139 | add_peer_to_torrent_and_return_peers( FLAG_MCA, ws, /* amount = */ 0 ); |
| @@ -143,7 +143,7 @@ static void livesync_handle_peersync( struct ot_workstruct *ws ) { | |||
| 143 | 143 | ||
| 144 | stats_issue_event(EVENT_SYNC, 0, | 144 | stats_issue_event(EVENT_SYNC, 0, |
| 145 | (ws->request_size - sizeof( g_tracker_id ) - sizeof( uint32_t ) ) / | 145 | (ws->request_size - sizeof( g_tracker_id ) - sizeof( uint32_t ) ) / |
| 146 | ((ssize_t)sizeof( ot_hash ) + (ssize_t)sizeof( ot_peer ))); | 146 | ((ssize_t)sizeof( ot_hash ) + OT_PEER_SIZE4)); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | /* Tickle the live sync module from time to time, so no events get | 149 | /* Tickle the live sync module from time to time, so no events get |
| @@ -164,9 +164,9 @@ void livesync_tell( struct ot_workstruct *ws ) { | |||
| 164 | pthread_mutex_lock(&g_outbuf_mutex); | 164 | pthread_mutex_lock(&g_outbuf_mutex); |
| 165 | 165 | ||
| 166 | memcpy( g_outbuf + g_outbuf_data, ws->hash, sizeof(ot_hash) ); | 166 | memcpy( g_outbuf + g_outbuf_data, ws->hash, sizeof(ot_hash) ); |
| 167 | memcpy( g_outbuf + g_outbuf_data + sizeof(ot_hash), &ws->peer, sizeof(ot_peer) ); | 167 | memcpy( g_outbuf + g_outbuf_data + sizeof(ot_hash), &ws->peer, OT_PEER_SIZE4 ); |
| 168 | 168 | ||
| 169 | g_outbuf_data += sizeof(ot_hash) + sizeof(ot_peer); | 169 | g_outbuf_data += sizeof(ot_hash) + OT_PEER_SIZE4; |
| 170 | 170 | ||
| 171 | if( g_outbuf_data >= LIVESYNC_OUTGOING_BUFFSIZE_PEERS - LIVESYNC_OUTGOING_WATERMARK_PEERS ) | 171 | if( g_outbuf_data >= LIVESYNC_OUTGOING_BUFFSIZE_PEERS - LIVESYNC_OUTGOING_WATERMARK_PEERS ) |
| 172 | livesync_issue_peersync(); | 172 | livesync_issue_peersync(); |
| @@ -43,7 +43,7 @@ typedef enum { | |||
| 43 | TASK_STATS_EVERYTHING = 0x0106, | 43 | TASK_STATS_EVERYTHING = 0x0106, |
| 44 | TASK_STATS_FULLLOG = 0x0107, | 44 | TASK_STATS_FULLLOG = 0x0107, |
| 45 | TASK_STATS_WOODPECKERS = 0x0108, | 45 | TASK_STATS_WOODPECKERS = 0x0108, |
| 46 | 46 | ||
| 47 | TASK_FULLSCRAPE = 0x0200, /* Default mode */ | 47 | TASK_FULLSCRAPE = 0x0200, /* Default mode */ |
| 48 | TASK_FULLSCRAPE_TPB_BINARY = 0x0201, | 48 | TASK_FULLSCRAPE_TPB_BINARY = 0x0201, |
| 49 | TASK_FULLSCRAPE_TPB_ASCII = 0x0202, | 49 | TASK_FULLSCRAPE_TPB_ASCII = 0x0202, |
| @@ -73,13 +73,13 @@ static time_t ot_start_time; | |||
| 73 | #define __LDR(P,D) ((__BYTE((P),(D))>>__SHFT((D)))&__MSK) | 73 | #define __LDR(P,D) ((__BYTE((P),(D))>>__SHFT((D)))&__MSK) |
| 74 | #define __STR(P,D,V) __BYTE((P),(D))=(__BYTE((P),(D))&~(__MSK<<__SHFT((D))))|((V)<<__SHFT((D))) | 74 | #define __STR(P,D,V) __BYTE((P),(D))=(__BYTE((P),(D))&~(__MSK<<__SHFT((D))))|((V)<<__SHFT((D))) |
| 75 | 75 | ||
| 76 | #ifdef WANT_V6 | 76 | //#ifdef WANT_V6 |
| 77 | #define STATS_NETWORK_NODE_MAXDEPTH (68-STATS_NETWORK_NODE_BITWIDTH) | 77 | //#define STATS_NETWORK_NODE_MAXDEPTH (68-STATS_NETWORK_NODE_BITWIDTH) |
| 78 | #define STATS_NETWORK_NODE_LIMIT (48-STATS_NETWORK_NODE_BITWIDTH) | 78 | //#define STATS_NETWORK_NODE_LIMIT (48-STATS_NETWORK_NODE_BITWIDTH) |
| 79 | #else | 79 | //#else |
| 80 | #define STATS_NETWORK_NODE_MAXDEPTH (28-STATS_NETWORK_NODE_BITWIDTH) | 80 | #define STATS_NETWORK_NODE_MAXDEPTH (28-STATS_NETWORK_NODE_BITWIDTH) |
| 81 | #define STATS_NETWORK_NODE_LIMIT (24-STATS_NETWORK_NODE_BITWIDTH) | 81 | #define STATS_NETWORK_NODE_LIMIT (24-STATS_NETWORK_NODE_BITWIDTH) |
| 82 | #endif | 82 | //#endif |
| 83 | 83 | ||
| 84 | typedef union stats_network_node stats_network_node; | 84 | typedef union stats_network_node stats_network_node; |
| 85 | union stats_network_node { | 85 | union stats_network_node { |
| @@ -219,12 +219,12 @@ static size_t stats_slash24s_txt( char *reply, size_t amount ) { | |||
| 219 | stats_network_node *slash24s_network_counters_root = NULL; | 219 | stats_network_node *slash24s_network_counters_root = NULL; |
| 220 | char *r=reply; | 220 | char *r=reply; |
| 221 | int bucket; | 221 | int bucket; |
| 222 | size_t i; | 222 | size_t i, peer_size = OT_PEER_SIZE4; |
| 223 | 223 | ||
| 224 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 224 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { |
| 225 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 225 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); |
| 226 | for( i=0; i<torrents_list->size; ++i ) { | 226 | for( i=0; i<torrents_list->size; ++i ) { |
| 227 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[i] ).peer_list; | 227 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[i] ).peer_list4; |
| 228 | ot_vector *bucket_list = &peer_list->peers; | 228 | ot_vector *bucket_list = &peer_list->peers; |
| 229 | int num_buckets = 1; | 229 | int num_buckets = 1; |
| 230 | 230 | ||
| @@ -236,9 +236,11 @@ static size_t stats_slash24s_txt( char *reply, size_t amount ) { | |||
| 236 | while( num_buckets-- ) { | 236 | while( num_buckets-- ) { |
| 237 | ot_peer *peers = (ot_peer*)bucket_list->data; | 237 | ot_peer *peers = (ot_peer*)bucket_list->data; |
| 238 | size_t numpeers = bucket_list->size; | 238 | size_t numpeers = bucket_list->size; |
| 239 | while( numpeers-- ) | 239 | while( numpeers-- ) { |
| 240 | if( stat_increase_network_count( &slash24s_network_counters_root, 0, (uintptr_t)(peers++) ) ) | 240 | if( stat_increase_network_count( &slash24s_network_counters_root, 0, (uintptr_t)(peers) ) ) |
| 241 | goto bailout_unlock; | 241 | goto bailout_unlock; |
| 242 | peers += peer_size; | ||
| 243 | } | ||
| 242 | ++bucket_list; | 244 | ++bucket_list; |
| 243 | } | 245 | } |
| 244 | } | 246 | } |
| @@ -285,8 +287,8 @@ typedef struct { | |||
| 285 | static int torrent_statter( ot_torrent *torrent, uintptr_t data ) { | 287 | static int torrent_statter( ot_torrent *torrent, uintptr_t data ) { |
| 286 | torrent_stats *stats = (torrent_stats*)data; | 288 | torrent_stats *stats = (torrent_stats*)data; |
| 287 | stats->torrent_count++; | 289 | stats->torrent_count++; |
| 288 | stats->peer_count += torrent->peer_list->peer_count; | 290 | stats->peer_count += torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; |
| 289 | stats->seed_count += torrent->peer_list->seed_count; | 291 | stats->seed_count += torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
| 290 | return 0; | 292 | return 0; |
| 291 | } | 293 | } |
| 292 | 294 | ||
| @@ -312,21 +314,23 @@ size_t stats_top_txt( char * reply, int amount ) { | |||
| 312 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 314 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); |
| 313 | for( j=0; j<torrents_list->size; ++j ) { | 315 | for( j=0; j<torrents_list->size; ++j ) { |
| 314 | ot_torrent *torrent = (ot_torrent*)(torrents_list->data) + j; | 316 | ot_torrent *torrent = (ot_torrent*)(torrents_list->data) + j; |
| 317 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | ||
| 318 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | ||
| 315 | idx = amount - 1; | 319 | idx = amount - 1; |
| 316 | while( (idx >= 0) && ( torrent->peer_list->peer_count > top100c[idx].val ) ) | 320 | while( (idx >= 0) && ( peer_count > top100c[idx].val ) ) |
| 317 | --idx; | 321 | --idx; |
| 318 | if ( idx++ != amount - 1 ) { | 322 | if ( idx++ != amount - 1 ) { |
| 319 | memmove( top100c + idx + 1, top100c + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); | 323 | memmove( top100c + idx + 1, top100c + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); |
| 320 | memcpy( &top100c[idx].hash, &torrent->hash, sizeof(ot_hash)); | 324 | memcpy( &top100c[idx].hash, &torrent->hash, sizeof(ot_hash)); |
| 321 | top100c[idx].val = torrent->peer_list->peer_count; | 325 | top100c[idx].val = peer_count; |
| 322 | } | 326 | } |
| 323 | idx = amount - 1; | 327 | idx = amount - 1; |
| 324 | while( (idx >= 0) && ( torrent->peer_list->seed_count > top100s[idx].val ) ) | 328 | while( (idx >= 0) && ( seed_count > top100s[idx].val ) ) |
| 325 | --idx; | 329 | --idx; |
| 326 | if ( idx++ != amount - 1 ) { | 330 | if ( idx++ != amount - 1 ) { |
| 327 | memmove( top100s + idx + 1, top100s + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); | 331 | memmove( top100s + idx + 1, top100s + idx, ( amount - 1 - idx ) * sizeof( ot_record ) ); |
| 328 | memcpy( &top100s[idx].hash, &torrent->hash, sizeof(ot_hash)); | 332 | memcpy( &top100s[idx].hash, &torrent->hash, sizeof(ot_hash)); |
| 329 | top100s[idx].val = torrent->peer_list->seed_count; | 333 | top100s[idx].val = seed_count; |
| 330 | } | 334 | } |
| 331 | } | 335 | } |
| 332 | mutex_bucket_unlock( bucket, 0 ); | 336 | mutex_bucket_unlock( bucket, 0 ); |
| @@ -718,7 +722,7 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event | |||
| 718 | break; | 722 | break; |
| 719 | case EVENT_SYNC: | 723 | case EVENT_SYNC: |
| 720 | ot_overall_sync_count+=event_data; | 724 | ot_overall_sync_count+=event_data; |
| 721 | break; | 725 | break; |
| 722 | case EVENT_BUCKET_LOCKED: | 726 | case EVENT_BUCKET_LOCKED: |
| 723 | ot_overall_stall_count++; | 727 | ot_overall_stall_count++; |
| 724 | break; | 728 | break; |
| @@ -13,6 +13,7 @@ | |||
| 13 | /* Libowfat */ | 13 | /* Libowfat */ |
| 14 | #include "socket.h" | 14 | #include "socket.h" |
| 15 | #include "io.h" | 15 | #include "io.h" |
| 16 | #include "ip6.h" | ||
| 16 | 17 | ||
| 17 | /* Opentracker */ | 18 | /* Opentracker */ |
| 18 | #include "trackerlogic.h" | 19 | #include "trackerlogic.h" |
| @@ -73,7 +74,7 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) { | |||
| 73 | ot_ip6 remoteip; | 74 | ot_ip6 remoteip; |
| 74 | uint32_t *inpacket = (uint32_t*)ws->inbuf; | 75 | uint32_t *inpacket = (uint32_t*)ws->inbuf; |
| 75 | uint32_t *outpacket = (uint32_t*)ws->outbuf; | 76 | uint32_t *outpacket = (uint32_t*)ws->outbuf; |
| 76 | uint32_t numwant, left, event, scopeid; | 77 | uint32_t left, event, scopeid; |
| 77 | uint32_t connid[2]; | 78 | uint32_t connid[2]; |
| 78 | uint32_t action; | 79 | uint32_t action; |
| 79 | uint16_t port, remoteport; | 80 | uint16_t port, remoteport; |
| @@ -141,34 +142,35 @@ int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) { | |||
| 141 | /* We do only want to know, if it is zero */ | 142 | /* We do only want to know, if it is zero */ |
| 142 | left = inpacket[64/4] | inpacket[68/4]; | 143 | left = inpacket[64/4] | inpacket[68/4]; |
| 143 | 144 | ||
| 144 | /* Limit amount of peers to OT_MAX_PEERS_UDP */ | ||
| 145 | numwant = ntohl( inpacket[92/4] ); | ||
| 146 | if (numwant > OT_MAX_PEERS_UDP) numwant = OT_MAX_PEERS_UDP; | ||
| 147 | |||
| 148 | event = ntohl( inpacket[80/4] ); | 145 | event = ntohl( inpacket[80/4] ); |
| 149 | port = *(uint16_t*)( ((char*)inpacket) + 96 ); | 146 | port = *(uint16_t*)( ((char*)inpacket) + 96 ); |
| 150 | ws->hash = (ot_hash*)( ((char*)inpacket) + 16 ); | 147 | ws->hash = (ot_hash*)( ((char*)inpacket) + 16 ); |
| 151 | 148 | ||
| 152 | OT_SETIP( &ws->peer, remoteip ); | 149 | OT_SETIP( ws->peer, remoteip ); |
| 153 | OT_SETPORT( &ws->peer, &port ); | 150 | OT_SETPORT( ws->peer, &port ); |
| 154 | OT_PEERFLAG( &ws->peer ) = 0; | 151 | OT_PEERFLAG( ws->peer ) = 0; |
| 155 | 152 | ||
| 156 | switch( event ) { | 153 | switch( event ) { |
| 157 | case 1: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_COMPLETED; break; | 154 | case 1: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_COMPLETED; break; |
| 158 | case 3: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_STOPPED; break; | 155 | case 3: OT_PEERFLAG( ws->peer ) |= PEER_FLAG_STOPPED; break; |
| 159 | default: break; | 156 | default: break; |
| 160 | } | 157 | } |
| 161 | 158 | ||
| 162 | if( !left ) | 159 | if( !left ) |
| 163 | OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_SEEDING; | 160 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_SEEDING; |
| 164 | 161 | ||
| 165 | outpacket[0] = htonl( 1 ); /* announce action */ | 162 | outpacket[0] = htonl( 1 ); /* announce action */ |
| 166 | outpacket[1] = inpacket[12/4]; | 163 | outpacket[1] = inpacket[12/4]; |
| 167 | 164 | ||
| 168 | if( OT_PEERFLAG( &ws->peer ) & PEER_FLAG_STOPPED ) { /* Peer is gone. */ | 165 | if( OT_PEERFLAG( ws->peer ) & PEER_FLAG_STOPPED ) { /* Peer is gone. */ |
| 169 | ws->reply = ws->outbuf; | 166 | ws->reply = ws->outbuf; |
| 170 | ws->reply_size = remove_peer_from_torrent( FLAG_UDP, ws ); | 167 | ws->reply_size = remove_peer_from_torrent( FLAG_UDP, ws ); |
| 171 | } else { | 168 | } else { |
| 169 | /* Limit amount of peers to OT_MAX_PEERS_UDP */ | ||
| 170 | uint32_t numwant = ntohl( inpacket[92/4] ); | ||
| 171 | size_t max_peers = ip6_isv4mapped(remoteip) ? OT_MAX_PEERS_UDP4 : OT_MAX_PEERS_UDP6; | ||
| 172 | if (numwant > max_peers) numwant = max_peers; | ||
| 173 | |||
| 172 | ws->reply = ws->outbuf + 8; | 174 | ws->reply = ws->outbuf + 8; |
| 173 | ws->reply_size = 8 + add_peer_to_torrent_and_return_peers( FLAG_UDP, ws, numwant ); | 175 | ws->reply_size = 8 + add_peer_to_torrent_and_return_peers( FLAG_UDP, ws, numwant ); |
| 174 | } | 176 | } |
diff --git a/ot_vector.c b/ot_vector.c index 2a632b2..c38f05d 100644 --- a/ot_vector.c +++ b/ot_vector.c | |||
| @@ -17,8 +17,11 @@ | |||
| 17 | #include "uint32.h" | 17 | #include "uint32.h" |
| 18 | #include "uint16.h" | 18 | #include "uint16.h" |
| 19 | 19 | ||
| 20 | static int vector_compare_peer(const void *peer1, const void *peer2 ) { | 20 | static int vector_compare_peer6(const void *peer1, const void *peer2 ) { |
| 21 | return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE ); | 21 | return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE6 ); |
| 22 | } | ||
| 23 | static int vector_compare_peer4(const void *peer1, const void *peer2 ) { | ||
| 24 | return memcmp( peer1, peer2, OT_PEER_COMPARE_SIZE4 ); | ||
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | /* This function gives us a binary search that returns a pointer, even if | 27 | /* This function gives us a binary search that returns a pointer, even if |
| @@ -47,10 +50,10 @@ void *binary_search( const void * const key, const void * base, const size_t mem | |||
| 47 | return (void*)base; | 50 | return (void*)base; |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | static uint8_t vector_hash_peer( ot_peer *peer, int bucket_count ) { | 53 | static uint8_t vector_hash_peer( ot_peer const *peer, size_t compare_size, int bucket_count ) { |
| 51 | unsigned int hash = 5381, i = OT_PEER_COMPARE_SIZE; | 54 | unsigned int hash = 5381; |
| 52 | uint8_t *p = (uint8_t*)peer; | 55 | uint8_t *p = (uint8_t*)peer; |
| 53 | while( i-- ) hash += (hash<<5) + *(p++); | 56 | while( compare_size-- ) hash += (hash<<5) + *(p++); |
| 54 | return hash % bucket_count; | 57 | return hash % bucket_count; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| @@ -82,27 +85,37 @@ void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, s | |||
| 82 | return match; | 85 | return match; |
| 83 | } | 86 | } |
| 84 | 87 | ||
| 85 | ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer *peer, int *exactmatch ) { | 88 | ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch ) { |
| 86 | ot_peer *match; | 89 | ot_peer *match, *end; |
| 90 | const size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | ||
| 91 | size_t match_to_end; | ||
| 87 | 92 | ||
| 88 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ | 93 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ |
| 89 | if( vector->space < vector->size ) | 94 | if( vector->space < vector->size ) |
| 90 | vector = ((ot_vector*)vector->data) + vector_hash_peer(peer, vector->size ); | 95 | vector = ((ot_vector*)vector->data) + vector_hash_peer(peer, compare_size, vector->size ); |
| 91 | match = (ot_peer*)binary_search( peer, vector->data, vector->size, sizeof(ot_peer), OT_PEER_COMPARE_SIZE, exactmatch ); | 96 | match = binary_search( peer, vector->data, vector->size, peer_size, compare_size, exactmatch ); |
| 92 | 97 | ||
| 93 | if( *exactmatch ) return match; | 98 | if( *exactmatch ) return match; |
| 94 | 99 | ||
| 100 | /* This is the amount of bytes that needs to be pushed backwards by peer_size bytes to make room for new peer */ | ||
| 101 | end = (ot_peer*)vector->data + vector->size * peer_size; | ||
| 102 | match_to_end = end - match; | ||
| 103 | |||
| 95 | if( vector->size + 1 > vector->space ) { | 104 | if( vector->size + 1 > vector->space ) { |
| 105 | ptrdiff_t offset = match - (ot_peer*)vector->data; | ||
| 96 | size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; | 106 | size_t new_space = vector->space ? OT_VECTOR_GROW_RATIO * vector->space : OT_VECTOR_MIN_MEMBERS; |
| 97 | ot_peer *new_data = realloc( vector->data, new_space * sizeof(ot_peer) ); | 107 | ot_peer *new_data = realloc( vector->data, new_space * peer_size ); |
| 108 | |||
| 98 | if( !new_data ) return NULL; | 109 | if( !new_data ) return NULL; |
| 99 | /* Adjust pointer if it moved by realloc */ | 110 | /* Adjust pointer if it moved by realloc */ |
| 100 | match = new_data + (match - (ot_peer*)vector->data); | 111 | match = new_data + offset; |
| 101 | 112 | ||
| 102 | vector->data = new_data; | 113 | vector->data = new_data; |
| 103 | vector->space = new_space; | 114 | vector->space = new_space; |
| 104 | } | 115 | } |
| 105 | memmove( match + 1, match, sizeof(ot_peer) * ( ((ot_peer*)vector->data) + vector->size - match ) ); | 116 | |
| 117 | /* Here we're guaranteed to have enough space in vector to move the block of peers after insertion point */ | ||
| 118 | memmove( match + peer_size, match, match_to_end); | ||
| 106 | 119 | ||
| 107 | vector->size++; | 120 | vector->size++; |
| 108 | return match; | 121 | return match; |
| @@ -113,26 +126,27 @@ ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer *peer, int *exac | |||
| 113 | 1 if a non-seeding peer was removed | 126 | 1 if a non-seeding peer was removed |
| 114 | 2 if a seeding peer was removed | 127 | 2 if a seeding peer was removed |
| 115 | */ | 128 | */ |
| 116 | int vector_remove_peer( ot_vector *vector, ot_peer *peer ) { | 129 | int vector_remove_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size) { |
| 117 | int exactmatch; | 130 | int exactmatch, was_seeder; |
| 118 | ot_peer *match, *end; | 131 | ot_peer *match, *end; |
| 132 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | ||
| 119 | 133 | ||
| 120 | if( !vector->size ) return 0; | 134 | if( !vector->size ) return 0; |
| 121 | 135 | ||
| 122 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ | 136 | /* If space is zero but size is set, we're dealing with a list of vector->size buckets */ |
| 123 | if( vector->space < vector->size ) | 137 | if( vector->space < vector->size ) |
| 124 | vector = ((ot_vector*)vector->data) + vector_hash_peer(peer, vector->size ); | 138 | vector = ((ot_vector*)vector->data) + vector_hash_peer(peer, compare_size, vector->size ); |
| 125 | 139 | ||
| 126 | end = ((ot_peer*)vector->data) + vector->size; | 140 | end = ((ot_peer*)vector->data) + peer_size * vector->size; |
| 127 | match = (ot_peer*)binary_search( peer, vector->data, vector->size, sizeof(ot_peer), OT_PEER_COMPARE_SIZE, &exactmatch ); | 141 | match = (ot_peer*)binary_search( peer, vector->data, vector->size, peer_size, compare_size, &exactmatch ); |
| 128 | if( !exactmatch ) return 0; | 142 | if( !exactmatch ) return 0; |
| 129 | 143 | ||
| 130 | exactmatch = ( OT_PEERFLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1; | 144 | was_seeder = ( OT_PEERFLAG_D( match, peer_size ) & PEER_FLAG_SEEDING ) ? 2 : 1; |
| 131 | memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) ); | 145 | memmove( match, match + peer_size, end - match - peer_size ); |
| 132 | 146 | ||
| 133 | vector->size--; | 147 | vector->size--; |
| 134 | vector_fixup_peers( vector ); | 148 | vector_fixup_peers( vector, peer_size ); |
| 135 | return exactmatch; | 149 | return was_seeder; |
| 136 | } | 150 | } |
| 137 | 151 | ||
| 138 | void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { | 152 | void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { |
| @@ -142,7 +156,8 @@ void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { | |||
| 142 | 156 | ||
| 143 | /* If this is being called after a unsuccessful malloc() for peer_list | 157 | /* If this is being called after a unsuccessful malloc() for peer_list |
| 144 | in add_peer_to_torrent, match->peer_list actually might be NULL */ | 158 | in add_peer_to_torrent, match->peer_list actually might be NULL */ |
| 145 | if( match->peer_list) free_peerlist( match->peer_list ); | 159 | if( match->peer_list6) free_peerlist( match->peer_list6 ); |
| 160 | if( match->peer_list4) free_peerlist( match->peer_list4 ); | ||
| 146 | 161 | ||
| 147 | memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) ); | 162 | memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) ); |
| 148 | if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space >= OT_VECTOR_SHRINK_RATIO * OT_VECTOR_MIN_MEMBERS ) ) { | 163 | if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space >= OT_VECTOR_SHRINK_RATIO * OT_VECTOR_MIN_MEMBERS ) ) { |
| @@ -158,9 +173,11 @@ void vector_clean_list( ot_vector * vector, int num_buckets ) { | |||
| 158 | return; | 173 | return; |
| 159 | } | 174 | } |
| 160 | 175 | ||
| 161 | void vector_redistribute_buckets( ot_peerlist * peer_list ) { | 176 | void vector_redistribute_buckets( ot_peerlist * peer_list, size_t peer_size ) { |
| 162 | int tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1; | 177 | int tmp, bucket, bucket_size_new, num_buckets_new, num_buckets_old = 1; |
| 163 | ot_vector * bucket_list_new, * bucket_list_old = &peer_list->peers; | 178 | ot_vector * bucket_list_new, * bucket_list_old = &peer_list->peers; |
| 179 | int (*sort_func)(const void *, const void *) = | ||
| 180 | peer_size == OT_PEER_SIZE6 ? &vector_compare_peer6 : &vector_compare_peer4; | ||
| 164 | 181 | ||
| 165 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { | 182 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { |
| 166 | num_buckets_old = peer_list->peers.size; | 183 | num_buckets_old = peer_list->peers.size; |
| @@ -198,33 +215,33 @@ void vector_redistribute_buckets( ot_peerlist * peer_list ) { | |||
| 198 | /* preallocate vectors to hold all peers */ | 215 | /* preallocate vectors to hold all peers */ |
| 199 | for( bucket=0; bucket<num_buckets_new; ++bucket ) { | 216 | for( bucket=0; bucket<num_buckets_new; ++bucket ) { |
| 200 | bucket_list_new[bucket].space = bucket_size_new; | 217 | bucket_list_new[bucket].space = bucket_size_new; |
| 201 | bucket_list_new[bucket].data = malloc( bucket_size_new * sizeof(ot_peer) ); | 218 | bucket_list_new[bucket].data = malloc( bucket_size_new * peer_size ); |
| 202 | if( !bucket_list_new[bucket].data ) | 219 | if( !bucket_list_new[bucket].data ) |
| 203 | return vector_clean_list( bucket_list_new, num_buckets_new ); | 220 | return vector_clean_list( bucket_list_new, num_buckets_new ); |
| 204 | } | 221 | } |
| 205 | 222 | ||
| 206 | /* Now sort them into the correct bucket */ | 223 | /* Now sort them into the correct bucket */ |
| 207 | for( bucket=0; bucket<num_buckets_old; ++bucket ) { | 224 | for( bucket=0; bucket<num_buckets_old; ++bucket ) { |
| 208 | ot_peer * peers_old = bucket_list_old[bucket].data, * peers_new; | 225 | ot_peer * peers_old = bucket_list_old[bucket].data; |
| 209 | int peer_count_old = bucket_list_old[bucket].size; | 226 | int peer_count_old = bucket_list_old[bucket].size; |
| 210 | while( peer_count_old-- ) { | 227 | while( peer_count_old-- ) { |
| 211 | ot_vector * bucket_dest = bucket_list_new; | 228 | ot_vector * bucket_dest = bucket_list_new; |
| 212 | if( num_buckets_new > 1 ) | 229 | if( num_buckets_new > 1 ) |
| 213 | bucket_dest += vector_hash_peer(peers_old, num_buckets_new); | 230 | bucket_dest += vector_hash_peer(peers_old, OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size), num_buckets_new); |
| 214 | if( bucket_dest->size + 1 > bucket_dest->space ) { | 231 | if( bucket_dest->size + 1 > bucket_dest->space ) { |
| 215 | void * tmp = realloc( bucket_dest->data, sizeof(ot_peer) * OT_VECTOR_GROW_RATIO * bucket_dest->space ); | 232 | void * tmp = realloc( bucket_dest->data, peer_size * OT_VECTOR_GROW_RATIO * bucket_dest->space ); |
| 216 | if( !tmp ) return vector_clean_list( bucket_list_new, num_buckets_new ); | 233 | if( !tmp ) return vector_clean_list( bucket_list_new, num_buckets_new ); |
| 217 | bucket_dest->data = tmp; | 234 | bucket_dest->data = tmp; |
| 218 | bucket_dest->space *= OT_VECTOR_GROW_RATIO; | 235 | bucket_dest->space *= OT_VECTOR_GROW_RATIO; |
| 219 | } | 236 | } |
| 220 | peers_new = (ot_peer*)bucket_dest->data; | 237 | memcpy((ot_peer*)bucket_dest->data + peer_size * bucket_dest->size++, peers_old, peer_size); |
| 221 | memcpy(peers_new + bucket_dest->size++, peers_old++, sizeof(ot_peer)); | 238 | peers_old += peer_size; |
| 222 | } | 239 | } |
| 223 | } | 240 | } |
| 224 | 241 | ||
| 225 | /* Now sort each bucket to later allow bsearch */ | 242 | /* Now sort each bucket to later allow bsearch */ |
| 226 | for( bucket=0; bucket<num_buckets_new; ++bucket ) | 243 | for( bucket=0; bucket<num_buckets_new; ++bucket ) |
| 227 | qsort( bucket_list_new[bucket].data, bucket_list_new[bucket].size, sizeof( ot_peer ), vector_compare_peer ); | 244 | qsort( bucket_list_new[bucket].data, bucket_list_new[bucket].size, peer_size, sort_func ); |
| 228 | 245 | ||
| 229 | /* Everything worked fine. Now link new bucket_list to peer_list */ | 246 | /* Everything worked fine. Now link new bucket_list to peer_list */ |
| 230 | if( OT_PEERLIST_HASBUCKETS( peer_list) ) | 247 | if( OT_PEERLIST_HASBUCKETS( peer_list) ) |
| @@ -244,7 +261,7 @@ void vector_redistribute_buckets( ot_peerlist * peer_list ) { | |||
| 244 | } | 261 | } |
| 245 | } | 262 | } |
| 246 | 263 | ||
| 247 | void vector_fixup_peers( ot_vector * vector ) { | 264 | void vector_fixup_peers( ot_vector * vector, size_t peer_size ) { |
| 248 | int need_fix = 0; | 265 | int need_fix = 0; |
| 249 | 266 | ||
| 250 | if( !vector->size ) { | 267 | if( !vector->size ) { |
| @@ -260,7 +277,7 @@ void vector_fixup_peers( ot_vector * vector ) { | |||
| 260 | need_fix++; | 277 | need_fix++; |
| 261 | } | 278 | } |
| 262 | if( need_fix ) | 279 | if( need_fix ) |
| 263 | vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) ); | 280 | vector->data = realloc( vector->data, vector->space * peer_size ); |
| 264 | } | 281 | } |
| 265 | 282 | ||
| 266 | const char *g_version_vector_c = "$Source$: $Revision$\n"; | 283 | const char *g_version_vector_c = "$Source$: $Revision$\n"; |
diff --git a/ot_vector.h b/ot_vector.h index f7f87aa..f60c291 100644 --- a/ot_vector.h +++ b/ot_vector.h | |||
| @@ -24,11 +24,13 @@ typedef struct { | |||
| 24 | void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size, | 24 | void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size, |
| 25 | size_t compare_size, int *exactmatch ); | 25 | size_t compare_size, int *exactmatch ); |
| 26 | void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ); | 26 | void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ); |
| 27 | ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer *peer, int *exactmatch ); | 27 | ot_peer *vector_find_or_insert_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size, int *exactmatch ); |
| 28 | 28 | ||
| 29 | int vector_remove_peer( ot_vector *vector, ot_peer *peer ); | 29 | int vector_remove_peer( ot_vector *vector, ot_peer const *peer, size_t peer_size); |
| 30 | void vector_remove_torrent( ot_vector *vector, ot_torrent *match ); | 30 | void vector_remove_torrent( ot_vector *vector, ot_torrent *match ); |
| 31 | void vector_redistribute_buckets( ot_peerlist * peer_list ); | 31 | |
| 32 | void vector_fixup_peers( ot_vector * vector ); | 32 | /* For ot_clean.c */ |
| 33 | void vector_redistribute_buckets( ot_peerlist * peer_list, size_t peer_size ); | ||
| 34 | void vector_fixup_peers( ot_vector * vector, size_t peer_size ); | ||
| 33 | 35 | ||
| 34 | #endif | 36 | #endif |
diff --git a/trackerlogic.c b/trackerlogic.c index 47e0085..9d564c1 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "byte.h" | 16 | #include "byte.h" |
| 17 | #include "io.h" | 17 | #include "io.h" |
| 18 | #include "iob.h" | 18 | #include "iob.h" |
| 19 | #include "ip6.h" | ||
| 19 | #include "array.h" | 20 | #include "array.h" |
| 20 | 21 | ||
| 21 | /* Opentracker */ | 22 | /* Opentracker */ |
| @@ -57,25 +58,33 @@ void add_torrent_from_saved_state( ot_hash hash, ot_time base, size_t down_count | |||
| 57 | return mutex_bucket_unlock_by_hash( hash, 0 ); | 58 | return mutex_bucket_unlock_by_hash( hash, 0 ); |
| 58 | 59 | ||
| 59 | /* Create a new torrent entry, then */ | 60 | /* Create a new torrent entry, then */ |
| 61 | byte_zero( torrent, sizeof( ot_torrent ) ); | ||
| 60 | memcpy( torrent->hash, hash, sizeof(ot_hash) ); | 62 | memcpy( torrent->hash, hash, sizeof(ot_hash) ); |
| 61 | 63 | ||
| 62 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { | 64 | if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || |
| 65 | !( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) { | ||
| 63 | vector_remove_torrent( torrents_list, torrent ); | 66 | vector_remove_torrent( torrents_list, torrent ); |
| 64 | return mutex_bucket_unlock_by_hash( hash, 0 ); | 67 | return mutex_bucket_unlock_by_hash( hash, 0 ); |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); | 70 | byte_zero( torrent->peer_list6, sizeof( ot_peerlist ) ); |
| 68 | torrent->peer_list->base = base; | 71 | byte_zero( torrent->peer_list4, sizeof( ot_peerlist ) ); |
| 69 | torrent->peer_list->down_count = down_count; | 72 | torrent->peer_list6->base = base; |
| 73 | torrent->peer_list4->base = base; | ||
| 74 | torrent->peer_list6->down_count = down_count; | ||
| 75 | torrent->peer_list4->down_count = down_count; | ||
| 70 | 76 | ||
| 71 | return mutex_bucket_unlock_by_hash( hash, 1 ); | 77 | return mutex_bucket_unlock_by_hash( hash, 1 ); |
| 72 | } | 78 | } |
| 73 | 79 | ||
| 74 | size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount ) { | 80 | size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount ) { |
| 75 | int exactmatch, delta_torrentcount = 0; | 81 | int exactmatch, delta_torrentcount = 0; |
| 76 | ot_torrent *torrent; | 82 | ot_torrent *torrent; |
| 77 | ot_peer *peer_dest; | 83 | ot_peer *peer_dest; |
| 78 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); | 84 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); |
| 85 | ot_peerlist *peer_list; | ||
| 86 | size_t peer_size; /* initialized in next line */ | ||
| 87 | ot_peer *peer_src = peer_from_peer6(&ws->peer, &peer_size); | ||
| 79 | 88 | ||
| 80 | if( !accesslist_hashisvalid( *ws->hash ) ) { | 89 | if( !accesslist_hashisvalid( *ws->hash ) ) { |
| 81 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | 90 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); |
| @@ -95,82 +104,88 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr | |||
| 95 | 104 | ||
| 96 | if( !exactmatch ) { | 105 | if( !exactmatch ) { |
| 97 | /* Create a new torrent entry, then */ | 106 | /* Create a new torrent entry, then */ |
| 107 | byte_zero( torrent, sizeof(ot_torrent)); | ||
| 98 | memcpy( torrent->hash, *ws->hash, sizeof(ot_hash) ); | 108 | memcpy( torrent->hash, *ws->hash, sizeof(ot_hash) ); |
| 99 | 109 | ||
| 100 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { | 110 | if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || |
| 111 | !( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) { | ||
| 101 | vector_remove_torrent( torrents_list, torrent ); | 112 | vector_remove_torrent( torrents_list, torrent ); |
| 102 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | 113 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); |
| 103 | return 0; | 114 | return 0; |
| 104 | } | 115 | } |
| 105 | 116 | ||
| 106 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); | 117 | byte_zero( torrent->peer_list6, sizeof( ot_peerlist ) ); |
| 118 | byte_zero( torrent->peer_list4, sizeof( ot_peerlist ) ); | ||
| 107 | delta_torrentcount = 1; | 119 | delta_torrentcount = 1; |
| 108 | } else | 120 | } else |
| 109 | clean_single_torrent( torrent ); | 121 | clean_single_torrent( torrent ); |
| 110 | 122 | ||
| 111 | torrent->peer_list->base = g_now_minutes; | 123 | torrent->peer_list6->base = g_now_minutes; |
| 124 | torrent->peer_list4->base = g_now_minutes; | ||
| 125 | |||
| 126 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | ||
| 112 | 127 | ||
| 113 | /* Check for peer in torrent */ | 128 | /* Check for peer in torrent */ |
| 114 | peer_dest = vector_find_or_insert_peer( &(torrent->peer_list->peers), &ws->peer, &exactmatch ); | 129 | peer_dest = vector_find_or_insert_peer( &(peer_list->peers), peer_src, peer_size, &exactmatch ); |
| 115 | if( !peer_dest ) { | 130 | if( !peer_dest ) { |
| 116 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); | 131 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); |
| 117 | return 0; | 132 | return 0; |
| 118 | } | 133 | } |
| 119 | 134 | ||
| 120 | /* Tell peer that it's fresh */ | 135 | /* Tell peer that it's fresh */ |
| 121 | OT_PEERTIME( &ws->peer ) = 0; | 136 | OT_PEERTIME( ws->peer, OT_PEER_SIZE6 ) = 0; |
| 122 | 137 | ||
| 123 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ | 138 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ |
| 124 | if( ( OT_PEERFLAG( &ws->peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) | 139 | if( ( OT_PEERFLAG( ws->peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) |
| 125 | OT_PEERFLAG( &ws->peer ) ^= PEER_FLAG_COMPLETED; | 140 | OT_PEERFLAG( ws->peer ) ^= PEER_FLAG_COMPLETED; |
| 126 | 141 | ||
| 127 | /* If we hadn't had a match create peer there */ | 142 | /* If we hadn't had a match create peer there */ |
| 128 | if( !exactmatch ) { | 143 | if( !exactmatch ) { |
| 129 | 144 | ||
| 130 | #ifdef WANT_SYNC_LIVE | 145 | #ifdef WANT_SYNC_LIVE |
| 131 | if( proto == FLAG_MCA ) | 146 | if( proto == FLAG_MCA ) |
| 132 | OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_FROM_SYNC; | 147 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_FROM_SYNC; |
| 133 | else | 148 | else |
| 134 | livesync_tell( ws ); | 149 | livesync_tell( ws ); |
| 135 | #endif | 150 | #endif |
| 136 | 151 | ||
| 137 | torrent->peer_list->peer_count++; | 152 | peer_list->peer_count++; |
| 138 | if( OT_PEERFLAG(&ws->peer) & PEER_FLAG_COMPLETED ) { | 153 | if( OT_PEERFLAG( ws->peer ) & PEER_FLAG_COMPLETED ) { |
| 139 | torrent->peer_list->down_count++; | 154 | peer_list->down_count++; |
| 140 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); | 155 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); |
| 141 | } | 156 | } |
| 142 | if( OT_PEERFLAG(&ws->peer) & PEER_FLAG_SEEDING ) | 157 | if( OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) |
| 143 | torrent->peer_list->seed_count++; | 158 | peer_list->seed_count++; |
| 144 | 159 | ||
| 145 | } else { | 160 | } else { |
| 146 | stats_issue_event( EVENT_RENEW, 0, OT_PEERTIME( peer_dest ) ); | 161 | stats_issue_event( EVENT_RENEW, 0, OT_PEERTIME( peer_dest, peer_size ) ); |
| 147 | #ifdef WANT_SPOT_WOODPECKER | 162 | #ifdef WANT_SPOT_WOODPECKER |
| 148 | if( ( OT_PEERTIME(peer_dest) > 0 ) && ( OT_PEERTIME(peer_dest) < 20 ) ) | 163 | if( ( OT_PEERTIME(peer_dest, peer_size) > 0 ) && ( OT_PEERTIME(peer_dest, peer_size) < 20 ) ) |
| 149 | stats_issue_event( EVENT_WOODPECKER, 0, (uintptr_t)&ws->peer ); | 164 | stats_issue_event( EVENT_WOODPECKER, 0, (uintptr_t)&ws->peer ); |
| 150 | #endif | 165 | #endif |
| 151 | #ifdef WANT_SYNC_LIVE | 166 | #ifdef WANT_SYNC_LIVE |
| 152 | /* Won't live sync peers that come back too fast. Only exception: | 167 | /* Won't live sync peers that come back too fast. Only exception: |
| 153 | fresh "completed" reports */ | 168 | fresh "completed" reports */ |
| 154 | if( proto != FLAG_MCA ) { | 169 | if( proto != FLAG_MCA ) { |
| 155 | if( OT_PEERTIME( peer_dest ) > OT_CLIENT_SYNC_RENEW_BOUNDARY || | 170 | if( OT_PEERTIME( peer_dest, peer_size ) > OT_CLIENT_SYNC_RENEW_BOUNDARY || |
| 156 | ( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(&ws->peer) & PEER_FLAG_COMPLETED ) ) ) | 171 | ( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED ) ) ) |
| 157 | livesync_tell( ws ); | 172 | livesync_tell( ws ); |
| 158 | } | 173 | } |
| 159 | #endif | 174 | #endif |
| 160 | 175 | ||
| 161 | if( (OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_PEERFLAG(&ws->peer) & PEER_FLAG_SEEDING ) ) | 176 | if( (OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING ) && !(OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) ) |
| 162 | torrent->peer_list->seed_count--; | 177 | peer_list->seed_count--; |
| 163 | if( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_PEERFLAG(&ws->peer) & PEER_FLAG_SEEDING ) ) | 178 | if( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) ) |
| 164 | torrent->peer_list->seed_count++; | 179 | peer_list->seed_count++; |
| 165 | if( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(&ws->peer) & PEER_FLAG_COMPLETED ) ) { | 180 | if( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED ) ) { |
| 166 | torrent->peer_list->down_count++; | 181 | peer_list->down_count++; |
| 167 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); | 182 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); |
| 168 | } | 183 | } |
| 169 | if( OT_PEERFLAG(peer_dest) & PEER_FLAG_COMPLETED ) | 184 | if( OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) |
| 170 | OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_COMPLETED; | 185 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_COMPLETED; |
| 171 | } | 186 | } |
| 172 | 187 | ||
| 173 | memcpy( peer_dest, &ws->peer, sizeof(ot_peer) ); | 188 | memcpy( peer_dest, peer_src, peer_size ); |
| 174 | #ifdef WANT_SYNC | 189 | #ifdef WANT_SYNC |
| 175 | if( proto == FLAG_MCA ) { | 190 | if( proto == FLAG_MCA ) { |
| 176 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); | 191 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); |
| @@ -183,10 +198,11 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr | |||
| 183 | return ws->reply_size; | 198 | return ws->reply_size; |
| 184 | } | 199 | } |
| 185 | 200 | ||
| 186 | static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { | 201 | static size_t return_peers_all( ot_peerlist *peer_list, size_t peer_size, char *reply ) { |
| 187 | unsigned int bucket, num_buckets = 1; | 202 | unsigned int bucket, num_buckets = 1; |
| 188 | ot_vector * bucket_list = &peer_list->peers; | 203 | ot_vector * bucket_list = &peer_list->peers; |
| 189 | size_t result = OT_PEER_COMPARE_SIZE * peer_list->peer_count; | 204 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); |
| 205 | size_t result = compare_size * peer_list->peer_count; | ||
| 190 | char * r_end = reply + result; | 206 | char * r_end = reply + result; |
| 191 | 207 | ||
| 192 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { | 208 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { |
| @@ -195,28 +211,30 @@ static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { | |||
| 195 | } | 211 | } |
| 196 | 212 | ||
| 197 | for( bucket = 0; bucket<num_buckets; ++bucket ) { | 213 | for( bucket = 0; bucket<num_buckets; ++bucket ) { |
| 198 | ot_peer * peers = (ot_peer*)bucket_list[bucket].data; | 214 | ot_peer *peers = bucket_list[bucket].data; |
| 199 | size_t peer_count = bucket_list[bucket].size; | 215 | size_t peer_count = bucket_list[bucket].size; |
| 200 | while( peer_count-- ) { | 216 | while( peer_count-- ) { |
| 201 | if( OT_PEERFLAG(peers) & PEER_FLAG_SEEDING ) { | 217 | if( OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING ) { |
| 202 | r_end-=OT_PEER_COMPARE_SIZE; | 218 | r_end -= peer_size; |
| 203 | memcpy(r_end,peers++,OT_PEER_COMPARE_SIZE); | 219 | memcpy( r_end, peers, compare_size); |
| 204 | } else { | 220 | } else { |
| 205 | memcpy(reply,peers++,OT_PEER_COMPARE_SIZE); | 221 | memcpy( reply, peers, compare_size ); |
| 206 | reply+=OT_PEER_COMPARE_SIZE; | 222 | reply += compare_size; |
| 207 | } | 223 | } |
| 224 | peers += peer_size; | ||
| 208 | } | 225 | } |
| 209 | } | 226 | } |
| 210 | return result; | 227 | return result; |
| 211 | } | 228 | } |
| 212 | 229 | ||
| 213 | static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t amount, char *reply ) { | 230 | static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply ) { |
| 214 | unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; | 231 | unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; |
| 215 | ot_vector * bucket_list = &peer_list->peers; | 232 | ot_vector * bucket_list = &peer_list->peers; |
| 216 | unsigned int shifted_pc = peer_list->peer_count; | 233 | unsigned int shifted_pc = peer_list->peer_count; |
| 217 | unsigned int shifted_step = 0; | 234 | unsigned int shifted_step = 0; |
| 218 | unsigned int shift = 0; | 235 | unsigned int shift = 0; |
| 219 | size_t result = OT_PEER_COMPARE_SIZE * amount; | 236 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); |
| 237 | size_t result = compare_size * amount; | ||
| 220 | char * r_end = reply + result; | 238 | char * r_end = reply + result; |
| 221 | 239 | ||
| 222 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { | 240 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { |
| @@ -235,7 +253,7 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee | |||
| 235 | bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; | 253 | bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; |
| 236 | 254 | ||
| 237 | while( amount-- ) { | 255 | while( amount-- ) { |
| 238 | ot_peer * peer; | 256 | ot_peer *peer; |
| 239 | 257 | ||
| 240 | /* This is the aliased, non shifted range, next value may fall into */ | 258 | /* This is the aliased, non shifted range, next value may fall into */ |
| 241 | unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - | 259 | unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - |
| @@ -246,13 +264,13 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee | |||
| 246 | bucket_offset -= bucket_list[bucket_index].size; | 264 | bucket_offset -= bucket_list[bucket_index].size; |
| 247 | bucket_index = ( bucket_index + 1 ) % num_buckets; | 265 | bucket_index = ( bucket_index + 1 ) % num_buckets; |
| 248 | } | 266 | } |
| 249 | peer = ((ot_peer*)bucket_list[bucket_index].data) + bucket_offset; | 267 | peer = bucket_list[bucket_index].data + peer_size * bucket_offset; |
| 250 | if( OT_PEERFLAG(peer) & PEER_FLAG_SEEDING ) { | 268 | if( OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING ) { |
| 251 | r_end-=OT_PEER_COMPARE_SIZE; | 269 | r_end -= compare_size; |
| 252 | memcpy(r_end,peer,OT_PEER_COMPARE_SIZE); | 270 | memcpy(r_end, peer, compare_size); |
| 253 | } else { | 271 | } else { |
| 254 | memcpy(reply,peer,OT_PEER_COMPARE_SIZE); | 272 | memcpy(reply, peer, compare_size); |
| 255 | reply+=OT_PEER_COMPARE_SIZE; | 273 | reply += compare_size; |
| 256 | } | 274 | } |
| 257 | } | 275 | } |
| 258 | return result; | 276 | return result; |
| @@ -267,15 +285,17 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee | |||
| 267 | * Does not yet check not to return self | 285 | * Does not yet check not to return self |
| 268 | */ | 286 | */ |
| 269 | size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { | 287 | size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { |
| 270 | ot_peerlist *peer_list = torrent->peer_list; | 288 | size_t peer_size = peer_size_from_peer6(&ws->peer); |
| 289 | ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | ||
| 271 | char *r = reply; | 290 | char *r = reply; |
| 291 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | ||
| 272 | 292 | ||
| 273 | if( amount > peer_list->peer_count ) | 293 | if( amount > peer_list->peer_count ) |
| 274 | amount = peer_list->peer_count; | 294 | amount = peer_list->peer_count; |
| 275 | 295 | ||
| 276 | if( proto == FLAG_TCP ) { | 296 | if( proto == FLAG_TCP ) { |
| 277 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 297 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
| 278 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie" PEERS_BENCODED "%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, OT_PEER_COMPARE_SIZE*amount ); | 298 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4, compare_size * amount ); |
| 279 | } else { | 299 | } else { |
| 280 | *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 300 | *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); |
| 281 | *(uint32_t*)(r+4) = htonl( peer_list->peer_count - peer_list->seed_count ); | 301 | *(uint32_t*)(r+4) = htonl( peer_list->peer_count - peer_list->seed_count ); |
| @@ -285,9 +305,9 @@ size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, | |||
| 285 | 305 | ||
| 286 | if( amount ) { | 306 | if( amount ) { |
| 287 | if( amount == peer_list->peer_count ) | 307 | if( amount == peer_list->peer_count ) |
| 288 | r += return_peers_all( peer_list, r ); | 308 | r += return_peers_all( peer_list, peer_size, r ); |
| 289 | else | 309 | else |
| 290 | r += return_peers_selection( ws, peer_list, amount, r ); | 310 | r += return_peers_selection( ws, peer_list, peer_size, amount, r ); |
| 291 | } | 311 | } |
| 292 | 312 | ||
| 293 | if( proto == FLAG_TCP ) | 313 | if( proto == FLAG_TCP ) |
| @@ -312,9 +332,10 @@ size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply ) { | |||
| 312 | memset( reply, 0, 12); | 332 | memset( reply, 0, 12); |
| 313 | delta_torrentcount = -1; | 333 | delta_torrentcount = -1; |
| 314 | } else { | 334 | } else { |
| 315 | r[0] = htonl( torrent->peer_list->seed_count ); | 335 | r[0] = htonl( torrent->peer_list6->seed_count + torrent->peer_list4->seed_count ); |
| 316 | r[1] = htonl( torrent->peer_list->down_count ); | 336 | r[1] = htonl( torrent->peer_list6->down_count + torrent->peer_list4->down_count ); |
| 317 | r[2] = htonl( torrent->peer_list->peer_count-torrent->peer_list->seed_count ); | 337 | r[2] = htonl( torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - |
| 338 | torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); | ||
| 318 | } | 339 | } |
| 319 | } | 340 | } |
| 320 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); | 341 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); |
| @@ -342,7 +363,10 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl | |||
| 342 | *r++='2';*r++='0';*r++=':'; | 363 | *r++='2';*r++='0';*r++=':'; |
| 343 | memcpy( r, hash, sizeof(ot_hash) ); r+=sizeof(ot_hash); | 364 | memcpy( r, hash, sizeof(ot_hash) ); r+=sizeof(ot_hash); |
| 344 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", | 365 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", |
| 345 | torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count ); | 366 | torrent->peer_list6->seed_count + torrent->peer_list4->seed_count, |
| 367 | torrent->peer_list6->down_count + torrent->peer_list4->down_count, | ||
| 368 | torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - | ||
| 369 | torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); | ||
| 346 | } | 370 | } |
| 347 | } | 371 | } |
| 348 | mutex_bucket_unlock_by_hash( *hash, delta_torrentcount ); | 372 | mutex_bucket_unlock_by_hash( *hash, delta_torrentcount ); |
| @@ -358,17 +382,19 @@ size_t remove_peer_from_torrent( PROTO_FLAG proto, struct ot_workstruct *ws ) { | |||
| 358 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); | 382 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); |
| 359 | ot_torrent *torrent = binary_search( ws->hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 383 | ot_torrent *torrent = binary_search( ws->hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
| 360 | ot_peerlist *peer_list = &dummy_list; | 384 | ot_peerlist *peer_list = &dummy_list; |
| 385 | size_t peer_size; /* initialized in next line */ | ||
| 386 | ot_peer *peer_src = peer_from_peer6(&ws->peer, &peer_size); | ||
| 361 | 387 | ||
| 362 | #ifdef WANT_SYNC_LIVE | 388 | #ifdef WANT_SYNC_LIVE |
| 363 | if( proto != FLAG_MCA ) { | 389 | if( proto != FLAG_MCA ) { |
| 364 | OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_STOPPED; | 390 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_STOPPED; |
| 365 | livesync_tell( ws ); | 391 | livesync_tell( ws ); |
| 366 | } | 392 | } |
| 367 | #endif | 393 | #endif |
| 368 | 394 | ||
| 369 | if( exactmatch ) { | 395 | if( exactmatch ) { |
| 370 | peer_list = torrent->peer_list; | 396 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; |
| 371 | switch( vector_remove_peer( &peer_list->peers, &ws->peer ) ) { | 397 | switch( vector_remove_peer( &peer_list->peers, peer_src, peer_size ) ) { |
| 372 | case 2: peer_list->seed_count--; /* Intentional fallthrough */ | 398 | case 2: peer_list->seed_count--; /* Intentional fallthrough */ |
| 373 | case 1: peer_list->peer_count--; /* Intentional fallthrough */ | 399 | case 1: peer_list->peer_count--; /* Intentional fallthrough */ |
| 374 | default: break; | 400 | default: break; |
| @@ -377,7 +403,7 @@ size_t remove_peer_from_torrent( PROTO_FLAG proto, struct ot_workstruct *ws ) { | |||
| 377 | 403 | ||
| 378 | if( proto == FLAG_TCP ) { | 404 | if( proto == FLAG_TCP ) { |
| 379 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 405 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
| 380 | ws->reply_size = sprintf( ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie" PEERS_BENCODED "0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, erval, erval / 2 ); | 406 | ws->reply_size = sprintf( ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, erval, erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4 ); |
| 381 | } | 407 | } |
| 382 | 408 | ||
| 383 | /* Handle UDP reply */ | 409 | /* Handle UDP reply */ |
| @@ -409,6 +435,23 @@ void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data | |||
| 409 | } | 435 | } |
| 410 | } | 436 | } |
| 411 | 437 | ||
| 438 | ot_peer *peer_from_peer6( ot_peer6 *peer, size_t *peer_size ) { | ||
| 439 | ot_ip6 *ip = (ot_ip6*)peer; | ||
| 440 | if( !ip6_isv4mapped(ip) ) { | ||
| 441 | *peer_size = OT_PEER_SIZE6; | ||
| 442 | return (ot_peer*)peer; | ||
| 443 | } | ||
| 444 | *peer_size = OT_PEER_SIZE4; | ||
| 445 | return (ot_peer*)(((uint8_t*)peer) + 12); | ||
| 446 | } | ||
| 447 | |||
| 448 | size_t peer_size_from_peer6(ot_peer6 *peer) { | ||
| 449 | ot_ip6 *ip = (ot_ip6*)peer; | ||
| 450 | if( !ip6_isv4mapped(ip)) | ||
| 451 | return OT_PEER_SIZE6; | ||
| 452 | return OT_PEER_SIZE4; | ||
| 453 | } | ||
| 454 | |||
| 412 | void exerr( char * message ) { | 455 | void exerr( char * message ) { |
| 413 | fprintf( stderr, "%s\n", message ); | 456 | fprintf( stderr, "%s\n", message ); |
| 414 | exit( 111 ); | 457 | exit( 111 ); |
| @@ -440,7 +483,8 @@ void trackerlogic_deinit( void ) { | |||
| 440 | if( torrents_list->size ) { | 483 | if( torrents_list->size ) { |
| 441 | for( j=0; j<torrents_list->size; ++j ) { | 484 | for( j=0; j<torrents_list->size; ++j ) { |
| 442 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + j; | 485 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + j; |
| 443 | free_peerlist( torrent->peer_list ); | 486 | free_peerlist( torrent->peer_list6 ); |
| 487 | free_peerlist( torrent->peer_list4 ); | ||
| 444 | delta_torrentcount -= 1; | 488 | delta_torrentcount -= 1; |
| 445 | } | 489 | } |
| 446 | free( torrents_list->data ); | 490 | free( torrents_list->data ); |
diff --git a/trackerlogic.h b/trackerlogic.h index f43b4f1..24ef097 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
| @@ -24,16 +24,12 @@ typedef time_t ot_time; | |||
| 24 | typedef char ot_ip6[16]; | 24 | typedef char ot_ip6[16]; |
| 25 | typedef struct { ot_ip6 address; int bits; } | 25 | typedef struct { ot_ip6 address; int bits; } |
| 26 | ot_net; | 26 | ot_net; |
| 27 | #ifdef WANT_V6 | ||
| 28 | #define OT_IP_SIZE 16 | ||
| 29 | #define PEERS_BENCODED "6:peers6" | ||
| 30 | /* List of peers should fit in a single UDP packet (around 1200 bytes) */ | 27 | /* List of peers should fit in a single UDP packet (around 1200 bytes) */ |
| 31 | #define OT_MAX_PEERS_UDP 66 | 28 | #define OT_MAX_PEERS_UDP6 66 |
| 32 | #else | 29 | #define OT_MAX_PEERS_UDP4 200 |
| 33 | #define OT_IP_SIZE 4 | 30 | |
| 34 | #define PEERS_BENCODED "5:peers" | 31 | #define OT_IP_SIZE6 16 |
| 35 | #define OT_MAX_PEERS_UDP 200 | 32 | #define OT_IP_SIZE4 4 |
| 36 | #endif | ||
| 37 | #define OT_PORT_SIZE 2 | 33 | #define OT_PORT_SIZE 2 |
| 38 | #define OT_FLAG_SIZE 1 | 34 | #define OT_FLAG_SIZE 1 |
| 39 | #define OT_TIME_SIZE 1 | 35 | #define OT_TIME_SIZE 1 |
| @@ -61,6 +57,7 @@ typedef struct { ot_ip6 address; int bits; } | |||
| 61 | #define OT_ADMINIP_MAX 64 | 57 | #define OT_ADMINIP_MAX 64 |
| 62 | #define OT_MAX_THREADS 64 | 58 | #define OT_MAX_THREADS 64 |
| 63 | 59 | ||
| 60 | /* Number of minutes after announce before peer is removed */ | ||
| 64 | #define OT_PEER_TIMEOUT 45 | 61 | #define OT_PEER_TIMEOUT 45 |
| 65 | 62 | ||
| 66 | /* We maintain a list of 1024 pointers to sorted list of ot_torrent structs | 63 | /* We maintain a list of 1024 pointers to sorted list of ot_torrent structs |
| @@ -78,23 +75,35 @@ extern volatile int g_opentracker_running; | |||
| 78 | extern uint32_t g_tracker_id; | 75 | extern uint32_t g_tracker_id; |
| 79 | typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA, FLAG_SELFPIPE } PROTO_FLAG; | 76 | typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA, FLAG_SELFPIPE } PROTO_FLAG; |
| 80 | 77 | ||
| 81 | #define OT_PEER_COMPARE_SIZE ((OT_IP_SIZE)+(OT_PORT_SIZE)) | 78 | #define OT_PEER_COMPARE_SIZE6 ((OT_IP_SIZE6)+(OT_PORT_SIZE)) |
| 82 | #define OT_PEER_SIZE ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE)) | 79 | #define OT_PEER_COMPARE_SIZE4 ((OT_IP_SIZE4)+(OT_PORT_SIZE)) |
| 83 | typedef uint8_t ot_peer[OT_PEER_SIZE]; | 80 | #define OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(PEER_SIZE) ((PEER_SIZE)-(OT_TIME_SIZE)-(OT_FLAG_SIZE)) |
| 81 | |||
| 82 | #define OT_PEER_SIZE6 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE6)) | ||
| 83 | #define OT_PEER_SIZE4 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE4)) | ||
| 84 | |||
| 85 | typedef uint8_t ot_peer[1]; | ||
| 86 | typedef uint8_t ot_peer6[OT_PEER_SIZE6]; | ||
| 87 | typedef uint8_t ot_peer4[OT_PEER_SIZE4]; | ||
| 84 | static const uint8_t PEER_FLAG_SEEDING = 0x80; | 88 | static const uint8_t PEER_FLAG_SEEDING = 0x80; |
| 85 | static const uint8_t PEER_FLAG_COMPLETED = 0x40; | 89 | static const uint8_t PEER_FLAG_COMPLETED = 0x40; |
| 86 | static const uint8_t PEER_FLAG_STOPPED = 0x20; | 90 | static const uint8_t PEER_FLAG_STOPPED = 0x20; |
| 87 | static const uint8_t PEER_FLAG_FROM_SYNC = 0x10; | 91 | static const uint8_t PEER_FLAG_FROM_SYNC = 0x10; |
| 88 | static const uint8_t PEER_FLAG_LEECHING = 0x00; | 92 | static const uint8_t PEER_FLAG_LEECHING = 0x00; |
| 89 | 93 | ||
| 90 | #ifdef WANT_V6 | 94 | /* Takes an ot_peer6 and returns the proper pointer to the peer and sets peer_size */ |
| 91 | #define OT_SETIP(peer,ip) memcpy((peer),(ip),(OT_IP_SIZE)) | 95 | ot_peer *peer_from_peer6(ot_peer6 *peer, size_t *peer_size); |
| 92 | #else | 96 | size_t peer_size_from_peer6(ot_peer6 *peer); |
| 93 | #define OT_SETIP(peer,ip) memcpy((peer),(((uint8_t*)ip)+12),(OT_IP_SIZE)) | 97 | |
| 94 | #endif | 98 | /* New style */ |
| 95 | #define OT_SETPORT(peer,port) memcpy(((uint8_t*)(peer))+(OT_IP_SIZE),(port),2) | 99 | #define OT_SETIP(peer,ip) memcpy((peer),(ip),OT_IP_SIZE6) |
| 96 | #define OT_PEERFLAG(peer) (((uint8_t*)(peer))[(OT_IP_SIZE)+2]) | 100 | #define OT_SETPORT(peer,port) memcpy(((uint8_t*)(peer))+(OT_IP_SIZE6),(port),2) |
| 97 | #define OT_PEERTIME(peer) (((uint8_t*)(peer))[(OT_IP_SIZE)+3]) | 101 | #define OT_PEERFLAG(peer) (((uint8_t*)(peer))[(OT_IP_SIZE6)+2]) |
| 102 | #define OT_PEERFLAG_D(peer,peersize) (((uint8_t*)(peer))[(peersize)-2]) | ||
| 103 | #define OT_PEERTIME(peer,peersize) (((uint8_t*)(peer))[(peersize)-1]) | ||
| 104 | |||
| 105 | #define PEERS_BENCODED6 "6:peers6" | ||
| 106 | #define PEERS_BENCODED4 "5:peers" | ||
| 98 | 107 | ||
| 99 | #define OT_HASH_COMPARE_SIZE (sizeof(ot_hash)) | 108 | #define OT_HASH_COMPARE_SIZE (sizeof(ot_hash)) |
| 100 | 109 | ||
| @@ -102,7 +111,8 @@ struct ot_peerlist; | |||
| 102 | typedef struct ot_peerlist ot_peerlist; | 111 | typedef struct ot_peerlist ot_peerlist; |
| 103 | typedef struct { | 112 | typedef struct { |
| 104 | ot_hash hash; | 113 | ot_hash hash; |
| 105 | ot_peerlist *peer_list; | 114 | ot_peerlist *peer_list6; |
| 115 | ot_peerlist *peer_list4; | ||
| 106 | } ot_torrent; | 116 | } ot_torrent; |
| 107 | 117 | ||
| 108 | #include "ot_vector.h" | 118 | #include "ot_vector.h" |
| @@ -131,7 +141,7 @@ struct ot_workstruct { | |||
| 131 | #endif | 141 | #endif |
| 132 | 142 | ||
| 133 | /* The peer currently in the working */ | 143 | /* The peer currently in the working */ |
| 134 | ot_peer peer; | 144 | ot_peer6 peer; /* Can fit v6 and v4 peers */ |
| 135 | 145 | ||
| 136 | /* Pointers into the request buffer */ | 146 | /* Pointers into the request buffer */ |
| 137 | ot_hash *hash; | 147 | ot_hash *hash; |
