mirror of
git://erdgeist.org/opentracker
synced 2025-02-17 06:31:30 +08:00
Now actually seems to work for the most parts
Added scraping Added graceful disconnect
This commit is contained in:
parent
c0f667defe
commit
688a4edd9e
4
Makefile
4
Makefile
@ -1,6 +1,6 @@
|
|||||||
CC?=gcc
|
CC?=gcc
|
||||||
CFLAGS+=-I../libowfat -Wall -pipe -g -ggdb
|
CFLAGS+=-I../libowfat -Wall -pipe -O2
|
||||||
LDFLAGS+=-L../libowfat/ -lowfat
|
LDFLAGS+=-L../libowfat/ -lowfat -s
|
||||||
|
|
||||||
SOURCES=opentracker.c trackerlogic.c scan_urlencoded_query.c
|
SOURCES=opentracker.c trackerlogic.c scan_urlencoded_query.c
|
||||||
|
|
||||||
|
114
opentracker.c
114
opentracker.c
@ -107,11 +107,10 @@ const char* http_header(struct http_data* r,const char* h)
|
|||||||
void httpresponse(struct http_data* h,int64 s)
|
void httpresponse(struct http_data* h,int64 s)
|
||||||
{
|
{
|
||||||
char *c, *d, *data, *reply = NULL;
|
char *c, *d, *data, *reply = NULL;
|
||||||
struct ot_peer peer;
|
ot_peer peer;
|
||||||
ot_torrent torrent;
|
ot_torrent *torrent;
|
||||||
ot_hash *hash = NULL;
|
ot_hash *hash = NULL;
|
||||||
unsigned long numwant;
|
int numwant, tmp, scanon;
|
||||||
int compact, scanon;
|
|
||||||
size_t reply_size = 0;
|
size_t reply_size = 0;
|
||||||
|
|
||||||
array_cat0(&h->r);
|
array_cat0(&h->r);
|
||||||
@ -137,14 +136,57 @@ e400:
|
|||||||
case 6: /* scrape ? */
|
case 6: /* scrape ? */
|
||||||
if (byte_diff(data,6,"scrape"))
|
if (byte_diff(data,6,"scrape"))
|
||||||
goto e404;
|
goto e404;
|
||||||
|
scanon = 1;
|
||||||
|
|
||||||
|
while( scanon ) {
|
||||||
|
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
|
||||||
|
case -2: /* terminator */
|
||||||
|
scanon = 0;
|
||||||
|
break;
|
||||||
|
case -1: /* error */
|
||||||
|
goto e404;
|
||||||
|
case 9:
|
||||||
|
if(byte_diff(data,9,"info_hash")) {
|
||||||
|
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scanned whole query string, wo */
|
||||||
|
if( !hash ) {
|
||||||
|
httperror(h,"400 Invalid Request","This server only serves specific scrapes.");
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enough for whole scrape string
|
||||||
|
reply = malloc( 128 );
|
||||||
|
if( reply )
|
||||||
|
reply_size = return_scrape_for_torrent( hash, reply );
|
||||||
|
if( !reply || ( reply_size < 0 ) ) {
|
||||||
|
if( reply ) free( reply );
|
||||||
|
goto e500;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if( byte_diff(data,8,"announce"))
|
if( byte_diff(data,8,"announce"))
|
||||||
goto e404;
|
goto e404;
|
||||||
|
|
||||||
peer.ip = h->ip;
|
peer.ip = h->ip;
|
||||||
peer.port_flags = 6881 << 16;
|
peer.port_flags = 6881 << 16;
|
||||||
numwant = 50;
|
numwant = 50;
|
||||||
compact = 1;
|
|
||||||
scanon = 1;
|
scanon = 1;
|
||||||
|
|
||||||
while( scanon ) {
|
while( scanon ) {
|
||||||
@ -155,19 +197,44 @@ e400:
|
|||||||
case -1: /* error */
|
case -1: /* error */
|
||||||
goto e404;
|
goto e404;
|
||||||
case 4:
|
case 4:
|
||||||
if(!byte_diff(data,4,"port"))
|
if(!byte_diff(data,4,"port")) {
|
||||||
/* scan int */ c;
|
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||||
else if(!byte_diff(data,4,"left"))
|
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || (tmp > 65536) ) goto e404;
|
||||||
/* scan int */ c;
|
peer.port_flags = ( tmp << 16 ) | ( peer.port_flags & 0xffff );
|
||||||
else
|
} else if(!byte_diff(data,4,"left")) {
|
||||||
|
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||||
|
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e404;
|
||||||
|
if( !tmp ) peer.port_flags |= PEER_FLAG_SEEDING;
|
||||||
|
} else
|
||||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
if(byte_diff(data,5,"event"))
|
||||||
|
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||||
|
else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
|
||||||
|
case -1:
|
||||||
|
goto e404;
|
||||||
case 7:
|
case 7:
|
||||||
if(!byte_diff(data,7,"numwant"))
|
if(!byte_diff(data,7,"stopped")) peer.port_flags |= PEER_FLAG_STOPPED;
|
||||||
/* scan int */ c;
|
break;
|
||||||
else if(!byte_diff(data,7,"compact"))
|
case 9:
|
||||||
/* scan flag */ c;
|
if(!byte_diff(data,9,"complete")) peer.port_flags |= PEER_FLAG_COMPLETED;
|
||||||
else
|
default: // Fall through intended
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
if(!byte_diff(data,7,"numwant")) {
|
||||||
|
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||||
|
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e404;
|
||||||
|
} else if(!byte_diff(data,7,"compact")) {
|
||||||
|
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||||
|
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e404;
|
||||||
|
if( !tmp ) {
|
||||||
|
httperror(h,"400 Invalid Request","This server only delivers compact results.");
|
||||||
|
goto bailout;
|
||||||
|
}
|
||||||
|
} else
|
||||||
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
@ -180,9 +247,8 @@ e400:
|
|||||||
case -1:
|
case -1:
|
||||||
goto e404;
|
goto e404;
|
||||||
case 20:
|
case 20:
|
||||||
hash = (ot_hash*)data; /* Fall through intended */
|
hash = (ot_hash*)data;
|
||||||
printf("hash: %s\n",*hash);
|
default: // Fall through intended
|
||||||
default:
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -192,27 +258,33 @@ e400:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Scanned whole query string */
|
/* Scanned whole query string */
|
||||||
if( !hash || ( compact == 0 ) ) goto e404;
|
if( !hash ) goto e404;
|
||||||
|
|
||||||
|
if( peer.port_flags & PEER_FLAG_STOPPED ) {
|
||||||
|
remove_peer_from_torrent( hash, &peer );
|
||||||
|
reply = strdup( "d15:warning message4:Okaye" ); reply_size = 26;
|
||||||
|
} else {
|
||||||
torrent = add_peer_to_torrent( hash, &peer );
|
torrent = add_peer_to_torrent( hash, &peer );
|
||||||
if( !torrent ) {
|
if( !torrent ) {
|
||||||
e500:
|
e500:
|
||||||
httperror(h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
httperror(h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
reply = malloc( numwant*6+24 );
|
reply = malloc( numwant*6+64 ); // peerlist + seeder, peers and lametta
|
||||||
if( reply )
|
if( reply )
|
||||||
reply_size = return_peers_for_torrent( torrent, numwant, reply );
|
reply_size = return_peers_for_torrent( torrent, numwant, reply );
|
||||||
if( !reply || ( reply_size < 0 ) ) {
|
if( !reply || ( reply_size < 0 ) ) {
|
||||||
if( reply ) free( reply );
|
if( reply ) free( reply );
|
||||||
goto e500;
|
goto e500;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: /* neither scrape nor announce */
|
default: /* neither scrape nor announce */
|
||||||
e404:
|
e404:
|
||||||
httperror(h,"404 Not Found","No such file or directory.");
|
httperror(h,"404 Not Found","No such file or directory.");
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
c=h->hdrbuf=(char*)malloc(500);
|
c=h->hdrbuf=(char*)malloc(500);
|
||||||
c+=fmt_str(c,"HTTP/1.1 200 OK\r\nContent-Type: text/plain");
|
c+=fmt_str(c,"HTTP/1.1 200 OK\r\nContent-Type: text/plain");
|
||||||
c+=fmt_str(c,"\r\nContent-Length: ");
|
c+=fmt_str(c,"\r\nContent-Length: ");
|
||||||
@ -239,7 +311,6 @@ void graceful( int s ) {
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int s=socket_tcp4();
|
int s=socket_tcp4();
|
||||||
uint32 scope_id;
|
|
||||||
unsigned long ip;
|
unsigned long ip;
|
||||||
uint16 port;
|
uint16 port;
|
||||||
|
|
||||||
@ -284,7 +355,6 @@ int main()
|
|||||||
io_close(n);
|
io_close(n);
|
||||||
} else
|
} else
|
||||||
io_close(n);
|
io_close(n);
|
||||||
buffer_putnlflush(buffer_2);
|
|
||||||
}
|
}
|
||||||
if (errno==EAGAIN)
|
if (errno==EAGAIN)
|
||||||
io_eagain(s);
|
io_eagain(s);
|
||||||
|
@ -49,3 +49,9 @@ size_t scan_urlencoded_query(char **string, char *deststring, int flags) {
|
|||||||
*string = (char *)s;
|
*string = (char *)s;
|
||||||
return d - (unsigned char*)deststring;
|
return d - (unsigned char*)deststring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t scan_fixed_int( char *data, size_t len, int *tmp ) {
|
||||||
|
*tmp = 0;
|
||||||
|
while( (len > 0) && (*data >= '0') && (*data <= '9') ) { --len; *tmp = 10**tmp + *data++-'0'; }
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
@ -12,4 +12,9 @@
|
|||||||
// or -1 for parse error
|
// or -1 for parse error
|
||||||
size_t scan_urlencoded_query(char **string, char *deststring, int flags);
|
size_t scan_urlencoded_query(char **string, char *deststring, int flags);
|
||||||
|
|
||||||
|
// data pointer to len chars of string
|
||||||
|
// len length of chars in data to parse
|
||||||
|
// number number to receive result
|
||||||
|
size_t scan_fixed_int( char *data, size_t len, int *number );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
101
trackerlogic.c
101
trackerlogic.c
@ -19,13 +19,14 @@
|
|||||||
//
|
//
|
||||||
int compare_hash( const void *hash1, const void *hash2 ) { return memcmp( hash1, hash2, sizeof( ot_hash )); }
|
int compare_hash( const void *hash1, const void *hash2 ) { return memcmp( hash1, hash2, sizeof( ot_hash )); }
|
||||||
int compare_ip_port( const void *peer1, const void *peer2 ) {
|
int compare_ip_port( const void *peer1, const void *peer2 ) {
|
||||||
if( ((ot_peer)peer1)->ip != ((ot_peer)peer2)->ip ) return ((ot_peer)peer1)->ip - ((ot_peer)peer2)->ip;
|
if( ((ot_peer*)peer1)->ip != ((ot_peer*)peer2)->ip ) return ((ot_peer*)peer1)->ip - ((ot_peer*)peer2)->ip;
|
||||||
return ((ot_peer)peer1)->port_flags - ((ot_peer)peer2)->port_flags; }
|
return ((ot_peer*)peer1)->port_flags - ((ot_peer*)peer2)->port_flags; }
|
||||||
|
|
||||||
void *binary_search( const void *key, const void *base,
|
static void *binary_search( const void *key, const void *base,
|
||||||
unsigned long member_count, const unsigned long member_size,
|
unsigned long member_count, const unsigned long member_size,
|
||||||
int (*compar) (const void *, const void *),
|
int (*compar) (const void *, const void *),
|
||||||
int *exactmatch ) {
|
int *exactmatch )
|
||||||
|
{
|
||||||
ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
|
ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
|
||||||
*exactmatch = 1;
|
*exactmatch = 1;
|
||||||
|
|
||||||
@ -51,9 +52,9 @@ char ths[1+2*20];char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+40;
|
|||||||
|
|
||||||
// GLOBAL VARIABLES
|
// GLOBAL VARIABLES
|
||||||
//
|
//
|
||||||
struct ot_vector all_torrents[256];
|
static ot_vector all_torrents[256];
|
||||||
|
|
||||||
void *vector_find_or_insert( ot_vector vector, void *key, size_t member_size, int(*compare_func)(const void*, const void*), int *exactmatch ) {
|
static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int(*compare_func)(const void*, const void*), int *exactmatch ) {
|
||||||
ot_byte *match = BINARY_FIND( key, vector->data, vector->size, member_size, compare_func, exactmatch );
|
ot_byte *match = BINARY_FIND( key, vector->data, vector->size, member_size, compare_func, exactmatch );
|
||||||
|
|
||||||
if( *exactmatch ) return match;
|
if( *exactmatch ) return match;
|
||||||
@ -73,21 +74,21 @@ void *vector_find_or_insert( ot_vector vector, void *key, size_t member_size, in
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vector_remove_peer( ot_vector vector, ot_peer peer ) {
|
static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
|
||||||
int exactmatch;
|
int exactmatch;
|
||||||
ot_peer match;
|
ot_peer *match;
|
||||||
|
|
||||||
if( !vector->size ) return 0;
|
if( !vector->size ) return 0;
|
||||||
match = BINARY_FIND( peer, vector->data, vector->size, sizeof( struct ot_peer ), compare_ip_port, &exactmatch );
|
match = BINARY_FIND( peer, vector->data, vector->size, sizeof( ot_peer ), compare_ip_port, &exactmatch );
|
||||||
|
|
||||||
if( !exactmatch ) return 0;
|
if( !exactmatch ) return 0;
|
||||||
exactmatch = match->port_flags & PEER_FLAG_SEEDING ? 2 : 1;
|
exactmatch = match->port_flags & PEER_FLAG_SEEDING ? 2 : 1;
|
||||||
MEMMOVE( match, match + 1, ((ot_peer)vector->data) + vector->size - match - 1 );
|
MEMMOVE( match, match + 1, ((ot_peer*)vector->data) + vector->size - match - 1 );
|
||||||
vector->size--;
|
vector->size--;
|
||||||
return exactmatch;
|
return exactmatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_peerlist( ot_peerlist peer_list ) {
|
static void free_peerlist( ot_peerlist *peer_list ) {
|
||||||
int i;
|
int i;
|
||||||
for( i=0; i<OT_POOLS_COUNT; ++i )
|
for( i=0; i<OT_POOLS_COUNT; ++i )
|
||||||
if( peer_list->peers[i].data )
|
if( peer_list->peers[i].data )
|
||||||
@ -95,10 +96,10 @@ void free_peerlist( ot_peerlist peer_list ) {
|
|||||||
free( peer_list );
|
free( peer_list );
|
||||||
}
|
}
|
||||||
|
|
||||||
int vector_remove_torrent( ot_vector vector, ot_hash *hash ) {
|
static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
|
||||||
int exactmatch;
|
int exactmatch;
|
||||||
ot_torrent end = ((ot_torrent)vector->data) + vector->size;
|
ot_torrent *end = ((ot_torrent*)vector->data) + vector->size;
|
||||||
ot_torrent match = BINARY_FIND( hash, vector->data, vector->size, sizeof( struct ot_torrent ), compare_hash, &exactmatch );
|
ot_torrent *match = BINARY_FIND( hash, vector->data, vector->size, sizeof( ot_torrent ), compare_hash, &exactmatch );
|
||||||
|
|
||||||
if( !exactmatch ) return -1;
|
if( !exactmatch ) return -1;
|
||||||
free_peerlist( match->peer_list );
|
free_peerlist( match->peer_list );
|
||||||
@ -111,11 +112,12 @@ int vector_remove_torrent( ot_vector vector, ot_hash *hash ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_peerlist( ot_peerlist peer_list ) {
|
// Returns 1, if torrent is gone, 0 otherwise
|
||||||
|
static int clean_peerlist( ot_peerlist *peer_list ) {
|
||||||
long timedout = NOW-peer_list->base;
|
long timedout = NOW-peer_list->base;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( !timedout ) return;
|
if( !timedout ) return 0;
|
||||||
if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
|
if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
|
||||||
|
|
||||||
for( i=OT_POOLS_COUNT-timedout; i<OT_POOLS_COUNT; ++i )
|
for( i=OT_POOLS_COUNT-timedout; i<OT_POOLS_COUNT; ++i )
|
||||||
@ -128,39 +130,40 @@ void clean_peerlist( ot_peerlist peer_list ) {
|
|||||||
byte_zero( peer_list->seed_count, sizeof( unsigned long ) * timedout );
|
byte_zero( peer_list->seed_count, sizeof( unsigned long ) * timedout );
|
||||||
|
|
||||||
peer_list->base = NOW;
|
peer_list->base = NOW;
|
||||||
|
return timedout == OT_POOLS_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
|
ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||||
int exactmatch;
|
int exactmatch;
|
||||||
ot_torrent torrent;
|
ot_torrent *torrent;
|
||||||
ot_peer peer_dest;
|
ot_peer *peer_dest;
|
||||||
ot_vector torrents_list = all_torrents + *hash[0], peer_pool;
|
ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool;
|
||||||
|
|
||||||
torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( struct ot_torrent ), compare_hash, &exactmatch );
|
torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), compare_hash, &exactmatch );
|
||||||
if( !torrent ) return NULL;
|
if( !torrent ) return NULL;
|
||||||
|
|
||||||
if( !exactmatch ) {
|
if( !exactmatch ) {
|
||||||
// Create a new torrent entry, then
|
// Create a new torrent entry, then
|
||||||
torrent->peer_list = malloc( sizeof (struct ot_peerlist) );
|
torrent->peer_list = malloc( sizeof (ot_peerlist) );
|
||||||
if( !torrent->peer_list ) {
|
if( !torrent->peer_list ) {
|
||||||
vector_remove_torrent( torrents_list, hash );
|
vector_remove_torrent( torrents_list, hash );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) );
|
MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) );
|
||||||
|
|
||||||
byte_zero( torrent->peer_list, sizeof( struct ot_peerlist ));
|
byte_zero( torrent->peer_list, sizeof( ot_peerlist ));
|
||||||
torrent->peer_list->base = NOW;
|
torrent->peer_list->base = NOW;
|
||||||
} else
|
} else
|
||||||
clean_peerlist( torrent->peer_list );
|
clean_peerlist( torrent->peer_list );
|
||||||
|
|
||||||
peer_pool = &torrent->peer_list->peers[0];
|
peer_pool = &torrent->peer_list->peers[0];
|
||||||
peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( struct ot_peer ), compare_ip_port, &exactmatch );
|
peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), compare_ip_port, &exactmatch );
|
||||||
|
|
||||||
// If we hadn't had a match in current pool, create peer there and
|
// If we hadn't had a match in current pool, create peer there and
|
||||||
// remove it from all older pools
|
// remove it from all older pools
|
||||||
if( !exactmatch ) {
|
if( !exactmatch ) {
|
||||||
int i;
|
int i;
|
||||||
MEMMOVE( peer_dest, peer, sizeof( struct ot_peer ) );
|
MEMMOVE( peer_dest, peer, sizeof( ot_peer ) );
|
||||||
if( peer->port_flags & PEER_FLAG_SEEDING )
|
if( peer->port_flags & PEER_FLAG_SEEDING )
|
||||||
torrent->peer_list->seed_count[0]++;
|
torrent->peer_list->seed_count[0]++;
|
||||||
for( i=1; i<OT_POOLS_COUNT; ++i ) {
|
for( i=1; i<OT_POOLS_COUNT; ++i ) {
|
||||||
@ -176,6 +179,8 @@ ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
|
|||||||
if( !(peer_dest->port_flags & PEER_FLAG_SEEDING ) && (peer->port_flags & PEER_FLAG_SEEDING ) )
|
if( !(peer_dest->port_flags & PEER_FLAG_SEEDING ) && (peer->port_flags & PEER_FLAG_SEEDING ) )
|
||||||
torrent->peer_list->seed_count[0]++;
|
torrent->peer_list->seed_count[0]++;
|
||||||
}
|
}
|
||||||
|
if( peer->port_flags & PEER_FLAG_COMPLETED )
|
||||||
|
torrent->peer_list->downloaded++;
|
||||||
|
|
||||||
return torrent;
|
return torrent;
|
||||||
}
|
}
|
||||||
@ -186,7 +191,7 @@ ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
|
|||||||
// * RANDOM may return huge values
|
// * RANDOM may return huge values
|
||||||
// * does not yet check not to return self
|
// * does not yet check not to return self
|
||||||
//
|
//
|
||||||
size_t 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 ) {
|
||||||
char *r = reply;
|
char *r = reply;
|
||||||
unsigned long peer_count, index;
|
unsigned long peer_count, index;
|
||||||
signed long pool_offset = -1, pool_index = 0;
|
signed long pool_offset = -1, pool_index = 0;
|
||||||
@ -214,6 +219,48 @@ size_t return_peers_for_torrent( ot_torrent torrent, unsigned long amount, char
|
|||||||
return r - reply;
|
return r - reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetches scrape info for a specific torrent
|
||||||
|
size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
|
||||||
|
char *r = reply;
|
||||||
|
int exactmatch, peers = 0, seeds = 0, i;
|
||||||
|
ot_vector *torrents_list = &all_torrents[*hash[0]];
|
||||||
|
ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), compare_hash, &exactmatch );
|
||||||
|
|
||||||
|
if( !exactmatch ) return 0;
|
||||||
|
clean_peerlist( torrent->peer_list );
|
||||||
|
|
||||||
|
for( i=0; i<OT_POOLS_COUNT; ++i ) {
|
||||||
|
peers += torrent->peer_list->peers[i].size;
|
||||||
|
seeds += torrent->peer_list->seed_count[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMMOVE( r, "d5:filesd20:", 12 ); MEMMOVE( r+12, hash, 20 );
|
||||||
|
r += FORMAT_FORMAT_STRING( r+32, "d8:completei%de10:downloadedi%lde10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
|
||||||
|
|
||||||
|
return r - reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||||
|
int exactmatch, i;
|
||||||
|
ot_vector *torrents_list = &all_torrents[*hash[0]];
|
||||||
|
ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), compare_hash, &exactmatch );
|
||||||
|
|
||||||
|
if( !exactmatch ) return;
|
||||||
|
|
||||||
|
for( i=0; i<OT_POOLS_COUNT; ++i )
|
||||||
|
switch( vector_remove_peer( &torrent->peer_list->peers[i], peer ) ) {
|
||||||
|
case 0: continue;
|
||||||
|
case 2: torrent->peer_list->seed_count[i]--;
|
||||||
|
case 1: default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_peerlist( torrent->peer_list );
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_torrents( void ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int init_logic( char *directory ) {
|
int init_logic( char *directory ) {
|
||||||
glob_t globber;
|
glob_t globber;
|
||||||
int i;
|
int i;
|
||||||
@ -257,7 +304,7 @@ void deinit_logic( ) {
|
|||||||
// Free all torrents...
|
// Free all torrents...
|
||||||
for(i=0; i<256; ++i ) {
|
for(i=0; i<256; ++i ) {
|
||||||
if( all_torrents[i].size ) {
|
if( all_torrents[i].size ) {
|
||||||
ot_torrent torrents_list = (ot_torrent)all_torrents[i].data;
|
ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data;
|
||||||
for( j=0; j<all_torrents[i].size; ++j )
|
for( j=0; j<all_torrents[i].size; ++j )
|
||||||
free_peerlist( torrents_list[j].peer_list );
|
free_peerlist( torrents_list[j].peer_list );
|
||||||
free( all_torrents[i].data );
|
free( all_torrents[i].data );
|
||||||
|
@ -32,40 +32,31 @@ typedef time_t ot_time;
|
|||||||
#define OT_POOLS_TIMEOUT 300
|
#define OT_POOLS_TIMEOUT 300
|
||||||
#define NOW (time(NULL)/OT_POOLS_TIMEOUT)
|
#define NOW (time(NULL)/OT_POOLS_TIMEOUT)
|
||||||
|
|
||||||
typedef struct ot_vector {
|
typedef struct {
|
||||||
void *data;
|
void *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t space;
|
size_t space;
|
||||||
} *ot_vector;
|
} ot_vector;
|
||||||
|
|
||||||
typedef struct ot_peer {
|
typedef struct {
|
||||||
ot_ip ip;
|
ot_ip ip;
|
||||||
ot_dword port_flags;
|
ot_dword port_flags;
|
||||||
} *ot_peer;
|
} ot_peer;
|
||||||
static const ot_byte PEER_FLAG_SEEDING = 0x80;
|
static const ot_byte PEER_FLAG_SEEDING = 0x80;
|
||||||
|
static const ot_byte PEER_FLAG_COMPLETED = 0x40;
|
||||||
|
static const ot_byte PEER_FLAG_STOPPED = 0x20;
|
||||||
|
|
||||||
typedef struct ot_peerlist {
|
typedef struct {
|
||||||
ot_time base;
|
ot_time base;
|
||||||
unsigned long seed_count[ OT_POOLS_COUNT ];
|
unsigned long seed_count[ OT_POOLS_COUNT ];
|
||||||
struct ot_vector peers[ OT_POOLS_COUNT ];
|
unsigned long downloaded;
|
||||||
} *ot_peerlist;
|
ot_vector peers[ OT_POOLS_COUNT ];
|
||||||
|
} ot_peerlist;
|
||||||
|
|
||||||
typedef struct ot_torrent {
|
typedef struct {
|
||||||
ot_hash hash;
|
ot_hash hash;
|
||||||
ot_peerlist peer_list;
|
ot_peerlist *peer_list;
|
||||||
} *ot_torrent;
|
} ot_torrent;
|
||||||
|
|
||||||
void *map_file( char *file_name, size_t map_size );
|
|
||||||
void unmap_file( char *file_name, void *map, size_t mapped_size, unsigned long real_size );
|
|
||||||
|
|
||||||
// This behaves quite like bsearch but allows to find
|
|
||||||
// the insertion point for inserts after unsuccessful searches
|
|
||||||
// in this case exactmatch is 0 on exit
|
|
||||||
//
|
|
||||||
void *binary_search( const void *key, const void *base,
|
|
||||||
const unsigned long member_count, const unsigned long member_size,
|
|
||||||
int (*compar) (const void *, const void *),
|
|
||||||
int *exactmatch );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exported functions
|
// Exported functions
|
||||||
@ -74,7 +65,10 @@ void *binary_search( const void *key, const void *base,
|
|||||||
int init_logic( char *chdir_directory );
|
int init_logic( char *chdir_directory );
|
||||||
void deinit_logic( );
|
void deinit_logic( );
|
||||||
|
|
||||||
ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer );
|
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 );
|
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply );
|
||||||
|
size_t return_scrape_for_torrent( ot_hash *hash, char *reply );
|
||||||
|
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer );
|
||||||
|
void cleanup_torrents( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user