1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-10 06:02:57 +00:00

get some pieces of the new tracker code into svn...

This commit is contained in:
Charles Kerr 2007-08-14 20:45:23 +00:00
parent d2d7d01df2
commit 2bf071543b
9 changed files with 510 additions and 1 deletions

View file

@ -1,4 +1,4 @@
AM_CPPFLAGS = -I. -I$(top_srcdir) $(LIBEVENT_CPPFLAGS) -D__TRANSMISSION__
AM_CPPFLAGS = -I. -I@top_srcdir@ -D__TRANSMISSION__
noinst_LIBRARIES = libtransmission.a
@ -23,11 +23,14 @@ libtransmission_a_SOURCES = \
net.c \
peer.c \
platform.c \
ptrarray.c \
publish.c \
ratecontrol.c \
sha1.c \
shared.c \
strlcat.c \
strlcpy.c \
timer.c \
torrent.c \
tracker.c \
transmission.c \
@ -61,9 +64,12 @@ noinst_HEADERS = \
peertree.h \
peerutils.h \
platform.h \
ptrarray.h \
publish.h \
ratecontrol.h \
sha1.h \
shared.h \
timer.h \
tracker.h \
transmission.h \
trcompat.h \

186
libtransmission/ptrarray.c Normal file
View file

@ -0,0 +1,186 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h> /* memmove */
#include "ptrarray.h"
#include "utils.h"
#define GROW 32
struct tr_ptrArray_s
{
void ** items;
int n_items;
int n_alloc;
};
tr_ptrArray_t*
tr_ptrArrayNew( void )
{
tr_ptrArray_t * p;
p = tr_new( tr_ptrArray_t, 1 );
p->n_items = 0;
p->n_alloc = GROW;
p->items = tr_new( void*, p->n_alloc );
return p;
}
void
tr_ptrArrayFree( tr_ptrArray_t * t )
{
assert( t != NULL );
assert( t->items != NULL );
tr_free( t->items );
tr_free( t );
}
void**
tr_ptrArrayPeek( tr_ptrArray_t * t, int * size )
{
*size = t->n_items;
return t->items;
}
int
tr_ptrArraySize( const tr_ptrArray_t * t )
{
return t->n_items;
}
int
tr_ptrArrayEmpty( const tr_ptrArray_t * t )
{
return t->n_items == 0;
}
void
tr_ptrArrayClear( tr_ptrArray_t * t )
{
t->n_items = 0;
}
int
tr_ptrArrayInsert( tr_ptrArray_t * t, void * ptr, int pos )
{
if( pos<0 || pos>t->n_items )
pos = t->n_items;
if( t->n_items >= t->n_alloc ) {
t->n_alloc = t->n_items + GROW;
t->items = tr_renew( void*, t->items, t->n_alloc );
}
memmove( t->items + pos + 1,
t->items + pos,
sizeof(void*) * (t->n_items - pos));
t->items[pos] = ptr;
t->n_items++;
return pos;
}
int
tr_ptrArrayAppend( tr_ptrArray_t * t, void * ptr )
{
return tr_ptrArrayInsert( t, ptr, -1 );
}
void
tr_ptrArrayErase( tr_ptrArray_t * t, int begin, int end )
{
assert( begin >= 0 );
if( end < 0 ) end = t->n_items;
assert( end > begin );
assert( end <= t->n_items );
memmove( t->items + begin,
t->items + end,
sizeof(void*) * (t->n_items - end) );
t->n_items -= (end - begin);
}
/**
***
**/
int
tr_ptrArrayLowerBound( const tr_ptrArray_t * t,
void * ptr,
int compare( const void *,const void * ),
int * exact_match )
{
int c = -1;
int len = t->n_items;
int first = 0;
while( len > 0 )
{
int half = len / 2;
int middle = first + half;
c = compare( t->items[middle], ptr );
if( c < 0 ) {
first = middle + 1;
len = len - half - 1;
} else if (!c ) {
if( exact_match )
*exact_match = 1;
return middle;
break;
} else {
len = half;
}
}
if( exact_match )
*exact_match = 0;
return first;
}
int
tr_ptrArrayInsertSorted( tr_ptrArray_t * t,
void * ptr,
int compare(const void*,const void*) )
{
const int pos = tr_ptrArrayLowerBound( t, ptr, compare, NULL );
return tr_ptrArrayInsert( t, ptr, pos );
}
void*
tr_ptrArrayFindSorted( tr_ptrArray_t * t,
void * ptr,
int compare(const void*,const void*) )
{
int match;
const int pos = tr_ptrArrayLowerBound( t, ptr, compare, &match );
return match ? t->items[pos] : NULL;
}
void*
tr_ptrArrayRemoveSorted( tr_ptrArray_t * t,
void * ptr,
int compare(const void*,const void*) )
{
void * ret = NULL;
int match;
const int pos = tr_ptrArrayLowerBound( t, ptr, compare, &match );
if( match ) {
ret = t->items[pos];
tr_ptrArrayErase( t, pos, pos+1 );
}
return ret;
}

