clean up the shutdown code a little bit.

This commit is contained in:
Charles Kerr 2007-10-02 16:12:44 +00:00
parent c271cec6a3
commit cdabb1c0b1
3 changed files with 131 additions and 111 deletions

View File

@ -171,20 +171,26 @@ tr_peerIoNewOutgoing( struct tr_handle * handle,
tr_netOpenTCP( in_addr, port, 0 ) );
}
void
tr_peerIoFree( tr_peerIo * c )
static void
io_dtor( void * vio )
{
if( c != NULL )
tr_peerIo * io = vio;
bufferevent_free( io->bufev );
tr_netClose( io->socket );
tr_cryptoFree( io->crypto );
tr_free( io );
}
void
tr_peerIoFree( tr_peerIo * io )
{
if( io != NULL )
{
c->canRead = NULL;
c->didWrite = NULL;
c->gotError = NULL;
bufferevent_free( c->bufev );
tr_netClose( c->socket );
tr_cryptoFree( c->crypto );
tr_free( c );
io->canRead = NULL;
io->didWrite = NULL;
io->gotError = NULL;
tr_runInEventThread( io->handle, io_dtor, io );
}
}

View File

@ -96,6 +96,7 @@ struct peer_atom
typedef struct
{
uint8_t hash[SHA_DIGEST_LENGTH];
tr_ptrArray * outgoingHandshakes; /* tr_handshake */
tr_ptrArray * pool; /* struct peer_atom */
tr_ptrArray * peers; /* tr_peer */
tr_timer * reconnectTimer;
@ -112,10 +113,10 @@ Torrent;
struct tr_peerMgr
{
int connectionCount;
tr_handle * handle;
tr_ptrArray * torrents; /* Torrent */
int connectionCount;
tr_ptrArray * handshakes; /* in-process */
tr_ptrArray * incomingHandshakes; /* tr_handshake */
};
/**
@ -195,9 +196,9 @@ handshakeCompare( const void * a, const void * b )
}
static tr_handshake*
getExistingHandshake( tr_peerMgr * mgr, const struct in_addr * in_addr )
getExistingHandshake( tr_ptrArray * handshakes, const struct in_addr * in_addr )
{
return tr_ptrArrayFindSorted( mgr->handshakes,
return tr_ptrArrayFindSorted( handshakes,
in_addr,
handshakeCompareToAddr );
}
@ -284,12 +285,15 @@ peerIsKnown( const Torrent * t, const struct in_addr * addr )
}
static int
peerIsInUse( const Torrent * t, const struct in_addr * addr )
peerIsInUse( const Torrent * ct, const struct in_addr * addr )
{
Torrent * t = (Torrent*) ct;
assert( torrentIsLocked ( t ) );
return ( getExistingPeer( (Torrent*)t, addr ) != NULL )
|| ( getExistingHandshake( ((Torrent*)t)->manager, addr ) != NULL );
return ( getExistingPeer( t, addr ) != NULL )
|| ( getExistingHandshake( t->outgoingHandshakes, addr ) != NULL )
|| ( getExistingHandshake( t->manager->incomingHandshakes, addr ) != NULL );
}
static tr_peer*
@ -374,13 +378,16 @@ removeAllPeers( Torrent * t )
/* torrent must have already been removed from manager->torrents */
static void
freeTorrent( Torrent * t )
torrentDestructor( Torrent * t )
{
uint8_t hash[SHA_DIGEST_LENGTH];
assert( t != NULL );
assert( !t->isRunning );
assert( t->peers != NULL );
assert( torrentIsLocked( t ) );
assert( tr_ptrArrayEmpty( t->outgoingHandshakes ) );
assert( tr_ptrArrayEmpty( t->peers ) );
memcpy( hash, t->hash, SHA_DIGEST_LENGTH );
@ -390,10 +397,50 @@ freeTorrent( Torrent * t )
tr_bitfieldFree( t->requested );
tr_ptrArrayFree( t->pool, (PtrArrayForeachFunc)tr_free );
tr_ptrArrayFree( t->peers, (PtrArrayForeachFunc)freePeer );
tr_ptrArrayFree( t->outgoingHandshakes, NULL );
tr_free( t );
}
static int reconnectPulse( void * vtorrent );
static void
restartReconnectTimer( Torrent * t )
{
tr_timerFree( &t->reconnectTimer );
if( t->isRunning )
t->reconnectTimer = tr_timerNew( t->manager->handle, reconnectPulse, t, RECONNECT_PERIOD_MSEC );
}
static int rechokePulse( void * vtorrent );
static void
restartChokeTimer( Torrent * t )
{
tr_timerFree( &t->rechokeTimer );
if( t->isRunning )
t->rechokeTimer = tr_timerNew( t->manager->handle, rechokePulse, t, RECHOKE_PERIOD_MSEC );
}
static Torrent*
torrentConstructor( tr_peerMgr * manager, tr_torrent * tor )
{
Torrent * t;
t = tr_new0( Torrent, 1 );
t->manager = manager;
t->tor = tor;
t->pool = tr_ptrArrayNew( );
t->peers = tr_ptrArrayNew( );
t->outgoingHandshakes = tr_ptrArrayNew( );
t->requested = tr_bitfieldNew( tor->blockCount );
restartChokeTimer( t );
restartReconnectTimer( t );
memcpy( t->hash, tor->info.hash, SHA_DIGEST_LENGTH );
return t;
}
/**
***
**/
@ -464,7 +511,7 @@ tr_peerMgrNew( tr_handle * handle )
tr_peerMgr * m = tr_new0( tr_peerMgr, 1 );
m->handle = handle;
m->torrents = tr_ptrArrayNew( );
m->handshakes = tr_ptrArrayNew( );
m->incomingHandshakes = tr_ptrArrayNew( );
return m;
}
@ -474,13 +521,13 @@ tr_peerMgrFree( tr_peerMgr * manager )
managerLock( manager );
/* free the torrents. */
tr_ptrArrayFree( manager->torrents, (PtrArrayForeachFunc)freeTorrent );
tr_ptrArrayFree( manager->torrents, (PtrArrayForeachFunc)torrentDestructor );
/* free the handshakes. Abort invokes handshakeDoneCB(), which removes
* the item from manager->handshakes, so this is a little roundabout... */
while( !tr_ptrArrayEmpty( manager->handshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( manager->handshakes, 0 ) );
tr_ptrArrayFree( manager->handshakes, NULL );
while( !tr_ptrArrayEmpty( manager->incomingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( manager->incomingHandshakes, 0 ) );
tr_ptrArrayFree( manager->incomingHandshakes, NULL );
managerUnlock( manager );
tr_free( manager );
@ -761,34 +808,6 @@ broadcastGotBlock( Torrent * t, uint32_t index, uint32_t offset, uint32_t length
tr_free( peers );
}
/**
***
**/
static int reconnectPulse( void * vtorrent );
static void
restartReconnectTimer( Torrent * t )
{
tr_timerFree( &t->reconnectTimer );
if( t->isRunning )
t->reconnectTimer = tr_timerNew( t->manager->handle, reconnectPulse, t, RECONNECT_PERIOD_MSEC );
}
/**
***
**/
static int rechokePulse( void * vtorrent );
static void
restartChokeTimer( Torrent * t )
{
tr_timerFree( &t->rechokeTimer );
if( t->isRunning )
t->rechokeTimer = tr_timerNew( t->manager->handle, rechokePulse, t, RECHOKE_PERIOD_MSEC );
}
static void
msgsCallbackFunc( void * vpeer, void * vevent, void * vt )
{
@ -853,6 +872,7 @@ ensureAtomExists( Torrent * t, const struct in_addr * addr, uint16_t port, uint8
}
}
/* FIXME: this is kind of a mess. */
static void
myHandshakeDoneCB( tr_handshake * handshake,
tr_peerIo * io,
@ -864,34 +884,33 @@ myHandshakeDoneCB( tr_handshake * handshake,
uint16_t port;
const struct in_addr * in_addr;
tr_peerMgr * manager = (tr_peerMgr*) vmanager;
const uint8_t * hash = NULL;
Torrent * t;
tr_handshake * ours;
assert( io != NULL );
assert( isConnected==0 || isConnected==1 );
ours = tr_ptrArrayRemoveSorted( manager->handshakes,
handshake,
handshakeCompare );
t = tr_peerIoHasTorrentHash( io )
? getExistingTorrent( manager, tr_peerIoGetTorrentHash( io ) )
: NULL;
if( tr_peerIoIsIncoming ( io ) )
ours = tr_ptrArrayRemoveSorted( manager->incomingHandshakes,
handshake, handshakeCompare );
else if( t != NULL )
ours = tr_ptrArrayRemoveSorted( t->outgoingHandshakes,
handshake, handshakeCompare );
else
ours = handshake;
assert( ours != NULL );
assert( ours == handshake );
in_addr = tr_peerIoGetAddress( io, &port );
if( !tr_peerIoHasTorrentHash( io ) ) /* incoming connection gone wrong? */
{
tr_peerIoFree( io );
--manager->connectionCount;
return;
}
hash = tr_peerIoGetTorrentHash( io );
t = getExistingTorrent( manager, hash );
if( t != NULL )
torrentLock( t );
in_addr = tr_peerIoGetAddress( io, &port );
if( !t || !t->isRunning )
{
tr_peerIoFree( io );
@ -930,22 +949,6 @@ myHandshakeDoneCB( tr_handshake * handshake,
torrentUnlock( t );
}
static void
initiateHandshake( tr_peerMgr * manager, tr_peerIo * io )
{
tr_handshake * handshake;
assert( io != NULL );
handshake = tr_handshakeNew( io,
manager->handle->encryptionMode,
myHandshakeDoneCB,
manager );
++manager->connectionCount;
tr_ptrArrayInsertSorted( manager->handshakes, handshake, handshakeCompare );
}
void
tr_peerMgrAddIncoming( tr_peerMgr * manager,
struct in_addr * addr,
@ -954,10 +957,17 @@ tr_peerMgrAddIncoming( tr_peerMgr * manager,
{
managerLock( manager );
if( getExistingHandshake( manager, addr ) == NULL )
if( getExistingHandshake( manager->incomingHandshakes, addr ) == NULL )
{
tr_peerIo * io = tr_peerIoNewIncoming( manager->handle, addr, port, socket );
initiateHandshake( manager, io );
tr_handshake * handshake = tr_handshakeNew( io,
manager->handle->encryptionMode,
myHandshakeDoneCB,
manager );
++manager->connectionCount;
tr_ptrArrayInsertSorted( manager->incomingHandshakes, handshake, handshakeCompare );
}
managerUnlock( manager );
@ -1104,20 +1114,20 @@ tr_peerMgrStartTorrent( tr_peerMgr * manager,
static void
stopTorrent( Torrent * t )
{
int i, size;
tr_peer ** peers;
assert( torrentIsLocked( t ) );
t->isRunning = 0;
tr_timerFree( &t->rechokeTimer );
tr_timerFree( &t->reconnectTimer );
peers = getConnectedPeers( t, &size );
for( i=0; i<size; ++i )
disconnectPeer( peers[i] );
/* disconnect the peers. */
tr_ptrArrayForeach( t->peers, (PtrArrayForeachFunc)freePeer );
tr_ptrArrayClear( t->peers );
tr_free( peers );
/* disconnect the handshakes. handshakeAbort calls handshakeDoneCB(),
* which removes the handshake from t->outgoingHandshakes... */
while( !tr_ptrArrayEmpty( t->outgoingHandshakes ) )
tr_handshakeAbort( tr_ptrArrayNth( t->outgoingHandshakes, 0 ) );
}
void
tr_peerMgrStopTorrent( tr_peerMgr * manager,
@ -1141,16 +1151,7 @@ tr_peerMgrAddTorrent( tr_peerMgr * manager,
assert( tor != NULL );
assert( getExistingTorrent( manager, tor->info.hash ) == NULL );
t = tr_new0( Torrent, 1 );
t->manager = manager;
t->tor = tor;
t->pool = tr_ptrArrayNew( );
t->peers = tr_ptrArrayNew( );
t->requested = tr_bitfieldNew( tor->blockCount );
restartChokeTimer( t );
restartReconnectTimer( t );
memcpy( t->hash, tor->info.hash, SHA_DIGEST_LENGTH );
t = torrentConstructor( manager, tor );
tr_ptrArrayInsertSorted( manager->torrents, t, torrentCompare );
managerUnlock( manager );
@ -1168,7 +1169,7 @@ tr_peerMgrRemoveTorrent( tr_peerMgr * manager,
assert( t != NULL );
stopTorrent( t );
tr_ptrArrayRemoveSorted( manager->torrents, t, torrentCompare );
freeTorrent( t );
torrentDestructor( t );
managerUnlock( manager );
}
@ -1612,11 +1613,24 @@ reconnectPulse( void * vtorrent )
/* add some new ones */
nAdd = MAX_CONNECTED_PEERS_PER_TORRENT - peerCount;
for( i=0; i<nAdd && i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i ) {
for( i=0; i<nAdd && i<nCandidates && i<MAX_RECONNECTIONS_PER_PULSE; ++i )
{
tr_peerMgr * mgr = t->manager;
struct peer_atom * atom = candidates[i];
tr_peerIo * io = tr_peerIoNewOutgoing( t->manager->handle, &atom->addr, atom->port, t->hash );
tordbg( t, "RECONNECT adding an outgoing connection...\n" );
initiateHandshake( t->manager, io );
tr_peerIo * io = tr_peerIoNewOutgoing( mgr->handle, &atom->addr, atom->port, t->hash );
tr_handshake * handshake = tr_handshakeNew( io,
mgr->handle->encryptionMode,
myHandshakeDoneCB,
mgr );
++mgr->connectionCount;
assert( tr_peerIoGetTorrentHash( io ) != NULL );
tr_ptrArrayInsertSorted( t->outgoingHandshakes, handshake, handshakeCompare );
atom->time = time( NULL );
}

View File

@ -312,7 +312,7 @@ tr_closeImpl( void * vh )
void
tr_close( tr_handle * h )
{
assert( tr_torrentCount( h ) == 0 );
//assert( tr_torrentCount( h ) == 0 );
tr_runInEventThread( h, tr_closeImpl, h );
while( !h->isClosed )