source: trunk/libtransmission/transmission.c @ 4346

Last change on this file since 4346 was 4346, checked in by charles, 15 years ago

dead code removal

  • Property svn:keywords set to Date Rev Author Id
File size: 11.4 KB
Line 
1/******************************************************************************
2 * $Id: transmission.c 4346 2007-12-26 20:45:08Z charles $
3 *
4 * Copyright (c) 2005-2007 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 <assert.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <signal.h>
31#include <sys/types.h> /* stat */
32#include <sys/stat.h> /* stat */
33#include <unistd.h> /* stat */
34#include <dirent.h> /* opendir */
35
36#include "transmission.h"
37#include "fdlimit.h"
38#include "list.h"
39#include "net.h"
40#include "peer-mgr.h"
41#include "platform.h"
42#include "ratecontrol.h"
43#include "shared.h"
44#include "stats.h"
45#include "torrent.h"
46#include "tracker.h"
47#include "trevent.h"
48#include "utils.h"
49
50/* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
51   characters, where x is the major version number, y is the
52   minor version number, z is the maintenance number, and b
53   designates beta (Azureus-style) */
54void
55tr_peerIdNew ( char * buf, int buflen )
56{
57    int i;
58    assert( buflen == TR_ID_LEN + 1 );
59
60    snprintf( buf, TR_ID_LEN, "%s", PEERID_PREFIX );
61    assert( strlen(buf) == 8 );
62    for( i=8; i<TR_ID_LEN; ++i ) {
63        const int r = tr_rand( 36 );
64        buf[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
65    }
66    buf[TR_ID_LEN] = '\0';
67}
68
69const char*
70getPeerId( void )
71{
72    static char * peerId = NULL;
73    if( !peerId ) {
74        peerId = tr_new0( char, TR_ID_LEN + 1 );
75        tr_peerIdNew( peerId, TR_ID_LEN + 1 );
76    }
77    return peerId;
78}
79
80/***
81****
82***/
83
84tr_encryption_mode
85tr_getEncryptionMode( tr_handle * handle )
86{
87    assert( handle != NULL );
88
89    return handle->encryptionMode;
90}
91
92void
93tr_setEncryptionMode( tr_handle * handle, tr_encryption_mode mode )
94{
95    assert( handle != NULL );
96    assert( mode==TR_ENCRYPTION_PREFERRED
97         || mode==TR_ENCRYPTION_REQUIRED
98         || mode==TR_PLAINTEXT_PREFERRED );
99
100    handle->encryptionMode = mode;
101}
102
103/***
104****
105***/
106
107tr_handle *
108tr_initFull( const char * tag,
109             int          isPexEnabled,
110             int          isNatEnabled,
111             int          publicPort,
112             int          encryptionMode,
113             int          isUploadLimitEnabled,
114             int          uploadLimit,
115             int          isDownloadLimitEnabled,
116             int          downloadLimit,
117             int          globalPeerLimit,
118             int          messageLevel,
119             int          isMessageQueueingEnabled )
120{
121    tr_handle * h;
122
123#ifndef WIN32
124    /* Don't exit when writing on a broken socket */
125    signal( SIGPIPE, SIG_IGN );
126#endif
127
128    tr_msgInit( );
129    tr_setMessageLevel( messageLevel );
130    tr_setMessageQueuing( isMessageQueueingEnabled );
131
132    h = tr_new0( tr_handle, 1 );
133    h->lock = tr_lockNew( );
134    h->isPexEnabled = isPexEnabled ? 1 : 0;
135    h->encryptionMode = encryptionMode;
136
137    tr_netInit(); /* must go before tr_eventInit */
138
139    tr_eventInit( h );
140    while( !h->events )
141        tr_wait( 50 );
142
143    h->tag = strdup( tag );
144    if( !h->tag ) {
145        free( h );
146        return NULL;
147    }
148
149    h->peerMgr = tr_peerMgrNew( h );
150
151    /* Initialize rate and file descripts controls */
152
153    h->upload = tr_rcInit();
154    tr_rcSetLimit( h->upload, uploadLimit );
155    h->useUploadLimit = isUploadLimitEnabled;
156
157    h->download = tr_rcInit();
158    tr_rcSetLimit( h->download, downloadLimit );
159    h->useDownloadLimit = isDownloadLimitEnabled;
160
161    tr_fdInit( globalPeerLimit );
162    h->shared = tr_sharedInit( h, isNatEnabled, publicPort );
163    h->isPortSet = publicPort >= 0;
164
165    tr_inf( TR_NAME " " LONG_VERSION_STRING " started" );
166
167    tr_statsInit( h );
168
169    return h;
170}
171
172tr_handle * tr_init( const char * tag )
173{
174    return tr_initFull( tag,
175                        TRUE, /* pex enabled */
176                        FALSE, /* nat enabled */
177                        -1, /* public port */
178                        TR_ENCRYPTION_PREFERRED, /* encryption mode */
179                        FALSE, /* use upload speed limit? */ 
180                        -1, /* upload speed limit */
181                        FALSE, /* use download speed limit? */
182                        -1, /* download speed limit */
183                        512, /* globalPeerLimit */
184                        TR_MSG_INF, /* message level */
185                        FALSE ); /* is message queueing enabled? */
186}
187
188/***
189****
190***/
191
192void
193tr_globalLock( struct tr_handle * handle )
194{
195    tr_lockLock( handle->lock );
196}
197
198void
199tr_globalUnlock( struct tr_handle * handle )
200{
201    tr_lockUnlock( handle->lock );
202}
203
204int
205tr_globalIsLocked( const struct tr_handle * handle )
206{
207    return tr_lockHave( handle->lock );
208}
209
210/***********************************************************************
211 * tr_setBindPort
212 ***********************************************************************
213 *
214 **********************************************************************/
215
216struct bind_port_data
217{
218    tr_handle * handle;
219    int port;
220};
221
222static void
223tr_setBindPortImpl( void * vdata )
224{
225    struct bind_port_data * data = vdata;
226    tr_handle * handle = data->handle;
227    const int port = data->port;
228
229    handle->isPortSet = 1;
230    tr_sharedSetPort( handle->shared, port );
231
232    tr_free( data );
233}
234
235void
236tr_setBindPort( tr_handle * handle, int port )
237{
238    struct bind_port_data * data = tr_new( struct bind_port_data, 1 );
239    data->handle = handle;
240    data->port = port;
241    tr_runInEventThread( handle, tr_setBindPortImpl, data );
242}
243
244int
245tr_getPublicPort( const tr_handle * h )
246{
247    assert( h != NULL );
248    return tr_sharedGetPublicPort( h->shared );
249}
250
251void tr_natTraversalEnable( tr_handle * h, int enable )
252{
253    tr_globalLock( h );
254    tr_sharedTraversalEnable( h->shared, enable );
255    tr_globalUnlock( h );
256}
257
258tr_handle_status * tr_handleStatus( tr_handle * h )
259{
260    tr_handle_status * s;
261
262    h->statCur = ( h->statCur + 1 ) % 2;
263    s = &h->stats[h->statCur];
264
265    tr_globalLock( h );
266
267    s->natTraversalStatus = tr_sharedTraversalStatus( h->shared );
268    s->publicPort = tr_sharedGetPublicPort( h->shared );
269
270    tr_globalUnlock( h );
271
272    return s;
273}
274
275/***
276****
277***/
278
279void
280tr_setUseGlobalSpeedLimit( tr_handle  * h,
281                           int          up_or_down,
282                           int          use_flag )
283{
284    char * ch = up_or_down==TR_UP ? &h->useUploadLimit
285                                  : &h->useDownloadLimit;
286    *ch = use_flag;
287}
288
289void
290tr_setGlobalSpeedLimit( tr_handle  * h,
291                        int          up_or_down,
292                        int          KiB_sec )
293{
294    if( up_or_down == TR_DOWN )
295        tr_rcSetLimit( h->download, KiB_sec );
296    else
297        tr_rcSetLimit( h->upload, KiB_sec );
298}
299
300void
301tr_getGlobalSpeedLimit( tr_handle  * h,
302                        int          up_or_down,
303                        int        * setme_enabled,
304                        int          * setme_KiBsec )
305{
306    if( setme_enabled != NULL )
307       *setme_enabled = up_or_down==TR_UP ? h->useUploadLimit
308                                          : h->useDownloadLimit;
309    if( setme_KiBsec != NULL )
310       *setme_KiBsec = tr_rcGetLimit( up_or_down==TR_UP ? h->upload
311                                                        : h->download );
312}
313
314
315void
316tr_setGlobalPeerLimit( tr_handle * handle UNUSED,
317                       uint16_t    maxGlobalPeers )
318{
319    tr_fdSetPeerLimit( maxGlobalPeers );
320}
321
322uint16_t
323tr_getGlobalPeerLimit( const tr_handle * handle UNUSED )
324{
325    return tr_fdGetPeerLimit( );
326}
327
328void
329tr_torrentRates( tr_handle * h, float * toClient, float * toPeer )
330{
331    const tr_torrent * tor;
332    tr_globalLock( h );
333
334    *toClient = *toPeer = 0.0;
335    for( tor = h->torrentList; tor; tor = tor->next )
336    {
337        float c, p;
338        tr_torrentGetRates( tor, &c, &p );
339        *toClient += c;
340        *toPeer += p;
341    }
342
343    tr_globalUnlock( h );
344}
345
346int
347tr_torrentCount( tr_handle * h )
348{
349    return h->torrentCount;
350}
351
352static void
353tr_closeImpl( void * vh )
354{
355    tr_handle * h = vh;
356    tr_torrent * t;
357
358    tr_sharedShuttingDown( h->shared );
359    tr_trackerShuttingDown( h );
360
361    for( t=h->torrentList; t!=NULL; t=t->next )
362        tr_torrentClose( t );
363
364    tr_peerMgrFree( h->peerMgr );
365
366    tr_rcClose( h->upload );
367    tr_rcClose( h->download );
368   
369    h->isClosed = TRUE;
370}
371
372static int
373deadlineReached( const uint64_t deadline )
374{
375    return tr_date( ) >= deadline;
376}
377
378#define SHUTDOWN_MAX_SECONDS 30
379
380void
381tr_close( tr_handle * h )
382{
383    const int maxwait_msec = SHUTDOWN_MAX_SECONDS * 1000;
384    const uint64_t deadline = tr_date( ) + maxwait_msec;
385
386    tr_runInEventThread( h, tr_closeImpl, h );
387    while( !h->isClosed && !deadlineReached( deadline ) )
388        tr_wait( 100 );
389
390    tr_eventClose( h );
391    while( h->events && !deadlineReached( deadline ) )
392        tr_wait( 100 );
393
394    tr_fdClose( );
395    tr_statsClose( h );
396    tr_lockFree( h->lock );
397    free( h->tag );
398    free( h );
399}
400
401tr_torrent **
402tr_loadTorrents ( tr_handle   * h,
403                  tr_ctor     * ctor,
404                  int         * setmeCount )
405{
406    int i, n = 0;
407    struct stat sb;
408    DIR * odir = NULL;
409    const char * dirname = tr_getTorrentsDirectory( );
410    tr_torrent ** torrents;
411    tr_list *l=NULL, *list=NULL;
412
413    tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
414
415    if( !stat( dirname, &sb )
416        && S_ISDIR( sb.st_mode )
417        && (( odir = opendir ( dirname ) )) )
418    {
419        struct dirent *d;
420        for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
421        {
422            if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
423            {
424                tr_torrent * tor;
425                char filename[MAX_PATH_LENGTH];
426                tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
427                tr_ctorSetMetainfoFromFile( ctor, filename );
428                tor = tr_torrentNew( h, ctor, NULL );
429                if( tor != NULL ) {
430                    tr_list_append( &list, tor );
431                    n++;
432                }
433            }
434        }
435        closedir( odir );
436    }
437
438    torrents = tr_new( tr_torrent*, n );
439    for( i=0, l=list; l!=NULL; l=l->next )
440        torrents[i++] = (tr_torrent*) l->data;
441    assert( i==n );
442
443    tr_list_free( &list, NULL );
444
445    *setmeCount = n;
446    tr_inf( "Loaded %d torrents from disk", *setmeCount );
447    return torrents;
448}
449
450/***
451****
452***/
453
454void
455tr_setPexEnabled( tr_handle * handle, int isPexEnabled )
456{
457    handle->isPexEnabled = isPexEnabled ? 1 : 0;
458}
459
460int
461tr_isPexEnabled( const tr_handle * handle )
462{
463    return handle->isPexEnabled;
464}
Note: See TracBrowser for help on using the repository browser.