source: trunk/libtransmission/transmission.c @ 766

Last change on this file since 766 was 766, checked in by livings124, 15 years ago

Get peers separately from the rest of the stats. This should also get rid of a memory leak.

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