diff options
-rw-r--r-- | opentracker.c | 61 | ||||
-rw-r--r-- | trackerlogic.c | 24 | ||||
-rw-r--r-- | trackerlogic.h | 14 |
3 files changed, 62 insertions, 37 deletions
diff --git a/opentracker.c b/opentracker.c index 8313d90..d46858d 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -97,15 +97,20 @@ const char* http_header(struct http_data* r,const char* h) | |||
97 | if (*c==' ' || *c=='\t') ++c; | 97 | if (*c==' ' || *c=='\t') ++c; |
98 | return c; | 98 | return c; |
99 | } | 99 | } |
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | return 0; | ||
102 | } | 103 | } |
103 | 104 | ||
104 | void httpresponse(struct http_data* h,int64 s) | 105 | void httpresponse(struct http_data* h,int64 s) |
105 | { | 106 | { |
106 | char *c, *d, *data; | 107 | char *c, *d, *data, *reply = NULL; |
107 | struct ot_peer peer; | 108 | struct ot_peer peer; |
109 | ot_torrent torrent; | ||
108 | ot_hash *hash = NULL; | 110 | ot_hash *hash = NULL; |
111 | unsigned long numwant; | ||
112 | int compact; | ||
113 | size_t reply_size = 0; | ||
109 | 114 | ||
110 | array_cat0(&h->r); | 115 | array_cat0(&h->r); |
111 | 116 | ||
@@ -128,10 +133,6 @@ e400: | |||
128 | while (c[1]=='/') ++c; | 133 | while (c[1]=='/') ++c; |
129 | 134 | ||
130 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { | 135 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { |
131 | case 0: | ||
132 | e404: | ||
133 | httperror(h,"404 Not Found","No such file or directory."); | ||
134 | goto bailout; | ||
135 | case 6: /* scrape ? */ | 136 | case 6: /* scrape ? */ |
136 | if (!byte_diff(c,6,"scrape")) | 137 | if (!byte_diff(c,6,"scrape")) |
137 | goto e404; | 138 | goto e404; |
@@ -142,6 +143,8 @@ e404: | |||
142 | 143 | ||
143 | byte_copy( peer.ip, 4, h->ip ); | 144 | byte_copy( peer.ip, 4, h->ip ); |
144 | peer.port = 6881; | 145 | peer.port = 6881; |
146 | numwant = 50; | ||
147 | compact = 1; | ||
145 | 148 | ||
146 | while( 1 ) { | 149 | while( 1 ) { |
147 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | 150 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { |
@@ -158,24 +161,42 @@ e404: | |||
158 | /* scan int */ c; | 161 | /* scan int */ c; |
159 | else if(!byte_diff(c,7,"compact")) | 162 | else if(!byte_diff(c,7,"compact")) |
160 | /* scan flag */ c; | 163 | /* scan flag */ c; |
161 | break; | 164 | break; |
162 | case 9: /* info_hash= */ | 165 | case 9: |
163 | if(!byte_diff(c,9,"info_hash")) { | 166 | if(byte_diff(c,9,"info_hash")) |
164 | /* ignore this, when we have less than 20 bytes */ | 167 | continue; |
165 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) | 168 | /* ignore this, when we have less than 20 bytes */ |
166 | case -1: | 169 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) { |
167 | httperror(h,"404 Not Found","No such file or directory."); | 170 | case -1: |
168 | goto bailout; | 171 | goto e404; |
169 | case 20: | 172 | case 20: |
170 | hash = (ot_hash*)data; /* Fall through intended */ | 173 | hash = (ot_hash*)data; /* Fall through intended */ |
171 | default: | 174 | default: |
172 | continue; | 175 | continue; |
173 | } | 176 | } |
174 | break; | 177 | default: |
178 | continue; | ||
175 | } | 179 | } |
176 | } | 180 | } |
181 | |||
182 | /* Scanned whole query string */ | ||
183 | if( !hash || ( compact == 0 ) ) goto e404; | ||
184 | torrent = add_peer_to_torrent( hash, &peer ); | ||
185 | if( !torrent ) { | ||
186 | e500: | ||
187 | httperror(h,"500 Internal Server Error","A server error has occured. Please retry later."); | ||
188 | goto bailout; | ||
189 | } | ||
190 | reply = malloc( numwant*6+10 ); | ||
191 | if( reply ) | ||
192 | reply_size = return_peers_for_torrent( torrent, numwant, reply ); | ||
193 | if( !reply || reply_size < 0 ) { | ||
194 | if( reply ) free( reply ); | ||
195 | goto e500; | ||
196 | } | ||
177 | break; | 197 | break; |
178 | default: /* neither scrape nor announce */ | 198 | default: /* neither scrape nor announce */ |
199 | e404: | ||
179 | httperror(h,"404 Not Found","No such file or directory."); | 200 | httperror(h,"404 Not Found","No such file or directory."); |
180 | goto bailout; | 201 | goto bailout; |
181 | } | 202 | } |
@@ -190,7 +211,7 @@ e404: | |||
190 | c+=fmt_httpdate(c,s.st_mtime); */ | 211 | c+=fmt_httpdate(c,s.st_mtime); */ |
191 | c+=fmt_str(c,"\r\nConnection: close\r\n\r\n"); | 212 | c+=fmt_str(c,"\r\nConnection: close\r\n\r\n"); |
192 | iob_addbuf(&h->iob,h->hdrbuf,c - h->hdrbuf); | 213 | iob_addbuf(&h->iob,h->hdrbuf,c - h->hdrbuf); |
193 | iob_addbuf(&h->iob,tracker_answer, tracker_answer_size); | 214 | if( reply && reply_size ) iob_addbuf(&h->iob,reply, reply_size ); |
194 | 215 | ||
195 | bailout: | 216 | bailout: |
196 | io_dontwantread(s); | 217 | io_dontwantread(s); |
diff --git a/trackerlogic.c b/trackerlogic.c index 6274c41..ab1f419 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -54,7 +54,7 @@ ot_byte *scratch_space = 0; | |||
54 | #define TESTSET( i ) (scratch_space[index]) | 54 | #define TESTSET( i ) (scratch_space[index]) |
55 | #define RANDOM random() | 55 | #define RANDOM random() |
56 | 56 | ||
57 | ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) { | 57 | ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) { |
58 | ot_torrent torrent; | 58 | ot_torrent torrent; |
59 | ot_peer peer_dest; | 59 | ot_peer peer_dest; |
60 | int exactmatch; | 60 | int exactmatch; |
@@ -66,7 +66,7 @@ ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) { | |||
66 | 66 | ||
67 | // Create a new torrent entry, then | 67 | // Create a new torrent entry, then |
68 | MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) ); | 68 | MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) ); |
69 | torrent->peer_list = map_file( to_hex( hash ) ); | 69 | torrent->peer_list = map_file( to_hex( *hash ) ); |
70 | torrent->peer_count = 0; | 70 | torrent->peer_count = 0; |
71 | torrent->seed_count = 0; | 71 | torrent->seed_count = 0; |
72 | } | 72 | } |
@@ -106,8 +106,9 @@ inline int TESTVALIDPEER( ot_peer p ) { return p->death > NOW; } | |||
106 | // * it is not guaranteed to see all peers, so no assumptions on active seeders/peers may be done | 106 | // * it is not guaranteed to see all peers, so no assumptions on active seeders/peers may be done |
107 | // * since compact format cannot handle v6 addresses, it must be enabled by OT_COMPACT_ONLY | 107 | // * since compact format cannot handle v6 addresses, it must be enabled by OT_COMPACT_ONLY |
108 | // | 108 | // |
109 | void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ) { | 109 | size_t return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ) { |
110 | register ot_peer peer_base = torrent->peer_list; | 110 | register ot_peer peer_base = torrent->peer_list; |
111 | char *r = reply; | ||
111 | unsigned long peer_count = torrent->peer_count; | 112 | unsigned long peer_count = torrent->peer_count; |
112 | unsigned long selected_count = 0, invalid_count = 0; | 113 | unsigned long selected_count = 0, invalid_count = 0; |
113 | unsigned long index = 0; | 114 | unsigned long index = 0; |
@@ -132,9 +133,9 @@ void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *r | |||
132 | index = 0; | 133 | index = 0; |
133 | 134 | ||
134 | #ifndef OT_COMPACT_ONLY | 135 | #ifndef OT_COMPACT_ONLY |
135 | reply += FORMAT_FIXED_STRING( reply, "d5:peersl" ); | 136 | r += FORMAT_FIXED_STRING( r, "d5:peersl" ); |
136 | #else | 137 | #else |
137 | reply += FORMAT_FORMAT_STRING( reply, "d5:peers%li:",6*selected_count ); | 138 | r += FORMAT_FORMAT_STRING( r, "d5:peers%li:",6*selected_count ); |
138 | #endif | 139 | #endif |
139 | 140 | ||
140 | while( selected_count-- ) { | 141 | while( selected_count-- ) { |
@@ -142,11 +143,11 @@ void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *r | |||
142 | while( !TESTSELECTED( index ) ) ++index; | 143 | while( !TESTSELECTED( index ) ) ++index; |
143 | peer = peer_base + index; | 144 | peer = peer_base + index; |
144 | #ifdef OT_COMPACT_ONLY | 145 | #ifdef OT_COMPACT_ONLY |
145 | MEMMOVE( reply, &peer->ip, 4 ); | 146 | MEMMOVE( r, &peer->ip, 4 ); |
146 | MEMMOVE( reply+4, &peer->port, 2 ); | 147 | MEMMOVE( r+4, &peer->port, 2 ); |
147 | reply += 6; | 148 | r += 6; |
148 | #else | 149 | #else |
149 | reply += FORMAT_FORMAT_STRING( reply, "d2:ip%d:%s7:peer id20:%20c4:porti%ie", | 150 | r += FORMAT_FORMAT_STRING( r, "d2:ip%d:%s7:peer id20:%20c4:porti%ie", |
150 | peer->flags & PEER_IP_LENGTH_MASK, | 151 | peer->flags & PEER_IP_LENGTH_MASK, |
151 | peer->ip, | 152 | peer->ip, |
152 | peer->id, | 153 | peer->id, |
@@ -154,10 +155,11 @@ void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *r | |||
154 | #endif | 155 | #endif |
155 | } | 156 | } |
156 | #ifndef OT_COMPACT_ONLY | 157 | #ifndef OT_COMPACT_ONLY |
157 | reply += FORMAT_FIXED_STRING( reply, "ee" ); | 158 | r += FORMAT_FIXED_STRING( r, "ee" ); |
158 | #else | 159 | #else |
159 | reply += FORMAT_FIXED_STRING( reply, "e" ); | 160 | r += FORMAT_FIXED_STRING( r, "e" ); |
160 | #endif | 161 | #endif |
162 | return r - reply; | ||
161 | } | 163 | } |
162 | 164 | ||
163 | // Compacts a torrents peer list | 165 | // Compacts a torrents peer list |
diff --git a/trackerlogic.h b/trackerlogic.h index 03ed577..ad18cba 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __TRACKERLOGIC_H__ | 1 | #ifndef __TRACKERLOGIC_H__ |
2 | #define __TRACKERLOGIC_H__ | 2 | #define __TRACKERLOGIC_H__ |
3 | 3 | ||
4 | #include <sys/types.h> | ||
5 | |||
4 | /* Should be called BYTE, WORD, DWORD - but some OSs already have that and there's no #iftypedef */ | 6 | /* Should be called BYTE, WORD, DWORD - but some OSs already have that and there's no #iftypedef */ |
5 | /* They mark memory used as data instead of integer or human readable string - | 7 | /* They mark memory used as data instead of integer or human readable string - |
6 | they should be cast before used as integer/text */ | 8 | they should be cast before used as integer/text */ |
@@ -12,8 +14,8 @@ typedef unsigned long ot_time; | |||
12 | typedef ot_byte ot_hash[20]; | 14 | typedef ot_byte ot_hash[20]; |
13 | typedef ot_byte ot_ip[ 4/*0*/ ]; | 15 | typedef ot_byte ot_ip[ 4/*0*/ ]; |
14 | // tunables | 16 | // tunables |
15 | const unsigned long OT_TIMEOUT = 2700; | 17 | static const unsigned long OT_TIMEOUT = 2700; |
16 | const unsigned long OT_HUGE_FILESIZE = 1024*1024*256; // Thats 256MB per file, enough for 204800 peers of 128 bytes | 18 | static const unsigned long OT_HUGE_FILESIZE = 1024*1024*256; // Thats 256MB per file, enough for 204800 peers of 128 bytes |
17 | 19 | ||
18 | // We will not service v6, yes | 20 | // We will not service v6, yes |
19 | #define OT_COMPACT_ONLY | 21 | #define OT_COMPACT_ONLY |
@@ -35,8 +37,8 @@ typedef struct ot_peer { | |||
35 | ot_time death; | 37 | ot_time death; |
36 | ot_byte flags; | 38 | ot_byte flags; |
37 | } *ot_peer; | 39 | } *ot_peer; |
38 | ot_byte PEER_FLAG_SEEDING = 0x80; | 40 | static const ot_byte PEER_FLAG_SEEDING = 0x80; |
39 | ot_byte PEER_IP_LENGTH_MASK = 0x3f; | 41 | static const ot_byte PEER_IP_LENGTH_MASK = 0x3f; |
40 | 42 | ||
41 | typedef struct { | 43 | typedef struct { |
42 | ot_hash hash; | 44 | ot_hash hash; |
@@ -64,8 +66,8 @@ void *binary_search( const void *key, const void *base, | |||
64 | int init_logic( char *chdir_directory ); | 66 | int init_logic( char *chdir_directory ); |
65 | void deinit_logic( ); | 67 | void deinit_logic( ); |
66 | 68 | ||
67 | ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ); | 69 | ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ); |
68 | void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ); | 70 | size_t return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ); |
69 | void heal_torrent( ot_torrent torrent ); | 71 | void heal_torrent( ot_torrent torrent ); |
70 | 72 | ||
71 | #endif | 73 | #endif |