mirror of
https://github.com/transmission/transmission
synced 2025-01-30 19:03:04 +00:00
Update 2006-01-11
This commit is contained in:
parent
a1de0a4fa0
commit
07b9da73fc
11 changed files with 402 additions and 159 deletions
2
Jamrules
2
Jamrules
|
@ -8,7 +8,7 @@ if ! $(DEFINES)
|
|||
VERSION_MAJOR = 0 ;
|
||||
VERSION_MINOR = 4 ;
|
||||
# VERSION_STRING = $(VERSION_MAJOR).$(VERSION_MINOR) ;
|
||||
VERSION_STRING = CVS-20051221 ;
|
||||
VERSION_STRING = 0.5-cvs ;
|
||||
|
||||
DEFINES += VERSION_MAJOR=$(VERSION_MAJOR)
|
||||
VERSION_MINOR=$(VERSION_MINOR)
|
||||
|
|
|
@ -89,11 +89,11 @@ typedef struct tr_completion_s tr_completion_t;
|
|||
#include "bencode.h"
|
||||
#include "metainfo.h"
|
||||
#include "tracker.h"
|
||||
#include "fdlimit.h"
|
||||
#include "peer.h"
|
||||
#include "net.h"
|
||||
#include "inout.h"
|
||||
#include "upload.h"
|
||||
#include "fdlimit.h"
|
||||
#include "clients.h"
|
||||
|
||||
struct tr_torrent_s
|
||||
|
@ -140,8 +140,6 @@ struct tr_torrent_s
|
|||
tr_io_t * io;
|
||||
uint64_t stopDate;
|
||||
|
||||
int bindSocket;
|
||||
int bindPort;
|
||||
int peerCount;
|
||||
tr_peer_t * peers[TR_MAX_PEER_COUNT];
|
||||
|
||||
|
@ -162,9 +160,17 @@ struct tr_handle_s
|
|||
tr_fd_t * fdlimit;
|
||||
|
||||
int bindPort;
|
||||
int bindSocket;
|
||||
|
||||
int acceptPeerCount;
|
||||
tr_peer_t * acceptPeers[TR_MAX_PEER_COUNT];
|
||||
|
||||
char id[21];
|
||||
char key[21];
|
||||
|
||||
volatile char acceptDie;
|
||||
tr_thread_t acceptThread;
|
||||
tr_lock_t acceptLock;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -106,11 +106,13 @@ int tr_netOpen( struct in_addr addr, in_port_t port )
|
|||
return s;
|
||||
}
|
||||
|
||||
int tr_netBind( int * port )
|
||||
int tr_netBind( int port )
|
||||
{
|
||||
int s, i;
|
||||
int s;
|
||||
struct sockaddr_in sock;
|
||||
int minPort, maxPort;
|
||||
#ifdef SO_REUSEADDR
|
||||
int optval;
|
||||
#endif
|
||||
|
||||
s = createSocket();
|
||||
if( s < 0 )
|
||||
|
@ -118,34 +120,25 @@ int tr_netBind( int * port )
|
|||
return -1;
|
||||
}
|
||||
|
||||
minPort = *port;
|
||||
maxPort = minPort + 1000;
|
||||
maxPort = MIN( maxPort, 65535 );
|
||||
#ifdef SO_REUSEADDR
|
||||
optval = 1;
|
||||
setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof( optval ) );
|
||||
#endif
|
||||
|
||||
for( i = minPort; i <= maxPort; i++ )
|
||||
{
|
||||
memset( &sock, 0, sizeof( sock ) );
|
||||
sock.sin_family = AF_INET;
|
||||
sock.sin_addr.s_addr = INADDR_ANY;
|
||||
sock.sin_port = htons( i );
|
||||
|
||||
if( !bind( s, (struct sockaddr *) &sock,
|
||||
sizeof( struct sockaddr_in ) ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i > maxPort )
|
||||
memset( &sock, 0, sizeof( sock ) );
|
||||
sock.sin_family = AF_INET;
|
||||
sock.sin_addr.s_addr = INADDR_ANY;
|
||||
sock.sin_port = htons( port );
|
||||
|
||||
if( bind( s, (struct sockaddr *) &sock,
|
||||
sizeof( struct sockaddr_in ) ) )
|
||||
{
|
||||
tr_err( "Could not bind port %d", port );
|
||||
tr_netClose( s );
|
||||
tr_err( "Could not bind any port from %d to %d",
|
||||
minPort, maxPort );
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_inf( "Binded port %d", i );
|
||||
*port = i;
|
||||
tr_inf( "Binded port %d", port );
|
||||
listen( s, 5 );
|
||||
|
||||
return s;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
int tr_netResolve ( char *, struct in_addr * );
|
||||
int tr_netOpen ( struct in_addr addr, in_port_t port );
|
||||
int tr_netBind ( int * );
|
||||
int tr_netBind ( int );
|
||||
int tr_netAccept ( int s, struct in_addr *, in_port_t * );
|
||||
void tr_netClose ( int s );
|
||||
|
||||
|
|
|
@ -123,32 +123,56 @@ void tr_peerAddOld( tr_torrent_t * tor, char * ip, int port )
|
|||
/***********************************************************************
|
||||
* tr_peerAddCompact
|
||||
***********************************************************************
|
||||
* Tries to add a peer. If 's' is a negative value, will use 'addr' and
|
||||
* 'port' to connect to the peer. Otherwise, use the already connected
|
||||
* socket 's'.
|
||||
* Tries to add a peer, using 'addr' and 'port' to connect to the peer.
|
||||
**********************************************************************/
|
||||
void tr_peerAddCompact( tr_torrent_t * tor, struct in_addr addr,
|
||||
in_port_t port, int s )
|
||||
in_port_t port )
|
||||
{
|
||||
tr_peer_t * peer;
|
||||
addWithAddr( tor, addr, port );
|
||||
}
|
||||
|
||||
if( s < 0 )
|
||||
{
|
||||
addWithAddr( tor, addr, port );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !( peer = peerInit( tor ) ) )
|
||||
{
|
||||
tr_netClose( s );
|
||||
tr_fdSocketClosed( tor->fdlimit, 0 );
|
||||
return;
|
||||
}
|
||||
/***********************************************************************
|
||||
* tr_peerInit
|
||||
***********************************************************************
|
||||
* Initializes a new peer.
|
||||
**********************************************************************/
|
||||
tr_peer_t * tr_peerInit( struct in_addr addr, in_port_t port, int s )
|
||||
{
|
||||
tr_peer_t * peer = peerInit();
|
||||
|
||||
peer->socket = s;
|
||||
peer->addr = addr;
|
||||
peer->port = port;
|
||||
peer->status = PEER_STATUS_CONNECTING;
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
void tr_peerAttach( tr_torrent_t * tor, tr_peer_t * peer )
|
||||
{
|
||||
peerAttach( tor, peer );
|
||||
}
|
||||
|
||||
void tr_peerDestroy( tr_fd_t * fdlimit, tr_peer_t * peer )
|
||||
{
|
||||
if( peer->bitfield )
|
||||
{
|
||||
free( peer->bitfield );
|
||||
}
|
||||
if( peer->buf )
|
||||
{
|
||||
free( peer->buf );
|
||||
}
|
||||
if( peer->outMessages )
|
||||
{
|
||||
free( peer->outMessages );
|
||||
}
|
||||
if( peer->status > PEER_STATUS_IDLE )
|
||||
{
|
||||
tr_netClose( peer->socket );
|
||||
tr_fdSocketClosed( fdlimit, 0 );
|
||||
}
|
||||
free( peer );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -175,29 +199,76 @@ void tr_peerRem( tr_torrent_t * tor, int i )
|
|||
{
|
||||
tr_uploadChoked( tor->upload );
|
||||
}
|
||||
if( peer->bitfield )
|
||||
{
|
||||
free( peer->bitfield );
|
||||
}
|
||||
if( peer->buf )
|
||||
{
|
||||
free( peer->buf );
|
||||
}
|
||||
if( peer->outMessages )
|
||||
{
|
||||
free( peer->outMessages );
|
||||
}
|
||||
if( peer->status > PEER_STATUS_IDLE )
|
||||
{
|
||||
tr_netClose( peer->socket );
|
||||
tr_fdSocketClosed( tor->fdlimit, 0 );
|
||||
}
|
||||
free( peer );
|
||||
tr_peerDestroy( tor->fdlimit, peer );
|
||||
tor->peerCount--;
|
||||
memmove( &tor->peers[i], &tor->peers[i+1],
|
||||
( tor->peerCount - i ) * sizeof( tr_peer_t * ) );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* tr_peerRead
|
||||
***********************************************************************
|
||||
*
|
||||
**********************************************************************/
|
||||
int tr_peerRead( tr_torrent_t * tor, tr_peer_t * peer )
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Try to read */
|
||||
for( ;; )
|
||||
{
|
||||
if( peer->size < 1 )
|
||||
{
|
||||
peer->size = 1024;
|
||||
peer->buf = malloc( peer->size );
|
||||
}
|
||||
else if( peer->pos >= peer->size )
|
||||
{
|
||||
peer->size *= 2;
|
||||
peer->buf = realloc( peer->buf, peer->size );
|
||||
}
|
||||
ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
|
||||
peer->size - peer->pos );
|
||||
if( ret & TR_NET_CLOSE )
|
||||
{
|
||||
peer_dbg( "connection closed" );
|
||||
return 1;
|
||||
}
|
||||
else if( ret & TR_NET_BLOCK )
|
||||
{
|
||||
break;
|
||||
}
|
||||
peer->date = tr_date();
|
||||
peer->pos += ret;
|
||||
if( NULL != tor )
|
||||
{
|
||||
if( parseBuf( tor, peer, ret ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( parseBufHeader( peer ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* tr_peerHash
|
||||
***********************************************************************
|
||||
*
|
||||
**********************************************************************/
|
||||
uint8_t * tr_peerHash( tr_peer_t * peer )
|
||||
{
|
||||
return parseBufHash( peer );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* tr_peerPulse
|
||||
***********************************************************************
|
||||
|
@ -234,25 +305,6 @@ void tr_peerPulse( tr_torrent_t * tor )
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for incoming connections */
|
||||
if( tor->bindSocket > -1 &&
|
||||
tor->peerCount < TR_MAX_PEER_COUNT &&
|
||||
!tr_fdSocketWillCreate( tor->fdlimit, 0 ) )
|
||||
{
|
||||
int s;
|
||||
struct in_addr addr;
|
||||
in_port_t port;
|
||||
s = tr_netAccept( tor->bindSocket, &addr, &port );
|
||||
if( s > -1 )
|
||||
{
|
||||
tr_peerAddCompact( tor, addr, port, s );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_fdSocketClosed( tor->fdlimit, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Shuffle peers */
|
||||
if( tor->peerCount > 1 )
|
||||
|
@ -274,36 +326,9 @@ void tr_peerPulse( tr_torrent_t * tor )
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Try to read */
|
||||
for( ;; )
|
||||
if( tr_peerRead( tor, tor->peers[i] ) )
|
||||
{
|
||||
if( peer->size < 1 )
|
||||
{
|
||||
peer->size = 1024;
|
||||
peer->buf = malloc( peer->size );
|
||||
}
|
||||
else if( peer->pos >= peer->size )
|
||||
{
|
||||
peer->size *= 2;
|
||||
peer->buf = realloc( peer->buf, peer->size );
|
||||
}
|
||||
ret = tr_netRecv( peer->socket, &peer->buf[peer->pos],
|
||||
peer->size - peer->pos );
|
||||
if( ret & TR_NET_CLOSE )
|
||||
{
|
||||
peer_dbg( "connection closed" );
|
||||
goto dropPeer;
|
||||
}
|
||||
else if( ret & TR_NET_BLOCK )
|
||||
{
|
||||
break;
|
||||
}
|
||||
peer->date = tr_date();
|
||||
peer->pos += ret;
|
||||
if( parseBuf( tor, peer, ret ) )
|
||||
{
|
||||
goto dropPeer;
|
||||
}
|
||||
goto dropPeer;
|
||||
}
|
||||
|
||||
if( peer->status < PEER_STATUS_CONNECTED )
|
||||
|
|
|
@ -26,9 +26,13 @@
|
|||
typedef struct tr_peer_s tr_peer_t;
|
||||
|
||||
void tr_peerAddOld ( tr_torrent_t *, char *, int );
|
||||
void tr_peerAddCompact ( tr_torrent_t *, struct in_addr,
|
||||
in_port_t, int );
|
||||
void tr_peerAddCompact ( tr_torrent_t *, struct in_addr, in_port_t );
|
||||
tr_peer_t * tr_peerInit ( struct in_addr, in_port_t, int );
|
||||
void tr_peerAttach ( tr_torrent_t *, tr_peer_t * );
|
||||
void tr_peerDestroy ( tr_fd_t *, tr_peer_t * );
|
||||
void tr_peerRem ( tr_torrent_t *, int );
|
||||
int tr_peerRead ( tr_torrent_t *, tr_peer_t * );
|
||||
uint8_t * tr_peerHash ( tr_peer_t * );
|
||||
void tr_peerPulse ( tr_torrent_t * );
|
||||
int tr_peerIsConnected ( tr_peer_t * );
|
||||
int tr_peerIsUploading ( tr_peer_t * );
|
||||
|
|
|
@ -396,6 +396,48 @@ static inline int parseMessage( tr_torrent_t * tor, tr_peer_t * peer,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline int parseBufHeader( tr_peer_t * peer )
|
||||
{
|
||||
uint8_t * p = peer->buf;
|
||||
|
||||
if( 4 > peer->pos )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( p[0] != 19 || memcmp( &p[1], "Bit", 3 ) )
|
||||
{
|
||||
/* Don't wait until we get 68 bytes, this is wrong
|
||||
already */
|
||||
peer_dbg( "GET handshake, invalid" );
|
||||
tr_netSend( peer->socket, (uint8_t *) "Nice try...\r\n", 13 );
|
||||
return 1;
|
||||
}
|
||||
if( peer->pos < 68 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( memcmp( &p[4], "Torrent protocol", 16 ) )
|
||||
{
|
||||
peer_dbg( "GET handshake, invalid" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t * parseBufHash( tr_peer_t * peer )
|
||||
{
|
||||
if( 48 > peer->pos )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return peer->buf + 28;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int parseBuf( tr_torrent_t * tor, tr_peer_t * peer,
|
||||
int newBytes )
|
||||
{
|
||||
|
@ -412,23 +454,8 @@ static inline int parseBuf( tr_torrent_t * tor, tr_peer_t * peer,
|
|||
{
|
||||
char * client;
|
||||
|
||||
if( p[0] != 19 || memcmp( &p[1], "Bit", 3 ) )
|
||||
if( parseBufHeader( peer ) )
|
||||
{
|
||||
/* Don't wait until we get 68 bytes, this is wrong
|
||||
already */
|
||||
peer_dbg( "GET handshake, invalid" );
|
||||
tr_netSend( peer->socket, (uint8_t *) "Nice try...\r\n", 13 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( peer->pos < 68 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( memcmp( &p[4], "Torrent protocol", 16 ) )
|
||||
{
|
||||
peer_dbg( "GET handshake, invalid" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,29 +25,40 @@ static void updateInterest( tr_torrent_t * tor, tr_peer_t * peer );
|
|||
/***********************************************************************
|
||||
* peerInit
|
||||
***********************************************************************
|
||||
* Returns NULL if we reached the maximum authorized number of peers.
|
||||
* Otherwise, allocates a new tr_peer_t, add it to the peers list and
|
||||
* returns a pointer to it.
|
||||
* Allocates a new tr_peer_t and returns a pointer to it.
|
||||
**********************************************************************/
|
||||
static tr_peer_t * peerInit( tr_torrent_t * tor )
|
||||
static tr_peer_t * peerInit()
|
||||
{
|
||||
tr_peer_t * peer;
|
||||
|
||||
if( tor->peerCount >= TR_MAX_PEER_COUNT )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
peer = calloc( sizeof( tr_peer_t ), 1 );
|
||||
peer->amChoking = 1;
|
||||
peer->peerChoking = 1;
|
||||
peer->date = tr_date();
|
||||
peer->keepAlive = peer->date;
|
||||
|
||||
tor->peers[tor->peerCount++] = peer;
|
||||
return peer;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* peerAttach
|
||||
***********************************************************************
|
||||
* Deallocates the tr_peer_t and returns 0 if we reached the maximum
|
||||
* authorized number of peers. Otherwise, adds the tr_peer_t to the
|
||||
* peers list.
|
||||
**********************************************************************/
|
||||
static int peerAttach( tr_torrent_t * tor, tr_peer_t * peer )
|
||||
{
|
||||
if( tor->peerCount >= TR_MAX_PEER_COUNT )
|
||||
{
|
||||
tr_peerDestroy( tor->fdlimit, peer );
|
||||
return 0;
|
||||
}
|
||||
|
||||
tor->peers[tor->peerCount++] = peer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int peerCmp( tr_peer_t * peer1, tr_peer_t * peer2 )
|
||||
{
|
||||
/* Wait until we got the peers' ids */
|
||||
|
@ -83,7 +94,8 @@ static void addWithAddr( tr_torrent_t * tor, struct in_addr addr,
|
|||
}
|
||||
}
|
||||
|
||||
if( !( peer = peerInit( tor ) ) )
|
||||
peer = peerInit();
|
||||
if( !peerAttach( tor, peer ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ struct tr_tracker_s
|
|||
uint8_t * buf;
|
||||
int size;
|
||||
int pos;
|
||||
|
||||
int bindPort;
|
||||
};
|
||||
|
||||
static void sendQuery ( tr_tracker_t * tc );
|
||||
|
@ -71,6 +73,8 @@ tr_tracker_t * tr_trackerInit( tr_handle_t * h, tr_torrent_t * tor )
|
|||
tc->size = 1024;
|
||||
tc->buf = malloc( tc->size );
|
||||
|
||||
tc->bindPort = h->bindPort;
|
||||
|
||||
return tc;
|
||||
}
|
||||
|
||||
|
@ -117,6 +121,12 @@ static int shouldConnect( tr_tracker_t * tc )
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tr_trackerChangePort( tr_tracker_t * tc, int port )
|
||||
{
|
||||
/* XXX this doesn't always work, should send stopped then started events */
|
||||
tc->bindPort = port;
|
||||
}
|
||||
|
||||
int tr_trackerPulse( tr_tracker_t * tc )
|
||||
{
|
||||
tr_torrent_t * tor = tc->tor;
|
||||
|
@ -264,7 +274,7 @@ static void sendQuery( tr_tracker_t * tc )
|
|||
"User-Agent: Transmission/%d.%d\r\n"
|
||||
"Connection: close\r\n\r\n",
|
||||
inf->trackerAnnounce, tor->hashString, tc->id,
|
||||
tor->bindPort, tor->uploaded[9], tor->downloaded[9],
|
||||
tc->bindPort, tor->uploaded[9], tor->downloaded[9],
|
||||
left, tor->key, event, inf->trackerAddress,
|
||||
VERSION_MAJOR, VERSION_MINOR );
|
||||
|
||||
|
@ -450,7 +460,7 @@ static void recvAnswer( tr_tracker_t * tc )
|
|||
memcpy( &addr, &bePeers->val.s.s[6*i], 4 );
|
||||
memcpy( &port, &bePeers->val.s.s[6*i+4], 2 );
|
||||
|
||||
tr_peerAddCompact( tor, addr, port, -1 );
|
||||
tr_peerAddCompact( tor, addr, port );
|
||||
}
|
||||
|
||||
if( bePeers->val.s.i / 6 >= 50 )
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
typedef struct tr_tracker_s tr_tracker_t;
|
||||
|
||||
tr_tracker_t * tr_trackerInit ( tr_handle_t *, tr_torrent_t * );
|
||||
void tr_trackerChangePort( tr_tracker_t *, int );
|
||||
int tr_trackerPulse ( tr_tracker_t * );
|
||||
void tr_trackerCompleted ( tr_tracker_t * );
|
||||
void tr_trackerStopped ( tr_tracker_t * );
|
||||
|
|
|
@ -29,6 +29,8 @@ static void torrentReallyStop( tr_handle_t * h, int t );
|
|||
static void downloadLoop( void * );
|
||||
static float rateDownload( tr_torrent_t * );
|
||||
static float rateUpload( tr_torrent_t * );
|
||||
static void acceptLoop( void * );
|
||||
static void acceptStop( tr_handle_t * h );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_init
|
||||
|
@ -67,6 +69,22 @@ tr_handle_t * tr_init()
|
|||
h->fdlimit = tr_fdInit();
|
||||
|
||||
h->bindPort = TR_DEFAULT_PORT;
|
||||
h->bindSocket = -1;
|
||||
|
||||
#ifndef BEOS_NETSERVER
|
||||
/* BeOS net_server seems to be unable to set incoming connections to
|
||||
non-blocking. Too bad. */
|
||||
if( !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
|
||||
{
|
||||
/* XXX should handle failure here in a better way */
|
||||
h->bindSocket = tr_netBind( h->bindPort );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
h->acceptDie = 0;
|
||||
tr_lockInit( &h->acceptLock );
|
||||
tr_threadCreate( &h->acceptThread, acceptLoop, h );
|
||||
|
||||
return h;
|
||||
}
|
||||
|
@ -78,8 +96,46 @@ tr_handle_t * tr_init()
|
|||
**********************************************************************/
|
||||
void tr_setBindPort( tr_handle_t * h, int port )
|
||||
{
|
||||
/* FIXME multithread safety */
|
||||
int ii, sock;
|
||||
|
||||
if( h->bindPort == port )
|
||||
return;
|
||||
|
||||
#ifndef BEOS_NETSERVER
|
||||
/* BeOS net_server seems to be unable to set incoming connections to
|
||||
non-blocking. Too bad. */
|
||||
if( !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
|
||||
{
|
||||
/* XXX should handle failure here in a better way */
|
||||
sock = tr_netBind( port );
|
||||
}
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
tr_lockLock( &h->acceptLock );
|
||||
|
||||
h->bindPort = port;
|
||||
|
||||
for( ii = 0; ii < h->torrentCount; ii++ )
|
||||
{
|
||||
tr_lockLock( &h->torrents[ii]->lock );
|
||||
if( NULL != h->torrents[ii]->tracker )
|
||||
{
|
||||
tr_trackerChangePort( h->torrents[ii]->tracker, port );
|
||||
}
|
||||
tr_lockUnlock( &h->torrents[ii]->lock );
|
||||
}
|
||||
|
||||
if( h->bindSocket > -1 )
|
||||
{
|
||||
tr_netClose( h->bindSocket );
|
||||
tr_fdSocketClosed( h->fdlimit, 0 );
|
||||
}
|
||||
|
||||
h->bindSocket = sock;
|
||||
|
||||
tr_lockUnlock( &h->acceptLock );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -196,8 +252,10 @@ int tr_torrentInit( tr_handle_t * h, const char * path )
|
|||
tor->fdlimit = h->fdlimit;
|
||||
|
||||
/* We have a new torrent */
|
||||
tr_lockLock( &h->acceptLock );
|
||||
h->torrents[h->torrentCount] = tor;
|
||||
(h->torrentCount)++;
|
||||
tr_lockUnlock( &h->acceptLock );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -241,15 +299,6 @@ void tr_torrentStart( tr_handle_t * h, int t )
|
|||
|
||||
tor->status = TR_STATUS_CHECK;
|
||||
tor->tracker = tr_trackerInit( h, tor );
|
||||
tor->bindPort = h->bindPort;
|
||||
#ifndef BEOS_NETSERVER
|
||||
/* BeOS net_server seems to be unable to set incoming connections to
|
||||
non-blocking. Too bad. */
|
||||
if( !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
|
||||
{
|
||||
tor->bindSocket = tr_netBind( &tor->bindPort );
|
||||
}
|
||||
#endif
|
||||
|
||||
now = tr_date();
|
||||
for( i = 0; i < 10; i++ )
|
||||
|
@ -291,11 +340,6 @@ static void torrentReallyStop( tr_handle_t * h, int t )
|
|||
{
|
||||
tr_peerRem( tor, 0 );
|
||||
}
|
||||
if( tor->bindSocket > -1 )
|
||||
{
|
||||
tr_netClose( tor->bindSocket );
|
||||
tr_fdSocketClosed( h->fdlimit, 0 );
|
||||
}
|
||||
|
||||
memset( tor->downloaded, 0, sizeof( tor->downloaded ) );
|
||||
memset( tor->uploaded, 0, sizeof( tor->uploaded ) );
|
||||
|
@ -445,6 +489,8 @@ void tr_torrentClose( tr_handle_t * h, int t )
|
|||
torrentReallyStop( h, t );
|
||||
}
|
||||
|
||||
tr_lockLock( &h->acceptLock );
|
||||
|
||||
h->torrentCount--;
|
||||
|
||||
tr_lockClose( &tor->lock );
|
||||
|
@ -460,10 +506,13 @@ void tr_torrentClose( tr_handle_t * h, int t )
|
|||
|
||||
memmove( &h->torrents[t], &h->torrents[t+1],
|
||||
( h->torrentCount - t ) * sizeof( void * ) );
|
||||
|
||||
tr_lockUnlock( &h->acceptLock );
|
||||
}
|
||||
|
||||
void tr_close( tr_handle_t * h )
|
||||
{
|
||||
acceptStop( h );
|
||||
tr_fdClose( h->fdlimit );
|
||||
tr_uploadClose( h->upload );
|
||||
free( h );
|
||||
|
@ -567,3 +616,119 @@ static float rateUpload( tr_torrent_t * tor )
|
|||
{
|
||||
return rateGeneric( tor->dates, tor->uploaded );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acceptLoop
|
||||
**********************************************************************/
|
||||
static void acceptLoop( void * _h )
|
||||
{
|
||||
tr_handle_t * h = _h;
|
||||
uint64_t date1, date2;
|
||||
int ii, jj;
|
||||
uint8_t * hash;
|
||||
|
||||
tr_dbg( "Accept thread started" );
|
||||
|
||||
#ifdef SYS_BEOS
|
||||
/* This is required because on BeOS, SIGINT is sent to each thread,
|
||||
which kills them not nicely */
|
||||
signal( SIGINT, SIG_IGN );
|
||||
#endif
|
||||
|
||||
tr_lockLock( &h->acceptLock );
|
||||
|
||||
while( !h->acceptDie )
|
||||
{
|
||||
date1 = tr_date();
|
||||
|
||||
/* Check for incoming connections */
|
||||
if( h->bindSocket > -1 &&
|
||||
h->acceptPeerCount < TR_MAX_PEER_COUNT &&
|
||||
!tr_fdSocketWillCreate( h->fdlimit, 0 ) )
|
||||
{
|
||||
int s;
|
||||
struct in_addr addr;
|
||||
in_port_t port;
|
||||
s = tr_netAccept( h->bindSocket, &addr, &port );
|
||||
if( s > -1 )
|
||||
{
|
||||
h->acceptPeers[h->acceptPeerCount++] = tr_peerInit( addr, port, s );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_fdSocketClosed( h->fdlimit, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
for( ii = 0; ii < h->acceptPeerCount; )
|
||||
{
|
||||
if( tr_peerRead( NULL, h->acceptPeers[ii] ) )
|
||||
{
|
||||
tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
|
||||
goto removePeer;
|
||||
}
|
||||
if( NULL != ( hash = tr_peerHash( h->acceptPeers[ii] ) ) )
|
||||
{
|
||||
for( jj = 0; jj < h->torrentCount; jj++ )
|
||||
{
|
||||
tr_lockLock( &h->torrents[jj]->lock );
|
||||
if( 0 == memcmp( h->torrents[jj]->info.hash, hash,
|
||||
SHA_DIGEST_LENGTH ) )
|
||||
{
|
||||
tr_peerAttach( h->torrents[jj], h->acceptPeers[ii] );
|
||||
tr_lockUnlock( &h->torrents[jj]->lock );
|
||||
goto removePeer;
|
||||
}
|
||||
tr_lockUnlock( &h->torrents[jj]->lock );
|
||||
}
|
||||
tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
|
||||
goto removePeer;
|
||||
}
|
||||
ii++;
|
||||
continue;
|
||||
removePeer:
|
||||
h->acceptPeerCount--;
|
||||
memmove( &h->acceptPeers[ii], &h->acceptPeers[ii+1],
|
||||
( h->acceptPeerCount - ii ) * sizeof( tr_peer_t * ) );
|
||||
}
|
||||
|
||||
/* Wait up to 20 ms */
|
||||
date2 = tr_date();
|
||||
if( date2 < date1 + 20 )
|
||||
{
|
||||
tr_lockUnlock( &h->acceptLock );
|
||||
tr_wait( date1 + 20 - date2 );
|
||||
tr_lockLock( &h->acceptLock );
|
||||
}
|
||||
}
|
||||
|
||||
tr_lockUnlock( &h->acceptLock );
|
||||
|
||||
tr_dbg( "Accept thread exited" );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acceptStop
|
||||
***********************************************************************
|
||||
* Joins the accept thread and frees/closes everything related to it.
|
||||
**********************************************************************/
|
||||
static void acceptStop( tr_handle_t * h )
|
||||
{
|
||||
int ii;
|
||||
|
||||
h->acceptDie = 1;
|
||||
tr_threadJoin( &h->acceptThread );
|
||||
tr_lockClose( &h->acceptLock );
|
||||
tr_dbg( "Accept thread joined" );
|
||||
|
||||
for( ii = 0; ii < h->acceptPeerCount; ii++ )
|
||||
{
|
||||
tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
|
||||
}
|
||||
|
||||
if( h->bindSocket > -1 )
|
||||
{
|
||||
tr_netClose( h->bindSocket );
|
||||
tr_fdSocketClosed( h->fdlimit, 0 );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue