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 /trackerlogic.c | |
parent | eb8834f7783cb85ae825976425800cd4af711263 (diff) |
Prepare opentracker for dual stack capabilities
Diffstat (limited to 'trackerlogic.c')
-rw-r--r-- | trackerlogic.c | 174 |
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 | ||
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 ); |