mirror of
git://erdgeist.org/opentracker
synced 2025-02-22 09:01:29 +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
|
||||
CFLAGS+=-I../libowfat -Wall -pipe -g -ggdb
|
||||
LDFLAGS+=-L../libowfat/ -lowfat
|
||||
CFLAGS+=-I../libowfat -Wall -pipe -O2
|
||||
LDFLAGS+=-L../libowfat/ -lowfat -s
|
||||
|
||||
SOURCES=opentracker.c trackerlogic.c scan_urlencoded_query.c
|
||||
|
||||
|
140
opentracker.c
140
opentracker.c
@ -106,13 +106,12 @@ const char* http_header(struct http_data* r,const char* h)
|
||||
|
||||
void httpresponse(struct http_data* h,int64 s)
|
||||
{
|
||||
char *c, *d, *data, *reply = NULL;
|
||||
struct ot_peer peer;
|
||||
ot_torrent torrent;
|
||||
ot_hash *hash = NULL;
|
||||
unsigned long numwant;
|
||||
int compact, scanon;
|
||||
size_t reply_size = 0;
|
||||
char *c, *d, *data, *reply = NULL;
|
||||
ot_peer peer;
|
||||
ot_torrent *torrent;
|
||||
ot_hash *hash = NULL;
|
||||
int numwant, tmp, scanon;
|
||||
size_t reply_size = 0;
|
||||
|
||||
array_cat0(&h->r);
|
||||
|
||||
@ -137,14 +136,57 @@ e400:
|
||||
case 6: /* scrape ? */
|
||||
if (byte_diff(data,6,"scrape"))
|
||||
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;
|
||||
case 8:
|
||||
if( byte_diff(data,8,"announce"))
|
||||
goto e404;
|
||||
|
||||
peer.ip = h->ip;
|
||||
peer.port_flags = 6881 << 16;
|
||||
numwant = 50;
|
||||
compact = 1;
|
||||
scanon = 1;
|
||||
|
||||
while( scanon ) {
|
||||
@ -155,19 +197,44 @@ e400:
|
||||
case -1: /* error */
|
||||
goto e404;
|
||||
case 4:
|
||||
if(!byte_diff(data,4,"port"))
|
||||
/* scan int */ c;
|
||||
else if(!byte_diff(data,4,"left"))
|
||||
/* scan int */ c;
|
||||
else
|
||||
if(!byte_diff(data,4,"port")) {
|
||||
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
|
||||
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || (tmp > 65536) ) goto e404;
|
||||
peer.port_flags = ( tmp << 16 ) | ( peer.port_flags & 0xffff );
|
||||
} 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 );
|
||||
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:
|
||||
if(!byte_diff(data,7,"stopped")) peer.port_flags |= PEER_FLAG_STOPPED;
|
||||
break;
|
||||
case 9:
|
||||
if(!byte_diff(data,9,"complete")) peer.port_flags |= PEER_FLAG_COMPLETED;
|
||||
default: // Fall through intended
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if(!byte_diff(data,7,"numwant"))
|
||||
/* scan int */ c;
|
||||
else if(!byte_diff(data,7,"compact"))
|
||||
/* scan flag */ c;
|
||||
else
|
||||
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 );
|
||||
break;
|
||||
case 9:
|
||||
@ -180,9 +247,8 @@ e400:
|
||||
case -1:
|
||||
goto e404;
|
||||
case 20:
|
||||
hash = (ot_hash*)data; /* Fall through intended */
|
||||
printf("hash: %s\n",*hash);
|
||||
default:
|
||||
hash = (ot_hash*)data;
|
||||
default: // Fall through intended
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
@ -192,20 +258,25 @@ e400:
|
||||
}
|
||||
|
||||
/* Scanned whole query string */
|
||||
if( !hash || ( compact == 0 ) ) goto e404;
|
||||
if( !hash ) goto e404;
|
||||
|
||||
torrent = add_peer_to_torrent( hash, &peer );
|
||||
if( !torrent ) {
|
||||
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 );
|
||||
if( !torrent ) {
|
||||
e500:
|
||||
httperror(h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
||||
goto bailout;
|
||||
}
|
||||
reply = malloc( numwant*6+24 );
|
||||
if( reply )
|
||||
reply_size = return_peers_for_torrent( torrent, numwant, reply );
|
||||
if( !reply || ( reply_size < 0 ) ) {
|
||||
if( reply ) free( reply );
|
||||
goto e500;
|
||||
httperror(h,"500 Internal Server Error","A server error has occured. Please retry later.");
|
||||
goto bailout;
|
||||
}
|
||||
reply = malloc( numwant*6+64 ); // peerlist + seeder, peers and lametta
|
||||
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 */
|
||||
@ -213,6 +284,7 @@ e404:
|
||||
httperror(h,"404 Not Found","No such file or directory.");
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
c=h->hdrbuf=(char*)malloc(500);
|
||||
c+=fmt_str(c,"HTTP/1.1 200 OK\r\nContent-Type: text/plain");
|
||||
c+=fmt_str(c,"\r\nContent-Length: ");
|
||||
@ -239,7 +311,6 @@ void graceful( int s ) {
|
||||
int main()
|
||||
{
|
||||
int s=socket_tcp4();
|
||||
uint32 scope_id;
|
||||
unsigned long ip;
|
||||
uint16 port;
|
||||
|
||||
@ -284,7 +355,6 @@ int main()
|
||||
io_close(n);
|
||||
} else
|
||||
io_close(n);
|
||||
buffer_putnlflush(buffer_2);
|
||||
}
|
||||
if (errno==EAGAIN)
|
||||
io_eagain(s);
|
||||
|
@ -49,3 +49,9 @@ size_t scan_urlencoded_query(char **string, char *deststring, int flags) {
|
||||
*string = (char *)s;
|
||||
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
|
||||
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
|
||||
|
109
trackerlogic.c
109
trackerlogic.c
@ -19,13 +19,14 @@
|
||||
//
|
||||
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 ) {
|
||||
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; }
|
||||
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; }
|
||||
|
||||
void *binary_search( const void *key, const void *base,
|
||||
unsigned long member_count, const unsigned long member_size,
|
||||
int (*compar) (const void *, const void *),
|
||||
int *exactmatch ) {
|
||||
static void *binary_search( const void *key, const void *base,
|
||||
unsigned long member_count, const unsigned long member_size,
|
||||
int (*compar) (const void *, const void *),
|
||||
int *exactmatch )
|
||||
{
|
||||
ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 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
|
||||
//
|
||||
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 );
|
||||
|
||||
if( *exactmatch ) return match;
|
||||
@ -72,22 +73,22 @@ void *vector_find_or_insert( ot_vector vector, void *key, size_t member_size, in
|
||||
vector->size++;
|
||||
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;
|
||||
ot_peer match;
|
||||
ot_peer *match;
|
||||
|
||||
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;
|
||||
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--;
|
||||
return exactmatch;
|
||||
}
|
||||
|
||||
void free_peerlist( ot_peerlist peer_list ) {
|
||||
static void free_peerlist( ot_peerlist *peer_list ) {
|
||||
int i;
|
||||
for( i=0; i<OT_POOLS_COUNT; ++i )
|
||||
if( peer_list->peers[i].data )
|
||||
@ -95,10 +96,10 @@ void free_peerlist( ot_peerlist 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;
|
||||
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 *end = ((ot_torrent*)vector->data) + vector->size;
|
||||
ot_torrent *match = BINARY_FIND( hash, vector->data, vector->size, sizeof( ot_torrent ), compare_hash, &exactmatch );
|
||||
|
||||
if( !exactmatch ) return -1;
|
||||
free_peerlist( match->peer_list );
|
||||
@ -111,11 +112,12 @@ int vector_remove_torrent( ot_vector vector, ot_hash *hash ) {
|
||||
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;
|
||||
int i;
|
||||
|
||||
if( !timedout ) return;
|
||||
if( !timedout ) return 0;
|
||||
if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
|
||||
|
||||
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 );
|
||||
|
||||
peer_list->base = NOW;
|
||||
return timedout == OT_POOLS_COUNT;
|
||||
}
|
||||
|
||||
ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
|
||||
int exactmatch;
|
||||
ot_torrent torrent;
|
||||
ot_peer peer_dest;
|
||||
ot_vector torrents_list = all_torrents + *hash[0], peer_pool;
|
||||
ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
|
||||
int exactmatch;
|
||||
ot_torrent *torrent;
|
||||
ot_peer *peer_dest;
|
||||
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( !exactmatch ) {
|
||||
// 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 ) {
|
||||
vector_remove_torrent( torrents_list, hash );
|
||||
return NULL;
|
||||
}
|
||||
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;
|
||||
} else
|
||||
clean_peerlist( torrent->peer_list );
|
||||
|
||||
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
|
||||
// remove it from all older pools
|
||||
if( !exactmatch ) {
|
||||
int i;
|
||||
MEMMOVE( peer_dest, peer, sizeof( struct ot_peer ) );
|
||||
MEMMOVE( peer_dest, peer, sizeof( ot_peer ) );
|
||||
if( peer->port_flags & PEER_FLAG_SEEDING )
|
||||
torrent->peer_list->seed_count[0]++;
|
||||
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 ) )
|
||||
torrent->peer_list->seed_count[0]++;
|
||||
}
|
||||
if( peer->port_flags & PEER_FLAG_COMPLETED )
|
||||
torrent->peer_list->downloaded++;
|
||||
|
||||
return torrent;
|
||||
}
|
||||
@ -186,7 +191,7 @@ ot_torrent add_peer_to_torrent( ot_hash *hash, ot_peer peer ) {
|
||||
// * RANDOM may return huge values
|
||||
// * 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;
|
||||
unsigned long peer_count, index;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 ) {
|
||||
glob_t globber;
|
||||
int i;
|
||||
@ -257,7 +304,7 @@ void deinit_logic( ) {
|
||||
// Free all torrents...
|
||||
for(i=0; i<256; ++i ) {
|
||||
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 )
|
||||
free_peerlist( torrents_list[j].peer_list );
|
||||
free( all_torrents[i].data );
|
||||
|
@ -32,40 +32,31 @@ typedef time_t ot_time;
|
||||
#define OT_POOLS_TIMEOUT 300
|
||||
#define NOW (time(NULL)/OT_POOLS_TIMEOUT)
|
||||
|
||||
typedef struct ot_vector {
|
||||
typedef struct {
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t space;
|
||||
} *ot_vector;
|
||||
} ot_vector;
|
||||
|
||||
typedef struct ot_peer {
|
||||
typedef struct {
|
||||
ot_ip ip;
|
||||
ot_dword port_flags;
|
||||
} *ot_peer;
|
||||
} ot_peer;
|
||||
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 {
|
||||
ot_time base;
|
||||
unsigned long seed_count[ OT_POOLS_COUNT ];
|
||||
struct ot_vector peers[ OT_POOLS_COUNT ];
|
||||
} *ot_peerlist;
|
||||
typedef struct {
|
||||
ot_time base;
|
||||
unsigned long seed_count[ OT_POOLS_COUNT ];
|
||||
unsigned long downloaded;
|
||||
ot_vector peers[ OT_POOLS_COUNT ];
|
||||
} ot_peerlist;
|
||||
|
||||
typedef struct ot_torrent {
|
||||
ot_hash hash;
|
||||
ot_peerlist peer_list;
|
||||
} *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 );
|
||||
typedef struct {
|
||||
ot_hash hash;
|
||||
ot_peerlist *peer_list;
|
||||
} ot_torrent;
|
||||
|
||||
//
|
||||
// Exported functions
|
||||
@ -74,7 +65,10 @@ void *binary_search( const void *key, const void *base,
|
||||
int init_logic( char *chdir_directory );
|
||||
void deinit_logic( );
|
||||
|
||||
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 );
|
||||
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_scrape_for_torrent( ot_hash *hash, char *reply );
|
||||
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer );
|
||||
void cleanup_torrents( void );
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user