View file

@ -0,0 +1,37 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#ifndef _TR_POINTERS_H_
#define _TR_POINTERS_H_
/**
* A simple pointer array that resizes itself dynamically.
*/
typedef struct tr_ptrArray_s tr_ptrArray_t;
tr_ptrArray_t * tr_ptrArrayNew ( void );
void tr_ptrArrayFree ( tr_ptrArray_t* );
void** tr_ptrArrayPeek ( tr_ptrArray_t*, int * size );
void** tr_ptrArrayBase ( tr_ptrArray_t* );
void tr_ptrArrayClear ( tr_ptrArray_t* );
int tr_ptrArrayInsert ( tr_ptrArray_t*, void*, int pos );
int tr_ptrArrayAppend ( tr_ptrArray_t*, void* );
void tr_ptrArrayErase ( tr_ptrArray_t*, int begin, int end );
int tr_ptrArraySize ( const tr_ptrArray_t* );
int tr_ptrArrayEmpty ( const tr_ptrArray_t* );
int tr_ptrArrayInsertSorted( tr_ptrArray_t*, void*,
int compare(const void*,const void*) );
void* tr_ptrArrayRemoveSorted( tr_ptrArray_t*, void*,
int compare(const void*,const void*) );
void* tr_ptrArrayFindSorted ( tr_ptrArray_t*, void*,
int compare(const void*,const void*) );
#endif

72
libtransmission/publish.c Normal file
View file

@ -0,0 +1,72 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#include "list.h"
#include "publish.h"
#include "utils.h"
struct tr_publisher_node
{
tr_delivery_func * func;
void * user_data;
};
struct tr_publisher_s
{
tr_list_t * list;
};
tr_publisher_t*
tr_publisherNew( void )
{
return tr_new0( tr_publisher_t, 1 );
}
void
tr_publisherFree( tr_publisher_t * p )
{
tr_list_free( &p->list );
tr_free( p );
}
tr_publisher_tag
tr_publisherSubscribe ( tr_publisher_t * p,
tr_delivery_func func,
void * user_data )
{
struct tr_publisher_node * node = tr_new( struct tr_publisher_node, 1 );
node->func = func;
node->user_data = user_data;
tr_list_append( &p->list, node );
return node;
}
void
tr_publisherUnsubscribe( tr_publisher_t * p,
tr_publisher_tag tag )
{
tr_list_remove_data( &p->list, tag );
tr_free( tag );
}
void
tr_publisherPublish( tr_publisher_t * p,
void * source,
void * event )
{
tr_list_t * walk;
for( walk=p->list; walk!=NULL; )
{
tr_list_t * next = walk->next;
struct tr_publisher_node * node = (struct tr_publisher_node*)walk->data;
(node->func)(source, event, node->user_data);
walk = next;
}
}

49
libtransmission/publish.h Normal file
View file

@ -0,0 +1,49 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#ifndef _TR_PUBLISHER_H_
#define _TR_PUBLISHER_H_
/**
*** A lightweight implementation of the 'Observable' design pattern.
**/
typedef struct tr_publisher_s tr_publisher_t;
typedef void * tr_publisher_tag;
typedef void tr_delivery_func( void * source,
void * event,
void * user_data );
/**
*** Observer API
**/
tr_publisher_tag tr_publisherSubscribe ( tr_publisher_t * publisher,
tr_delivery_func delivery_func,
void * user_data );
void tr_publisherUnsubscribe ( tr_publisher_t * publisher,
tr_publisher_tag tag );
/**
*** Observable API
**/
tr_publisher_t * tr_publisherNew ( void );
void tr_publisherFree ( tr_publisher_t * publisher );
void tr_publisherPublish ( tr_publisher_t * publisher,
void * source,
void * event );
#endif

