source: trunk/libtransmission/transmission.c @ 3921

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

some progress on the overall statistics, though probably not visible to end users yet

  • Property svn:keywords set to Date Rev Author Id
File size: 9.4 KB
Line 
1/******************************************************************************
2 * $Id: transmission.c 3921 2007-11-21 20:03:53Z 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 "trevent.h"
46#include "utils.h"
47
48/* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
49   characters, where x is the major version number, y is the
50   minor version number, z is the maintenance number, and b
51   designates beta (Azureus-style) */
52void
53tr_peerIdNew ( char * buf, int buflen )
54{
55    int i;
56    assert( buflen == TR_ID_LEN + 1 );
57
58    snprintf( buf, TR_ID_LEN, "%s", PEERID_PREFIX );
59    assert( strlen(buf) == 8 );
60    for( i=8; i<TR_ID_LEN; ++i ) {
61        const int r = tr_rand( 36 );
62        buf[i] = ( r < 26 ) ? ( 'a' + r ) : ( '0' + r - 26 ) ;
63    }
64    buf[TR_ID_LEN] = '\0';
65}
66
67const char*
68getPeerId( void )
69{
70    static char * peerId = NULL;
71    if( !peerId ) {
72        peerId = tr_new0( char, TR_ID_LEN + 1 );
73        tr_peerIdNew( peerId, TR_ID_LEN + 1 );
74    }
75    return peerId;
76}
77
78/***
79****
80***/
81
82tr_encryption_mode
83tr_getEncryptionMode( tr_handle * handle )
84{
85    assert( handle != NULL );
86
87    return handle->encryptionMode;
88}
89
90void
91tr_setEncryptionMode( tr_handle * handle, tr_encryption_mode mode )
92{
93    assert( handle != NULL );
94    assert( mode==TR_ENCRYPTION_PREFERRED
95         || mode==TR_ENCRYPTION_REQUIRED
96         || mode==TR_PLAINTEXT_PREFERRED );
97
98    handle->encryptionMode = mode;
99}
100
101/***
102****
103***/
104
105
106/***********************************************************************
107 * tr_init
108 ***********************************************************************
109 * Allocates a tr_handle structure and initializes a few things
110 **********************************************************************/
111tr_handle * tr_init( const char * tag )
112{
113    tr_handle * h;
114
115#ifndef WIN32
116    /* Don't exit when writing on a broken socket */
117    signal( SIGPIPE, SIG_IGN );
118#endif
119
120    tr_msgInit();
121
122    h = tr_new0( tr_handle, 1 );
123    if( !h )
124        return NULL;
125
126    h->lock = tr_lockNew( );
127
128    h->encryptionMode = TR_ENCRYPTION_PREFERRED;
129
130    tr_netInit(); /* must go before tr_eventInit */
131
132    tr_eventInit( h );
133    while( !h->events )
134        tr_wait( 50 );
135
136    h->tag = strdup( tag );
137    if( !h->tag ) {
138        free( h );
139        return NULL;
140    }
141
142    h->peerMgr = tr_peerMgrNew( h );
143
144    /* Initialize rate and file descripts controls */
145    h->upload   = tr_rcInit();
146    h->download = tr_rcInit();
147
148    tr_fdInit();
149    h->shared = tr_sharedInit( h );
150
151    tr_inf( TR_NAME " " LONG_VERSION_STRING " started" );
152
153    tr_statsInit( h );
154
155    return h;
156}
157
158/***
159****
160***/
161
162void
163tr_globalLock( struct tr_handle * handle )
164{
165    tr_lockLock( handle->lock );
166}
167
168void
169tr_globalUnlock( struct tr_handle * handle )
170{
171    tr_lockUnlock( handle->lock );
172}
173
174int
175tr_globalIsLocked( const struct tr_handle * handle )
176{
177    return tr_lockHave( handle->lock );
178}
179
180/***********************************************************************
181 * tr_setBindPort
182 ***********************************************************************
183 *
184 **********************************************************************/
185void tr_setBindPort( tr_handle * h, int port )
186{
187    h->isPortSet = 1;
188    tr_sharedSetPort( h->shared, port );
189}
190
191int
192tr_getPublicPort( const tr_handle * h )
193{
194    assert( h != NULL );
195    return tr_sharedGetPublicPort( h->shared );
196}
197
198void tr_natTraversalEnable( tr_handle * h, int enable )
199{
200    tr_globalLock( h );
201    tr_sharedTraversalEnable( h->shared, enable );
202    tr_globalUnlock( h );
203}
204
205tr_handle_status * tr_handleStatus( tr_handle * h )
206{
207    tr_handle_status * s;
208
209    h->statCur = ( h->statCur + 1 ) % 2;
210    s = &h->stats[h->statCur];
211
212    tr_globalLock( h );
213
214    s->natTraversalStatus = tr_sharedTraversalStatus( h->shared );
215    s->publicPort = tr_sharedGetPublicPort( h->shared );
216
217    tr_globalUnlock( h );
218
219    return s;
220}
221
222/***
223****
224***/
225
226void
227tr_setUseGlobalSpeedLimit( tr_handle  * h,
228                           int          up_or_down,
229                           int          use_flag )
230{
231    char * ch = up_or_down==TR_UP ? &h->useUploadLimit
232                                  : &h->useDownloadLimit;
233    *ch = use_flag;
234}
235
236void
237tr_setGlobalSpeedLimit( tr_handle  * h,
238                        int          up_or_down,
239                        int          KiB_sec )
240{
241    if( up_or_down == TR_DOWN )
242        tr_rcSetLimit( h->download, KiB_sec );
243    else
244        tr_rcSetLimit( h->upload, KiB_sec );
245}
246
247void
248tr_getGlobalSpeedLimit( tr_handle  * h,
249                        int          up_or_down,
250                        int        * setme_enabled,
251                        int          * setme_KiBsec )
252{
253    if( setme_enabled != NULL )
254       *setme_enabled = up_or_down==TR_UP ? h->useUploadLimit
255                                          : h->useDownloadLimit;
256    if( setme_KiBsec != NULL )
257       *setme_KiBsec = tr_rcGetLimit( up_or_down==TR_UP ? h->upload
258                                                        : h->download );
259}
260
261void
262tr_torrentRates( tr_handle * h, float * toClient, float * toPeer )
263{
264    const tr_torrent * tor;
265    tr_globalLock( h );
266
267    *toClient = *toPeer = 0.0;
268    for( tor = h->torrentList; tor; tor = tor->next )
269    {
270        float c, p;
271        tr_torrentGetRates( tor, &c, &p );
272        *toClient += c;
273        *toPeer += p;
274    }
275
276    tr_globalUnlock( h );
277}
278
279int
280tr_torrentCount( tr_handle * h )
281{
282    return h->torrentCount;
283}
284
285void
286tr_torrentIterate( tr_handle * h, tr_callback_t func, void * d )
287{
288    tr_torrent * tor, * next;
289
290    for( tor = h->torrentList; tor; tor = next )
291    {
292        next = tor->next;
293        func( tor, d );
294    }
295}
296
297static void
298tr_closeImpl( void * vh )
299{
300    tr_handle * h = vh;
301    tr_torrent * t;
302
303    for( t=h->torrentList; t!=NULL; t=t->next )
304        tr_torrentClose( t );
305
306    tr_peerMgrFree( h->peerMgr );
307
308    tr_rcClose( h->upload );
309    tr_rcClose( h->download );
310   
311    tr_natTraversalEnable( h, 0 );
312    while( tr_handleStatus( h )->natTraversalStatus != TR_NAT_TRAVERSAL_DISABLED )
313        tr_wait( 100 );
314
315    tr_sharedClose( h->shared );
316    tr_fdClose();
317
318    h->isClosed = TRUE;
319}
320
321static int
322deadlineReached( const uint64_t deadline )
323{
324    return tr_date( ) >= deadline;
325}
326
327void
328tr_close( tr_handle * h )
329{
330    const int maxwait_msec = 6 * 1000;
331    const uint64_t deadline = tr_date( ) + maxwait_msec;
332
333    tr_runInEventThread( h, tr_closeImpl, h );
334    while( !h->isClosed && !deadlineReached( deadline ) )
335        tr_wait( 100 );
336
337    tr_eventClose( h );
338    while( h->events && !deadlineReached( deadline ) )
339        tr_wait( 100 );
340
341    tr_statsClose( h );
342    tr_lockFree( h->lock );
343    free( h->tag );
344    free( h );
345}
346
347tr_torrent **
348tr_loadTorrents ( tr_handle   * h,
349                  const char  * fallbackDestination,
350                  int           isPaused,
351                  int         * setmeCount )
352{
353    int i, n = 0;
354    struct stat sb;
355    DIR * odir = NULL;
356    const char * torrentDir = tr_getTorrentsDirectory( );
357    tr_torrent ** torrents;
358    tr_list *l=NULL, *list=NULL;
359
360    if( !stat( torrentDir, &sb )
361        && S_ISDIR( sb.st_mode )
362        && (( odir = opendir ( torrentDir ) )) )
363    {
364        struct dirent *d;
365        for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
366        {
367            if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
368            {
369                tr_torrent * tor;
370                char path[MAX_PATH_LENGTH];
371                tr_buildPath( path, sizeof(path), torrentDir, d->d_name, NULL );
372                tor = tr_torrentLoad( h, path, fallbackDestination, isPaused, NULL );
373                if( tor != NULL ) {
374                    tr_list_append( &list, tor );
375                    n++;
376                }
377            }
378        }
379        closedir( odir );
380    }
381
382    torrents = tr_new( tr_torrent*, n );
383    for( i=0, l=list; l!=NULL; l=l->next )
384        torrents[i++] = (tr_torrent*) l->data;
385    assert( i==n );
386
387    tr_list_free( &list, NULL );
388
389    *setmeCount = n;
390    tr_inf( "Loaded %d torrents from disk", *setmeCount );
391    return torrents;
392}
Note: See TracBrowser for help on using the repository browser.