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; |