2
* This file Copyright (C) 2008-2010 Mnemosyne LLC
4
* This file is licensed by the GPL version 2. Works owned by the
5
* Transmission project are granted a special exemption to clause 2(b)
6
* so that the bulk of its code can remain under the MIT license.
7
* This exemption does not extend to derived works not owned by
8
* the Transmission project.
10
* $Id: session.c 10303 2010-03-06 15:05:05Z charles $
14
#include <errno.h> /* ENOENT */
16
#include <string.h> /* memcpy */
19
#include <sys/types.h> /* stat(), umask() */
20
#include <sys/stat.h> /* stat(), umask() */
21
#include <unistd.h> /* stat */
22
#include <dirent.h> /* opendir */
26
#include "transmission.h"
27
#include "announcer.h"
28
#include "bandwidth.h"
30
#include "blocklist.h"
34
#include "metainfo.h" /* tr_metainfoFree */
38
#include "platform.h" /* tr_lock */
39
#include "port-forwarding.h"
40
#include "rpc-server.h"
53
SAVE_INTERVAL_SECS = 120
57
#define dbgmsg( ... ) \
59
if( tr_deepLoggingIsActive( ) ) \
60
tr_deepLog( __FILE__, __LINE__, NULL, __VA_ARGS__ ); \
64
getRandomPort( tr_session * s )
66
return tr_cryptoWeakRandInt( s->randomPortHigh - s->randomPortLow + 1) + s->randomPortLow;
69
/* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
70
characters, where x is the major version number, y is the
71
minor version number, z is the maintenance number, and b
72
designates beta (Azureus-style) */
79
uint8_t * buf = tr_new( uint8_t, 21 );
80
const char * pool = "0123456789abcdefghijklmnopqrstuvwxyz";
83
memcpy( buf, PEERID_PREFIX, 8 );
85
for( i = 8; i < 19; ++i )
87
val = tr_cryptoRandInt( base );
92
val = total % base ? base - ( total % base ) : 0;
102
static uint8_t * id = NULL;
105
id = tr_peerIdNew( );
114
tr_sessionGetEncryption( tr_session * session )
118
return session->encryptionMode;
122
tr_sessionSetEncryption( tr_session * session,
123
tr_encryption_mode mode )
126
assert( mode == TR_ENCRYPTION_PREFERRED
127
|| mode == TR_ENCRYPTION_REQUIRED
128
|| mode == TR_CLEAR_PREFERRED );
130
session->encryptionMode = mode;
146
close_bindinfo( struct tr_bindinfo * b )
148
if( ( b != NULL ) && ( b->socket >=0 ) )
151
tr_netCloseSocket( b->socket );
156
close_incoming_peer_port( tr_session * session )
158
close_bindinfo( session->public_ipv4 );
159
close_bindinfo( session->public_ipv6 );
163
free_incoming_peer_port( tr_session * session )
165
close_bindinfo( session->public_ipv4 );
166
tr_free( session->public_ipv4 );
167
session->public_ipv4 = NULL;
169
close_bindinfo( session->public_ipv6 );
170
tr_free( session->public_ipv6 );
171
session->public_ipv6 = NULL;
175
accept_incoming_peer( int fd, short what UNUSED, void * vsession )
179
tr_address clientAddr;
180
tr_session * session = vsession;
182
clientSocket = tr_netAccept( session, fd, &clientAddr, &clientPort );
183
if( clientSocket > 0 ) {
184
tr_deepLog( __FILE__, __LINE__, NULL, "new incoming connection %d (%s)",
185
clientSocket, tr_peerIoAddrStr( &clientAddr, clientPort ) );
186
tr_peerMgrAddIncoming( session->peerMgr, &clientAddr, clientPort, clientSocket );
191
open_incoming_peer_port( tr_session * session )
193
struct tr_bindinfo * b;
195
/* bind an ipv4 port to listen for incoming peers... */
196
b = session->public_ipv4;
197
b->socket = tr_netBindTCP( &b->addr, session->peerPort, FALSE );
198
if( b->socket >= 0 ) {
199
event_set( &b->ev, b->socket, EV_READ | EV_PERSIST, accept_incoming_peer, session );
200
event_add( &b->ev, NULL );
203
/* and do the exact same thing for ipv6, if it's supported... */
204
if( tr_net_hasIPv6( session->peerPort ) ) {
205
b = session->public_ipv6;
206
b->socket = tr_netBindTCP( &b->addr, session->peerPort, FALSE );
207
if( b->socket >= 0 ) {
208
event_set( &b->ev, b->socket, EV_READ | EV_PERSIST, accept_incoming_peer, session );
209
event_add( &b->ev, NULL );
215
tr_sessionGetPublicAddress( const tr_session * session, int tr_af_type )
219
case TR_AF_INET: return &session->public_ipv4->addr;
220
case TR_AF_INET6: return &session->public_ipv6->addr; break;
221
default: return NULL;
230
#define TR_DEFAULT_ENCRYPTION TR_CLEAR_PREFERRED
232
#define TR_DEFAULT_ENCRYPTION TR_ENCRYPTION_PREFERRED
236
tr_sessionGetDefaultSettings( const char * configDir, tr_benc * d )
238
char * incompleteDir = tr_buildPath( configDir, "Incomplete", NULL );
240
assert( tr_bencIsDict( d ) );
242
tr_bencDictReserve( d, 35 );
243
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, FALSE );
244
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, TRUE );
245
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_getDefaultDownloadDir( ) );
246
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED, 100 );
247
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, FALSE );
248
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION );
249
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, incompleteDir );
250
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, FALSE );
251
tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD, TRUE );
252
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF );
253
tr_bencDictAddInt ( d, TR_PREFS_KEY_OPEN_FILE_LIMIT, atoi( TR_DEFAULT_OPEN_FILE_LIMIT_STR ) );
254
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
255
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
256
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, atoi( TR_DEFAULT_PEER_PORT_STR ) );
257
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, FALSE );
258
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, 49152 );
259
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, 65535 );
260
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, atoi( TR_DEFAULT_PEER_SOCKET_TOS_STR ) );
261
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, TRUE );
262
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, TRUE );
263
#ifdef HAVE_FALLOCATE64
264
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_FULL );
266
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_SPARSE );
268
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY, "" );
269
tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_AUTH_ENABLED, FALSE );
270
tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_ENABLED, FALSE );
271
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY_PASSWORD, "" );
272
tr_bencDictAddInt ( d, TR_PREFS_KEY_PROXY_PORT, 80 );
273
tr_bencDictAddInt ( d, TR_PREFS_KEY_PROXY_TYPE, TR_PROXY_HTTP );
274
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY_USERNAME, "" );
275
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, 2.0 );
276
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, FALSE );
277
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, TRUE );
278
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, FALSE );
279
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, "0.0.0.0" );
280
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, TRUE );
281
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, "" );
282
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, "" );
283
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST );
284
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, TRUE );
285
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, atoi( TR_DEFAULT_RPC_PORT_STR ) );
286
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, FALSE );
287
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP, 50 ); /* half the regular */
288
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN, 50 ); /* half the regular */
289
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, 540 ); /* 9am */
290
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, FALSE );
291
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, 1020 ); /* 5pm */
292
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, TR_SCHED_ALL );
293
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED, 100 );
294
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, FALSE );
295
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, 022 );
296
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 );
297
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, TR_DEFAULT_BIND_ADDRESS_IPV4 );
298
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, TR_DEFAULT_BIND_ADDRESS_IPV6 );
300
tr_free( incompleteDir );
304
tr_sessionGetSettings( tr_session * s, struct tr_benc * d )
306
assert( tr_bencIsDict( d ) );
308
tr_bencDictReserve( d, 30 );
309
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, tr_blocklistIsEnabled( s ) );
310
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, s->isDHTEnabled );
311
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, s->downloadDir );
312
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED, tr_sessionGetSpeedLimit( s, TR_DOWN ) );
313
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_DOWN ) );
314
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, s->encryptionMode );
315
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) );
316
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionIsIncompleteDirEnabled( s ) );
317
tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD, s->useLazyBitfield );
318
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, tr_getMessageLevel( ) );
319
tr_bencDictAddInt ( d, TR_PREFS_KEY_OPEN_FILE_LIMIT, tr_fdGetFileLimit( s ) );
320
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, tr_sessionGetPeerLimit( s ) );
321
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, s->peerLimitPerTorrent );
322
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( s ) );
323
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, s->isPortRandom );
324
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, s->randomPortLow );
325
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, s->randomPortHigh );
326
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, s->peerSocketTOS );
327
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, s->isPexEnabled );
328
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
329
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, s->preallocationMode );
330
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY, s->proxy );
331
tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_AUTH_ENABLED, s->isProxyAuthEnabled );
332
tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_ENABLED, s->isProxyEnabled );
333
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY_PASSWORD, s->proxyPassword );
334
tr_bencDictAddInt ( d, TR_PREFS_KEY_PROXY_PORT, s->proxyPort );
335
tr_bencDictAddInt ( d, TR_PREFS_KEY_PROXY_TYPE, s->proxyType );
336
tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY_USERNAME, s->proxyUsername );
337
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, s->desiredRatio );
338
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, s->isRatioLimited );
339
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, tr_sessionIsIncompleteFileNamingEnabled( s ) );
340
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, tr_sessionIsRPCPasswordEnabled( s ) );
341
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, tr_sessionGetRPCBindAddress( s ) );
342
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, tr_sessionIsRPCEnabled( s ) );
343
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, tr_sessionGetRPCPassword( s ) );
344
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, tr_sessionGetRPCPort( s ) );
345
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, tr_sessionGetRPCUsername( s ) );
346
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, tr_sessionGetRPCWhitelist( s ) );
347
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled( s ) );
348
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( s ) );
349
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP, tr_sessionGetAltSpeed( s, TR_UP ) );
350
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN, tr_sessionGetAltSpeed( s, TR_DOWN ) );
351
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, tr_sessionGetAltSpeedBegin( s ) );
352
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, tr_sessionUsesAltSpeedTime( s ) );
353
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, tr_sessionGetAltSpeedEnd( s ) );
354
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, tr_sessionGetAltSpeedDay( s ) );
355
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED, tr_sessionGetSpeedLimit( s, TR_UP ) );
356
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_UP ) );
357
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, s->umask );
358
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent );
359
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, tr_ntop_non_ts( &s->public_ipv4->addr ) );
360
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, tr_ntop_non_ts( &s->public_ipv6->addr ) );
364
tr_sessionLoadSettings( tr_benc * d, const char * configDir, const char * appName )
368
tr_benc fileSettings;
369
tr_benc sessionDefaults;
371
tr_bool success = FALSE;
373
assert( tr_bencIsDict( d ) );
375
/* initializing the defaults: caller may have passed in some app-level defaults.
376
* preserve those and use the session defaults to fill in any missing gaps. */
377
tr_bencInitDict( &sessionDefaults, 0 );
378
tr_sessionGetDefaultSettings( configDir, &sessionDefaults );
379
tr_bencMergeDicts( &sessionDefaults, d );
380
tmp = *d; *d = sessionDefaults; sessionDefaults = tmp;
382
/* if caller didn't specify a config dir, use the default */
383
if( !configDir || !*configDir )
384
configDir = tr_getDefaultConfigDir( appName );
386
/* file settings override the defaults */
387
filename = tr_buildPath( configDir, "settings.json", NULL );
388
err = tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename );
390
tr_bencMergeDicts( d, &fileSettings );
391
tr_bencFree( &fileSettings );
395
tr_bencFree( &sessionDefaults );
397
success = (err==0) || (err==ENOENT);
402
tr_sessionSaveSettings( tr_session * session,
403
const char * configDir,
404
const tr_benc * clientSettings )
407
char * filename = tr_buildPath( configDir, "settings.json", NULL );
409
assert( tr_bencIsDict( clientSettings ) );
411
tr_bencInitDict( &settings, 0 );
413
/* the existing file settings are the fallback values */
415
tr_benc fileSettings;
416
const int err = tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename );
419
tr_bencMergeDicts( &settings, &fileSettings );
420
tr_bencFree( &fileSettings );
424
/* the client's settings override the file settings */
425
tr_bencMergeDicts( &settings, clientSettings );
427
/* the session's true values override the file & client settings */
429
tr_benc sessionSettings;
430
tr_bencInitDict( &sessionSettings, 0 );
431
tr_sessionGetSettings( session, &sessionSettings );
432
tr_bencMergeDicts( &settings, &sessionSettings );
433
tr_bencFree( &sessionSettings );
436
/* save the result */
437
tr_bencToFile( &settings, TR_FMT_JSON, filename );
441
tr_bencFree( &settings );
449
* Periodically save the .resume files of any torrents whose
450
* status has recently changed. This prevents loss of metadata
451
* in the case of a crash, unclean shutdown, clumsy user, etc.
454
onSaveTimer( int foo UNUSED, short bar UNUSED, void * vsession )
456
tr_torrent * tor = NULL;
457
tr_session * session = vsession;
459
while(( tor = tr_torrentNext( session, tor )))
460
tr_torrentSave( tor );
462
tr_statsSaveDirty( session );
464
tr_timerAdd( session->saveTimer, SAVE_INTERVAL_SECS, 0 );
471
static void tr_sessionInitImpl( void * );
475
tr_session * session;
476
const char * configDir;
478
tr_bool messageQueuingEnabled;
479
tr_benc * clientSettings;
483
tr_sessionInit( const char * tag,
484
const char * configDir,
485
tr_bool messageQueuingEnabled,
486
tr_benc * clientSettings )
489
tr_session * session;
490
struct init_data data;
494
assert( tr_bencIsDict( clientSettings ) );
496
/* initialize the bare skeleton of the session object */
497
session = tr_new0( tr_session, 1 );
498
session->bandwidth = tr_bandwidthNew( session, NULL );
499
session->lock = tr_lockNew( );
500
session->tag = tr_strdup( tag );
501
session->magicNumber = SESSION_MAGIC_NUMBER;
502
session->buffer = tr_valloc( SESSION_BUFFER_SIZE );
503
tr_bencInitList( &session->removedTorrents, 0 );
505
/* nice to start logging at the very beginning */
506
if( tr_bencDictFindInt( clientSettings, TR_PREFS_KEY_MSGLEVEL, &i ) )
507
tr_setMessageLevel( i );
509
/* start the libtransmission thread */
510
tr_netInit( ); /* must go before tr_eventInit */
511
tr_eventInit( session );
512
assert( session->events != NULL );
514
/* run the rest in the libtransmission thread */
516
data.session = session;
517
data.configDir = configDir;
518
data.messageQueuingEnabled = messageQueuingEnabled;
519
data.clientSettings = clientSettings;
520
tr_runInEventThread( session, tr_sessionInitImpl, &data );
527
static void turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser );
530
onNowTimer( int foo UNUSED, short bar UNUSED, void * vsession )
534
const int max = 999999;
536
tr_session * session = vsession;
538
assert( tr_isSession( session ) );
539
assert( session->nowTimer != NULL );
541
/* schedule the next timer for right after the next second begins */
542
gettimeofday( &tv, NULL );
543
usec = 1000000 - tv.tv_usec;
544
if( usec > max ) usec = max;
545
if( usec < min ) usec = min;
546
tr_timerAdd( session->nowTimer, 0, usec );
547
/* fprintf( stderr, "time %zu sec, %zu microsec\n", (size_t)tr_time(), (size_t)tv.tv_usec ); */
549
/* tr_session things to do once per second */
550
tr_timeUpdate( tv.tv_sec );
551
turtleCheckClock( session, &session->turtle, FALSE );
554
static void loadBlocklists( tr_session * session );
557
tr_sessionInitImpl( void * vdata )
560
struct init_data * data = vdata;
561
tr_benc * clientSettings = data->clientSettings;
562
tr_session * session = data->session;
564
assert( tr_amInEventThread( session ) );
565
assert( tr_bencIsDict( clientSettings ) );
567
dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p",
568
session->bandwidth );
570
tr_bencInitDict( &settings, 0 );
571
tr_sessionGetDefaultSettings( data->configDir, &settings );
572
tr_bencMergeDicts( &settings, clientSettings );
574
session->nowTimer = tr_new0( struct event, 1 );
575
evtimer_set( session->nowTimer, onNowTimer, session );
576
onNowTimer( 0, 0, session );
579
/* Don't exit when writing on a broken socket */
580
signal( SIGPIPE, SIG_IGN );
583
tr_setMessageQueuing( data->messageQueuingEnabled );
585
tr_setConfigDir( session, data->configDir );
587
session->peerMgr = tr_peerMgrNew( session );
589
session->shared = tr_sharedInit( session );
596
char * filename = tr_buildPath( session->configDir, "blocklists", NULL );
597
tr_mkdirp( filename, 0777 );
599
loadBlocklists( session );
602
assert( tr_isSession( session ) );
604
session->saveTimer = tr_new0( struct event, 1 );
605
evtimer_set( session->saveTimer, onSaveTimer, session );
606
tr_timerAdd( session->saveTimer, SAVE_INTERVAL_SECS, 0 );
608
tr_announcerInit( session );
610
/* first %s is the application name
611
second %s is the version number */
612
tr_inf( _( "%s %s started" ), TR_NAME, LONG_VERSION_STRING );
614
tr_statsInit( session );
616
tr_webInit( session );
618
tr_sessionSet( session, &settings );
620
if( session->isDHTEnabled )
622
tr_dhtInit( session, &session->public_ipv4->addr );
626
tr_bencFree( &settings );
630
static void turtleBootstrap( tr_session *, struct tr_turtle_info * );
633
sessionSetImpl( void * vdata )
639
struct tr_bindinfo b;
640
struct init_data * data = vdata;
641
tr_session * session = data->session;
642
tr_benc * settings = data->clientSettings;
643
struct tr_turtle_info * turtle = &session->turtle;
645
assert( tr_isSession( session ) );
646
assert( tr_bencIsDict( settings ) );
647
assert( tr_amInEventThread( session ) );
649
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_MSGLEVEL, &i ) )
650
tr_setMessageLevel( i );
652
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_UMASK, &i ) ) {
653
session->umask = (mode_t)i;
654
umask( session->umask );
658
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_LAZY_BITFIELD, &boolVal ) )
659
tr_sessionSetLazyBitfieldEnabled( session, boolVal );
660
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i ) )
661
tr_sessionSetPeerLimitPerTorrent( session, i );
662
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PEX_ENABLED, &boolVal ) )
663
tr_sessionSetPexEnabled( session, boolVal );
664
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_DHT_ENABLED, &boolVal ) )
665
tr_sessionSetDHTEnabled( session, boolVal );
666
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ENCRYPTION, &i ) )
667
tr_sessionSetEncryption( session, i );
668
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_SOCKET_TOS, &i ) )
669
session->peerSocketTOS = i;
670
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, &boolVal ) )
671
tr_blocklistSetEnabled( session, boolVal );
673
/* files and directories */
674
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PREALLOCATION, &i ) )
675
session->preallocationMode = i;
676
if( tr_bencDictFindStr( settings, TR_PREFS_KEY_DOWNLOAD_DIR, &str ) )
677
tr_sessionSetDownloadDir( session, str );
678
if( tr_bencDictFindStr( settings, TR_PREFS_KEY_INCOMPLETE_DIR, &str ) )
679
tr_sessionSetIncompleteDir( session, str );
680
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, &boolVal ) )
681
tr_sessionSetIncompleteDirEnabled( session, boolVal );
682
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_RENAME_PARTIAL_FILES, &boolVal ) )
683
tr_sessionSetIncompleteFileNamingEnabled( session, boolVal );
686
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PROXY_ENABLED, &boolVal ) )
687
tr_sessionSetProxyEnabled( session, boolVal );
688
if( tr_bencDictFindStr( settings, TR_PREFS_KEY_PROXY, &str ) )
689
tr_sessionSetProxy( session, str );
690
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PROXY_PORT, &i ) )
691
tr_sessionSetProxyPort( session, i );
692
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PROXY_TYPE, &i ) )
693
tr_sessionSetProxyType( session, i );
694
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PROXY_AUTH_ENABLED, &boolVal ) )
695
tr_sessionSetProxyAuthEnabled( session, boolVal );
696
if( tr_bencDictFindStr( settings, TR_PREFS_KEY_PROXY_USERNAME, &str ) )
697
tr_sessionSetProxyUsername( session, str );
698
if( tr_bencDictFindStr( settings, TR_PREFS_KEY_PROXY_PASSWORD, &str ) )
699
tr_sessionSetProxyPassword( session, str );
702
if( session->rpcServer != NULL ) /* close the old one */
703
tr_rpcClose( &session->rpcServer );
704
session->rpcServer = tr_rpcInit( session, settings );
706
/* public addresses */
708
free_incoming_peer_port( session );
710
str = TR_PREFS_KEY_BIND_ADDRESS_IPV4;
711
tr_bencDictFindStr( settings, TR_PREFS_KEY_BIND_ADDRESS_IPV4, &str );
712
if( !tr_pton( str, &b.addr ) || ( b.addr.type != TR_AF_INET ) )
713
b.addr = tr_inaddr_any;
715
session->public_ipv4 = tr_memdup( &b, sizeof( struct tr_bindinfo ) );
716
tr_webSetInterface( session, &session->public_ipv4->addr );
718
str = TR_PREFS_KEY_BIND_ADDRESS_IPV6;
719
tr_bencDictFindStr( settings, TR_PREFS_KEY_BIND_ADDRESS_IPV6, &str );
720
if( !tr_pton( str, &b.addr ) || ( b.addr.type != TR_AF_INET6 ) )
721
b.addr = tr_in6addr_any;
723
session->public_ipv6 = tr_memdup( &b, sizeof( struct tr_bindinfo ) );
725
/* incoming peer port */
726
if( tr_bencDictFindInt ( settings, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, &i ) )
727
session->randomPortLow = i;
728
if( tr_bencDictFindInt ( settings, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, &i ) )
729
session->randomPortHigh = i;
730
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, &boolVal ) )
731
tr_sessionSetPeerPortRandomOnStart( session, boolVal );
732
if( !tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_PORT, &i ) )
733
i = session->peerPort;
734
tr_sessionSetPeerPort( session, boolVal ? getRandomPort( session ) : i );
735
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PORT_FORWARDING, &boolVal ) )
736
tr_sessionSetPortForwardingEnabled( session, boolVal );
738
/* file and peer socket limits */
739
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &i ) )
740
tr_fdSetPeerLimit( session, i );
741
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i ) )
742
tr_fdSetFileLimit( session, i );
747
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, &i ) )
748
session->uploadSlotsPerTorrent = i;
750
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_USPEED, &i ) )
751
tr_sessionSetSpeedLimit( session, TR_UP, i );
752
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_USPEED_ENABLED, &boolVal ) )
753
tr_sessionLimitSpeed( session, TR_UP, boolVal );
755
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_DSPEED, &i ) )
756
tr_sessionSetSpeedLimit( session, TR_DOWN, i );
757
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_DSPEED_ENABLED, &boolVal ) )
758
tr_sessionLimitSpeed( session, TR_DOWN, boolVal );
760
if( tr_bencDictFindReal( settings, TR_PREFS_KEY_RATIO, &d ) )
761
tr_sessionSetRatioLimit( session, d );
762
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_RATIO_ENABLED, &boolVal ) )
763
tr_sessionSetRatioLimited( session, boolVal );
769
/* update the turtle mode's fields */
770
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_UP, &i ) )
771
turtle->speedLimit[TR_UP] = i;
772
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_DOWN, &i ) )
773
turtle->speedLimit[TR_DOWN] = i;
774
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, &i ) )
775
turtle->beginMinute = i;
776
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_END, &i ) )
777
turtle->endMinute = i;
778
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, &i ) )
780
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, &boolVal ) )
781
turtle->isClockEnabled = boolVal;
782
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_ALT_SPEED_ENABLED, &boolVal ) )
783
turtle->isEnabled = boolVal;
784
turtleBootstrap( session, turtle );
790
tr_sessionSet( tr_session * session, struct tr_benc * settings )
792
struct init_data data;
794
data.session = session;
795
data.clientSettings = settings;
797
/* run the rest in the libtransmission thread */
798
tr_runInEventThread( session, sessionSetImpl, &data );
808
tr_sessionSetDownloadDir( tr_session * session, const char * dir )
810
assert( tr_isSession( session ) );
812
if( session->downloadDir != dir )
814
tr_free( session->downloadDir );
815
session->downloadDir = tr_strdup( dir );
820
tr_sessionGetDownloadDir( const tr_session * session )
822
assert( tr_isSession( session ) );
824
return session->downloadDir;
832
tr_sessionSetIncompleteFileNamingEnabled( tr_session * session, tr_bool b )
834
assert( tr_isSession( session ) );
835
assert( tr_isBool( b ) );
837
session->isIncompleteFileNamingEnabled = b;
841
tr_sessionIsIncompleteFileNamingEnabled( const tr_session * session )
843
assert( tr_isSession( session ) );
845
return session->isIncompleteFileNamingEnabled;
854
tr_sessionSetIncompleteDir( tr_session * session, const char * dir )
856
assert( tr_isSession( session ) );
858
if( session->incompleteDir != dir )
860
tr_free( session->incompleteDir );
862
session->incompleteDir = tr_strdup( dir );
867
tr_sessionGetIncompleteDir( const tr_session * session )
869
assert( tr_isSession( session ) );
871
return session->incompleteDir;
875
tr_sessionSetIncompleteDirEnabled( tr_session * session, tr_bool b )
877
assert( tr_isSession( session ) );
878
assert( tr_isBool( b ) );
880
session->isIncompleteDirEnabled = b;
884
tr_sessionIsIncompleteDirEnabled( const tr_session * session )
886
assert( tr_isSession( session ) );
888
return session->isIncompleteDirEnabled;
896
tr_sessionGetBuffer( tr_session * session )
898
assert( tr_isSession( session ) );
899
assert( !session->bufferInUse );
900
assert( tr_amInEventThread( session ) );
902
session->bufferInUse = TRUE;
903
return session->buffer;
907
tr_sessionReleaseBuffer( tr_session * session )
909
assert( tr_isSession( session ) );
910
assert( session->bufferInUse );
911
assert( tr_amInEventThread( session ) );
913
session->bufferInUse = FALSE;
917
tr_sessionLock( tr_session * session )
919
assert( tr_isSession( session ) );
921
tr_lockLock( session->lock );
925
tr_sessionUnlock( tr_session * session )
927
assert( tr_isSession( session ) );
929
tr_lockUnlock( session->lock );
933
tr_sessionIsLocked( const tr_session * session )
935
return tr_isSession( session ) && tr_lockHave( session->lock );
938
/***********************************************************************
940
***********************************************************************
942
**********************************************************************/
945
setPeerPort( void * session )
947
tr_torrent * tor = NULL;
949
assert( tr_isSession( session ) );
951
close_incoming_peer_port( session );
952
open_incoming_peer_port( session );
953
tr_sharedPortChanged( session );
955
while(( tor = tr_torrentNext( session, tor )))
956
tr_torrentChangeMyPort( tor );
960
tr_sessionSetPeerPort( tr_session * session, tr_port port )
962
assert( tr_isSession( session ) );
964
if( session->peerPort != port )
966
session->peerPort = port;
968
tr_runInEventThread( session, setPeerPort, session );
973
tr_sessionGetPeerPort( const tr_session * session )
975
assert( tr_isSession( session ) );
977
return session->peerPort;
981
tr_sessionSetPeerPortRandom( tr_session * session )
983
assert( tr_isSession( session ) );
985
tr_sessionSetPeerPort( session, getRandomPort( session ) );
986
return session->peerPort;
990
tr_sessionSetPeerPortRandomOnStart( tr_session * session,
993
assert( tr_isSession( session ) );
995
session->isPortRandom = random;
999
tr_sessionGetPeerPortRandomOnStart( tr_session * session )
1001
assert( tr_isSession( session ) );
1003
return session->isPortRandom;
1007
tr_sessionGetPortForwarding( const tr_session * session )
1009
assert( tr_isSession( session ) );
1011
return tr_sharedTraversalStatus( session->shared );
1019
updateSeedRatio( tr_session * session )
1021
tr_torrent * tor = NULL;
1023
while(( tor = tr_torrentNext( session, tor )))
1024
tor->needsSeedRatioCheck = TRUE;
1028
tr_sessionSetRatioLimited( tr_session * session, tr_bool isLimited )
1030
assert( tr_isSession( session ) );
1032
session->isRatioLimited = isLimited;
1033
updateSeedRatio( session );
1037
tr_sessionSetRatioLimit( tr_session * session, double desiredRatio )
1039
assert( tr_isSession( session ) );
1041
session->desiredRatio = desiredRatio;
1042
updateSeedRatio( session );
1046
tr_sessionIsRatioLimited( const tr_session * session )
1048
assert( tr_isSession( session ) );
1050
return session->isRatioLimited;
1054
tr_sessionGetRatioLimit( const tr_session * session )
1056
assert( tr_isSession( session ) );
1058
return session->desiredRatio;
1068
tr_sessionGetActiveSpeedLimit( const tr_session * session, tr_direction dir, int * setme )
1070
int isLimited = TRUE;
1072
if( !tr_isSession( session ) )
1075
if( tr_sessionUsesAltSpeed( session ) )
1076
*setme = tr_sessionGetAltSpeed( session, dir );
1077
else if( tr_sessionIsSpeedLimited( session, dir ) )
1078
*setme = tr_sessionGetSpeedLimit( session, dir );
1086
updateBandwidth( tr_session * session, tr_direction dir )
1089
const tr_bool isLimited = tr_sessionGetActiveSpeedLimit( session, dir, &limit );
1090
const tr_bool zeroCase = isLimited && !limit;
1092
tr_bandwidthSetLimited( session->bandwidth, dir, isLimited && !zeroCase );
1094
tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, limit );
1098
turtleFindNextChange( struct tr_turtle_info * t )
1102
time_t today_began_at;
1105
const time_t now = tr_time( );
1106
const int SECONDS_PER_DAY = 86400;
1108
tr_localtime_r( &now, &tm );
1109
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
1110
today_began_at = mktime( &tm );
1112
next_begin = today_began_at + ( t->beginMinute * 60 );
1113
if( next_begin <= now )
1114
next_begin += SECONDS_PER_DAY;
1116
next_end = today_began_at + ( t->endMinute * 60 );
1117
if( next_end <= now )
1118
next_end += SECONDS_PER_DAY;
1120
if( next_begin < next_end ) {
1121
t->_nextChangeAt = next_begin;
1122
t->_nextChangeValue = TRUE;
1124
t->_nextChangeAt = next_end;
1125
t->_nextChangeValue = FALSE;
1128
/* if the next change is today, look for today in t->days.
1129
if the next change is tomorrow to turn limits OFF, look for today in t->days.
1130
if the next change is tomorrow to turn limits ON, look for tomorrow in t->days. */
1131
if( t->_nextChangeValue && (( t->_nextChangeAt >= today_began_at + SECONDS_PER_DAY )))
1132
day = ( tm.tm_wday + 1 ) % 7;
1135
t->_nextChangeAllowed = ( t->days & (1<<day) ) != 0;
1137
if( t->isClockEnabled && t->_nextChangeAllowed ) {
1139
tr_localtime_r( &t->_nextChangeAt, &tm );
1140
strftime( buf, sizeof( buf ), "%a %b %d %T %Y", &tm );
1141
tr_inf( "Turtle clock updated: at %s we'll turn limits %s", buf, (t->_nextChangeValue?"on":"off") );
1146
altSpeedToggled( void * vsession )
1148
tr_session * session = vsession;
1149
struct tr_turtle_info * t = &session->turtle;
1151
assert( tr_isSession( session ) );
1153
updateBandwidth( session, TR_UP );
1154
updateBandwidth( session, TR_DOWN );
1155
turtleFindNextChange( t );
1157
if( t->callback != NULL )
1158
(*t->callback)( session, t->isEnabled, t->changedByUser, t->callbackUserData );
1162
useAltSpeed( tr_session * s, struct tr_turtle_info * t, tr_bool enabled, tr_bool byUser )
1164
assert( tr_isSession( s ) );
1165
assert( t != NULL );
1166
assert( tr_isBool( enabled ) );
1167
assert( tr_isBool( byUser ) );
1169
if( t->isEnabled != enabled )
1171
t->isEnabled = enabled;
1172
t->changedByUser = byUser;
1173
tr_runInEventThread( s, altSpeedToggled, s );
1178
turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
1180
const time_t now = tr_time( );
1181
const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( ));
1187
const tr_bool enabled = t->_nextChangeValue;
1189
if( t->isClockEnabled && t->_nextChangeAllowed )
1191
tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") );
1192
useAltSpeed( session, t, enabled, byUser );
1195
turtleFindNextChange( t );
1199
/* Called after the turtle's fields are loaded from an outside source.
1200
* It initializes the implementation fields
1201
* and turns on turtle mode if the clock settings say to. */
1203
turtleBootstrap( tr_session * session, struct tr_turtle_info * turtle )
1205
turtleFindNextChange( turtle );
1207
turtle->changedByUser = FALSE;
1209
if( turtle->isClockEnabled )
1210
turtle->isEnabled = !turtle->_nextChangeValue;
1212
altSpeedToggled( session );
1216
**** Primary session speed limits
1220
tr_sessionSetSpeedLimit( tr_session * s, tr_direction d, int KB_s )
1222
assert( tr_isSession( s ) );
1223
assert( tr_isDirection( d ) );
1224
assert( KB_s >= 0 );
1226
s->speedLimit[d] = KB_s;
1228
updateBandwidth( s, d );
1232
tr_sessionGetSpeedLimit( const tr_session * s, tr_direction d )
1234
assert( tr_isSession( s ) );
1235
assert( tr_isDirection( d ) );
1237
return s->speedLimit[d];
1241
tr_sessionLimitSpeed( tr_session * s, tr_direction d, tr_bool b )
1243
assert( tr_isSession( s ) );
1244
assert( tr_isDirection( d ) );
1245
assert( tr_isBool( b ) );
1247
s->speedLimitEnabled[d] = b;
1249
updateBandwidth( s, d );
1253
tr_sessionIsSpeedLimited( const tr_session * s, tr_direction d )
1255
assert( tr_isSession( s ) );
1256
assert( tr_isDirection( d ) );
1258
return s->speedLimitEnabled[d];
1262
**** Alternative speed limits that are used during scheduled times
1266
tr_sessionSetAltSpeed( tr_session * s, tr_direction d, int KB_s )
1268
assert( tr_isSession( s ) );
1269
assert( tr_isDirection( d ) );
1270
assert( KB_s >= 0 );
1272
s->turtle.speedLimit[d] = KB_s;
1274
updateBandwidth( s, d );
1278
tr_sessionGetAltSpeed( const tr_session * s, tr_direction d )
1280
assert( tr_isSession( s ) );
1281
assert( tr_isDirection( d ) );
1283
return s->turtle.speedLimit[d];
1287
userPokedTheClock( tr_session * s, struct tr_turtle_info * t )
1289
tr_dbg( "Refreshing the turtle mode clock due to user changes" );
1292
turtleFindNextChange( t );
1294
if( t->isClockEnabled && t->_nextChangeAllowed )
1295
useAltSpeed( s, t, !t->_nextChangeValue, TRUE );
1299
tr_sessionUseAltSpeedTime( tr_session * s, tr_bool b )
1301
struct tr_turtle_info * t = &s->turtle;
1303
assert( tr_isSession( s ) );
1304
assert( tr_isBool ( b ) );
1306
if( t->isClockEnabled != b ) {
1307
t->isClockEnabled = b;
1308
userPokedTheClock( s, t );
1313
tr_sessionUsesAltSpeedTime( const tr_session * s )
1315
assert( tr_isSession( s ) );
1317
return s->turtle.isClockEnabled;
1321
tr_sessionSetAltSpeedBegin( tr_session * s, int minute )
1323
assert( tr_isSession( s ) );
1324
assert( 0<=minute && minute<(60*24) );
1326
if( s->turtle.beginMinute != minute ) {
1327
s->turtle.beginMinute = minute;
1328
userPokedTheClock( s, &s->turtle );
1333
tr_sessionGetAltSpeedBegin( const tr_session * s )
1335
assert( tr_isSession( s ) );
1337
return s->turtle.beginMinute;
1341
tr_sessionSetAltSpeedEnd( tr_session * s, int minute )
1343
assert( tr_isSession( s ) );
1344
assert( 0<=minute && minute<(60*24) );
1346
if( s->turtle.endMinute != minute ) {
1347
s->turtle.endMinute = minute;
1348
userPokedTheClock( s, &s->turtle );
1353
tr_sessionGetAltSpeedEnd( const tr_session * s )
1355
assert( tr_isSession( s ) );
1357
return s->turtle.endMinute;
1361
tr_sessionSetAltSpeedDay( tr_session * s, tr_sched_day days )
1363
assert( tr_isSession( s ) );
1365
if( s->turtle.days != days ) {
1366
s->turtle.days = days;
1367
userPokedTheClock( s, &s->turtle );
1372
tr_sessionGetAltSpeedDay( const tr_session * s )
1374
assert( tr_isSession( s ) );
1376
return s->turtle.days;
1380
tr_sessionUseAltSpeed( tr_session * session, tr_bool enabled )
1382
useAltSpeed( session, &session->turtle, enabled, TRUE );
1386
tr_sessionUsesAltSpeed( const tr_session * s )
1388
assert( tr_isSession( s ) );
1390
return s->turtle.isEnabled;
1394
tr_sessionSetAltSpeedFunc( tr_session * session,
1395
tr_altSpeedFunc func,
1398
assert( tr_isSession( session ) );
1400
session->turtle.callback = func;
1401
session->turtle.callbackUserData = userData;
1405
tr_sessionClearAltSpeedFunc( tr_session * session )
1407
tr_sessionSetAltSpeedFunc( session, NULL, NULL );
1415
tr_sessionSetPeerLimit( tr_session * session, uint16_t maxGlobalPeers )
1417
assert( tr_isSession( session ) );
1419
tr_fdSetPeerLimit( session, maxGlobalPeers );
1423
tr_sessionGetPeerLimit( const tr_session * session )
1425
assert( tr_isSession( session ) );
1427
return tr_fdGetPeerLimit( session );
1431
tr_sessionSetPeerLimitPerTorrent( tr_session * session, uint16_t n )
1433
assert( tr_isSession( session ) );
1435
session->peerLimitPerTorrent = n;
1439
tr_sessionGetPeerLimitPerTorrent( const tr_session * session )
1441
assert( tr_isSession( session ) );
1443
return session->peerLimitPerTorrent;
1451
tr_sessionGetPieceSpeed( const tr_session * session, tr_direction dir )
1453
return tr_isSession( session ) ? tr_bandwidthGetPieceSpeed( session->bandwidth, 0, dir ) : 0.0;
1457
tr_sessionGetRawSpeed( const tr_session * session, tr_direction dir )
1459
return tr_isSession( session ) ? tr_bandwidthGetRawSpeed( session->bandwidth, 0, dir ) : 0.0;
1463
tr_sessionCountTorrents( const tr_session * session )
1465
return tr_isSession( session ) ? session->torrentCount : 0;
1469
compareTorrentByCur( const void * va, const void * vb )
1471
const tr_torrent * a = *(const tr_torrent**)va;
1472
const tr_torrent * b = *(const tr_torrent**)vb;
1473
const uint64_t aCur = a->downloadedCur + a->uploadedCur;
1474
const uint64_t bCur = b->downloadedCur + b->uploadedCur;
1477
return aCur > bCur ? -1 : 1; /* close the biggest torrents first */
1482
static void closeBlocklists( tr_session * );
1485
sessionCloseImpl( void * vsession )
1487
tr_session * session = vsession;
1490
tr_torrent ** torrents;
1492
assert( tr_isSession( session ) );
1494
free_incoming_peer_port( session );
1496
if( session->isDHTEnabled )
1497
tr_dhtUninit( session );
1499
evtimer_del( session->saveTimer );
1500
tr_free( session->saveTimer );
1501
session->saveTimer = NULL;
1503
evtimer_del( session->nowTimer );
1504
tr_free( session->nowTimer );
1505
session->nowTimer = NULL;
1507
tr_verifyClose( session );
1508
tr_sharedClose( session );
1509
tr_rpcClose( &session->rpcServer );
1511
/* close the torrents. get the most active ones first so that
1512
* if we can't get them all closed in a reasonable amount of time,
1513
* at least we get the most important ones first. */
1515
n = session->torrentCount;
1516
torrents = tr_new( tr_torrent *, session->torrentCount );
1517
for( i = 0; i < n; ++i )
1518
torrents[i] = tor = tr_torrentNext( session, tor );
1519
qsort( torrents, n, sizeof( tr_torrent* ), compareTorrentByCur );
1520
for( i = 0; i < n; ++i )
1521
tr_torrentFree( torrents[i] );
1522
tr_free( torrents );
1524
tr_announcerClose( session );
1525
tr_statsClose( session );
1526
tr_peerMgrFree( session->peerMgr );
1527
tr_webClose( session, TR_WEB_CLOSE_WHEN_IDLE );
1529
closeBlocklists( session );
1531
tr_fdClose( session );
1533
session->isClosed = TRUE;
1537
deadlineReached( const time_t deadline )
1539
return time( NULL ) >= deadline;
1542
#define SHUTDOWN_MAX_SECONDS 20
1545
tr_sessionClose( tr_session * session )
1547
const time_t deadline = time( NULL ) + SHUTDOWN_MAX_SECONDS;
1549
assert( tr_isSession( session ) );
1551
dbgmsg( "shutting down transmission session %p", session );
1553
/* close the session */
1554
tr_runInEventThread( session, sessionCloseImpl, session );
1555
while( !session->isClosed && !deadlineReached( deadline ) )
1557
dbgmsg( "waiting for the libtransmission thread to finish" );
1558
tr_wait_msec( 100 );
1561
/* "shared" and "tracker" have live sockets,
1562
* so we need to keep the transmission thread alive
1563
* for a bit while they tell the router & tracker
1564
* that we're closing now */
1565
while( ( session->shared || session->web || session->announcer )
1566
&& !deadlineReached( deadline ) )
1568
dbgmsg( "waiting on port unmap (%p) or announcer (%p)",
1569
session->shared, session->announcer );
1570
tr_wait_msec( 100 );
1573
tr_webClose( session, TR_WEB_CLOSE_NOW );
1575
/* close the libtransmission thread */
1576
tr_eventClose( session );
1577
while( session->events != NULL )
1579
static tr_bool forced = FALSE;
1580
dbgmsg( "waiting for libtransmission thread to finish" );
1581
tr_wait_msec( 500 );
1582
if( deadlineReached( deadline ) && !forced )
1587
if( time( NULL ) >= deadline + 3 )
1592
/* free the session memory */
1593
tr_bencFree( &session->removedTorrents );
1594
tr_bandwidthFree( session->bandwidth );
1595
tr_lockFree( session->lock );
1596
if( session->metainfoLookup ) {
1597
tr_bencFree( session->metainfoLookup );
1598
tr_free( session->metainfoLookup );
1600
tr_free( session->buffer );
1601
tr_free( session->tag );
1602
tr_free( session->configDir );
1603
tr_free( session->resumeDir );
1604
tr_free( session->torrentDir );
1605
tr_free( session->downloadDir );
1606
tr_free( session->incompleteDir );
1607
tr_free( session->proxy );
1608
tr_free( session->proxyUsername );
1609
tr_free( session->proxyPassword );
1614
tr_sessionLoadTorrents( tr_session * session,
1621
const char * dirname = tr_getTorrentDir( session );
1622
tr_torrent ** torrents;
1623
tr_list * l = NULL, *list = NULL;
1625
assert( tr_isSession( session ) );
1627
tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
1629
if( !stat( dirname, &sb )
1630
&& S_ISDIR( sb.st_mode )
1631
&& ( ( odir = opendir ( dirname ) ) ) )
1634
for( d = readdir( odir ); d != NULL; d = readdir( odir ) )
1636
if( d->d_name && d->d_name[0] != '.' ) /* skip dotfiles, ., and ..
1640
char * path = tr_buildPath( dirname, d->d_name, NULL );
1641
tr_ctorSetMetainfoFromFile( ctor, path );
1642
if(( tor = tr_torrentNew( ctor, NULL )))
1644
tr_list_append( &list, tor );
1653
torrents = tr_new( tr_torrent *, n );
1654
for( i = 0, l = list; l != NULL; l = l->next )
1655
torrents[i++] = (tr_torrent*) l->data;
1658
tr_list_free( &list, NULL );
1661
tr_inf( _( "Loaded %d torrents" ), n );
1673
tr_sessionSetPexEnabled( tr_session * session,
1676
assert( tr_isSession( session ) );
1678
session->isPexEnabled = enabled != 0;
1682
tr_sessionIsPexEnabled( const tr_session * session )
1684
assert( tr_isSession( session ) );
1686
return session->isPexEnabled;
1690
tr_sessionAllowsDHT( const tr_session * session UNUSED )
1692
return tr_sessionIsDHTEnabled( session );
1696
tr_sessionIsDHTEnabled( const tr_session * session )
1698
assert( tr_isSession( session ) );
1700
return session->isDHTEnabled;
1704
toggleDHTImpl( void * data )
1706
tr_session * session = data;
1707
assert( tr_isSession( session ) );
1709
if( session->isDHTEnabled )
1710
tr_dhtUninit( session );
1712
session->isDHTEnabled = !session->isDHTEnabled;
1714
if( session->isDHTEnabled )
1715
tr_dhtInit( session, &session->public_ipv4->addr );
1719
tr_sessionSetDHTEnabled( tr_session * session, tr_bool enabled )
1721
assert( tr_isSession( session ) );
1722
assert( tr_isBool( enabled ) );
1724
if( ( enabled != 0 ) != ( session->isDHTEnabled != 0 ) )
1725
tr_runInEventThread( session, toggleDHTImpl, session );
1733
tr_sessionSetLazyBitfieldEnabled( tr_session * session,
1736
assert( tr_isSession( session ) );
1738
session->useLazyBitfield = enabled != 0;
1742
tr_sessionIsLazyBitfieldEnabled( const tr_session * session )
1744
assert( tr_isSession( session ) );
1746
return session->useLazyBitfield;
1753
struct port_forwarding_data
1756
struct tr_shared * shared;
1760
setPortForwardingEnabled( void * vdata )
1762
struct port_forwarding_data * data = vdata;
1763
tr_sharedTraversalEnable( data->shared, data->enabled );
1768
tr_sessionSetPortForwardingEnabled( tr_session * session, tr_bool enabled )
1770
struct port_forwarding_data * d;
1771
d = tr_new0( struct port_forwarding_data, 1 );
1772
d->shared = session->shared;
1773
d->enabled = enabled;
1774
tr_runInEventThread( session, setPortForwardingEnabled, d );
1778
tr_sessionIsPortForwardingEnabled( const tr_session * session )
1780
assert( tr_isSession( session ) );
1782
return tr_sharedTraversalIsEnabled( session->shared );
1790
tr_stringEndsWith( const char * str, const char * end )
1792
const size_t slen = strlen( str );
1793
const size_t elen = strlen( end );
1795
return slen >= elen && !memcmp( &str[slen - elen], end, elen );
1799
loadBlocklists( tr_session * session )
1806
tr_list * list = NULL;
1807
const tr_bool isEnabled = session->isBlocklistEnabled;
1809
/* walk through the directory and find blocklists */
1810
dirname = tr_buildPath( session->configDir, "blocklists", NULL );
1812
&sb ) && S_ISDIR( sb.st_mode )
1813
&& ( ( odir = opendir( dirname ) ) ) )
1816
for( d = readdir( odir ); d; d = readdir( odir ) )
1820
if( !d->d_name || d->d_name[0] == '.' ) /* skip dotfiles, ., and ..
1824
filename = tr_buildPath( dirname, d->d_name, NULL );
1826
if( tr_stringEndsWith( filename, ".bin" ) )
1828
/* if we don't already have this blocklist, add it */
1829
if( !tr_list_find( list, filename,
1830
(TrListCompareFunc)strcmp ) )
1832
tr_list_append( &list,
1833
_tr_blocklistNew( filename, isEnabled ) );
1839
/* strip out the file suffix, if there is one, and add ".bin"
1842
const char * dot = strrchr( d->d_name, '.' );
1843
const int len = dot ? dot - d->d_name
1844
: (int)strlen( d->d_name );
1845
char * tmp = tr_strdup_printf(
1846
"%s" TR_PATH_DELIMITER_STR "%*.*s.bin",
1847
dirname, len, len, d->d_name );
1848
b = _tr_blocklistNew( tmp, isEnabled );
1849
_tr_blocklistSetContent( b, filename );
1850
tr_list_append( &list, b );
1855
tr_free( filename );
1861
session->blocklists = list;
1864
tr_dbg( "Found %d blocklists in \"%s\"", binCount, dirname );
1866
tr_dbg( "Found %d new blocklists in \"%s\"", newCount, dirname );
1872
closeBlocklists( tr_session * session )
1874
tr_list_free( &session->blocklists,
1875
(TrListForeachFunc)_tr_blocklistFree );
1879
tr_sessionReloadBlocklists( tr_session * session )
1881
closeBlocklists( session );
1882
loadBlocklists( session );
1886
tr_blocklistGetRuleCount( const tr_session * session )
1891
assert( tr_isSession( session ) );
1893
for( l = session->blocklists; l; l = l->next )
1894
n += _tr_blocklistGetRuleCount( l->data );
1899
tr_blocklistIsEnabled( const tr_session * session )
1901
assert( tr_isSession( session ) );
1903
return session->isBlocklistEnabled;
1907
tr_blocklistSetEnabled( tr_session * session,
1912
assert( tr_isSession( session ) );
1914
session->isBlocklistEnabled = isEnabled != 0;
1916
for( l=session->blocklists; l!=NULL; l=l->next )
1917
_tr_blocklistSetEnabled( l->data, isEnabled );
1921
tr_blocklistExists( const tr_session * session )
1923
assert( tr_isSession( session ) );
1925
return session->blocklists != NULL;
1929
tr_blocklistSetContent( tr_session * session,
1930
const char * contentFilename )
1935
const char * defaultName = "level1.bin";
1936
tr_sessionLock( session );
1938
for( b = NULL, l = session->blocklists; !b && l; l = l->next )
1939
if( tr_stringEndsWith( _tr_blocklistGetFilename( l->data ),
1945
char * path = tr_buildPath( session->configDir, "blocklists", defaultName, NULL );
1946
b = _tr_blocklistNew( path, session->isBlocklistEnabled );
1947
tr_list_append( &session->blocklists, b );
1951
ruleCount = _tr_blocklistSetContent( b, contentFilename );
1952
tr_sessionUnlock( session );
1957
tr_sessionIsAddressBlocked( const tr_session * session,
1958
const tr_address * addr )
1962
assert( tr_isSession( session ) );
1964
for( l = session->blocklists; l; l = l->next )
1965
if( _tr_blocklistHasAddress( l->data, addr ) )
1975
metainfoLookupInit( tr_session * session )
1978
const char * dirname = tr_getTorrentDir( session );
1980
tr_ctor * ctor = NULL;
1984
assert( tr_isSession( session ) );
1986
/* walk through the directory and find the mappings */
1987
lookup = tr_new0( tr_benc, 1 );
1988
tr_bencInitDict( lookup, 0 );
1989
ctor = tr_ctorNew( session );
1990
tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
1991
if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && ( ( odir = opendir( dirname ) ) ) )
1994
while(( d = readdir( odir )))
1996
if( d->d_name && d->d_name[0] != '.' )
1999
char * path = tr_buildPath( dirname, d->d_name, NULL );
2000
tr_ctorSetMetainfoFromFile( ctor, path );
2001
if( !tr_torrentParse( ctor, &inf ) )
2004
tr_bencDictAddStr( lookup, inf.hashString, path );
2011
tr_ctorFree( ctor );
2013
session->metainfoLookup = lookup;
2014
tr_dbg( "Found %d torrents in \"%s\"", n, dirname );
2018
tr_sessionFindTorrentFile( const tr_session * session,
2019
const char * hashString )
2021
const char * filename = NULL;
2022
if( !session->metainfoLookup )
2023
metainfoLookupInit( (tr_session*)session );
2024
tr_bencDictFindStr( session->metainfoLookup, hashString, &filename );
2029
tr_sessionSetTorrentFile( tr_session * session,
2030
const char * hashString,
2031
const char * filename )
2033
/* since we walk session->configDir/torrents/ to build the lookup table,
2034
* and tr_sessionSetTorrentFile() is just to tell us there's a new file
2035
* in that same directory, we don't need to do anything here if the
2036
* lookup table hasn't been built yet */
2037
if( session->metainfoLookup )
2038
tr_bencDictAddStr( session->metainfoLookup, hashString, filename );
2042
tr_torrentNext( tr_session * session,
2047
assert( !session || tr_isSession( session ) );
2052
ret = session->torrentList;
2064
tr_sessionSetRPCEnabled( tr_session * session,
2067
assert( tr_isSession( session ) );
2069
tr_rpcSetEnabled( session->rpcServer, isEnabled );
2073
tr_sessionIsRPCEnabled( const tr_session * session )
2075
assert( tr_isSession( session ) );
2077
return tr_rpcIsEnabled( session->rpcServer );
2081
tr_sessionSetRPCPort( tr_session * session,
2084
assert( tr_isSession( session ) );
2086
tr_rpcSetPort( session->rpcServer, port );
2090
tr_sessionGetRPCPort( const tr_session * session )
2092
assert( tr_isSession( session ) );
2094
return tr_rpcGetPort( session->rpcServer );
2098
tr_sessionSetRPCCallback( tr_session * session,
2102
assert( tr_isSession( session ) );
2104
session->rpc_func = func;
2105
session->rpc_func_user_data = user_data;
2109
tr_sessionSetRPCWhitelist( tr_session * session,
2110
const char * whitelist )
2112
assert( tr_isSession( session ) );
2114
tr_rpcSetWhitelist( session->rpcServer, whitelist );
2118
tr_sessionGetRPCWhitelist( const tr_session * session )
2120
assert( tr_isSession( session ) );
2122
return tr_rpcGetWhitelist( session->rpcServer );
2126
tr_sessionSetRPCWhitelistEnabled( tr_session * session,
2129
assert( tr_isSession( session ) );
2131
tr_rpcSetWhitelistEnabled( session->rpcServer, isEnabled );
2135
tr_sessionGetRPCWhitelistEnabled( const tr_session * session )
2137
assert( tr_isSession( session ) );
2139
return tr_rpcGetWhitelistEnabled( session->rpcServer );
2144
tr_sessionSetRPCPassword( tr_session * session,
2145
const char * password )
2147
assert( tr_isSession( session ) );
2149
tr_rpcSetPassword( session->rpcServer, password );
2153
tr_sessionGetRPCPassword( const tr_session * session )
2155
assert( tr_isSession( session ) );
2157
return tr_rpcGetPassword( session->rpcServer );
2161
tr_sessionSetRPCUsername( tr_session * session,
2162
const char * username )
2164
assert( tr_isSession( session ) );
2166
tr_rpcSetUsername( session->rpcServer, username );
2170
tr_sessionGetRPCUsername( const tr_session * session )
2172
assert( tr_isSession( session ) );
2174
return tr_rpcGetUsername( session->rpcServer );
2178
tr_sessionSetRPCPasswordEnabled( tr_session * session,
2181
assert( tr_isSession( session ) );
2183
tr_rpcSetPasswordEnabled( session->rpcServer, isEnabled );
2187
tr_sessionIsRPCPasswordEnabled( const tr_session * session )
2189
assert( tr_isSession( session ) );
2191
return tr_rpcIsPasswordEnabled( session->rpcServer );
2195
tr_sessionGetRPCBindAddress( const tr_session * session )
2197
assert( tr_isSession( session ) );
2199
return tr_rpcGetBindAddress( session->rpcServer );
2207
tr_sessionIsProxyEnabled( const tr_session * session )
2209
assert( tr_isSession( session ) );
2211
return session->isProxyEnabled;
2215
tr_sessionSetProxyEnabled( tr_session * session,
2218
assert( tr_isSession( session ) );
2219
assert( tr_isBool( isEnabled ) );
2221
session->isProxyEnabled = isEnabled != 0;
2225
tr_sessionGetProxyType( const tr_session * session )
2227
assert( tr_isSession( session ) );
2229
return session->proxyType;
2233
tr_sessionSetProxyType( tr_session * session,
2234
tr_proxy_type type )
2236
assert( tr_isSession( session ) );
2238
session->proxyType = type;
2242
tr_sessionGetProxy( const tr_session * session )
2244
assert( tr_isSession( session ) );
2246
return session->proxy;
2250
tr_sessionGetProxyPort( const tr_session * session )
2252
assert( tr_isSession( session ) );
2254
return session->proxyPort;
2258
tr_sessionSetProxy( tr_session * session,
2259
const char * proxy )
2261
assert( tr_isSession( session ) );
2263
if( proxy != session->proxy )
2265
tr_free( session->proxy );
2266
session->proxy = tr_strdup( proxy );
2271
tr_sessionSetProxyPort( tr_session * session,
2274
assert( tr_isSession( session ) );
2276
session->proxyPort = port;
2280
tr_sessionIsProxyAuthEnabled( const tr_session * session )
2282
assert( tr_isSession( session ) );
2284
return session->isProxyAuthEnabled;
2288
tr_sessionSetProxyAuthEnabled( tr_session * session,
2291
assert( tr_isSession( session ) );
2292
assert( tr_isBool( isEnabled ) );
2294
session->isProxyAuthEnabled = isEnabled != 0;
2298
tr_sessionGetProxyUsername( const tr_session * session )
2300
assert( tr_isSession( session ) );
2302
return session->proxyUsername;
2306
tr_sessionSetProxyUsername( tr_session * session,
2307
const char * username )
2309
assert( tr_isSession( session ) );
2311
if( username != session->proxyUsername )
2313
tr_free( session->proxyUsername );
2314
session->proxyUsername = tr_strdup( username );
2319
tr_sessionGetProxyPassword( const tr_session * session )
2321
assert( tr_isSession( session ) );
2323
return session->proxyPassword;
2327
tr_sessionSetProxyPassword( tr_session * session,
2328
const char * password )
2330
assert( tr_isSession( session ) );
2332
if( password != session->proxyPassword )
2334
tr_free( session->proxyPassword );
2335
session->proxyPassword = tr_strdup( password );
2340
tr_sessionGetActiveTorrentCount( tr_session * session )
2343
tr_torrent * tor = NULL;
2345
assert( tr_isSession( session ) );
2347
while(( tor = tr_torrentNext( session, tor )))
2348
if( tr_torrentGetActivity( tor ) != TR_STATUS_STOPPED )