diff options
Diffstat (limited to 'trackerlogic.c')
-rw-r--r-- | trackerlogic.c | 568 |
1 files changed, 287 insertions, 281 deletions
diff --git a/trackerlogic.c b/trackerlogic.c index f01348d..6cc239e 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -4,119 +4,117 @@ | |||
4 | $id$ */ | 4 | $id$ */ |
5 | 5 | ||
6 | /* System */ | 6 | /* System */ |
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <stdio.h> | ||
10 | #include <arpa/inet.h> | 7 | #include <arpa/inet.h> |
11 | #include <unistd.h> | ||
12 | #include <errno.h> | 8 | #include <errno.h> |
13 | #include <stdint.h> | 9 | #include <stdint.h> |
10 | #include <stdio.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <string.h> | ||
13 | #include <unistd.h> | ||
14 | 14 | ||
15 | /* Libowfat */ | 15 | /* Libowfat */ |
16 | #include "array.h" | ||
16 | #include "byte.h" | 17 | #include "byte.h" |
17 | #include "io.h" | 18 | #include "io.h" |
18 | #include "iob.h" | 19 | #include "iob.h" |
19 | #include "ip6.h" | 20 | #include "ip6.h" |
20 | #include "array.h" | ||
21 | 21 | ||
22 | /* Opentracker */ | 22 | /* Opentracker */ |
23 | #include "trackerlogic.h" | ||
24 | #include "ot_vector.h" | ||
25 | #include "ot_mutex.h" | ||
26 | #include "ot_stats.h" | ||
27 | #include "ot_clean.h" | ||
28 | #include "ot_http.h" | ||
29 | #include "ot_accesslist.h" | 23 | #include "ot_accesslist.h" |
24 | #include "ot_clean.h" | ||
30 | #include "ot_fullscrape.h" | 25 | #include "ot_fullscrape.h" |
26 | #include "ot_http.h" | ||
31 | #include "ot_livesync.h" | 27 | #include "ot_livesync.h" |
28 | #include "ot_mutex.h" | ||
29 | #include "ot_stats.h" | ||
30 | #include "ot_vector.h" | ||
31 | #include "trackerlogic.h" | ||
32 | 32 | ||
33 | /* Forward declaration */ | 33 | /* Forward declaration */ |
34 | size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); | 34 | size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto); |
35 | 35 | ||
36 | void free_peerlist( ot_peerlist *peer_list ) { | 36 | void free_peerlist(ot_peerlist *peer_list) { |
37 | if( peer_list->peers.data ) { | 37 | if (peer_list->peers.data) { |
38 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) | 38 | if (OT_PEERLIST_HASBUCKETS(peer_list)) |
39 | vector_clean_list( (ot_vector*)peer_list->peers.data, peer_list->peers.size ); | 39 | vector_clean_list((ot_vector *)peer_list->peers.data, peer_list->peers.size); |
40 | else | 40 | else |
41 | free( peer_list->peers.data ); | 41 | free(peer_list->peers.data); |
42 | } | 42 | } |
43 | free( peer_list ); | 43 | free(peer_list); |
44 | } | 44 | } |
45 | 45 | ||
46 | void add_torrent_from_saved_state( ot_hash const hash, ot_time base, size_t down_count ) { | 46 | void add_torrent_from_saved_state(ot_hash const hash, ot_time base, size_t down_count) { |
47 | int exactmatch; | 47 | int exactmatch; |
48 | ot_torrent *torrent; | 48 | ot_torrent *torrent; |
49 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); | 49 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); |
50 | 50 | ||
51 | if( !accesslist_hashisvalid( hash ) ) | 51 | if (!accesslist_hashisvalid(hash)) |
52 | return mutex_bucket_unlock_by_hash( hash, 0 ); | 52 | return mutex_bucket_unlock_by_hash(hash, 0); |
53 | 53 | ||
54 | torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 54 | torrent = vector_find_or_insert(torrents_list, (void *)hash, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
55 | if( !torrent || exactmatch ) | 55 | if (!torrent || exactmatch) |
56 | return mutex_bucket_unlock_by_hash( hash, 0 ); | 56 | return mutex_bucket_unlock_by_hash(hash, 0); |
57 | 57 | ||
58 | /* Create a new torrent entry, then */ | 58 | /* Create a new torrent entry, then */ |
59 | byte_zero( torrent, sizeof( ot_torrent ) ); | 59 | byte_zero(torrent, sizeof(ot_torrent)); |
60 | memcpy( torrent->hash, hash, sizeof(ot_hash) ); | 60 | memcpy(torrent->hash, hash, sizeof(ot_hash)); |
61 | 61 | ||
62 | if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || | 62 | if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) { |
63 | !( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) { | 63 | vector_remove_torrent(torrents_list, torrent); |
64 | vector_remove_torrent( torrents_list, torrent ); | 64 | return mutex_bucket_unlock_by_hash(hash, 0); |
65 | return mutex_bucket_unlock_by_hash( hash, 0 ); | ||
66 | } | 65 | } |
67 | 66 | ||
68 | byte_zero( torrent->peer_list6, sizeof( ot_peerlist ) ); | 67 | byte_zero(torrent->peer_list6, sizeof(ot_peerlist)); |
69 | byte_zero( torrent->peer_list4, sizeof( ot_peerlist ) ); | 68 | byte_zero(torrent->peer_list4, sizeof(ot_peerlist)); |
70 | torrent->peer_list6->base = base; | 69 | torrent->peer_list6->base = base; |
71 | torrent->peer_list4->base = base; | 70 | torrent->peer_list4->base = base; |
72 | torrent->peer_list6->down_count = down_count; | 71 | torrent->peer_list6->down_count = down_count; |
73 | torrent->peer_list4->down_count = down_count; | 72 | torrent->peer_list4->down_count = down_count; |
74 | 73 | ||
75 | return mutex_bucket_unlock_by_hash( hash, 1 ); | 74 | return mutex_bucket_unlock_by_hash(hash, 1); |
76 | } | 75 | } |
77 | 76 | ||
78 | size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount ) { | 77 | size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount) { |
79 | int exactmatch, delta_torrentcount = 0; | 78 | int exactmatch, delta_torrentcount = 0; |
80 | ot_torrent *torrent; | 79 | ot_torrent *torrent; |
81 | ot_peer *peer_dest; | 80 | ot_peer *peer_dest; |
82 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); | 81 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); |
83 | ot_peerlist *peer_list; | 82 | ot_peerlist *peer_list; |
84 | size_t peer_size; /* initialized in next line */ | 83 | size_t peer_size; /* initialized in next line */ |
85 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); | 84 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); |
86 | 85 | ||
87 | if( !accesslist_hashisvalid( *ws->hash ) ) { | 86 | if (!accesslist_hashisvalid(*ws->hash)) { |
88 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | 87 | mutex_bucket_unlock_by_hash(*ws->hash, 0); |
89 | if( proto == FLAG_TCP ) { | 88 | if (proto == FLAG_TCP) { |
90 | const char invalid_hash[] = "d14:failure reason63:Requested download is not authorized for use with this tracker.e"; | 89 | const char invalid_hash[] = "d14:failure reason63:Requested download is not authorized for use with this tracker.e"; |
91 | memcpy( ws->reply, invalid_hash, strlen( invalid_hash ) ); | 90 | memcpy(ws->reply, invalid_hash, strlen(invalid_hash)); |
92 | return strlen( invalid_hash ); | 91 | return strlen(invalid_hash); |
93 | } | 92 | } |
94 | return 0; | 93 | return 0; |
95 | } | 94 | } |
96 | 95 | ||
97 | torrent = vector_find_or_insert( torrents_list, (void*)ws->hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 96 | torrent = vector_find_or_insert(torrents_list, (void *)ws->hash, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
98 | if( !torrent ) { | 97 | if (!torrent) { |
99 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | 98 | mutex_bucket_unlock_by_hash(*ws->hash, 0); |
100 | return 0; | 99 | return 0; |
101 | } | 100 | } |
102 | 101 | ||
103 | if( !exactmatch ) { | 102 | if (!exactmatch) { |
104 | /* Create a new torrent entry, then */ | 103 | /* Create a new torrent entry, then */ |
105 | byte_zero( torrent, sizeof(ot_torrent)); | 104 | byte_zero(torrent, sizeof(ot_torrent)); |
106 | memcpy( torrent->hash, *ws->hash, sizeof(ot_hash) ); | 105 | memcpy(torrent->hash, *ws->hash, sizeof(ot_hash)); |
107 | 106 | ||
108 | if( !( torrent->peer_list6 = malloc( sizeof (ot_peerlist) ) ) || | 107 | if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) { |
109 | !( torrent->peer_list4 = malloc( sizeof (ot_peerlist) ) ) ) { | 108 | vector_remove_torrent(torrents_list, torrent); |
110 | vector_remove_torrent( torrents_list, torrent ); | 109 | mutex_bucket_unlock_by_hash(*ws->hash, 0); |
111 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | ||
112 | return 0; | 110 | return 0; |
113 | } | 111 | } |
114 | 112 | ||
115 | byte_zero( torrent->peer_list6, sizeof( ot_peerlist ) ); | 113 | byte_zero(torrent->peer_list6, sizeof(ot_peerlist)); |
116 | byte_zero( torrent->peer_list4, sizeof( ot_peerlist ) ); | 114 | byte_zero(torrent->peer_list4, sizeof(ot_peerlist)); |
117 | delta_torrentcount = 1; | 115 | delta_torrentcount = 1; |
118 | } else | 116 | } else |
119 | clean_single_torrent( torrent ); | 117 | clean_single_torrent(torrent); |
120 | 118 | ||
121 | torrent->peer_list6->base = g_now_minutes; | 119 | torrent->peer_list6->base = g_now_minutes; |
122 | torrent->peer_list4->base = g_now_minutes; | 120 | torrent->peer_list4->base = g_now_minutes; |
@@ -124,99 +122,99 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr | |||
124 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | 122 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; |
125 | 123 | ||
126 | /* Check for peer in torrent */ | 124 | /* Check for peer in torrent */ |
127 | peer_dest = vector_find_or_insert_peer( &(peer_list->peers), peer_src, peer_size, &exactmatch ); | 125 | peer_dest = vector_find_or_insert_peer(&(peer_list->peers), peer_src, peer_size, &exactmatch); |
128 | if( !peer_dest ) { | 126 | if (!peer_dest) { |
129 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); | 127 | mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); |
130 | return 0; | 128 | return 0; |
131 | } | 129 | } |
132 | 130 | ||
133 | /* Tell peer that it's fresh */ | 131 | /* Tell peer that it's fresh */ |
134 | OT_PEERTIME( ws->peer, OT_PEER_SIZE6 ) = 0; | 132 | OT_PEERTIME(ws->peer, OT_PEER_SIZE6) = 0; |
135 | 133 | ||
136 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ | 134 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ |
137 | if( ( OT_PEERFLAG( ws->peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) | 135 | if ((OT_PEERFLAG(ws->peer) & (PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING)) == PEER_FLAG_COMPLETED) |
138 | OT_PEERFLAG( ws->peer ) ^= PEER_FLAG_COMPLETED; | 136 | OT_PEERFLAG(ws->peer) ^= PEER_FLAG_COMPLETED; |
139 | 137 | ||
140 | /* If we hadn't had a match create peer there */ | 138 | /* If we hadn't had a match create peer there */ |
141 | if( !exactmatch ) { | 139 | if (!exactmatch) { |
142 | 140 | ||
143 | #ifdef WANT_SYNC_LIVE | 141 | #ifdef WANT_SYNC_LIVE |
144 | if( proto == FLAG_MCA ) | 142 | if (proto == FLAG_MCA) |
145 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_FROM_SYNC; | 143 | OT_PEERFLAG(ws->peer) |= PEER_FLAG_FROM_SYNC; |
146 | else | 144 | else |
147 | livesync_tell( ws ); | 145 | livesync_tell(ws); |
148 | #endif | 146 | #endif |
149 | 147 | ||
150 | peer_list->peer_count++; | 148 | peer_list->peer_count++; |
151 | if( OT_PEERFLAG( ws->peer ) & PEER_FLAG_COMPLETED ) { | 149 | if (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED) { |
152 | peer_list->down_count++; | 150 | peer_list->down_count++; |
153 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); | 151 | stats_issue_event(EVENT_COMPLETED, 0, (uintptr_t)ws); |
154 | } | 152 | } |
155 | if( OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) | 153 | if (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING) |
156 | peer_list->seed_count++; | 154 | peer_list->seed_count++; |
157 | 155 | ||
158 | } else { | 156 | } else { |
159 | stats_issue_event( EVENT_RENEW, 0, OT_PEERTIME( peer_dest, peer_size ) ); | 157 | stats_issue_event(EVENT_RENEW, 0, OT_PEERTIME(peer_dest, peer_size)); |
160 | #ifdef WANT_SPOT_WOODPECKER | 158 | #ifdef WANT_SPOT_WOODPECKER |
161 | if( ( OT_PEERTIME(peer_dest, peer_size) > 0 ) && ( OT_PEERTIME(peer_dest, peer_size) < 20 ) ) | 159 | if ((OT_PEERTIME(peer_dest, peer_size) > 0) && (OT_PEERTIME(peer_dest, peer_size) < 20)) |
162 | stats_issue_event( EVENT_WOODPECKER, 0, (uintptr_t)&ws->peer ); | 160 | stats_issue_event(EVENT_WOODPECKER, 0, (uintptr_t)&ws->peer); |
163 | #endif | 161 | #endif |
164 | #ifdef WANT_SYNC_LIVE | 162 | #ifdef WANT_SYNC_LIVE |
165 | /* Won't live sync peers that come back too fast. Only exception: | 163 | /* Won't live sync peers that come back too fast. Only exception: |
166 | fresh "completed" reports */ | 164 | fresh "completed" reports */ |
167 | if( proto != FLAG_MCA ) { | 165 | if (proto != FLAG_MCA) { |
168 | if( OT_PEERTIME( peer_dest, peer_size ) > OT_CLIENT_SYNC_RENEW_BOUNDARY || | 166 | if (OT_PEERTIME(peer_dest, peer_size) > OT_CLIENT_SYNC_RENEW_BOUNDARY || |
169 | ( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED ) ) ) | 167 | (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED))) |
170 | livesync_tell( ws ); | 168 | livesync_tell(ws); |
171 | } | 169 | } |
172 | #endif | 170 | #endif |
173 | 171 | ||
174 | if( (OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING ) && !(OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) ) | 172 | if ((OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING) && !(OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING)) |
175 | peer_list->seed_count--; | 173 | peer_list->seed_count--; |
176 | if( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING ) ) | 174 | if (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING)) |
177 | peer_list->seed_count++; | 175 | peer_list->seed_count++; |
178 | if( !(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED ) ) { | 176 | if (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED)) { |
179 | peer_list->down_count++; | 177 | peer_list->down_count++; |
180 | stats_issue_event( EVENT_COMPLETED, 0, (uintptr_t)ws ); | 178 | stats_issue_event(EVENT_COMPLETED, 0, (uintptr_t)ws); |
181 | } | 179 | } |
182 | if( OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED ) | 180 | if (OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) |
183 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_COMPLETED; | 181 | OT_PEERFLAG(ws->peer) |= PEER_FLAG_COMPLETED; |
184 | } | 182 | } |
185 | 183 | ||
186 | memcpy( peer_dest, peer_src, peer_size ); | 184 | memcpy(peer_dest, peer_src, peer_size); |
187 | #ifdef WANT_SYNC | 185 | #ifdef WANT_SYNC |
188 | if( proto == FLAG_MCA ) { | 186 | if (proto == FLAG_MCA) { |
189 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); | 187 | mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); |
190 | return 0; | 188 | return 0; |
191 | } | 189 | } |
192 | #endif | 190 | #endif |
193 | 191 | ||
194 | ws->reply_size = return_peers_for_torrent( ws, torrent, amount, ws->reply, proto ); | 192 | ws->reply_size = return_peers_for_torrent(ws, torrent, amount, ws->reply, proto); |
195 | mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); | 193 | mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); |
196 | return ws->reply_size; | 194 | return ws->reply_size; |
197 | } | 195 | } |
198 | 196 | ||
199 | static size_t return_peers_all( ot_peerlist *peer_list, size_t peer_size, char *reply ) { | 197 | static size_t return_peers_all(ot_peerlist *peer_list, size_t peer_size, char *reply) { |
200 | unsigned int bucket, num_buckets = 1; | 198 | unsigned int bucket, num_buckets = 1; |
201 | ot_vector * bucket_list = &peer_list->peers; | 199 | ot_vector *bucket_list = &peer_list->peers; |
202 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | 200 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); |
203 | size_t result = compare_size * peer_list->peer_count; | 201 | size_t result = compare_size * peer_list->peer_count; |
204 | char * r_end = reply + result; | 202 | char *r_end = reply + result; |
205 | 203 | ||
206 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { | 204 | if (OT_PEERLIST_HASBUCKETS(peer_list)) { |
207 | num_buckets = bucket_list->size; | 205 | num_buckets = bucket_list->size; |
208 | bucket_list = (ot_vector *)bucket_list->data; | 206 | bucket_list = (ot_vector *)bucket_list->data; |
209 | } | 207 | } |
210 | 208 | ||
211 | for( bucket = 0; bucket<num_buckets; ++bucket ) { | 209 | for (bucket = 0; bucket < num_buckets; ++bucket) { |
212 | ot_peer *peers = bucket_list[bucket].data; | 210 | ot_peer *peers = bucket_list[bucket].data; |
213 | size_t peer_count = bucket_list[bucket].size; | 211 | size_t peer_count = bucket_list[bucket].size; |
214 | while( peer_count-- ) { | 212 | while (peer_count--) { |
215 | if( OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING ) { | 213 | if (OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING) { |
216 | r_end -= compare_size; | 214 | r_end -= compare_size; |
217 | memcpy( r_end, peers, compare_size); | 215 | memcpy(r_end, peers, compare_size); |
218 | } else { | 216 | } else { |
219 | memcpy( reply, peers, compare_size ); | 217 | memcpy(reply, peers, compare_size); |
220 | reply += compare_size; | 218 | reply += compare_size; |
221 | } | 219 | } |
222 | peers += peer_size; | 220 | peers += peer_size; |
@@ -225,45 +223,47 @@ static size_t return_peers_all( ot_peerlist *peer_list, size_t peer_size, char * | |||
225 | return result; | 223 | return result; |
226 | } | 224 | } |
227 | 225 | ||
228 | static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply ) { | 226 | static size_t return_peers_selection(struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply) { |
229 | unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; | 227 | unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; |
230 | ot_vector * bucket_list = &peer_list->peers; | 228 | ot_vector *bucket_list = &peer_list->peers; |
231 | unsigned int shifted_pc = peer_list->peer_count; | 229 | unsigned int shifted_pc = peer_list->peer_count; |
232 | unsigned int shifted_step = 0; | 230 | unsigned int shifted_step = 0; |
233 | unsigned int shift = 0; | 231 | unsigned int shift = 0; |
234 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); | 232 | size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); |
235 | size_t result = compare_size * amount; | 233 | size_t result = compare_size * amount; |
236 | char * r_end = reply + result; | 234 | char *r_end = reply + result; |
237 | 235 | ||
238 | if( OT_PEERLIST_HASBUCKETS(peer_list) ) { | 236 | if (OT_PEERLIST_HASBUCKETS(peer_list)) { |
239 | num_buckets = bucket_list->size; | 237 | num_buckets = bucket_list->size; |
240 | bucket_list = (ot_vector *)bucket_list->data; | 238 | bucket_list = (ot_vector *)bucket_list->data; |
241 | } | 239 | } |
242 | 240 | ||
243 | /* Make fixpoint arithmetic as exact as possible */ | 241 | /* Make fixpoint arithmetic as exact as possible */ |
244 | #define MAXPRECBIT (1<<(8*sizeof(int)-3)) | 242 | #define MAXPRECBIT (1 << (8 * sizeof(int) - 3)) |
245 | while( !(shifted_pc & MAXPRECBIT ) ) { shifted_pc <<= 1; shift++; } | 243 | while (!(shifted_pc & MAXPRECBIT)) { |
246 | shifted_step = shifted_pc/amount; | 244 | shifted_pc <<= 1; |
245 | shift++; | ||
246 | } | ||
247 | shifted_step = shifted_pc / amount; | ||
247 | #undef MAXPRECBIT | 248 | #undef MAXPRECBIT |
248 | 249 | ||
249 | /* Initialize somewhere in the middle of peers so that | 250 | /* Initialize somewhere in the middle of peers so that |
250 | fixpoint's aliasing doesn't alway miss the same peers */ | 251 | fixpoint's aliasing doesn't alway miss the same peers */ |
251 | bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; | 252 | bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; |
252 | 253 | ||
253 | while( amount-- ) { | 254 | while (amount--) { |
254 | ot_peer *peer; | 255 | ot_peer *peer; |
255 | 256 | ||
256 | /* This is the aliased, non shifted range, next value may fall into */ | 257 | /* This is the aliased, non shifted range, next value may fall into */ |
257 | unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - | 258 | unsigned int diff = (((amount + 1) * shifted_step) >> shift) - ((amount * shifted_step) >> shift); |
258 | ( ( amount * shifted_step ) >> shift ); | 259 | bucket_offset += 1 + nrand48(ws->rand48_state) % diff; |
259 | bucket_offset += 1 + nrand48(ws->rand48_state) % diff; | ||
260 | 260 | ||
261 | while( bucket_offset >= bucket_list[bucket_index].size ) { | 261 | while (bucket_offset >= bucket_list[bucket_index].size) { |
262 | bucket_offset -= bucket_list[bucket_index].size; | 262 | bucket_offset -= bucket_list[bucket_index].size; |
263 | bucket_index = ( bucket_index + 1 ) % num_buckets; | 263 | bucket_index = (bucket_index + 1) % num_buckets; |
264 | } | 264 | } |
265 | peer = bucket_list[bucket_index].data + peer_size * bucket_offset; | 265 | peer = bucket_list[bucket_index].data + peer_size * bucket_offset; |
266 | if( OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING ) { | 266 | if (OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING) { |
267 | r_end -= compare_size; | 267 | r_end -= compare_size; |
268 | memcpy(r_end, peer, compare_size); | 268 | memcpy(r_end, peer, compare_size); |
269 | } else { | 269 | } else { |
@@ -274,51 +274,51 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee | |||
274 | return result; | 274 | return result; |
275 | } | 275 | } |
276 | 276 | ||
277 | static size_t return_peers_for_torrent_udp( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply ) { | 277 | static size_t return_peers_for_torrent_udp(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply) { |
278 | char *r = reply; | 278 | char *r = reply; |
279 | size_t peer_size = peer_size_from_peer6(&ws->peer); | 279 | size_t peer_size = peer_size_from_peer6(&ws->peer); |
280 | ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | 280 | ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; |
281 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | 281 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; |
282 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | 282 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
283 | 283 | ||
284 | if( amount > peer_list->peer_count ) | 284 | if (amount > peer_list->peer_count) |
285 | amount = peer_list->peer_count; | 285 | amount = peer_list->peer_count; |
286 | 286 | ||
287 | *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 287 | *(uint32_t *)(r + 0) = htonl(OT_CLIENT_REQUEST_INTERVAL_RANDOM); |
288 | *(uint32_t*)(r+4) = htonl( peer_count - seed_count ); | 288 | *(uint32_t *)(r + 4) = htonl(peer_count - seed_count); |
289 | *(uint32_t*)(r+8) = htonl( seed_count ); | 289 | *(uint32_t *)(r + 8) = htonl(seed_count); |
290 | r += 12; | 290 | r += 12; |
291 | 291 | ||
292 | if( amount ) { | 292 | if (amount) { |
293 | if( amount == peer_list->peer_count ) | 293 | if (amount == peer_list->peer_count) |
294 | r += return_peers_all( peer_list, peer_size, r ); | 294 | r += return_peers_all(peer_list, peer_size, r); |
295 | else | 295 | else |
296 | r += return_peers_selection( ws, peer_list, peer_size, amount, r ); | 296 | r += return_peers_selection(ws, peer_list, peer_size, amount, r); |
297 | } | 297 | } |
298 | return r - reply; | 298 | return r - reply; |
299 | } | 299 | } |
300 | 300 | ||
301 | static size_t return_peers_for_torrent_tcp( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply ) { | 301 | static size_t return_peers_for_torrent_tcp(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply) { |
302 | char *r = reply; | 302 | char *r = reply; |
303 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 303 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
304 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | 304 | size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
305 | size_t down_count = torrent->peer_list6->down_count + torrent->peer_list4->down_count; | 305 | size_t down_count = torrent->peer_list6->down_count + torrent->peer_list4->down_count; |
306 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - seed_count; | 306 | size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - seed_count; |
307 | 307 | ||
308 | /* Simple case: amount of peers in both lists is less than requested, here we return all results */ | 308 | /* Simple case: amount of peers in both lists is less than requested, here we return all results */ |
309 | size_t amount_v4 = torrent->peer_list4->peer_count; | 309 | size_t amount_v4 = torrent->peer_list4->peer_count; |
310 | size_t amount_v6 = torrent->peer_list6->peer_count; | 310 | size_t amount_v6 = torrent->peer_list6->peer_count; |
311 | 311 | ||
312 | /* Complex case: both lists have more than enough entries and we need to split between v4 and v6 clients */ | 312 | /* Complex case: both lists have more than enough entries and we need to split between v4 and v6 clients */ |
313 | if( amount_v4 + amount_v6 > amount ) { | 313 | if (amount_v4 + amount_v6 > amount) { |
314 | size_t amount_left, percent_v6 = 0, percent_v4 = 0, left_v6, left_v4; | 314 | size_t amount_left, percent_v6 = 0, percent_v4 = 0, left_v6, left_v4; |
315 | const size_t SCALE = 1024; | 315 | const size_t SCALE = 1024; |
316 | 316 | ||
317 | /* If possible, fill at least a quarter of peer from each family */ | 317 | /* If possible, fill at least a quarter of peer from each family */ |
318 | if( amount / 4 <= amount_v4 ) | 318 | if (amount / 4 <= amount_v4) |
319 | amount_v4 = amount / 4; | 319 | amount_v4 = amount / 4; |
320 | if( amount / 4 <= amount_v6 ) | 320 | if (amount / 4 <= amount_v6) |
321 | amount_v6 = amount / 4; | 321 | amount_v6 = amount / 4; |
322 | 322 | ||
323 | /* Fill the rest according to which family's pool provides more peers */ | 323 | /* Fill the rest according to which family's pool provides more peers */ |
324 | amount_left = amount - (amount_v4 + amount_v6); | 324 | amount_left = amount - (amount_v4 + amount_v6); |
@@ -326,37 +326,38 @@ static size_t return_peers_for_torrent_tcp( struct ot_workstruct * ws, ot_torren | |||
326 | left_v4 = torrent->peer_list4->peer_count - amount_v4; | 326 | left_v4 = torrent->peer_list4->peer_count - amount_v4; |
327 | left_v6 = torrent->peer_list6->peer_count - amount_v6; | 327 | left_v6 = torrent->peer_list6->peer_count - amount_v6; |
328 | 328 | ||
329 | if( left_v4 + left_v6 ) { | 329 | if (left_v4 + left_v6) { |
330 | percent_v4 = (SCALE * left_v4) / (left_v4 + left_v6); | 330 | percent_v4 = (SCALE * left_v4) / (left_v4 + left_v6); |
331 | percent_v6 = (SCALE * left_v6) / (left_v4 + left_v6); | 331 | percent_v6 = (SCALE * left_v6) / (left_v4 + left_v6); |
332 | } | 332 | } |
333 | 333 | ||
334 | amount_v4 += (amount_left * percent_v4) / SCALE; | 334 | amount_v4 += (amount_left * percent_v4) / SCALE; |
335 | amount_v6 += (amount_left * percent_v6) / SCALE; | 335 | amount_v6 += (amount_left * percent_v6) / SCALE; |
336 | 336 | ||
337 | /* Integer division rounding can leave out a peer */ | 337 | /* Integer division rounding can leave out a peer */ |
338 | if( amount_v4 + amount_v6 < amount && amount_v6 < torrent->peer_list6->peer_count ) | 338 | if (amount_v4 + amount_v6 < amount && amount_v6 < torrent->peer_list6->peer_count) |
339 | ++amount_v6; | 339 | ++amount_v6; |
340 | if( amount_v4 + amount_v6 < amount && amount_v4 < torrent->peer_list4->peer_count ) | 340 | if (amount_v4 + amount_v6 < amount && amount_v4 < torrent->peer_list4->peer_count) |
341 | ++amount_v4; | 341 | ++amount_v4; |
342 | } | 342 | } |
343 | 343 | ||
344 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, erval/2 ); | 344 | r += |
345 | sprintf(r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, erval / 2); | ||
345 | 346 | ||
346 | if( amount_v4 ) { | 347 | if (amount_v4) { |
347 | r += sprintf( r, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4); | 348 | r += sprintf(r, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4); |
348 | if( amount_v4 == torrent->peer_list4->peer_count ) | 349 | if (amount_v4 == torrent->peer_list4->peer_count) |
349 | r += return_peers_all( torrent->peer_list4, OT_PEER_SIZE4, r ); | 350 | r += return_peers_all(torrent->peer_list4, OT_PEER_SIZE4, r); |
350 | else | 351 | else |
351 | r += return_peers_selection( ws, torrent->peer_list4, OT_PEER_SIZE4, amount_v4, r ); | 352 | r += return_peers_selection(ws, torrent->peer_list4, OT_PEER_SIZE4, amount_v4, r); |
352 | } | 353 | } |
353 | 354 | ||
354 | if( amount_v6 ) { | 355 | if (amount_v6) { |
355 | r += sprintf( r, PEERS_BENCODED6 "%zd:", OT_PEER_COMPARE_SIZE6 * amount_v6); | 356 | r += sprintf(r, PEERS_BENCODED6 "%zd:", OT_PEER_COMPARE_SIZE6 * amount_v6); |
356 | if( amount_v6 == torrent->peer_list6->peer_count ) | 357 | if (amount_v6 == torrent->peer_list6->peer_count) |
357 | r += return_peers_all( torrent->peer_list6, OT_PEER_SIZE6, r ); | 358 | r += return_peers_all(torrent->peer_list6, OT_PEER_SIZE6, r); |
358 | else | 359 | else |
359 | r += return_peers_selection( ws, torrent->peer_list6, OT_PEER_SIZE6, amount_v6, r ); | 360 | r += return_peers_selection(ws, torrent->peer_list6, OT_PEER_SIZE6, amount_v6, r); |
360 | } | 361 | } |
361 | 362 | ||
362 | *r++ = 'e'; | 363 | *r++ = 'e'; |
@@ -365,154 +366,159 @@ static size_t return_peers_for_torrent_tcp( struct ot_workstruct * ws, ot_torren | |||
365 | } | 366 | } |
366 | 367 | ||
367 | /* Compiles a list of random peers for a torrent | 368 | /* Compiles a list of random peers for a torrent |
368 | * Reply must have enough space to hold: | 369 | * Reply must have enough space to hold: |
369 | * 92 + 6 * amount bytes for TCP/IPv4 | 370 | * 92 + 6 * amount bytes for TCP/IPv4 |
370 | * 92 + 18 * amount bytes for TCP/IPv6 | 371 | * 92 + 18 * amount bytes for TCP/IPv6 |
371 | * 12 + 6 * amount bytes for UDP/IPv4 | 372 | * 12 + 6 * amount bytes for UDP/IPv4 |
372 | * 12 + 18 * amount bytes for UDP/IPv6 | 373 | * 12 + 18 * amount bytes for UDP/IPv6 |
373 | * Does not yet check not to return self | 374 | * Does not yet check not to return self |
374 | */ | 375 | */ |
375 | size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { | 376 | size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto) { |
376 | return proto == FLAG_TCP ? return_peers_for_torrent_tcp(ws, torrent, amount, reply) : return_peers_for_torrent_udp(ws, torrent, amount, reply); | 377 | return proto == FLAG_TCP ? return_peers_for_torrent_tcp(ws, torrent, amount, reply) : return_peers_for_torrent_udp(ws, torrent, amount, reply); |
377 | } | 378 | } |
378 | 379 | ||
379 | /* Fetches scrape info for a specific torrent */ | 380 | /* Fetches scrape info for a specific torrent */ |
380 | size_t return_udp_scrape_for_torrent( ot_hash const hash, char *reply ) { | 381 | size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply) { |
381 | int exactmatch, delta_torrentcount = 0; | 382 | int exactmatch, delta_torrentcount = 0; |
382 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); | 383 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); |
383 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 384 | ot_torrent *torrent = binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
384 | 385 | ||
385 | if( !exactmatch ) { | 386 | if (!exactmatch) { |
386 | memset( reply, 0, 12); | 387 | memset(reply, 0, 12); |
387 | } else { | 388 | } else { |
388 | uint32_t *r = (uint32_t*) reply; | 389 | uint32_t *r = (uint32_t *)reply; |
389 | 390 | ||
390 | if( clean_single_torrent( torrent ) ) { | 391 | if (clean_single_torrent(torrent)) { |
391 | vector_remove_torrent( torrents_list, torrent ); | 392 | vector_remove_torrent(torrents_list, torrent); |
392 | memset( reply, 0, 12); | 393 | memset(reply, 0, 12); |
393 | delta_torrentcount = -1; | 394 | delta_torrentcount = -1; |
394 | } else { | 395 | } else { |
395 | r[0] = htonl( torrent->peer_list6->seed_count + torrent->peer_list4->seed_count ); | 396 | r[0] = htonl(torrent->peer_list6->seed_count + torrent->peer_list4->seed_count); |
396 | r[1] = htonl( torrent->peer_list6->down_count + torrent->peer_list4->down_count ); | 397 | r[1] = htonl(torrent->peer_list6->down_count + torrent->peer_list4->down_count); |
397 | r[2] = htonl( torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - | 398 | r[2] = htonl(torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); |
398 | torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); | ||
399 | } | 399 | } |
400 | } | 400 | } |
401 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); | 401 | mutex_bucket_unlock_by_hash(hash, delta_torrentcount); |
402 | return 12; | 402 | return 12; |
403 | } | 403 | } |
404 | 404 | ||
405 | /* Fetches scrape info for a specific torrent */ | 405 | /* Fetches scrape info for a specific torrent */ |
406 | size_t return_tcp_scrape_for_torrent( ot_hash const *hash_list, int amount, char *reply ) { | 406 | size_t return_tcp_scrape_for_torrent(ot_hash const *hash_list, int amount, char *reply) { |
407 | char *r = reply; | 407 | char *r = reply; |
408 | int exactmatch, i; | 408 | int exactmatch, i; |
409 | 409 | ||
410 | r += sprintf( r, "d5:filesd" ); | 410 | r += sprintf(r, "d5:filesd"); |
411 | 411 | ||
412 | for( i=0; i<amount; ++i ) { | 412 | for (i = 0; i < amount; ++i) { |
413 | int delta_torrentcount = 0; | 413 | int delta_torrentcount = 0; |
414 | ot_hash const *hash = hash_list + i; | 414 | ot_hash const *hash = hash_list + i; |
415 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *hash ); | 415 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*hash); |
416 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 416 | ot_torrent *torrent = binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
417 | 417 | ||
418 | if( exactmatch ) { | 418 | if (exactmatch) { |
419 | if( clean_single_torrent( torrent ) ) { | 419 | if (clean_single_torrent(torrent)) { |
420 | vector_remove_torrent( torrents_list, torrent ); | 420 | vector_remove_torrent(torrents_list, torrent); |
421 | delta_torrentcount = -1; | 421 | delta_torrentcount = -1; |
422 | } else { | 422 | } else { |
423 | *r++='2';*r++='0';*r++=':'; | 423 | *r++ = '2'; |
424 | memcpy( r, hash, sizeof(ot_hash) ); r+=sizeof(ot_hash); | 424 | *r++ = '0'; |
425 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", | 425 | *r++ = ':'; |
426 | torrent->peer_list6->seed_count + torrent->peer_list4->seed_count, | 426 | memcpy(r, hash, sizeof(ot_hash)); |
427 | torrent->peer_list6->down_count + torrent->peer_list4->down_count, | 427 | r += sizeof(ot_hash); |
428 | torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - | 428 | r += sprintf(r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", torrent->peer_list6->seed_count + torrent->peer_list4->seed_count, |
429 | torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); | 429 | torrent->peer_list6->down_count + torrent->peer_list4->down_count, |
430 | torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); | ||
430 | } | 431 | } |
431 | } | 432 | } |
432 | mutex_bucket_unlock_by_hash( *hash, delta_torrentcount ); | 433 | mutex_bucket_unlock_by_hash(*hash, delta_torrentcount); |
433 | } | 434 | } |
434 | 435 | ||
435 | *r++ = 'e'; *r++ = 'e'; | 436 | *r++ = 'e'; |
437 | *r++ = 'e'; | ||
436 | return r - reply; | 438 | return r - reply; |
437 | } | 439 | } |
438 | 440 | ||
439 | static ot_peerlist dummy_list; | 441 | static ot_peerlist dummy_list; |
440 | size_t remove_peer_from_torrent( PROTO_FLAG proto, struct ot_workstruct *ws ) { | 442 | size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws) { |
441 | int exactmatch; | 443 | int exactmatch; |
442 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( *ws->hash ); | 444 | ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); |
443 | ot_torrent *torrent = binary_search( ws->hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 445 | ot_torrent *torrent = binary_search(ws->hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); |
444 | ot_peerlist *peer_list = &dummy_list; | 446 | ot_peerlist *peer_list = &dummy_list; |
445 | size_t peer_size; /* initialized in next line */ | 447 | size_t peer_size; /* initialized in next line */ |
446 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); | 448 | ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); |
447 | size_t peer_count = 0, seed_count = 0; | 449 | size_t peer_count = 0, seed_count = 0; |
448 | 450 | ||
449 | #ifdef WANT_SYNC_LIVE | 451 | #ifdef WANT_SYNC_LIVE |
450 | if( proto != FLAG_MCA ) { | 452 | if (proto != FLAG_MCA) { |
451 | OT_PEERFLAG( ws->peer ) |= PEER_FLAG_STOPPED; | 453 | OT_PEERFLAG(ws->peer) |= PEER_FLAG_STOPPED; |
452 | livesync_tell( ws ); | 454 | livesync_tell(ws); |
453 | } | 455 | } |
454 | #endif | 456 | #endif |
455 | 457 | ||
456 | if( exactmatch ) { | 458 | if (exactmatch) { |
457 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; | 459 | peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; |
458 | switch( vector_remove_peer( &peer_list->peers, peer_src, peer_size ) ) { | 460 | switch (vector_remove_peer(&peer_list->peers, peer_src, peer_size)) { |
459 | case 2: peer_list->seed_count--; /* Intentional fallthrough */ | 461 | case 2: |
460 | case 1: peer_list->peer_count--; /* Intentional fallthrough */ | 462 | peer_list->seed_count--; /* Intentional fallthrough */ |
461 | default: break; | 463 | case 1: |
464 | peer_list->peer_count--; /* Intentional fallthrough */ | ||
465 | default: | ||
466 | break; | ||
462 | } | 467 | } |
463 | 468 | ||
464 | peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; | 469 | peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; |
465 | seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; | 470 | seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; |
466 | } | 471 | } |
467 | 472 | ||
468 | 473 | if (proto == FLAG_TCP) { | |
469 | if( proto == FLAG_TCP ) { | 474 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
470 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 475 | ws->reply_size = sprintf(ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", seed_count, peer_count - seed_count, erval, |
471 | ws->reply_size = sprintf( ws->reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", seed_count, peer_count - seed_count, erval, erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4 ); | 476 | erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4); |
472 | } | 477 | } |
473 | 478 | ||
474 | /* Handle UDP reply */ | 479 | /* Handle UDP reply */ |
475 | if( proto == FLAG_UDP ) { | 480 | if (proto == FLAG_UDP) { |
476 | ((uint32_t*)ws->reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 481 | ((uint32_t *)ws->reply)[2] = htonl(OT_CLIENT_REQUEST_INTERVAL_RANDOM); |
477 | ((uint32_t*)ws->reply)[3] = htonl( peer_count - seed_count ); | 482 | ((uint32_t *)ws->reply)[3] = htonl(peer_count - seed_count); |
478 | ((uint32_t*)ws->reply)[4] = htonl( seed_count); | 483 | ((uint32_t *)ws->reply)[4] = htonl(seed_count); |
479 | ws->reply_size = 20; | 484 | ws->reply_size = 20; |
480 | } | 485 | } |
481 | 486 | ||
482 | mutex_bucket_unlock_by_hash( *ws->hash, 0 ); | 487 | mutex_bucket_unlock_by_hash(*ws->hash, 0); |
483 | return ws->reply_size; | 488 | return ws->reply_size; |
484 | } | 489 | } |
485 | 490 | ||
486 | void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data ), uintptr_t data ) { | 491 | void iterate_all_torrents(int (*for_each)(ot_torrent *torrent, uintptr_t data), uintptr_t data) { |
487 | int bucket; | 492 | int bucket; |
488 | size_t j; | 493 | size_t j; |
489 | 494 | ||
490 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 495 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
491 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 496 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
492 | ot_torrent *torrents = (ot_torrent*)(torrents_list->data); | 497 | ot_torrent *torrents = (ot_torrent *)(torrents_list->data); |
493 | 498 | ||
494 | for( j=0; j<torrents_list->size; ++j ) | 499 | for (j = 0; j < torrents_list->size; ++j) |
495 | if( for_each( torrents + j, data ) ) | 500 | if (for_each(torrents + j, data)) |
496 | break; | 501 | break; |
497 | 502 | ||
498 | mutex_bucket_unlock( bucket, 0 ); | 503 | mutex_bucket_unlock(bucket, 0); |
499 | if( !g_opentracker_running ) return; | 504 | if (!g_opentracker_running) |
505 | return; | ||
500 | } | 506 | } |
501 | } | 507 | } |
502 | 508 | ||
503 | ot_peer *peer_from_peer6( ot_peer6 *peer, size_t *peer_size ) { | 509 | ot_peer *peer_from_peer6(ot_peer6 *peer, size_t *peer_size) { |
504 | ot_ip6 *ip = (ot_ip6*)peer; | 510 | ot_ip6 *ip = (ot_ip6 *)peer; |
505 | if( !ip6_isv4mapped(ip) ) { | 511 | if (!ip6_isv4mapped(ip)) { |
506 | *peer_size = OT_PEER_SIZE6; | 512 | *peer_size = OT_PEER_SIZE6; |
507 | return (ot_peer*)peer; | 513 | return (ot_peer *)peer; |
508 | } | 514 | } |
509 | *peer_size = OT_PEER_SIZE4; | 515 | *peer_size = OT_PEER_SIZE4; |
510 | return (ot_peer*)(((uint8_t*)peer) + 12); | 516 | return (ot_peer *)(((uint8_t *)peer) + 12); |
511 | } | 517 | } |
512 | 518 | ||
513 | size_t peer_size_from_peer6(ot_peer6 *peer) { | 519 | size_t peer_size_from_peer6(ot_peer6 *peer) { |
514 | ot_ip6 *ip = (ot_ip6*)peer; | 520 | ot_ip6 *ip = (ot_ip6 *)peer; |
515 | if( !ip6_isv4mapped(ip)) | 521 | if (!ip6_isv4mapped(ip)) |
516 | return OT_PEER_SIZE6; | 522 | return OT_PEER_SIZE6; |
517 | return OT_PEER_SIZE4; | 523 | return OT_PEER_SIZE4; |
518 | } | 524 | } |
@@ -520,20 +526,20 @@ size_t peer_size_from_peer6(ot_peer6 *peer) { | |||
520 | #ifdef _DEBUG_RANDOMTORRENTS | 526 | #ifdef _DEBUG_RANDOMTORRENTS |
521 | void trackerlogic_add_random_torrents(size_t amount) { | 527 | void trackerlogic_add_random_torrents(size_t amount) { |
522 | struct ot_workstruct ws; | 528 | struct ot_workstruct ws; |
523 | memset( &ws, 0, sizeof(ws) ); | 529 | memset(&ws, 0, sizeof(ws)); |
524 | 530 | ||
525 | ws.inbuf=malloc(G_INBUF_SIZE); | 531 | ws.inbuf = malloc(G_INBUF_SIZE); |
526 | ws.outbuf=malloc(G_OUTBUF_SIZE); | 532 | ws.outbuf = malloc(G_OUTBUF_SIZE); |
527 | ws.reply=ws.outbuf; | 533 | ws.reply = ws.outbuf; |
528 | ws.hash=(ot_hash*)ws.inbuf; | 534 | ws.hash = (ot_hash *)ws.inbuf; |
529 | 535 | ||
530 | while( amount-- ) { | 536 | while (amount--) { |
531 | arc4random_buf(ws.hash, sizeof(ot_hash)); | 537 | arc4random_buf(ws.hash, sizeof(ot_hash)); |
532 | arc4random_buf(&ws.peer, sizeof(ws.peer)); | 538 | arc4random_buf(&ws.peer, sizeof(ws.peer)); |
533 | 539 | ||
534 | OT_PEERFLAG(ws.peer) &= PEER_FLAG_SEEDING | PEER_FLAG_COMPLETED | PEER_FLAG_STOPPED; | 540 | OT_PEERFLAG(ws.peer) &= PEER_FLAG_SEEDING | PEER_FLAG_COMPLETED | PEER_FLAG_STOPPED; |
535 | 541 | ||
536 | add_peer_to_torrent_and_return_peers( FLAG_TCP, &ws, 1 ); | 542 | add_peer_to_torrent_and_return_peers(FLAG_TCP, &ws, 1); |
537 | } | 543 | } |
538 | 544 | ||
539 | free(ws.inbuf); | 545 | free(ws.inbuf); |
@@ -541,54 +547,54 @@ void trackerlogic_add_random_torrents(size_t amount) { | |||
541 | } | 547 | } |
542 | #endif | 548 | #endif |
543 | 549 | ||
544 | void exerr( char * message ) { | 550 | void exerr(char *message) { |
545 | fprintf( stderr, "%s\n", message ); | 551 | fprintf(stderr, "%s\n", message); |
546 | exit( 111 ); | 552 | exit(111); |
547 | } | 553 | } |
548 | 554 | ||
549 | void trackerlogic_init( ) { | 555 | void trackerlogic_init() { |
550 | g_tracker_id = random(); | 556 | g_tracker_id = random(); |
551 | 557 | ||
552 | if( !g_stats_path ) | 558 | if (!g_stats_path) |
553 | g_stats_path = "stats"; | 559 | g_stats_path = "stats"; |
554 | g_stats_path_len = strlen( g_stats_path ); | 560 | g_stats_path_len = strlen(g_stats_path); |
555 | 561 | ||
556 | /* Initialise background worker threads */ | 562 | /* Initialise background worker threads */ |
557 | mutex_init( ); | 563 | mutex_init(); |
558 | clean_init( ); | 564 | clean_init(); |
559 | fullscrape_init( ); | 565 | fullscrape_init(); |
560 | accesslist_init( ); | 566 | accesslist_init(); |
561 | livesync_init( ); | 567 | livesync_init(); |
562 | stats_init( ); | 568 | stats_init(); |
563 | } | 569 | } |
564 | 570 | ||
565 | void trackerlogic_deinit( void ) { | 571 | void trackerlogic_deinit(void) { |
566 | int bucket, delta_torrentcount = 0; | 572 | int bucket, delta_torrentcount = 0; |
567 | size_t j; | 573 | size_t j; |
568 | 574 | ||
569 | /* Free all torrents... */ | 575 | /* Free all torrents... */ |
570 | for(bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 576 | for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { |
571 | ot_vector *torrents_list = mutex_bucket_lock( bucket ); | 577 | ot_vector *torrents_list = mutex_bucket_lock(bucket); |
572 | if( torrents_list->size ) { | 578 | if (torrents_list->size) { |
573 | for( j=0; j<torrents_list->size; ++j ) { | 579 | for (j = 0; j < torrents_list->size; ++j) { |
574 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + j; | 580 | ot_torrent *torrent = ((ot_torrent *)(torrents_list->data)) + j; |
575 | free_peerlist( torrent->peer_list6 ); | 581 | free_peerlist(torrent->peer_list6); |
576 | free_peerlist( torrent->peer_list4 ); | 582 | free_peerlist(torrent->peer_list4); |
577 | delta_torrentcount -= 1; | 583 | delta_torrentcount -= 1; |
578 | } | 584 | } |
579 | free( torrents_list->data ); | 585 | free(torrents_list->data); |
580 | } | 586 | } |
581 | mutex_bucket_unlock( bucket, delta_torrentcount ); | 587 | mutex_bucket_unlock(bucket, delta_torrentcount); |
582 | } | 588 | } |
583 | 589 | ||
584 | /* Deinitialise background worker threads */ | 590 | /* Deinitialise background worker threads */ |
585 | stats_deinit( ); | 591 | stats_deinit(); |
586 | livesync_deinit( ); | 592 | livesync_deinit(); |
587 | accesslist_deinit( ); | 593 | accesslist_deinit(); |
588 | fullscrape_deinit( ); | 594 | fullscrape_deinit(); |
589 | clean_deinit( ); | 595 | clean_deinit(); |
590 | /* Release mutexes */ | 596 | /* Release mutexes */ |
591 | mutex_deinit( ); | 597 | mutex_deinit(); |
592 | } | 598 | } |
593 | 599 | ||
594 | const char *g_version_trackerlogic_c = "$Source$: $Revision$\n"; | 600 | const char *g_version_trackerlogic_c = "$Source$: $Revision$\n"; |