if (*c==' ' || *c=='\t') ++c;
return c;
}
- return 0;
+ return 0;
}
+ return 0;
}
void httpresponse(struct http_data* h,int64 s)
{
- char *c, *d, *data;
+ char *c, *d, *data, *reply = NULL;
struct ot_peer peer;
+ ot_torrent torrent;
ot_hash *hash = NULL;
+ unsigned long numwant;
+ int compact;
+ size_t reply_size = 0;
array_cat0(&h->r);
while (c[1]=='/') ++c;
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
- case 0:
-e404:
- httperror(h,"404 Not Found","No such file or directory.");
- goto bailout;
case 6: /* scrape ? */
if (!byte_diff(c,6,"scrape"))
goto e404;
byte_copy( peer.ip, 4, h->ip );
peer.port = 6881;
+ numwant = 50;
+ compact = 1;
while( 1 ) {
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
/* scan int */ c;
else if(!byte_diff(c,7,"compact"))
/* scan flag */ c;
- break;
- case 9: /* info_hash= */
- if(!byte_diff(c,9,"info_hash")) {
- /* ignore this, when we have less than 20 bytes */
- switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) )
- case -1:
- httperror(h,"404 Not Found","No such file or directory.");
- goto bailout;
- case 20:
- hash = (ot_hash*)data; /* Fall through intended */
- default:
- continue;
+ break;
+ case 9:
+ if(byte_diff(c,9,"info_hash"))
+ continue;
+ /* ignore this, when we have less than 20 bytes */
+ switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
+ case -1:
+ goto e404;
+ case 20:
+ hash = (ot_hash*)data; /* Fall through intended */
+ default:
+ continue;
}
- break;
+ default:
+ continue;
}
}
+
+ /* Scanned whole query string */
+ if( !hash || ( compact == 0 ) ) goto e404;
+ torrent = add_peer_to_torrent( hash, &peer );
+ if( !torrent ) {
+e500:
+ httperror(h,"500 Internal Server Error","A server error has occured. Please retry later.");
+ goto bailout;
+ }
+ reply = malloc( numwant*6+10 );
+ if( reply )
+ reply_size = return_peers_for_torrent( torrent, numwant, reply );
+ if( !reply || reply_size < 0 ) {
+ if( reply ) free( reply );
+ goto e500;
+ }
break;
default: /* neither scrape nor announce */
+e404:
httperror(h,"404 Not Found","No such file or directory.");
goto bailout;
}
c+=fmt_httpdate(c,s.st_mtime); */
c+=fmt_str(c,"\r\nConnection: close\r\n\r\n");
iob_addbuf(&h->iob,h->hdrbuf,c - h->hdrbuf);
- iob_addbuf(&h->iob,tracker_answer, tracker_answer_size);
+ if( reply && reply_size ) iob_addbuf(&h->iob,reply, reply_size );
bailout:
io_dontwantread(s);
#define TESTSET( i ) (scratch_space[index])
#define RANDOM random()
-ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) {
+ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
ot_torrent torrent;
ot_peer peer_dest;
int exactmatch;
// Create a new torrent entry, then
MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) );
- torrent->peer_list = map_file( to_hex( hash ) );
+ torrent->peer_list = map_file( to_hex( *hash ) );
torrent->peer_count = 0;
torrent->seed_count = 0;
}
// * it is not guaranteed to see all peers, so no assumptions on active seeders/peers may be done
// * since compact format cannot handle v6 addresses, it must be enabled by OT_COMPACT_ONLY
//
-void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ) {
+size_t return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply ) {
register ot_peer peer_base = torrent->peer_list;
+ char *r = reply;
unsigned long peer_count = torrent->peer_count;
unsigned long selected_count = 0, invalid_count = 0;
unsigned long index = 0;
index = 0;
#ifndef OT_COMPACT_ONLY
- reply += FORMAT_FIXED_STRING( reply, "d5:peersl" );
+ r += FORMAT_FIXED_STRING( r, "d5:peersl" );
#else
- reply += FORMAT_FORMAT_STRING( reply, "d5:peers%li:",6*selected_count );
+ r += FORMAT_FORMAT_STRING( r, "d5:peers%li:",6*selected_count );
#endif
while( selected_count-- ) {
while( !TESTSELECTED( index ) ) ++index;
peer = peer_base + index;
#ifdef OT_COMPACT_ONLY
- MEMMOVE( reply, &peer->ip, 4 );
- MEMMOVE( reply+4, &peer->port, 2 );
- reply += 6;
+ MEMMOVE( r, &peer->ip, 4 );
+ MEMMOVE( r+4, &peer->port, 2 );
+ r += 6;
#else
- reply += FORMAT_FORMAT_STRING( reply, "d2:ip%d:%s7:peer id20:%20c4:porti%ie",
+ r += FORMAT_FORMAT_STRING( r, "d2:ip%d:%s7:peer id20:%20c4:porti%ie",
peer->flags & PEER_IP_LENGTH_MASK,
peer->ip,
peer->id,
#endif
}
#ifndef OT_COMPACT_ONLY
- reply += FORMAT_FIXED_STRING( reply, "ee" );
+ r += FORMAT_FIXED_STRING( r, "ee" );
#else
- reply += FORMAT_FIXED_STRING( reply, "e" );
+ r += FORMAT_FIXED_STRING( r, "e" );
#endif
+ return r - reply;
}
// Compacts a torrents peer list
#ifndef __TRACKERLOGIC_H__
#define __TRACKERLOGIC_H__
+#include <sys/types.h>
+
/* Should be called BYTE, WORD, DWORD - but some OSs already have that and there's no #iftypedef */
/* They mark memory used as data instead of integer or human readable string -
they should be cast before used as integer/text */
typedef ot_byte ot_hash[20];
typedef ot_byte ot_ip[ 4/*0*/ ];
// tunables
-const unsigned long OT_TIMEOUT = 2700;
-const unsigned long OT_HUGE_FILESIZE = 1024*1024*256; // Thats 256MB per file, enough for 204800 peers of 128 bytes
+static const unsigned long OT_TIMEOUT = 2700;
+static const unsigned long OT_HUGE_FILESIZE = 1024*1024*256; // Thats 256MB per file, enough for 204800 peers of 128 bytes
// We will not service v6, yes
#define OT_COMPACT_ONLY
ot_time death;
ot_byte flags;
} *ot_peer;
-ot_byte PEER_FLAG_SEEDING = 0x80;
-ot_byte PEER_IP_LENGTH_MASK = 0x3f;
+static const ot_byte PEER_FLAG_SEEDING = 0x80;
+static const ot_byte PEER_IP_LENGTH_MASK = 0x3f;
typedef struct {
ot_hash hash;
int init_logic( char *chdir_directory );
void deinit_logic( );
-ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer );
-void return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply );
+ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer );
+size_t return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char *reply );
void heal_torrent( ot_torrent torrent );
#endif