104
libtransmission/timer.c Normal file
View file

@ -0,0 +1,104 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#include <assert.h>
#include <sys/types.h> /* u_char for event.h */
#include <event.h>
#include "transmission.h"
#include "timer.h"
#include "utils.h"
typedef int tr_timer_func ( void * user_data );
typedef void tr_data_free_func( void * user_data );
/***
****
***/
struct timer_node
{
struct event event;
tr_timer_func * func;
void * user_data;
tr_data_free_func * free_func;
struct timeval tv;
int refcount;
};
static void
unref( struct timer_node * node, int count )
{
assert( node != NULL );
assert( node->refcount > 0 );
node->refcount -= count;
if( node->refcount > 0 )
return;
if( node->free_func != NULL )
(node->free_func)( node->user_data );
event_del( &node->event );
tr_free( node );
}
void
tr_timerFree( struct timer_node ** node )
{
assert( node != NULL );
if( *node )
{
unref( *node, 1 );
*node = NULL;
}
}
static void
timerCB( int fd UNUSED, short event UNUSED, void * arg )
{
struct timer_node * node = (struct timer_node *) arg;
int val;
++node->refcount;
val = (node->func)(node->user_data);
if( !val )
unref( node, 2 );
else {
timeout_add( &node->event, &node->tv );
unref( node, 1 );
}
}
tr_timer_tag
tr_timerNew( tr_timer_func func,
void * user_data,
tr_data_free_func free_func,
int timeout_milliseconds )
{
struct timer_node * node;
const unsigned long microseconds = timeout_milliseconds * 1000;
assert( func != NULL );
assert( timeout_milliseconds >= 0 );
node = tr_new( struct timer_node, 1 );
node->func = func;
node->user_data = user_data;
node->free_func = free_func;
node->refcount = 1;
node->tv.tv_sec = microseconds / 1000000;
node->tv.tv_usec = microseconds % 1000000;
timeout_set( &node->event, timerCB, node );
timeout_add( &node->event, &node->tv );
return node;
}

37
libtransmission/timer.h Normal file
View file

@ -0,0 +1,37 @@
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*/
#ifndef _TR_TIMER_H_
#define _TR_TIMER_H_
typedef struct timer_node * tr_timer_tag;
/**
* Calls timer_func(user_data) after the specified interval.
* The timer is freed if timer_func returns zero.
* Otherwise, it's called again after the same interval.
*
* If free_func is non-NULL, free_func(user_data) is called
* by the timer when it's freed (either from timer_func returning
* zero or from a client call to tr_timerFree). This is useful
* if user_data has resources that need to be freed.
*/
tr_timer_tag tr_timerNew( int timer_func( void * user_data ),
void * user_data,
void free_func( void * user_data ),
int timeout_milliseconds );
/**
* Frees a timer and sets its tag to NULL.
*/
void tr_timerFree( tr_timer_tag * tag );
#endif

View file

@ -33,6 +33,8 @@
#include <unistd.h> /* stat */
#include <dirent.h> /* opendir */
#include <event.h>
#include "transmission.h"
#include "fdlimit.h"
#include "list.h"
@ -61,6 +63,19 @@ tr_peerIdNew ( char * buf, int buflen )
buf[TR_ID_LEN] = '\0';
}
static void
libeventThreadFunc( void * unused UNUSED )
{
tr_dbg( "libevent thread starting" );
event_init( );
for ( ;; )
{
event_dispatch( );
tr_wait( 50 ); /* 1/20th of a second */
}
tr_dbg( "libevent thread exiting" );
}
/***********************************************************************
* tr_init
@ -72,6 +87,8 @@ tr_handle_t * tr_init( const char * tag )
tr_handle_t * h;
int i;
tr_threadNew( libeventThreadFunc, NULL, "libeventThreadFunc" );
tr_msgInit();
tr_netInit();
tr_netResolveThreadInit();

View file

@ -27,6 +27,7 @@
#include <inttypes.h>
#include <stdarg.h>
#include <stddef.h> /* for size_t */
void tr_msgInit( void );