From 07b9da73fc471d94abf03422d5f0d8617bd7f7a1 Mon Sep 17 00:00:00 2001 From: Eric Petit Date: Thu, 12 Jan 2006 19:12:58 +0000 Subject: [PATCH] Update 2006-01-11 --- Jamrules | 2 +- libtransmission/internal.h | 12 +- libtransmission/net.c | 43 +++----- libtransmission/net.h | 2 +- libtransmission/peer.c | 191 ++++++++++++++++++-------------- libtransmission/peer.h | 8 +- libtransmission/peerparse.h | 59 +++++++--- libtransmission/peerutils.h | 34 ++++-- libtransmission/tracker.c | 14 ++- libtransmission/tracker.h | 1 + libtransmission/transmission.c | 195 ++++++++++++++++++++++++++++++--- 11 files changed, 402 insertions(+), 159 deletions(-) diff --git a/Jamrules b/Jamrules index e638aef91..9f5939a21 100644 --- a/Jamrules +++ b/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) diff --git a/libtransmission/internal.h b/libtransmission/internal.h index 1d372baaf..1ac0510ce 100644 --- a/libtransmission/internal.h +++ b/libtransmission/internal.h @@ -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 diff --git a/libtransmission/net.c b/libtransmission/net.c index 7d3e9634c..78637acfb 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -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; diff --git a/libtransmission/net.h b/libtransmission/net.h index 84548cafa..c0584eb71 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -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 ); diff --git a/libtransmission/peer.c b/libtransmission/peer.c index b4b479863..be1e3ba52 100644 --- a/libtransmission/peer.c +++ b/libtransmission/peer.c @@ -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 ) diff --git a/libtransmission/peer.h b/libtransmission/peer.h index bbbae6bd2..f9e111b54 100644 --- a/libtransmission/peer.h +++ b/libtransmission/peer.h @@ -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 * ); diff --git a/libtransmission/peerparse.h b/libtransmission/peerparse.h index 96170f7dc..c1a423d5a 100644 --- a/libtransmission/peerparse.h +++ b/libtransmission/peerparse.h @@ -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; } diff --git a/libtransmission/peerutils.h b/libtransmission/peerutils.h index 74f180582..6d699e587 100644 --- a/libtransmission/peerutils.h +++ b/libtransmission/peerutils.h @@ -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; } diff --git a/libtransmission/tracker.c b/libtransmission/tracker.c index 0c48b07bb..019d696d5 100644 --- a/libtransmission/tracker.c +++ b/libtransmission/tracker.c @@ -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 ) diff --git a/libtransmission/tracker.h b/libtransmission/tracker.h index 4e521157c..72ff03f2e 100644 --- a/libtransmission/tracker.h +++ b/libtransmission/tracker.h @@ -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 * ); diff --git a/libtransmission/transmission.c b/libtransmission/transmission.c index 60c9f5f98..063bd2af6 100644 --- a/libtransmission/transmission.c +++ b/libtransmission/transmission.c @@ -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 ); + } +}