source: branches/oneport/libtransmission/transmission.c @ 42

Last change on this file since 42 was 42, checked in by joshe, 16 years ago

Whoops, use the empty stop response workaround when changing ports too.
Turn off the port debug code.

File size: 23.0 KB
Line 
1/******************************************************************************
2 * Copyright (c) 2005 Eric Petit
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *****************************************************************************/
22
23#include "transmission.h"
24
25/***********************************************************************
26 * Local prototypes
27 **********************************************************************/
28static void torrentReallyStop( tr_handle_t * h, int t );
29static void  downloadLoop( void * );
30static float rateDownload( tr_torrent_t * );
31static float rateUpload( tr_torrent_t * );
32static void  acceptLoop( void * );
33static void acceptStop( tr_handle_t * h );
34
35/***********************************************************************
36 * tr_init
37 ***********************************************************************
38 * Allocates a tr_handle_t structure and initializes a few things
39 **********************************************************************/
40tr_handle_t * tr_init()
41{
42    tr_handle_t * h;
43    int           i, r;
44
45    h = calloc( sizeof( tr_handle_t ), 1 );
46
47    /* Generate a peer id : "-TRxxyy-" + 12 random alphanumeric
48       characters, where xx is the major version number and yy the
49       minor version number (Azureus-style) */
50    sprintf( h->id, "-TR%02d%02d-", VERSION_MAJOR, VERSION_MINOR );
51    for( i = 8; i < 20; i++ )
52    {
53        r        = tr_rand( 36 );
54        h->id[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
55    }
56
57    /* Random key */
58    for( i = 0; i < 20; i++ )
59    {
60        r         = tr_rand( 36 );
61        h->key[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
62    }
63
64    /* Don't exit when writing on a broken socket */
65    signal( SIGPIPE, SIG_IGN );
66
67    /* Initialize rate and file descripts controls */
68    h->upload  = tr_uploadInit();
69    h->fdlimit = tr_fdInit();
70
71    h->bindPort = TR_DEFAULT_PORT;
72    h->bindSocket = -1;
73
74#ifndef BEOS_NETSERVER
75    /* BeOS net_server seems to be unable to set incoming connections to
76       non-blocking. Too bad. */
77    if( !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
78    {
79        /* XXX should handle failure here in a better way */
80        h->bindSocket = tr_netBind( h->bindPort );
81    }
82#endif
83
84
85    h->acceptDie = 0;
86    tr_lockInit( &h->acceptLock );
87    tr_threadCreate( &h->acceptThread, acceptLoop, h );
88
89    return h;
90}
91
92/***********************************************************************
93 * tr_setBindPort
94 ***********************************************************************
95 *
96 **********************************************************************/
97void tr_setBindPort( tr_handle_t * h, int port )
98{
99    int ii, sock;
100
101    printf("changing port from %i to %i\n", h->bindPort, port);
102
103    if( h->bindPort == port )
104      return;
105
106#ifndef BEOS_NETSERVER
107    /* BeOS net_server seems to be unable to set incoming connections to
108       non-blocking. Too bad. */
109    if( !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
110    {
111        /* XXX should handle failure here in a better way */
112        sock = tr_netBind( port );
113    }
114#else
115    return;
116#endif
117
118    tr_lockLock( &h->acceptLock );
119
120    h->bindPort = port;
121
122    for( ii = 0; ii < h->torrentCount; ii++ )
123    {
124        tr_lockLock( &h->torrents[ii]->lock );
125        if( NULL != h->torrents[ii]->tracker )
126        {
127            tr_trackerChangePort( h->torrents[ii]->tracker, port );
128        }
129        tr_lockUnlock( &h->torrents[ii]->lock );
130    }
131
132#ifndef PORT_DEBUG
133    if( h->bindSocket > -1 )
134    {
135        tr_netClose( h->bindSocket );
136        tr_fdSocketClosed( h->fdlimit, 0 );
137    }
138#endif
139
140    h->bindSocket = sock;
141
142    tr_lockUnlock( &h->acceptLock );
143}
144
145/***********************************************************************
146 * tr_setUploadLimit
147 ***********************************************************************
148 *
149 **********************************************************************/
150void tr_setUploadLimit( tr_handle_t * h, int limit )
151{
152    tr_uploadSetLimit( h->upload, limit );
153}
154
155/***********************************************************************
156 * tr_torrentRates
157 ***********************************************************************
158 *
159 **********************************************************************/
160void tr_torrentRates( tr_handle_t * h, float * dl, float * ul )
161{
162    int            i;
163    tr_torrent_t * tor;
164
165    *dl = 0.0;
166    *ul = 0.0;
167
168    for( i = 0; i < h->torrentCount; i++ )
169    {
170        tor = h->torrents[i];
171        tr_lockLock( &tor->lock );
172        *dl += rateDownload( tor );
173        *ul += rateUpload( tor );
174        tr_lockUnlock( &tor->lock );
175    }
176}
177
178/***********************************************************************
179 * tr_torrentInit
180 ***********************************************************************
181 * Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
182 * to fill it.
183 **********************************************************************/
184int tr_torrentInit( tr_handle_t * h, const char * path )
185{
186    tr_torrent_t  * tor;
187    tr_info_t     * inf;
188    int             i;
189    char          * s1, * s2;
190
191    if( h->torrentCount >= TR_MAX_TORRENT_COUNT )
192    {
193        tr_err( "Maximum number of torrents reached" );
194        return 1;
195    }
196
197    tor = calloc( sizeof( tr_torrent_t ), 1 );
198    inf = &tor->info;
199
200    /* Parse torrent file */
201    if( tr_metainfoParse( inf, path ) )
202    {
203        free( tor );
204        return 1;
205    }
206
207    /* Make sure this torrent is not already open */
208    for( i = 0; i < h->torrentCount; i++ )
209    {
210        if( !memcmp( tor->info.hash, h->torrents[i]->info.hash,
211                     SHA_DIGEST_LENGTH ) )
212        {
213            tr_err( "Torrent already open" );
214            free( tor );
215            return 1;
216        }
217    }
218
219    tor->status = TR_STATUS_PAUSE;
220    tor->id     = h->id;
221    tor->key    = h->key;
222        tor->finished = 0;
223
224
225    /* Guess scrape URL */
226    s1 = strchr( inf->trackerAnnounce, '/' );
227    while( ( s2 = strchr( s1 + 1, '/' ) ) )
228    {
229        s1 = s2;
230    }
231    s1++;
232    if( !strncmp( s1, "announce", 8 ) )
233    {
234        int pre  = (long) s1 - (long) inf->trackerAnnounce;
235        int post = strlen( inf->trackerAnnounce ) - pre - 8;
236        memcpy( tor->scrape, inf->trackerAnnounce, pre );
237        sprintf( &tor->scrape[pre], "scrape" );
238        memcpy( &tor->scrape[pre+6], &inf->trackerAnnounce[pre+8], post );
239    }
240
241    /* Escaped info hash for HTTP queries */
242    for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
243    {
244        sprintf( &tor->hashString[3*i], "%%%02x", inf->hash[i] );
245    }
246
247    /* Block size: usually 16 ko, or less if we have to */
248    tor->blockSize  = MIN( inf->pieceSize, 1 << 14 );
249    tor->blockCount = ( inf->totalSize + tor->blockSize - 1 ) /
250                        tor->blockSize;
251    tor->completion = tr_cpInit( tor );
252
253    tr_lockInit( &tor->lock );
254
255    tor->upload  = h->upload;
256    tor->fdlimit = h->fdlimit;
257 
258    /* We have a new torrent */
259    tr_lockLock( &h->acceptLock );
260    h->torrents[h->torrentCount] = tor;
261    (h->torrentCount)++;
262    tr_lockUnlock( &h->acceptLock );
263
264    return 0;
265}
266
267/***********************************************************************
268 * tr_torrentScrape
269 ***********************************************************************
270 * Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
271 * to fill it.
272 **********************************************************************/
273int tr_torrentScrape( tr_handle_t * h, int t, int * s, int * l )
274{
275    return tr_trackerScrape( h->torrents[t], s, l );
276}
277
278void tr_torrentSetFolder( tr_handle_t * h, int t, const char * path )
279{
280    tr_torrent_t * tor = h->torrents[t];
281
282    tor->destination = strdup( path );
283}
284
285char * tr_torrentGetFolder( tr_handle_t * h, int t )
286{
287    tr_torrent_t * tor = h->torrents[t];
288
289    return tor->destination;
290}
291
292void tr_torrentStart( tr_handle_t * h, int t )
293{
294    tr_torrent_t * tor = h->torrents[t];
295    uint64_t       now;
296    int            i;
297
298    if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
299    {
300        /* Join the thread first */
301        torrentReallyStop( h, t );
302    }
303
304    tor->status   = TR_STATUS_CHECK;
305    tor->tracker  = tr_trackerInit( h, tor );
306
307    now = tr_date();
308    for( i = 0; i < 10; i++ )
309    {
310        tor->dates[i] = now;
311    }
312
313    tor->die = 0;
314    tr_threadCreate( &tor->thread, downloadLoop, tor );
315}
316
317void tr_torrentStop( tr_handle_t * h, int t )
318{
319    tr_torrent_t * tor = h->torrents[t];
320
321    tr_lockLock( &tor->lock );
322    tr_trackerStopped( tor->tracker );
323    tor->status = TR_STATUS_STOPPING;
324    tor->stopDate = tr_date();
325    tr_lockUnlock( &tor->lock );
326}
327
328/***********************************************************************
329 * torrentReallyStop
330 ***********************************************************************
331 * Joins the download thread and frees/closes everything related to it.
332 **********************************************************************/
333static void torrentReallyStop( tr_handle_t * h, int t )
334{
335    tr_torrent_t * tor = h->torrents[t];
336
337    tor->die = 1;
338    tr_threadJoin( &tor->thread );
339    tr_dbg( "Thread joined" );
340
341    tr_trackerClose( tor->tracker );
342
343    while( tor->peerCount > 0 )
344    {
345        tr_peerRem( tor, 0 );
346    }
347
348    memset( tor->downloaded, 0, sizeof( tor->downloaded ) );
349    memset( tor->uploaded,   0, sizeof( tor->uploaded ) );
350}
351
352/***********************************************************************
353 * tr_torrentCount
354 ***********************************************************************
355 *
356 **********************************************************************/
357int tr_torrentCount( tr_handle_t * h )
358{
359    return h->torrentCount;
360}
361
362int tr_getFinished( tr_handle_t * h, int i)
363{
364        return h->torrents[i]->finished;
365}
366void tr_setFinished( tr_handle_t * h, int i, int val)
367{
368        h->torrents[i]->finished = val;
369}
370
371int tr_torrentStat( tr_handle_t * h, tr_stat_t ** stat )
372{
373    tr_stat_t * s;
374    tr_torrent_t * tor;
375    tr_info_t * inf;
376    int i, j, k, piece;
377
378    if( h->torrentCount < 1 )
379    {
380        *stat = NULL;
381        return 0;
382    }
383
384    s = malloc( h->torrentCount * sizeof( tr_stat_t ) );
385
386    for( i = 0; i < h->torrentCount; i++ )
387    {
388        tor = h->torrents[i];
389        inf = &tor->info;
390
391        if( ( tor->status & TR_STATUS_STOPPED ) ||
392            ( ( tor->status & TR_STATUS_STOPPING ) &&
393              tr_date() > tor->stopDate + 60000 ) )
394        {
395            torrentReallyStop( h, i );
396            tor->status = TR_STATUS_PAUSE;
397        }
398
399        tr_lockLock( &tor->lock );
400
401        memcpy( &s[i].info, &tor->info, sizeof( tr_info_t ) );
402        s[i].status = tor->status;
403        memcpy( s[i].error, tor->error, sizeof( s[i].error ) );
404
405        s[i].peersTotal       = 0;
406        s[i].peersUploading   = 0;
407        s[i].peersDownloading = 0;
408
409        for( j = 0; j < tor->peerCount; j++ )
410        {
411            if( tr_peerIsConnected( tor->peers[j] ) )
412            {
413                (s[i].peersTotal)++;
414                if( tr_peerIsUploading( tor->peers[j] ) )
415                {
416                    (s[i].peersUploading)++;
417                }
418                if( tr_peerIsDownloading( tor->peers[j] ) )
419                {
420                    (s[i].peersDownloading)++;
421                }
422            }
423        }
424
425        s[i].progress     = tr_cpCompletionAsFloat( tor->completion );
426        s[i].rateDownload = rateDownload( tor );
427        s[i].rateUpload   = rateUpload( tor );
428       
429        s[i].seeders      = tr_trackerSeeders(tor);
430                s[i].leechers     = tr_trackerLeechers(tor);
431
432        if( s[i].rateDownload < 0.1 )
433        {
434            s[i].eta = -1;
435        }
436        else
437        {
438            s[i].eta = (float) ( 1.0 - s[i].progress ) *
439                (float) inf->totalSize / s[i].rateDownload / 1024.0;
440            if( s[i].eta > 99 * 3600 + 59 * 60 + 59 )
441            {
442                s[i].eta = -1;
443            }
444        }
445
446        for( j = 0; j < 120; j++ )
447        {
448            piece = j * inf->pieceCount / 120;
449
450            if( tr_cpPieceIsComplete( tor->completion, piece ) )
451            {
452                s[i].pieces[j] = -1;
453                continue;
454            }
455
456            s[i].pieces[j] = 0;
457           
458            for( k = 0; k < tor->peerCount; k++ )
459            {
460                if( tr_peerBitfield( tor->peers[k] ) &&
461                    tr_bitfieldHas( tr_peerBitfield( tor->peers[k] ), piece ) )
462                {
463                    (s[i].pieces[j])++;
464                }
465            }
466        }
467
468        s[i].downloaded = tor->downloaded[9];
469        s[i].uploaded   = tor->uploaded[9];
470
471        s[i].folder = tor->destination;
472
473        tr_lockUnlock( &tor->lock );
474    }
475
476    *stat = s;
477    return h->torrentCount;
478}
479
480/***********************************************************************
481 * tr_torrentClose
482 ***********************************************************************
483 * Frees memory allocated by tr_torrentInit.
484 **********************************************************************/
485void tr_torrentClose( tr_handle_t * h, int t )
486{
487    tr_torrent_t * tor = h->torrents[t];
488    tr_info_t    * inf = &tor->info;
489
490    if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
491    {
492        /* Join the thread first */
493        torrentReallyStop( h, t );
494    }
495
496    tr_lockLock( &h->acceptLock );
497
498    h->torrentCount--;
499
500    tr_lockClose( &tor->lock );
501    tr_cpClose( tor->completion );
502
503    if( tor->destination )
504    {
505        free( tor->destination );
506    }
507    free( inf->pieces );
508    free( inf->files );
509    free( tor );
510
511    memmove( &h->torrents[t], &h->torrents[t+1],
512             ( h->torrentCount - t ) * sizeof( void * ) );
513
514    tr_lockUnlock( &h->acceptLock );
515}
516
517void tr_close( tr_handle_t * h )
518{
519    acceptStop( h );
520    tr_fdClose( h->fdlimit );
521    tr_uploadClose( h->upload );
522    free( h );
523}
524
525/***********************************************************************
526 * downloadLoop
527 **********************************************************************/
528static void downloadLoop( void * _tor )
529{
530    tr_torrent_t * tor = _tor;
531    uint64_t       date1, date2;
532
533    tr_dbg( "Thread started" );
534
535#ifdef SYS_BEOS
536    /* This is required because on BeOS, SIGINT is sent to each thread,
537       which kills them not nicely */
538    signal( SIGINT, SIG_IGN );
539#endif
540
541    tr_lockLock( &tor->lock );
542
543    tr_cpReset( tor->completion );
544    tor->io     = tr_ioInit( tor );
545    tor->status = tr_cpIsSeeding( tor->completion ) ?
546                      TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
547
548    while( !tor->die )
549    {
550        date1 = tr_date();
551
552        /* Are we finished ? */
553        if( ( tor->status & TR_STATUS_DOWNLOAD ) &&
554            tr_cpIsSeeding( tor->completion ) )
555        {
556            /* Done */
557            tor->status = TR_STATUS_SEED;
558                        tor->finished = 1;
559            tr_trackerCompleted( tor->tracker );
560        }
561
562        /* Receive/send messages */
563        tr_peerPulse( tor );
564
565        /* Try to get new peers or to send a message to the tracker */
566        tr_trackerPulse( tor->tracker );
567
568        if( tor->status & TR_STATUS_STOPPED )
569        {
570            break;
571        }
572
573        /* Wait up to 20 ms */
574        date2 = tr_date();
575        if( date2 < date1 + 20 )
576        {
577            tr_lockUnlock( &tor->lock );
578            tr_wait( date1 + 20 - date2 );
579            tr_lockLock( &tor->lock );
580        }
581    }
582
583    tr_lockUnlock( &tor->lock );
584
585    tr_ioClose( tor->io );
586
587    tor->status = TR_STATUS_STOPPED;
588
589    tr_dbg( "Thread exited" );
590}
591
592/***********************************************************************
593 * rateDownload, rateUpload
594 **********************************************************************/
595static float rateGeneric( uint64_t * dates, uint64_t * counts )
596{
597    float ret;
598    int i;
599
600    ret = 0.0;
601    for( i = 0; i < 9; i++ )
602    {
603        if( dates[i+1] == dates[i] )
604        {
605            continue;
606        }
607        ret += (float) ( i + 1 ) * 1000.0 / 1024.0 *
608            (float) ( counts[i+1] - counts[i] ) /
609            (float) ( dates[i+1] - dates[i] );
610    }
611    ret *= 1000.0 / 1024.0 / 45.0;
612
613    return ret;
614}
615static float rateDownload( tr_torrent_t * tor )
616{
617    return rateGeneric( tor->dates, tor->downloaded );
618}
619static float rateUpload( tr_torrent_t * tor )
620{
621    return rateGeneric( tor->dates, tor->uploaded );
622}
623
624/***********************************************************************
625 * acceptLoop
626 **********************************************************************/
627static void acceptLoop( void * _h )
628{
629    tr_handle_t * h = _h;
630    uint64_t      date1, date2;
631    int           ii, jj;
632    uint8_t     * hash;
633#ifdef PORT_DEBUG
634    int           oldport, oldsocket;
635    int           oldPeerCount;
636    tr_peer_t   * oldPeers[TR_MAX_PEER_COUNT];
637#endif
638
639    tr_dbg( "Accept thread started" );
640
641#ifdef SYS_BEOS
642    /* This is required because on BeOS, SIGINT is sent to each thread,
643       which kills them not nicely */
644    signal( SIGINT, SIG_IGN );
645#endif
646
647    tr_lockLock( &h->acceptLock );
648
649#ifdef PORT_DEBUG
650    oldport = h->bindPort;
651    oldsocket = h->bindSocket;
652#endif
653
654    while( !h->acceptDie )
655    {
656        date1 = tr_date();
657
658        /* Check for incoming connections */
659        if( h->bindSocket > -1 &&
660            h->acceptPeerCount < TR_MAX_PEER_COUNT &&
661            !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
662        {
663            int            s;
664            struct in_addr addr;
665            in_port_t      port;
666            s = tr_netAccept( h->bindSocket, &addr, &port );
667            if( s > -1 )
668            {
669                h->acceptPeers[h->acceptPeerCount++] = tr_peerInit( addr, port, s );
670            }
671            else
672            {
673                tr_fdSocketClosed( h->fdlimit, 0 );
674            }
675        }
676
677        for( ii = 0; ii < h->acceptPeerCount; )
678        {
679            if( tr_peerRead( NULL, h->acceptPeers[ii] ) )
680            {
681                printf( "failed to read from peer on new port %i\n", h->bindPort );
682                tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
683                goto removePeer;
684            }
685            if( NULL != ( hash = tr_peerHash( h->acceptPeers[ii] ) ) )
686            {
687                for( jj = 0; jj < h->torrentCount; jj++ )
688                {
689                    tr_lockLock( &h->torrents[jj]->lock );
690                    if( 0 == memcmp( h->torrents[jj]->info.hash, hash,
691                                     SHA_DIGEST_LENGTH ) )
692                    {
693                        printf( "got peer on new port %i for \"%s\"\n",
694                                h->bindPort, h->torrents[jj]->info.name );
695                        tr_peerAttach( h->torrents[jj], h->acceptPeers[ii] );
696                        tr_lockUnlock( &h->torrents[jj]->lock );
697                        goto removePeer;
698                    }
699                    tr_lockUnlock( &h->torrents[jj]->lock );
700                }
701                printf( "failed to match hash for peer on new port %i\n", h->bindPort );
702                tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
703                goto removePeer;
704            }
705            ii++;
706            continue;
707           removePeer:
708            h->acceptPeerCount--;
709            memmove( &h->acceptPeers[ii], &h->acceptPeers[ii+1],
710                     ( h->acceptPeerCount - ii ) * sizeof( tr_peer_t * ) );
711        }
712
713#ifdef PORT_DEBUG
714        if( oldsocket != h->bindSocket) {
715        /* Check for incoming connections */
716        if( oldsocket > -1 &&
717            oldPeerCount < TR_MAX_PEER_COUNT &&
718            !tr_fdSocketWillCreate( h->fdlimit, 0 ) )
719        {
720            int            s;
721            struct in_addr addr;
722            in_port_t      port;
723            s = tr_netAccept( oldsocket, &addr, &port );
724            if( s > -1 )
725            {
726                oldPeers[oldPeerCount++] = tr_peerInit( addr, port, s );
727            }
728            else
729            {
730                tr_fdSocketClosed( h->fdlimit, 0 );
731            }
732        }
733
734        for( ii = 0; ii < oldPeerCount; )
735        {
736            if( tr_peerRead( NULL, oldPeers[ii] ) )
737            {
738                printf( "failed to read from peer on old port %i\n", oldport );
739                tr_peerDestroy( h->fdlimit, oldPeers[ii] );
740                goto removeOldPeer;
741            }
742            if( NULL != ( hash = tr_peerHash( oldPeers[ii] ) ) )
743            {
744                for( jj = 0; jj < h->torrentCount; jj++ )
745                {
746                    tr_lockLock( &h->torrents[jj]->lock );
747                    if( 0 == memcmp( h->torrents[jj]->info.hash, hash,
748                                     SHA_DIGEST_LENGTH ) )
749                    {
750                        printf( "got peer on old port %i for \"%s\"\n",
751                                oldport, h->torrents[jj]->info.name );
752                        tr_lockUnlock( &h->torrents[jj]->lock );
753                        goto removeOldPeer;
754                    }
755                    tr_lockUnlock( &h->torrents[jj]->lock );
756                }
757                printf( "failed to match hash for peer on old port %i\n", oldport );
758                tr_peerDestroy( h->fdlimit, oldPeers[ii] );
759                goto removeOldPeer;
760            }
761            ii++;
762            continue;
763           removeOldPeer:
764            oldPeerCount--;
765            memmove( &oldPeers[ii], &oldPeers[ii+1],
766                     ( oldPeerCount - ii ) * sizeof( tr_peer_t * ) );
767        }
768        }
769#endif
770
771        /* Wait up to 20 ms */
772        date2 = tr_date();
773        if( date2 < date1 + 20 )
774        {
775            tr_lockUnlock( &h->acceptLock );
776            tr_wait( date1 + 20 - date2 );
777            tr_lockLock( &h->acceptLock );
778        }
779    }
780
781    tr_lockUnlock( &h->acceptLock );
782
783    tr_dbg( "Accept thread exited" );
784}
785
786/***********************************************************************
787 * acceptStop
788 ***********************************************************************
789 * Joins the accept thread and frees/closes everything related to it.
790 **********************************************************************/
791static void acceptStop( tr_handle_t * h )
792{
793    int ii;
794
795    h->acceptDie = 1;
796    tr_threadJoin( &h->acceptThread );
797    tr_lockClose( &h->acceptLock );
798    tr_dbg( "Accept thread joined" );
799
800    for( ii = 0; ii < h->acceptPeerCount; ii++ )
801    {
802        tr_peerDestroy( h->fdlimit, h->acceptPeers[ii] );
803    }
804
805    if( h->bindSocket > -1 )
806    {
807        tr_netClose( h->bindSocket );
808        tr_fdSocketClosed( h->fdlimit, 0 );
809    }
810}
Note: See TracBrowser for help on using the repository browser.