summaryrefslogtreecommitdiff
path: root/trackerlogic.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2024-04-03 22:25:30 +0200
committerDirk Engling <erdgeist@erdgeist.org>2024-04-03 22:25:30 +0200
commit2afc4893bf802700a1decfff57673cefc861c7e7 (patch)
tree9a0817371ac05062dbcf25107fcf5a6481feccc0 /trackerlogic.c
parenteb8834f7783cb85ae825976425800cd4af711263 (diff)
Prepare opentracker for dual stack capabilities
Diffstat (limited to 'trackerlogic.c')
-rw-r--r--trackerlogic.c174
1 files changed, 109 insertions, 65 deletions
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
74size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount ) { 80size_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
186static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { 201static 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
213static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t amount, char *reply ) { 230static 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*/
269size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { 287size_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
438ot_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
448size_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
412void exerr( char * message ) { 455void 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 );