summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--opentracker.c402
-rw-r--r--scan_urlencoded_query.c16
-rw-r--r--scan_urlencoded_query.h29
-rw-r--r--trackerlogic.c125
-rw-r--r--trackerlogic.h32
6 files changed, 304 insertions, 302 deletions
diff --git a/Makefile b/Makefile
index b6d7d7e..65937c6 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC?=gcc
2FEATURES=-DWANT_IP_FROM_QUERY_STRING #-DWANT_BLACKLIST -DWANT_CLOSED_TRACKER 2FEATURES=-DWANT_IP_FROM_QUERY_STRING #-DWANT_BLACKLIST -DWANT_CLOSED_TRACKER
3#DEBUG_OPTS=-g -ggdb -pg # -fprofile-arcs -ftest-coverage 3#DEBUG_OPTS=-g -ggdb -pg # -fprofile-arcs -ftest-coverage
4DEBUG_OPTS=-s -Os 4DEBUG_OPTS=-s -Os
5CFLAGS+=-I../libowfat -Wall -pipe 5CFLAGS+=-I../libowfat -Wall -pipe # -pedantic -ansi
6LDFLAGS+=-L../libowfat/ -lowfat -lm 6LDFLAGS+=-L../libowfat/ -lowfat -lm
7 7
8HEADERS=trackerlogic.h scan_urlencoded_query.h 8HEADERS=trackerlogic.h scan_urlencoded_query.h
diff --git a/opentracker.c b/opentracker.c
index ac09089..f4b5e21 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -6,8 +6,8 @@
6#include "socket.h" 6#include "socket.h"
7#include "io.h" 7#include "io.h"
8#include "buffer.h" 8#include "buffer.h"
9#include "ip6.h"
10#include "array.h" 9#include "array.h"
10#include "byte.h"
11#include "case.h" 11#include "case.h"
12#include "fmt.h" 12#include "fmt.h"
13#include "str.h" 13#include "str.h"
@@ -25,14 +25,14 @@
25#include "trackerlogic.h" 25#include "trackerlogic.h"
26#include "scan_urlencoded_query.h" 26#include "scan_urlencoded_query.h"
27 27
28unsigned long const OT_CLIENT_TIMEOUT = 15; 28unsigned int const OT_CLIENT_TIMEOUT = 15;
29unsigned long const OT_CLIENT_TIMEOUT_CHECKINTERVAL = 5; 29unsigned int const OT_CLIENT_TIMEOUT_CHECKINTERVAL = 5;
30 30
31static unsigned int ot_overall_connections = 0; 31static unsigned int ot_overall_connections = 0;
32static time_t ot_start_time; 32static time_t ot_start_time;
33static const unsigned int SUCCESS_HTTP_HEADER_LENGTH = 80; 33static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80;
34static const unsigned int SUCCESS_HTTP_SIZE_OFF = 17; 34static const size_t SUCCESS_HTTP_SIZE_OFF = 17;
35// To always have space for error messages 35/* To always have space for error messages ;) */
36static char static_reply[8192]; 36static char static_reply[8192];
37 37
38static void carp(const char* routine) { 38static void carp(const char* routine) {
@@ -49,13 +49,12 @@ static void panic(const char* routine) {
49 49
50struct http_data { 50struct http_data {
51 array r; 51 array r;
52 unsigned long ip; 52 unsigned char ip[4];
53}; 53};
54 54
55int header_complete(struct http_data* r) { 55int header_complete(struct http_data* r) {
56 long l = array_bytes(&r->r); 56 int l = array_bytes(&r->r), i;
57 const char* c = array_start(&r->r); 57 const char* c = array_start(&r->r);
58 long i;
59 58
60 for (i=0; i+1<l; ++i) { 59 for (i=0; i+1<l; ++i) {
61 if (c[i]=='\n' && c[i+1]=='\n') return i+2; 60 if (c[i]=='\n' && c[i+1]=='\n') return i+2;
@@ -64,7 +63,7 @@ int header_complete(struct http_data* r) {
64 return 0; 63 return 0;
65} 64}
66 65
67// whoever sends data is not interested in its input-array 66/* whoever sends data is not interested in its input-array */
68void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) { 67void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
69 size_t written_size; 68 size_t written_size;
70 69
@@ -73,7 +72,7 @@ void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
73 if( ( written_size < 0 ) || ( written_size == size ) ) { 72 if( ( written_size < 0 ) || ( written_size == size ) ) {
74 free(h); io_close( s ); 73 free(h); io_close( s );
75 } else { 74 } else {
76 // here we would take a copy of the buffer and remember it 75 /* here we would take a copy of the buffer and remember it */
77 fprintf( stderr, "Should have handled this.\n" ); 76 fprintf( stderr, "Should have handled this.\n" );
78 free(h); io_close( s ); 77 free(h); io_close( s );
79 } 78 }
@@ -85,218 +84,225 @@ void httperror(int64 s,struct http_data* h,const char* title,const char* message
85 senddata(s,h,static_reply,reply_size); 84 senddata(s,h,static_reply,reply_size);
86} 85}
87 86
88// bestimmten http parameter auslesen und adresse zurueckgeben
89const char* http_header(struct http_data* r,const char* h) { 87const char* http_header(struct http_data* r,const char* h) {
90 long i; 88 int i, l = array_bytes(&r->r);
91 89 int sl = strlen(h);
92 long l = array_bytes(&r->r); 90 const char* c = array_start(&r->r);
93 long sl = strlen(h); 91
94 const char* c = array_start(&r->r); 92 for (i=0; i+sl+2<l; ++i) {
95 93 if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') {
96 for (i=0; i+sl+2<l; ++i) 94 c+=i+sl+1;
97 { 95 if (*c==' ' || *c=='\t') ++c;
98 if (c[i]=='\n' && case_equalb(c+i+1,sl,h) && c[i+sl+1]==':') 96 return c;
99 {
100 c+=i+sl+1;
101 if (*c==' ' || *c=='\t') ++c;
102 return c;
103 }
104 return 0;
105 } 97 }
106 return 0; 98 return 0;
99 }
100 return 0;
107} 101}
108 102
109void httpresponse(int64 s,struct http_data* h) 103void httpresponse(int64 s,struct http_data* h)
110{ 104{
111 char *c, *data; // must be enough 105 char *c, *data;
112 ot_peer peer; 106 ot_peer peer;
113 ot_torrent *torrent; 107 ot_torrent *torrent;
114 ot_hash *hash = NULL; 108 ot_hash *hash = NULL;
115 int numwant, tmp, scanon; 109 int numwant, tmp, scanon;
116 unsigned short port = htons(6881); 110 unsigned short port = htons(6881);
117 size_t reply_size = 0; 111 size_t reply_size = 0;
118 112
119 array_cat0(&h->r); 113 array_cat0(&h->r);
120 c = array_start(&h->r); 114 c = array_start(&h->r);
121 115
122 if (byte_diff(c,4,"GET ")) { 116 if (byte_diff(c,4,"GET ")) {
123e400: 117e400:
124 return httperror(s,h,"400 Invalid Request","This server only understands GET."); 118 return httperror(s,h,"400 Invalid Request","This server only understands GET.");
125 } 119 }
126
127 c+=4;
128 for (data=c; *data!=' '&&*data!='\t'&&*data!='\n'&&*data!='\r'; ++data) ;
129
130 if (*data!=' ') goto e400;
131 *data=0;
132 if (c[0]!='/') goto e404;
133 while (*c=='/') ++c;
134 120
135 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) 121 c+=4;
136 { 122 for (data=c; *data!=' '&&*data!='\t'&&*data!='\n'&&*data!='\r'; ++data) ;
137 case 6: /* scrape ? */ 123
138 if (byte_diff(data,6,"scrape")) 124 if (*data!=' ') goto e400;
125 *data=0;
126 if (c[0]!='/') goto e404;
127 while (*c=='/') ++c;
128
129 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
130 case 6: /* scrape ? */
131 if (byte_diff(data,6,"scrape"))
132 goto e404;
133 scanon = 1;
134
135 while( scanon ) {
136 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
137 case -2: /* terminator */
138 scanon = 0;
139 break;
140 case -1: /* error */
139 goto e404; 141 goto e404;
140 scanon = 1; 142 case 9:
141 143 if(byte_diff(data,9,"info_hash")) {
142 while( scanon ) {
143 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
144 case -2: /* terminator */
145 scanon = 0;
146 break;
147 case -1: /* error */
148 goto e404;
149 case 9:
150 if(byte_diff(data,9,"info_hash")) {
151 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
152 continue;
153 }
154 /* ignore this, when we have less than 20 bytes */
155 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
156e400_param:
157 return httperror(s,h,"400 Invalid Request","Invalid parameter");
158 }
159 hash = (ot_hash*)data; /* Fall through intended */
160 break;
161 default:
162 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 144 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
163 break; 145 continue;
146 }
147 /* ignore this, when we have less than 20 bytes */
148 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
149e400_param:
150 return httperror(s,h,"400 Invalid Request","Invalid parameter");
164 } 151 }
152 hash = (ot_hash*)data; /* Fall through intended */
153 break;
154 default:
155 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
156 break;
165 } 157 }
158 }
166 159
167 /* Scanned whole query string, wo */ 160 /* Scanned whole query string, wo */
168 if( !hash ) 161 if( !hash )
169 return httperror(s,h,"400 Invalid Request","This server only serves specific scrapes."); 162 return httperror(s,h,"400 Invalid Request","This server only serves specific scrapes.");
170 163
171 // Enough for http header + whole scrape string 164 /* Enough for http header + whole scrape string */
172 if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 ) 165 if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
173 goto e500; 166 goto e500;
174 break; 167 break;
175 case 8: 168 case 8:
176 if( byte_diff(data,8,"announce")) 169 if( byte_diff(data,8,"announce"))
170 goto e404;
171
172 OT_SETIP( &peer, h->ip);
173 OT_SETPORT( &peer, &port );
174 OT_FLAG( &peer ) = 0;
175 numwant = 50;
176 scanon = 1;
177
178 while( scanon ) {
179 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
180 case -2: /* terminator */
181 scanon = 0;
182 break;
183 case -1: /* error */
177 goto e404; 184 goto e404;
178
179 OT_SETIP( &peer, &h->ip);
180 OT_SETPORT( &peer, &port );
181 OT_FLAG( &peer ) = 0;
182 numwant = 50;
183 scanon = 1;
184
185 while( scanon ) {
186 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
187 case -2: /* terminator */
188 scanon = 0;
189 break;
190 case -1: /* error */
191 goto e404;
192#ifdef WANT_IP_FROM_QUERY_STRING 185#ifdef WANT_IP_FROM_QUERY_STRING
193 case 2: 186 case 2:
194 if(!byte_diff(data,2,"ip")) { 187 if(!byte_diff(data,2,"ip")) {
195 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 188 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
196 unsigned char ip[4]; 189 unsigned char ip[4];
197 if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param; 190 if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param;
198 OT_SETIP ( &peer, ip ); 191 OT_SETIP ( &peer, ip );
199 } else 192 } else
200 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 193 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
201 break; 194 break;
202#endif 195#endif
203 case 4: 196 case 4:
204 if(!byte_diff(data,4,"port")) { 197 if(!byte_diff(data,4,"port")) {
205 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 198 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
206 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param; 199 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param;
207 port = htons( tmp ); OT_SETPORT ( &peer, &port ); 200 port = htons( tmp ); OT_SETPORT ( &peer, &port );
208 } else if(!byte_diff(data,4,"left")) { 201 } else if(!byte_diff(data,4,"left")) {
209 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ); 202 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
210 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param; 203 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
211 if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING; 204 if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
212 } else 205 } else
213 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 206 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
214 break; 207 break;
215 case 5: 208 case 5:
216 if(byte_diff(data,5,"event")) 209 if(byte_diff(data,5,"event"))
217 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 210 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
218 else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { 211 else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
219 case -1: 212 case -1:
220 goto e400_param; 213 goto e400_param;
221 case 7:
222 if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
223 break;
224 case 9:
225 if(!byte_diff(data,9,"complete")) OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED;
226 default: // Fall through intended
227 break;
228 }
229 break;
230 case 7: 214 case 7:
231 if(!byte_diff(data,7,"numwant")) { 215 if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
232 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
233 if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
234 if( numwant > 200 ) numwant = 200;
235 } else if(!byte_diff(data,7,"compact")) {
236 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
237 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
238 if( !tmp )
239 return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
240 } else
241 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
242 break; 216 break;
243 case 9: 217 case 9:
244 if(byte_diff(data,9,"info_hash")) { 218 if(!byte_diff(data,9,"complete")) OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED;
245 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 219 default: /* Fall through intended */
246 continue;
247 }
248 /* ignore this, when we have less than 20 bytes */
249 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
250 goto e400;
251 hash = (ot_hash*)data;
252 break; 220 break;
253 default: 221 }
222 break;
223 case 7:
224 if(!byte_diff(data,7,"numwant")) {
225 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
226 if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
227 if( numwant > 200 ) numwant = 200;
228 } else if(!byte_diff(data,7,"compact")) {
229 size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
230 if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
231 if( !tmp )
232 return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
233 } else
254 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); 234 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
255 break; 235 break;
236 case 9:
237 if(byte_diff(data,9,"info_hash")) {
238 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
239 continue;
256 } 240 }
241 /* ignore this, when we have less than 20 bytes */
242 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
243 goto e400;
244 hash = (ot_hash*)data;
245 break;
246 default:
247 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
248 break;
257 } 249 }
250 }
258 251
259 /* Scanned whole query string */ 252 /* Scanned whole query string */
260 if( !hash ) goto e400; 253 if( !hash ) goto e400;
261 254
262 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) { 255 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
263 remove_peer_from_torrent( hash, &peer ); 256 remove_peer_from_torrent( hash, &peer );
264 MEMMOVE( static_reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 ); 257 memmove( static_reply + SUCCESS_HTTP_HEADER_LENGTH, "d15:warning message4:Okaye", reply_size = 26 );
265 } else { 258 } else {
266 torrent = add_peer_to_torrent( hash, &peer ); 259 torrent = add_peer_to_torrent( hash, &peer );
267 if( !torrent ) { 260 if( !torrent ) {
268e500: 261e500:
269 return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later."); 262 return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later.");
270 }
271 if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
272 goto e500;
273 } 263 }
274 break; 264 if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_reply ) ) <= 0 )
275 case 11: 265 goto e500;
276 if( byte_diff(data,11,"mrtg_scrape"))
277 goto e404;
278 {
279 unsigned long seconds_elapsed = time( NULL ) - ot_start_time;
280 reply_size = sprintf( static_reply + SUCCESS_HTTP_HEADER_LENGTH,
281 "%d\n%d\nUp: %ld seconds (%ld hours)\nPretuned by german engineers, currently handling %li connections per second.",
282 ot_overall_connections, ot_overall_connections, seconds_elapsed,
283 seconds_elapsed / 3600, ot_overall_connections / ( seconds_elapsed ? seconds_elapsed : 1 ) );
284 }
285 break;
286 default: /* neither *scrape nor announce */
287e404:
288 return httperror(s,h,"404 Not Found","No such file or directory.");
289 } 266 }
290 267 break;
291 if( reply_size ) { 268 case 11:
292 size_t reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_reply, 0, "%zd", reply_size ); 269 if( byte_diff(data,11,"mrtg_scrape"))
293 reply_size += 1 + sprintf( static_reply + reply_off, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", reply_size ); 270 goto e404;
294 static_reply[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n'; 271 {
295 senddata( s, h, static_reply + reply_off, reply_size ); 272 time_t seconds_elapsed = time( NULL ) - ot_start_time;
296 } else { 273 reply_size = sprintf( static_reply + SUCCESS_HTTP_HEADER_LENGTH,
297 if( h ) array_reset(&h->r); 274 "%d\n%d\nUp: %ld seconds (%ld hours)\nPretuned by german engineers, currently handling %li connections per second.",
298 free( h ); io_close( s ); 275 ot_overall_connections, ot_overall_connections, seconds_elapsed,
276 seconds_elapsed / 3600, ot_overall_connections / ( seconds_elapsed ? seconds_elapsed : 1 ) );
299 } 277 }
278 break;
279 default: /* neither *scrape nor announce */
280e404:
281 return httperror(s,h,"404 Not Found","No such file or directory.");
282 }
283
284 if( reply_size ) {
285 /* This one is rather ugly, so I take you step by step through it.
286
287 1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to
288 write to a fixed location, leaving SUCCESS_HTTP_HEADER_LENGTH bytes in our static buffer, which is enough for the static string
289 plus dynamic space needed to expand our Content-Length value. We reserve SUCCESS_HTTP_SIZE_OFF for it expansion and calculate
290 the space NOT needed to expand in reply_off
291 */
292 size_t reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( static_reply, 0, "%zd", reply_size );
293
294 /* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete
295 packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */
296 reply_size += 1 + sprintf( static_reply + reply_off, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", reply_size );
297
298 /* 3. Finally we join both blocks neatly */
299 static_reply[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
300
301 senddata( s, h, static_reply + reply_off, reply_size );
302 } else {
303 if( h ) array_reset(&h->r);
304 free( h ); io_close( s );
305 }
300} 306}
301 307
302void graceful( int s ) { 308void graceful( int s ) {
@@ -346,10 +352,10 @@ void help( char *name ) {
346int main( int argc, char **argv ) { 352int main( int argc, char **argv ) {
347 int s=socket_tcp4(); 353 int s=socket_tcp4();
348 tai6464 t, next_timeout_check; 354 tai6464 t, next_timeout_check;
349 unsigned long ip;
350 char *serverip = NULL; 355 char *serverip = NULL;
351 char *serverdir = "."; 356 char *serverdir = ".";
352 uint16 port = 6969; 357 uint16 port = 6969;
358 unsigned char ip[4];
353 359
354 while( 1 ) { 360 while( 1 ) {
355 switch( getopt(argc,argv,":i:p:d:ocbBh") ) { 361 switch( getopt(argc,argv,":i:p:d:ocbBh") ) {
@@ -412,16 +418,16 @@ allparsed:
412 } 418 }
413 419
414 while( ( i = io_canread() ) != -1 ) { 420 while( ( i = io_canread() ) != -1 ) {
415 if( i == s ) { // ist es der serversocket? 421 if( i == s ) {
416 int n; 422 int n;
417 while( ( n = socket_accept4( s, (void*)&ip, &port) ) != -1 ) { 423 while( ( n = socket_accept4( s, (char*)ip, &port) ) != -1 ) {
418 if( io_fd( n ) ) { 424 if( io_fd( n ) ) {
419 struct http_data* h=(struct http_data*)malloc(sizeof(struct http_data)); 425 struct http_data* h=(struct http_data*)malloc(sizeof(struct http_data));
420 io_wantread(n); 426 io_wantread(n);
421 427
422 if (h) { 428 if (h) {
423 byte_zero(h,sizeof(struct http_data)); 429 byte_zero(h,sizeof(struct http_data));
424 h->ip=ip; 430 memmove(h->ip,ip,sizeof(ip));
425 taia_now(&t); 431 taia_now(&t);
426 taia_addsec(&t,&t,OT_CLIENT_TIMEOUT); 432 taia_addsec(&t,&t,OT_CLIENT_TIMEOUT);
427 io_timeout(n,t); 433 io_timeout(n,t);
@@ -437,7 +443,7 @@ allparsed:
437 else 443 else
438 carp("socket_accept4"); 444 carp("socket_accept4");
439 } else { 445 } else {
440 char buf[8192]; 446 /* unsigned (sic!) */ char buf[8192];
441 struct http_data* h=io_getcookie(i); 447 struct http_data* h=io_getcookie(i);
442 448
443 int l=io_tryread(i,buf,sizeof buf); 449 int l=io_tryread(i,buf,sizeof buf);
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c
index ec145f9..223a4ad 100644
--- a/scan_urlencoded_query.c
+++ b/scan_urlencoded_query.c
@@ -4,15 +4,15 @@
4#include "scan.h" 4#include "scan.h"
5#include "scan_urlencoded_query.h" 5#include "scan_urlencoded_query.h"
6 6
7// Idea is to do a in place replacement or guarantee at least 7/* Idea is to do a in place replacement or guarantee at least
8// strlen( string ) bytes in deststring 8 strlen( string ) bytes in deststring
9// watch http://www.ietf.org/rfc/rfc2396.txt 9 watch http://www.ietf.org/rfc/rfc2396.txt
10// unreserved = alphanum | mark 10 unreserved = alphanum | mark
11// mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 11 mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
12// we add '%' to the matrix to not stop at encoded chars. 12 we add '%' to the matrix to not stop at encoded chars.
13 13*/
14static const unsigned char reserved_matrix[] = { 0xA2, 0x63, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x47}; 14static const unsigned char reserved_matrix[] = { 0xA2, 0x63, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x47};
15inline int is_unreserved( unsigned char c ) { 15static int is_unreserved( unsigned char c ) {
16 if( ( c <= 32 ) || ( c >= 127 ) ) return 0; return 1&(reserved_matrix[(c-32)>>3]>>(c&7)); 16 if( ( c <= 32 ) || ( c >= 127 ) ) return 0; return 1&(reserved_matrix[(c-32)>>3]>>(c&7));
17} 17}
18 18
diff --git a/scan_urlencoded_query.h b/scan_urlencoded_query.h
index 83f9be0..7663278 100644
--- a/scan_urlencoded_query.h
+++ b/scan_urlencoded_query.h
@@ -8,23 +8,26 @@
8#define SCAN_SEARCHPATH_PARAM 1 8#define SCAN_SEARCHPATH_PARAM 1
9#define SCAN_SEARCHPATH_VALUE 2 9#define SCAN_SEARCHPATH_VALUE 2
10 10
11// string pointer to source, pointer to after terminator on return 11/* string pointer to source, pointer to after terminator on return
12// deststring pointer to destination 12 deststring pointer to destination
13// flags determines, what to parse 13 flags determines, what to parse
14// returns number of valid converted characters in deststring 14 returns number of valid converted characters in deststring
15// or -1 for parse error 15 or -1 for parse error
16*/
16size_t scan_urlencoded_query(char **string, char *deststring, int flags); 17size_t scan_urlencoded_query(char **string, char *deststring, int flags);
17 18
18// data pointer to len chars of string 19/* data pointer to len chars of string
19// len length of chars in data to parse 20 len length of chars in data to parse
20// number number to receive result 21 number number to receive result
21// returns number of bytes not parsed, mostly !=0 means fail 22 returns number of bytes not parsed, mostly !=0 means fail
23*/
22size_t scan_fixed_int( char *data, size_t len, int *number ); 24size_t scan_fixed_int( char *data, size_t len, int *number );
23 25
24// data pointer to len chars of string 26/* data pointer to len chars of string
25// len length of chars in data to parse 27 len length of chars in data to parse
26// ip buffer to receive result 28 ip buffer to receive result
27// returns number of bytes not parsed, mostly !=0 means fail 29 returns number of bytes not parsed, mostly !=0 means fail
30*/
28size_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] ); 31size_t scan_fixed_ip( char *data, size_t len, unsigned char ip[4] );
29 32
30#endif 33#endif
diff --git a/trackerlogic.c b/trackerlogic.c
index 85e8156..2b8ffaf 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -22,8 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#endif 23#endif
24 24
25// GLOBAL VARIABLES 25/* GLOBAL VARIABLES */
26//
27static ot_vector all_torrents[256]; 26static ot_vector all_torrents[256];
28 27
29#ifdef WANT_CLOSED_TRACKER 28#ifdef WANT_CLOSED_TRACKER
@@ -36,36 +35,37 @@ int g_check_blacklist = 1;
36static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2; 35static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2;
37#endif 36#endif
38 37
39// This function gives us a binary search that returns a pointer, even if 38/* This function gives us a binary search that returns a pointer, even if
40// no exact match is found. In that case it sets exactmatch 0 and gives 39 no exact match is found. In that case it sets exactmatch 0 and gives
41// calling functions the chance to insert data 40 calling functions the chance to insert data
42// 41*/
43static void *binary_search( const void *key, const void *base, unsigned long member_count, const unsigned long member_size, 42static void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size,
44 int compare_size, int *exactmatch ) { 43 size_t compare_size, int *exactmatch ) {
44 size_t mc = member_count;
45 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1); 45 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
46 *exactmatch = 1; 46 *exactmatch = 1;
47 47
48 while( member_count ) { 48 while( mc ) {
49 int cmp = memcmp( lookat, key, compare_size); 49 int cmp = memcmp( lookat, key, compare_size);
50 if (cmp == 0) return (void *)lookat; 50 if (cmp == 0) return (void *)lookat;
51 if (cmp < 0) { 51 if (cmp < 0) {
52 base = (void*)(lookat + member_size); 52 base = (void*)(lookat + member_size);
53 --member_count; 53 --mc;
54 } 54 }
55 member_count >>= 1; 55 mc >>= 1;
56 lookat = ((ot_byte*)base) + member_size * (member_count >> 1); 56 lookat = ((ot_byte*)base) + member_size * (mc >> 1);
57 } 57 }
58 *exactmatch = 0; 58 *exactmatch = 0;
59 return (void*)lookat; 59 return (void*)lookat;
60} 60}
61 61
62// Converter function from memory to human readable hex strings 62/* Converter function from memory to human readable hex strings
63// * definitely not thread safe!!! 63 - definitely not thread safe!!!
64// 64*/
65char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;} 65char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;}
66 66
67static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) { 67static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) {
68 ot_byte *match = BINARY_FIND( key, vector->data, vector->size, member_size, compare_size, exactmatch ); 68 ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch );
69 69
70 if( *exactmatch ) return match; 70 if( *exactmatch ) return match;
71 71
@@ -74,13 +74,13 @@ static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_
74 ot_byte *new_data = realloc( vector->data, new_space * member_size ); 74 ot_byte *new_data = realloc( vector->data, new_space * member_size );
75 if( !new_data ) return NULL; 75 if( !new_data ) return NULL;
76 76
77 // Adjust pointer if it moved by realloc 77 /* Adjust pointer if it moved by realloc */
78 match = new_data + (match - (ot_byte*)vector->data); 78 match = new_data + (match - (ot_byte*)vector->data);
79 79
80 vector->data = new_data; 80 vector->data = new_data;
81 vector->space = new_space; 81 vector->space = new_space;
82 } 82 }
83 MEMMOVE( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match ); 83 memmove( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match );
84 vector->size++; 84 vector->size++;
85 return match; 85 return match;
86} 86}
@@ -91,11 +91,11 @@ static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
91 ot_peer *match; 91 ot_peer *match;
92 92
93 if( !vector->size ) return 0; 93 if( !vector->size ) return 0;
94 match = BINARY_FIND( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); 94 match = binary_search( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
95 95
96 if( !exactmatch ) return 0; 96 if( !exactmatch ) return 0;
97 exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1; 97 exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1;
98 MEMMOVE( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) ); 98 memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );
99 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { 99 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
100 vector->space /= OT_VECTOR_SHRINK_RATIO; 100 vector->space /= OT_VECTOR_SHRINK_RATIO;
101 vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) ); 101 vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) );
@@ -117,15 +117,15 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
117 ot_torrent *match; 117 ot_torrent *match;
118 118
119 if( !vector->size ) return 0; 119 if( !vector->size ) return 0;
120 match = BINARY_FIND( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 120 match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
121 121
122 if( !exactmatch ) return 0; 122 if( !exactmatch ) return 0;
123 123
124 // If this is being called after a unsuccessful malloc() for peer_list 124 /* If this is being called after a unsuccessful malloc() for peer_list
125 // in add_peer_to_torrent, match->peer_list actually might be NULL 125 in add_peer_to_torrent, match->peer_list actually might be NULL */
126 if( match->peer_list) free_peerlist( match->peer_list ); 126 if( match->peer_list) free_peerlist( match->peer_list );
127 127
128 MEMMOVE( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) ); 128 memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) );
129 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { 129 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
130 vector->space /= OT_VECTOR_SHRINK_RATIO; 130 vector->space /= OT_VECTOR_SHRINK_RATIO;
131 vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) ); 131 vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) );
@@ -133,22 +133,21 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
133 return 1; 133 return 1;
134} 134}
135 135
136// Returns 1, if torrent is gone, 0 otherwise 136/* Returns 1, if torrent is gone, 0 otherwise */
137static int clean_peerlist( ot_peerlist *peer_list ) { 137static int clean_peerlist( ot_peerlist *peer_list ) {
138 long timedout = NOW-peer_list->base; 138 int i, timedout = (int)( NOW - peer_list->base );
139 int i;
140 139
141 if( !timedout ) return 0; 140 if( !timedout ) return 0;
142 if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT; 141 if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
143 142
144 for( i=OT_POOLS_COUNT-timedout; i<OT_POOLS_COUNT; ++i ) 143 for( i = OT_POOLS_COUNT - timedout; i < OT_POOLS_COUNT; ++i )
145 free( peer_list->peers[i].data); 144 free( peer_list->peers[i].data);
146 145
147 MEMMOVE( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) ); 146 memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) );
148 byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout ); 147 byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout );
149 148
150 MEMMOVE( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( unsigned long ) * (OT_POOLS_COUNT-timedout) ); 149 memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout) );
151 byte_zero( peer_list->seed_count, sizeof( unsigned long ) * timedout ); 150 byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout );
152 151
153 peer_list->base = NOW; 152 peer_list->base = NOW;
154 return timedout == OT_POOLS_COUNT; 153 return timedout == OT_POOLS_COUNT;
@@ -178,8 +177,8 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
178 if( !torrent ) return NULL; 177 if( !torrent ) return NULL;
179 178
180 if( !exactmatch ) { 179 if( !exactmatch ) {
181 // Create a new torrent entry, then 180 /* Create a new torrent entry, then */
182 MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) ); 181 memmove( &torrent->hash, hash, sizeof( ot_hash ) );
183 182
184 torrent->peer_list = malloc( sizeof (ot_peerlist) ); 183 torrent->peer_list = malloc( sizeof (ot_peerlist) );
185 if( !torrent->peer_list ) { 184 if( !torrent->peer_list ) {
@@ -195,11 +194,11 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
195 peer_pool = &torrent->peer_list->peers[0]; 194 peer_pool = &torrent->peer_list->peers[0];
196 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); 195 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
197 196
198 // If we hadn't had a match in current pool, create peer there and 197 /* If we hadn't had a match in current pool, create peer there and
199 // remove it from all older pools 198 remove it from all older pools */
200 if( !exactmatch ) { 199 if( !exactmatch ) {
201 int i; 200 int i;
202 MEMMOVE( peer_dest, peer, sizeof( ot_peer ) ); 201 memmove( peer_dest, peer, sizeof( ot_peer ) );
203 if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) 202 if( OT_FLAG(peer) & PEER_FLAG_SEEDING )
204 torrent->peer_list->seed_count[0]++; 203 torrent->peer_list->seed_count[0]++;
205 for( i=1; i<OT_POOLS_COUNT; ++i ) { 204 for( i=1; i<OT_POOLS_COUNT; ++i ) {
@@ -221,27 +220,30 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
221 return torrent; 220 return torrent;
222} 221}
223 222
224// Compiles a list of random peers for a torrent 223/* Compiles a list of random peers for a torrent
225// * reply must have enough space to hold 24+6*amount bytes 224 * reply must have enough space to hold 24+6*amount bytes
226// * Selector function can be anything, maybe test for seeds, etc. 225 * Selector function can be anything, maybe test for seeds, etc.
227// * RANDOM may return huge values 226 * RANDOM may return huge values
228// * does not yet check not to return self 227 * does not yet check not to return self
229// 228*/
230size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply ) { 229size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) {
231 char *r = reply; 230 char *r = reply;
232 unsigned long peer_count, seed_count, index; 231 unsigned int peer_count, seed_count, index;
233 signed long pool_offset = -1, pool_index = 0; 232 int pool_offset = -1, pool_index = 0, wert = -1;
234 signed long wert = -1;
235 233
236#ifdef WANT_CLOSED_TRACKER 234#ifdef WANT_CLOSED_TRACKER
237 if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) { 235 if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) {
238 return( FORMAT_FORMAT_STRING( reply, "d14:failure reason43:This torrent is not served by this tracker.e" ) ); 236 const char * const notvalid = "d14:failure reason43:This torrent is not served by this tracker.e";
237 memmove( reply, notvalid, sizeof(notvalid));
238 return sizeof(notvalid);
239 } 239 }
240#endif 240#endif
241 241
242#ifdef WANT_BLACKLIST 242#ifdef WANT_BLACKLIST
243 if( torrent == OT_TORRENT_ON_BLACKLIST ) { 243 if( torrent == OT_TORRENT_ON_BLACKLIST ) {
244 return( FORMAT_FORMAT_STRING( reply, "d14:failure reason29:This torrent is black listed.e" ) ); 244 const char * const blacklisted = "d14:failure reason29:This torrent is black listed.e";
245 memmove( reply, blacklisted, sizeof(blacklisted));
246 return sizeof(blacklisted);
245 } 247 }
246#endif 248#endif
247 249
@@ -251,23 +253,19 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
251 } 253 }
252 if( peer_count < amount ) amount = peer_count; 254 if( peer_count < amount ) amount = peer_count;
253 255
254 r += FORMAT_FORMAT_STRING( r, "d8:completei%lie10:incompletei%lie8:intervali600e5:peers%li:", seed_count, peer_count-seed_count, 6*amount ); 256 r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali600e5:peers%i:", seed_count, peer_count-seed_count, 6*amount );
255 for( index = 0; index < amount; ++index ) { 257 for( index = 0; index < amount; ++index ) {
256 double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index )); 258 double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index ));
257 int off = random() % (int)floor( step ); 259 int off = random() % (int)floor( step );
258 off = 1 + ( off % ( peer_count - wert - 1 )); 260 off = 1 + ( off % ( peer_count - wert - 1 ));
259 wert += off; pool_offset += off; 261 wert += off; pool_offset += off;
260 262
261 // In some rare occasions random gets the last peer a round to early
262 // correct that and return last peer twice
263 // if( wert >= peer_count ) { wert--; pool_offset--; }
264
265 while( pool_offset >= torrent->peer_list->peers[pool_index].size ) { 263 while( pool_offset >= torrent->peer_list->peers[pool_index].size ) {
266 pool_offset -= torrent->peer_list->peers[pool_index].size; 264 pool_offset -= torrent->peer_list->peers[pool_index].size;
267 pool_index++; 265 pool_index++;
268 } 266 }
269 267
270 MEMMOVE( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 ); 268 memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 );
271 r += 6; 269 r += 6;
272 } 270 }
273 *r++ = 'e'; 271 *r++ = 'e';
@@ -275,12 +273,12 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
275 return r - reply; 273 return r - reply;
276} 274}
277 275
278// Fetches scrape info for a specific torrent 276/* Fetches scrape info for a specific torrent */
279size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) { 277size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
280 char *r = reply; 278 char *r = reply;
281 int exactmatch, peers = 0, seeds = 0, i; 279 int exactmatch, peers = 0, seeds = 0, i;
282 ot_vector *torrents_list = &all_torrents[*hash[0]]; 280 ot_vector *torrents_list = &all_torrents[*hash[0]];
283 ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 281 ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
284 282
285 if( !exactmatch ) return 0; 283 if( !exactmatch ) return 0;
286 clean_peerlist( torrent->peer_list ); 284 clean_peerlist( torrent->peer_list );
@@ -290,8 +288,8 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
290 seeds += torrent->peer_list->seed_count[i]; 288 seeds += torrent->peer_list->seed_count[i];
291 } 289 }
292 290
293 MEMMOVE( r, "d5:filesd20:", 12 ); MEMMOVE( r+12, hash, 20 ); 291 memmove( r, "d5:filesd20:", 12 ); memmove( r+12, hash, 20 );
294 r += FORMAT_FORMAT_STRING( r+32, "d8:completei%de10:downloadedi%lde10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32; 292 r += sprintf( r+32, "d8:completei%de10:downloadedi%de10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
295 293
296 return r - reply; 294 return r - reply;
297} 295}
@@ -299,11 +297,11 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
299void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) { 297void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
300 int exactmatch, i; 298 int exactmatch, i;
301 ot_vector *torrents_list = &all_torrents[*hash[0]]; 299 ot_vector *torrents_list = &all_torrents[*hash[0]];
302 ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 300 ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
303 301
304 if( !exactmatch ) return; 302 if( !exactmatch ) return;
305 303
306 // Maybe this does the job 304 /* Maybe this does the job */
307 if( clean_peerlist( torrent->peer_list ) ) { 305 if( clean_peerlist( torrent->peer_list ) ) {
308#ifdef WANT_CLOSED_TRACKER 306#ifdef WANT_CLOSED_TRACKER
309 if( !g_closedtracker ) 307 if( !g_closedtracker )
@@ -332,7 +330,7 @@ int init_logic( char *serverdir ) {
332 330
333 srandom( time(NULL)); 331 srandom( time(NULL));
334 332
335 // Initialize control structures 333 /* Initialize control structures */
336 byte_zero( all_torrents, sizeof (all_torrents)); 334 byte_zero( all_torrents, sizeof (all_torrents));
337 335
338 return 0; 336 return 0;
@@ -340,7 +338,8 @@ int init_logic( char *serverdir ) {
340 338
341void deinit_logic( ) { 339void deinit_logic( ) {
342 int i, j; 340 int i, j;
343 // Free all torrents... 341
342 /* Free all torrents... */
344 for(i=0; i<256; ++i ) { 343 for(i=0; i<256; ++i ) {
345 if( all_torrents[i].size ) { 344 if( all_torrents[i].size ) {
346 ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data; 345 ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data;
diff --git a/trackerlogic.h b/trackerlogic.h
index 812cfce..178f8db 100644
--- a/trackerlogic.h
+++ b/trackerlogic.h
@@ -18,18 +18,12 @@ typedef ot_byte ot_hash[20];
18typedef ot_dword ot_ip; 18typedef ot_dword ot_ip;
19typedef time_t ot_time; 19typedef time_t ot_time;
20 20
21#define MEMMOVE memmove 21/* We maintain a list of 256 pointers to sorted list of ot_torrent structs
22#define BZERO bzero 22 Sort key is, of course, its hash */
23#define FORMAT_FIXED_STRING sprintf
24#define FORMAT_FORMAT_STRING sprintf
25#define BINARY_FIND binary_search
26 23
27// We maintain a list of 256 pointers to sorted list of ot_torrent structs 24/* This list points to 9 pools of peers each grouped in five-minute-intervals
28// Sort key is, of course, its hash 25 thus achieving a timeout of 2700s or 45 minutes
29 26 These pools are sorted by its binary content */
30// This list points to 9 pools of peers each grouped in five-minute-intervals
31// thus achieving a timeout of 2700s or 45 minutes
32// These pools are sorted by its binary content
33 27
34#define OT_POOLS_COUNT 9 28#define OT_POOLS_COUNT 9
35#define OT_POOLS_TIMEOUT 300 29#define OT_POOLS_TIMEOUT 300
@@ -52,8 +46,8 @@ static const ot_byte PEER_FLAG_SEEDING = 0x80;
52static const ot_byte PEER_FLAG_COMPLETED = 0x40; 46static const ot_byte PEER_FLAG_COMPLETED = 0x40;
53static const ot_byte PEER_FLAG_STOPPED = 0x20; 47static const ot_byte PEER_FLAG_STOPPED = 0x20;
54 48
55#define OT_SETIP( peer, ip ) MEMMOVE((peer),(ip),4); 49#define OT_SETIP( peer, ip ) memmove((peer),(ip),4);
56#define OT_SETPORT( peer, port ) MEMMOVE(((ot_byte*)peer)+4,(port),2); 50#define OT_SETPORT( peer, port ) memmove(((ot_byte*)peer)+4,(port),2);
57#define OT_FLAG(peer) (((ot_byte*)(peer))[6]) 51#define OT_FLAG(peer) (((ot_byte*)(peer))[6])
58 52
59#define OT_PEER_COMPARE_SIZE ((size_t)6) 53#define OT_PEER_COMPARE_SIZE ((size_t)6)
@@ -61,8 +55,8 @@ static const ot_byte PEER_FLAG_STOPPED = 0x20;
61 55
62typedef struct { 56typedef struct {
63 ot_time base; 57 ot_time base;
64 unsigned long seed_count[ OT_POOLS_COUNT ]; 58 size_t seed_count[ OT_POOLS_COUNT ];
65 unsigned long downloaded; 59 unsigned int downloaded;
66 ot_vector peers[ OT_POOLS_COUNT ]; 60 ot_vector peers[ OT_POOLS_COUNT ];
67} ot_peerlist; 61} ot_peerlist;
68 62
@@ -71,9 +65,9 @@ typedef struct {
71 ot_peerlist *peer_list; 65 ot_peerlist *peer_list;
72} ot_torrent; 66} ot_torrent;
73 67
74// 68/*
75// Exported functions 69 Exported functions
76// 70*/
77 71
78int init_logic( char *serverdir ); 72int init_logic( char *serverdir );
79void deinit_logic( ); 73void deinit_logic( );
@@ -86,7 +80,7 @@ extern int g_check_blacklist;
86#endif 80#endif
87 81
88ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ); 82ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer );
89size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply ); 83size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply );
90size_t return_scrape_for_torrent( ot_hash *hash, char *reply ); 84size_t return_scrape_for_torrent( ot_hash *hash, char *reply );
91void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ); 85void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer );
92void cleanup_torrents( void ); 86void cleanup_torrents( void );