~ubuntu-branches/ubuntu/lucid/transmission/lucid-proposed

« back to all changes in this revision

Viewing changes to libtransmission/session.c

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Klimonda, Krzysztof Klimonda, Chris Coulson
  • Date: 2010-02-16 17:50:22 UTC
  • mfrom: (1.1.32 upstream)
  • Revision ID: james.westby@ubuntu.com-20100216175022-91sugt46rcjx5ug7
Tags: 1.90-0ubuntu1
[ Krzysztof Klimonda ]
* New upstream release (LP: #522726)
* Fixes bugs:
  - Support Application Indicators (LP: #497882)
  - Better file preallocation with fallocate() (LP: #445592)
  - Speed limit of 0 is not honored (LP: #473652)
  - incorrectly sent information (LP: #521140)
* Refreshed 99_autoreconf.patch 
* debian/control:
  - Build-Depend on libappindicator-dev

[ Chris Coulson ]
* Add ${misc:Depends} in debian/control to make Lintian happy
* Update Standards-Version to 3.8.4. No other changes necessary

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * This exemption does not extend to derived works not owned by
8
8
 * the Transmission project.
9
9
 *
10
 
 * $Id: session.c 9965 2010-01-19 19:37:00Z charles $
 
10
 * $Id: session.c 10217 2010-02-16 00:00:22Z charles $
11
11
 */
12
12
 
13
13
#include <assert.h>
 
14
#include <errno.h> /* ENOENT */
14
15
#include <stdlib.h>
15
16
#include <string.h> /* memcpy */
16
17
 
225
226
****
226
227
***/
227
228
 
228
 
static tr_bool
229
 
isAltTime( const tr_session * s )
230
 
{
231
 
    int minutes, day;
232
 
    tr_bool withinTime;
233
 
    struct tm tm;
234
 
    const time_t now = time( NULL );
235
 
    const int begin = s->altSpeedTimeBegin;
236
 
    const int end = s->altSpeedTimeEnd;
237
 
    const tr_bool toNextDay = begin > end;
238
 
 
239
 
    tr_localtime_r( &now, &tm );
240
 
    minutes = tm.tm_hour*60 + tm.tm_min;
241
 
    day = tm.tm_wday;
242
 
 
243
 
    if( !toNextDay )
244
 
        withinTime = ( begin <= minutes ) && ( minutes < end );
245
 
    else /* goes past midnight */
246
 
        withinTime = ( begin <= minutes ) || ( minutes < end );
247
 
 
248
 
    if( !withinTime )
249
 
        return FALSE;
250
 
 
251
 
    if( toNextDay && (minutes < end) )
252
 
    {
253
 
        --day;
254
 
        if( day == -1 )
255
 
            day = 6;
256
 
    }
257
 
 
258
 
    return ((1<<day) & s->altSpeedTimeDay) != 0;
259
 
}
260
 
 
261
 
/***
262
 
****
263
 
***/
264
 
 
265
229
#ifdef TR_EMBEDDED
266
230
 #define TR_DEFAULT_ENCRYPTION   TR_CLEAR_PREFERRED
267
231
#else
296
260
    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_SOCKET_TOS,          atoi( TR_DEFAULT_PEER_SOCKET_TOS_STR ) );
297
261
    tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED,              TRUE );
298
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 );
 
265
#else
299
266
    tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION,            TR_PREALLOCATE_SPARSE );
 
267
#endif
300
268
    tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY,                    "" );
301
269
    tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_AUTH_ENABLED,       FALSE );
302
270
    tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_ENABLED,            FALSE );
395
363
tr_bool
396
364
tr_sessionLoadSettings( tr_benc * d, const char * configDir, const char * appName )
397
365
{
 
366
    int err = 0;
398
367
    char * filename;
399
368
    tr_benc fileSettings;
400
369
    tr_benc sessionDefaults;
416
385
 
417
386
    /* file settings override the defaults */
418
387
    filename = tr_buildPath( configDir, "settings.json", NULL );
419
 
    if( !tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename ) ) {
 
388
    err = tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename );
 
389
    if( !err ) {
420
390
        tr_bencMergeDicts( d, &fileSettings );
421
391
        tr_bencFree( &fileSettings );
422
 
        success = TRUE;
423
392
    }
424
393
 
425
394
    /* cleanup */
426
395
    tr_bencFree( &sessionDefaults );
427
396
    tr_free( filename );
 
397
    success = (err==0) || (err==ENOENT);
428
398
    return success;
429
399
}
430
400
 
443
413
    /* the existing file settings are the fallback values */
444
414
    {
445
415
        tr_benc fileSettings;
446
 
        if( !tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename ) )
 
416
        const int err = tr_bencLoadFile( &fileSettings, TR_FMT_JSON, filename );
 
417
        if( !err )
447
418
        {
448
419
            tr_bencMergeDicts( &settings, &fileSettings );
449
420
            tr_bencFree( &fileSettings );
464
435
 
465
436
    /* save the result */
466
437
    tr_bencToFile( &settings, TR_FMT_JSON, filename );
467
 
    tr_inf( "Saved \"%s\"", filename );
468
438
 
469
439
    /* cleanup */
470
440
    tr_free( filename );
499
469
***/
500
470
 
501
471
static void tr_sessionInitImpl( void * );
502
 
static void onAltTimer( int, short, void* );
503
 
static void setAltTimer( tr_session * session );
504
472
 
505
473
struct init_data
506
474
{
555
523
    return session;
556
524
}
557
525
 
558
 
static void useAltSpeed( tr_session * session, tr_bool enabled, tr_bool byUser );
559
 
static void useAltSpeedTime( tr_session * session, tr_bool enabled, tr_bool byUser );
 
526
static void turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser );
560
527
 
561
528
static void
562
529
onNowTimer( int foo UNUSED, short bar UNUSED, void * vsession )
576
543
    if( usec > max ) usec = max;
577
544
    if( usec < min ) usec = min;
578
545
    tr_timerAdd( session->nowTimer, 0, usec );
 
546
    /* fprintf( stderr, "time %zu sec, %zu microsec\n", (size_t)tr_time(), (size_t)tv.tv_usec ); */
579
547
 
580
 
    /* update libtransmission's epoch time */
 
548
    /* tr_session things to do once per second */
581
549
    tr_timeUpdate( tv.tv_sec );
582
 
    /* fprintf( stderr, "time %zu sec, %zu microsec\n", (size_t)tr_time(), (size_t)tv.tv_usec ); */
 
550
    turtleCheckClock( session, &session->turtle, FALSE );
583
551
}
584
552
 
585
553
static void loadBlocklists( tr_session * session );
632
600
 
633
601
    assert( tr_isSession( session ) );
634
602
 
635
 
    session->altTimer = tr_new0( struct event, 1 );
636
 
    evtimer_set( session->altTimer, onAltTimer, session );
637
 
    setAltTimer( session );
638
 
 
639
603
    session->saveTimer = tr_new0( struct event, 1 );
640
604
    evtimer_set( session->saveTimer, onSaveTimer, session );
641
605
    tr_timerAdd( session->saveTimer, SAVE_INTERVAL_SECS, 0 );
662
626
    data->done = TRUE;
663
627
}
664
628
 
 
629
static void turtleBootstrap( tr_session *, struct tr_turtle_info * );
 
630
 
665
631
static void
666
632
sessionSetImpl( void * vdata )
667
633
{
673
639
    struct init_data * data = vdata;
674
640
    tr_session * session = data->session;
675
641
    tr_benc * settings = data->clientSettings;
 
642
    struct tr_turtle_info * turtle = &session->turtle;
676
643
 
677
644
    assert( tr_isSession( session ) );
678
645
    assert( tr_bencIsDict( settings ) );
795
762
        tr_sessionSetRatioLimited( session, boolVal );
796
763
 
797
764
    /**
798
 
    ***  Alternate speed limits
 
765
    ***  Turtle Mode
799
766
    **/
800
767
 
 
768
    /* update the turtle mode's fields */
801
769
    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_UP, &i ) )
802
 
        tr_sessionSetAltSpeed( session, TR_UP, i );
 
770
        turtle->speedLimit[TR_UP] = i;
803
771
    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_DOWN, &i ) )
804
 
        tr_sessionSetAltSpeed( session, TR_DOWN, i );
 
772
        turtle->speedLimit[TR_DOWN] = i;
805
773
    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, &i ) )
806
 
        tr_sessionSetAltSpeedBegin( session, i );
 
774
        turtle->beginMinute = i;
807
775
    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_END, &i ) )
808
 
        tr_sessionSetAltSpeedEnd( session, i );
 
776
        turtle->endMinute = i;
809
777
    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, &i ) )
810
 
        tr_sessionSetAltSpeedDay( session, i );
 
778
        turtle->days = i;
811
779
    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, &boolVal ) )
812
 
        useAltSpeedTime( session, boolVal, FALSE );
813
 
    if( boolVal )
814
 
        useAltSpeed( session, isAltTime( session ), FALSE );
815
 
    else if( tr_bencDictFindBool( settings, TR_PREFS_KEY_ALT_SPEED_ENABLED, &boolVal ) )
816
 
        useAltSpeed( session, boolVal, FALSE );
 
780
        turtle->isClockEnabled = boolVal;
 
781
    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_ALT_SPEED_ENABLED, &boolVal ) )
 
782
        turtle->isEnabled = boolVal;
 
783
    turtleBootstrap( session, turtle );
817
784
 
818
785
    data->done = TRUE;
819
786
}
1070
1037
}
1071
1038
 
1072
1039
/***
 
1040
****
1073
1041
****  SPEED LIMITS
 
1042
****
1074
1043
***/
1075
1044
 
1076
1045
tr_bool
1104
1073
}
1105
1074
 
1106
1075
static void
 
1076
turtleFindNextChange( struct tr_turtle_info * t )
 
1077
{
 
1078
    int day;
 
1079
    struct tm tm;
 
1080
    time_t today_began_at;
 
1081
    time_t next_begin;
 
1082
    time_t next_end;
 
1083
    const time_t now = tr_time( );
 
1084
    const int SECONDS_PER_DAY = 86400;
 
1085
 
 
1086
    tr_localtime_r( &now, &tm );
 
1087
    tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
 
1088
    today_began_at = mktime( &tm );
 
1089
 
 
1090
    next_begin = today_began_at + ( t->beginMinute * 60 );
 
1091
    if( next_begin <= now )
 
1092
        next_begin += SECONDS_PER_DAY;
 
1093
 
 
1094
    next_end = today_began_at + ( t->endMinute * 60 );
 
1095
    if( next_end <= now )
 
1096
        next_end += SECONDS_PER_DAY;
 
1097
 
 
1098
    if( next_begin < next_end ) {
 
1099
        t->_nextChangeAt = next_begin;
 
1100
        t->_nextChangeValue = TRUE;
 
1101
    } else {
 
1102
        t->_nextChangeAt = next_end;
 
1103
        t->_nextChangeValue = FALSE;
 
1104
    }
 
1105
 
 
1106
    /* if the next change is today, look for today in t->days.
 
1107
       if the next change is tomorrow to turn limits OFF, look for today in t->days.
 
1108
       if the next change is tomorrow to turn limits ON, look for tomorrow in t->days. */
 
1109
    if( t->_nextChangeValue && (( t->_nextChangeAt >= today_began_at + SECONDS_PER_DAY )))
 
1110
        day = ( tm.tm_wday + 1 ) % 7;
 
1111
    else
 
1112
        day = tm.tm_wday;
 
1113
    t->_nextChangeAllowed = ( t->days & (1<<day) ) != 0;
 
1114
 
 
1115
    if( t->isClockEnabled && t->_nextChangeAllowed ) {
 
1116
        char buf[128];
 
1117
        tr_localtime_r( &t->_nextChangeAt, &tm );
 
1118
        strftime( buf, sizeof( buf ), "%a %b %d %T %Y", &tm );
 
1119
        tr_inf( "Turtle clock updated: at %s we'll turn limits %s", buf, (t->_nextChangeValue?"on":"off") );
 
1120
    }
 
1121
}
 
1122
 
 
1123
static void
1107
1124
altSpeedToggled( void * vsession )
1108
1125
{
1109
1126
    tr_session * session = vsession;
 
1127
    struct tr_turtle_info * t = &session->turtle;
1110
1128
 
1111
1129
    assert( tr_isSession( session ) );
1112
1130
 
1113
1131
    updateBandwidth( session, TR_UP );
1114
1132
    updateBandwidth( session, TR_DOWN );
1115
 
 
1116
 
    if( session->altCallback != NULL )
1117
 
        (*session->altCallback)( session, session->altSpeedEnabled, session->altSpeedChangedByUser, session->altCallbackUserData );
1118
 
}
1119
 
 
1120
 
/* tell the alt speed limit timer to fire again at the top of the minute */
1121
 
static void
1122
 
setAltTimer( tr_session * session )
1123
 
{
1124
 
    const time_t now = time( NULL );
1125
 
    struct tm tm;
1126
 
 
1127
 
    assert( tr_isSession( session ) );
1128
 
    assert( session->altTimer != NULL );
1129
 
 
1130
 
    tr_localtime_r( &now, &tm );
1131
 
    tr_timerAdd( session->altTimer, 60-tm.tm_sec, 0 );
1132
 
}
1133
 
 
1134
 
/* this is called once a minute to:
1135
 
 * (1) update session->isAltTime
1136
 
 * (2) alter the speed limits when the alt limits go on and off */
1137
 
static void
1138
 
onAltTimer( int foo UNUSED, short bar UNUSED, void * vsession )
1139
 
{
1140
 
    tr_session * session = vsession;
1141
 
 
1142
 
    assert( tr_isSession( session ) );
1143
 
 
1144
 
    if( session->altSpeedTimeEnabled )
1145
 
    {
1146
 
        const time_t now = time( NULL );
1147
 
        struct tm tm;
1148
 
        int currentMinute, day;
1149
 
        tr_bool isBeginTime, isEndTime, isDay;
1150
 
        tr_localtime_r( &now, &tm );
1151
 
        currentMinute = tm.tm_hour*60 + tm.tm_min;
1152
 
        day = tm.tm_wday;
1153
 
 
1154
 
        isBeginTime = currentMinute == session->altSpeedTimeBegin;
1155
 
        isEndTime = currentMinute == session->altSpeedTimeEnd;
1156
 
        if( isBeginTime || isEndTime )
 
1133
    turtleFindNextChange( t );
 
1134
 
 
1135
    if( t->callback != NULL )
 
1136
        (*t->callback)( session, t->isEnabled, t->changedByUser, t->callbackUserData );
 
1137
}
 
1138
 
 
1139
static void
 
1140
useAltSpeed( tr_session * s, struct tr_turtle_info * t, tr_bool enabled, tr_bool byUser )
 
1141
{
 
1142
    assert( tr_isSession( s ) );
 
1143
    assert( t != NULL );
 
1144
    assert( tr_isBool( enabled ) );
 
1145
    assert( tr_isBool( byUser ) );
 
1146
 
 
1147
    if( t->isEnabled != enabled )
 
1148
    {
 
1149
        t->isEnabled = enabled;
 
1150
        t->changedByUser = byUser;
 
1151
        tr_runInEventThread( s, altSpeedToggled, s );
 
1152
    }
 
1153
}
 
1154
 
 
1155
static void
 
1156
turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
 
1157
{
 
1158
    const time_t now = tr_time( );
 
1159
    const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( ));
 
1160
 
 
1161
    t->testedAt = now;
 
1162
 
 
1163
    if( hit )
 
1164
    {
 
1165
        const tr_bool enabled = t->_nextChangeValue;
 
1166
 
 
1167
        if( t->isClockEnabled && t->_nextChangeAllowed )
1157
1168
        {
1158
 
            /* if looking at the end date, look at the next day if end time is before begin time */
1159
 
            if( isEndTime && !isBeginTime && session->altSpeedTimeEnd < session->altSpeedTimeBegin )
1160
 
            {
1161
 
                --day;
1162
 
                if( day == -1 )
1163
 
                    day = 6;
1164
 
            }
1165
 
 
1166
 
            isDay = ((1<<day) & session->altSpeedTimeDay) != 0;
1167
 
 
1168
 
            if( isDay )
1169
 
                useAltSpeed( session, isBeginTime, FALSE );
 
1169
            tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") );
 
1170
            useAltSpeed( session, t, enabled, byUser );
1170
1171
        }
 
1172
 
 
1173
        turtleFindNextChange( t );
1171
1174
    }
1172
 
 
1173
 
    setAltTimer( session );
 
1175
}
 
1176
 
 
1177
/* Called after the turtle's fields are loaded from an outside source.
 
1178
 * It initializes the implementation fields 
 
1179
 * and turns on turtle mode if the clock settings say to. */
 
1180
static void
 
1181
turtleBootstrap( tr_session * session, struct tr_turtle_info * turtle )
 
1182
{
 
1183
    tr_bool isEnabled;
 
1184
 
 
1185
    turtleFindNextChange( turtle );
 
1186
 
 
1187
    if( turtle->isClockEnabled )
 
1188
        isEnabled = !turtle->_nextChangeValue;
 
1189
    else
 
1190
        isEnabled = turtle->isEnabled;
 
1191
 
 
1192
    useAltSpeed( session, turtle, isEnabled, FALSE );
1174
1193
}
1175
1194
 
1176
1195
/***
1230
1249
    assert( tr_isDirection( d ) );
1231
1250
    assert( KB_s >= 0 );
1232
1251
 
1233
 
    s->altSpeed[d] = KB_s;
 
1252
    s->turtle.speedLimit[d] = KB_s;
1234
1253
 
1235
1254
    updateBandwidth( s, d );
1236
1255
}
1241
1260
    assert( tr_isSession( s ) );
1242
1261
    assert( tr_isDirection( d ) );
1243
1262
 
1244
 
    return s->altSpeed[d];
 
1263
    return s->turtle.speedLimit[d];
1245
1264
}
1246
1265
 
1247
 
void
1248
 
useAltSpeedTime( tr_session * session, tr_bool enabled, tr_bool byUser )
 
1266
static void
 
1267
userPokedTheClock( tr_session * s, struct tr_turtle_info * t )
1249
1268
{
1250
 
    assert( tr_isSession( session ) );
1251
 
    assert( tr_isBool( enabled ) );
1252
 
    assert( tr_isBool( byUser ) );
1253
 
 
1254
 
    if( session->altSpeedTimeEnabled != enabled )
1255
 
    {
1256
 
        const tr_bool isAlt = isAltTime( session );
1257
 
 
1258
 
        session->altSpeedTimeEnabled = enabled;
1259
 
 
1260
 
        if( enabled && session->altSpeedEnabled != isAlt )
1261
 
            useAltSpeed( session, isAlt, byUser );
1262
 
    }
 
1269
    tr_dbg( "Refreshing the turtle mode clock due to user changes" );
 
1270
 
 
1271
    t->testedAt = 0;
 
1272
    turtleFindNextChange( t );
 
1273
 
 
1274
    if( t->isClockEnabled && t->_nextChangeAllowed )
 
1275
        useAltSpeed( s, t, !t->_nextChangeValue, TRUE );
1263
1276
}
 
1277
 
1264
1278
void
1265
1279
tr_sessionUseAltSpeedTime( tr_session * s, tr_bool b )
1266
1280
{
1267
 
    useAltSpeedTime( s, b, TRUE );
 
1281
    struct tr_turtle_info * t = &s->turtle;
 
1282
 
 
1283
    assert( tr_isSession( s ) );
 
1284
    assert( tr_isBool ( b ) );
 
1285
 
 
1286
    if( t->isClockEnabled != b ) {
 
1287
        t->isClockEnabled = b;
 
1288
        userPokedTheClock( s, t );
 
1289
    }
1268
1290
}
1269
1291
 
1270
1292
tr_bool
1272
1294
{
1273
1295
    assert( tr_isSession( s ) );
1274
1296
 
1275
 
    return s->altSpeedTimeEnabled;
 
1297
    return s->turtle.isClockEnabled;
1276
1298
}
1277
1299
 
1278
1300
void
1279
 
tr_sessionSetAltSpeedBegin( tr_session * s, int minutes )
 
1301
tr_sessionSetAltSpeedBegin( tr_session * s, int minute )
1280
1302
{
1281
1303
    assert( tr_isSession( s ) );
1282
 
    assert( 0<=minutes && minutes<(60*24) );
1283
 
 
1284
 
    if( s->altSpeedTimeBegin != minutes )
1285
 
    {
1286
 
        s->altSpeedTimeBegin = minutes;
1287
 
 
1288
 
        if( tr_sessionUsesAltSpeedTime( s ) )
1289
 
            useAltSpeed( s, isAltTime( s ), TRUE );
 
1304
    assert( 0<=minute && minute<(60*24) );
 
1305
 
 
1306
    if( s->turtle.beginMinute != minute ) {
 
1307
        s->turtle.beginMinute = minute;
 
1308
        userPokedTheClock( s, &s->turtle );
1290
1309
    }
1291
1310
}
1292
1311
 
1295
1314
{
1296
1315
    assert( tr_isSession( s ) );
1297
1316
 
1298
 
    return s->altSpeedTimeBegin;
 
1317
    return s->turtle.beginMinute;
1299
1318
}
1300
1319
 
1301
1320
void
1302
 
tr_sessionSetAltSpeedEnd( tr_session * s, int minutes )
 
1321
tr_sessionSetAltSpeedEnd( tr_session * s, int minute )
1303
1322
{
1304
1323
    assert( tr_isSession( s ) );
1305
 
    assert( 0<=minutes && minutes<(60*24) );
1306
 
 
1307
 
    if( s->altSpeedTimeEnd != minutes )
1308
 
    {
1309
 
        s->altSpeedTimeEnd = minutes;
1310
 
 
1311
 
        if( tr_sessionUsesAltSpeedTime( s ) )
1312
 
            useAltSpeed( s, isAltTime( s ), TRUE );
 
1324
    assert( 0<=minute && minute<(60*24) );
 
1325
 
 
1326
    if( s->turtle.endMinute != minute ) {
 
1327
        s->turtle.endMinute = minute;
 
1328
        userPokedTheClock( s, &s->turtle );
1313
1329
    }
1314
1330
}
1315
1331
 
1318
1334
{
1319
1335
    assert( tr_isSession( s ) );
1320
1336
 
1321
 
    return s->altSpeedTimeEnd;
 
1337
    return s->turtle.endMinute;
1322
1338
}
1323
1339
 
1324
1340
void
1325
 
tr_sessionSetAltSpeedDay( tr_session * s, tr_sched_day day )
 
1341
tr_sessionSetAltSpeedDay( tr_session * s, tr_sched_day days )
1326
1342
{
1327
1343
    assert( tr_isSession( s ) );
1328
1344
 
1329
 
    if( s->altSpeedTimeDay != day )
1330
 
    {
1331
 
        s->altSpeedTimeDay = day;
1332
 
 
1333
 
        if( tr_sessionUsesAltSpeedTime( s ) )
1334
 
            useAltSpeed( s, isAltTime( s ), TRUE );
 
1345
    if( s->turtle.days != days ) {
 
1346
        s->turtle.days = days;
 
1347
        userPokedTheClock( s, &s->turtle );
1335
1348
    }
1336
1349
}
1337
1350
 
1340
1353
{
1341
1354
    assert( tr_isSession( s ) );
1342
1355
 
1343
 
    return s->altSpeedTimeDay;
1344
 
}
1345
 
 
1346
 
void
1347
 
useAltSpeed( tr_session * s, tr_bool enabled, tr_bool byUser )
1348
 
{
1349
 
    assert( tr_isSession( s ) );
1350
 
    assert( tr_isBool( enabled ) );
1351
 
    assert( tr_isBool( byUser ) );
1352
 
 
1353
 
    if( s->altSpeedEnabled != enabled)
1354
 
    {
1355
 
        s->altSpeedEnabled = enabled;
1356
 
        s->altSpeedChangedByUser = byUser;
1357
 
 
1358
 
        tr_runInEventThread( s, altSpeedToggled, s );
1359
 
    }
1360
 
}
 
1356
    return s->turtle.days;
 
1357
}
 
1358
 
1361
1359
void
1362
1360
tr_sessionUseAltSpeed( tr_session * session, tr_bool enabled )
1363
1361
{
1364
 
    useAltSpeed( session, enabled, TRUE );
 
1362
    useAltSpeed( session, &session->turtle, enabled, TRUE );
1365
1363
}
1366
1364
 
1367
1365
tr_bool
1369
1367
{
1370
1368
    assert( tr_isSession( s ) );
1371
1369
 
1372
 
    return s->altSpeedEnabled;
 
1370
    return s->turtle.isEnabled;
1373
1371
}
1374
1372
 
1375
1373
void
1379
1377
{
1380
1378
    assert( tr_isSession( session ) );
1381
1379
 
1382
 
    session->altCallback = func;
1383
 
    session->altCallbackUserData = userData;
 
1380
    session->turtle.callback = func;
 
1381
    session->turtle.callbackUserData = userData;
1384
1382
}
1385
1383
 
1386
1384
void
1486
1484
    tr_free( session->nowTimer );
1487
1485
    session->nowTimer = NULL;
1488
1486
 
1489
 
    evtimer_del( session->altTimer );
1490
 
    tr_free( session->altTimer );
1491
 
    session->altTimer = NULL;
1492
 
 
1493
1487
    tr_verifyClose( session );
1494
1488
    tr_sharedClose( session );
1495
1489
    tr_rpcClose( &session->rpcServer );
1520
1514
}
1521
1515
 
1522
1516
static int
1523
 
deadlineReached( const uint64_t deadline )
 
1517
deadlineReached( const time_t deadline )
1524
1518
{
1525
 
    return tr_date( ) >= deadline;
 
1519
    return time( NULL ) >= deadline;
1526
1520
}
1527
1521
 
1528
1522
#define SHUTDOWN_MAX_SECONDS 20
1530
1524
void
1531
1525
tr_sessionClose( tr_session * session )
1532
1526
{
1533
 
    const int      maxwait_msec = SHUTDOWN_MAX_SECONDS * 1000;
1534
 
    const uint64_t deadline = tr_date( ) + maxwait_msec;
 
1527
    const time_t deadline = time( NULL ) + SHUTDOWN_MAX_SECONDS;
1535
1528
 
1536
1529
    assert( tr_isSession( session ) );
1537
1530
 
1563
1556
    {
1564
1557
        static tr_bool forced = FALSE;
1565
1558
        dbgmsg( "waiting for libtransmission thread to finish" );
1566
 
        tr_wait_msec( 100 );
 
1559
        tr_wait_msec( 500 );
1567
1560
        if( deadlineReached( deadline ) && !forced )
1568
1561
        {
1569
1562
            event_loopbreak( );
1570
1563
            forced = TRUE;
 
1564
 
 
1565
            if( time( NULL ) >= deadline + 3 )
 
1566
                break;
1571
1567
        }
1572
1568
    }
1573
1569
 
1731
1727
****
1732
1728
***/
1733
1729
 
 
1730
struct port_forwarding_data
 
1731
{
 
1732
    tr_bool enabled;
 
1733
    struct tr_shared * shared;
 
1734
};
 
1735
 
 
1736
static void
 
1737
setPortForwardingEnabled( void * vdata )
 
1738
{
 
1739
    struct port_forwarding_data * data = vdata;
 
1740
    tr_sharedTraversalEnable( data->shared, data->enabled );
 
1741
    tr_free( data );
 
1742
}
 
1743
 
1734
1744
void
1735
 
tr_sessionSetPortForwardingEnabled( tr_session  * session,
1736
 
                                    tr_bool       enabled )
 
1745
tr_sessionSetPortForwardingEnabled( tr_session  * session, tr_bool enabled )
1737
1746
{
1738
 
    assert( tr_isSession( session ) );
1739
 
 
1740
 
    tr_sessionLock( session );
1741
 
    tr_sharedTraversalEnable( session->shared, enabled );
1742
 
    tr_sessionUnlock( session );
 
1747
    struct port_forwarding_data * d;
 
1748
    d = tr_new0( struct port_forwarding_data, 1 );
 
1749
    d->shared = session->shared;
 
1750
    d->enabled = enabled;
 
1751
    tr_runInEventThread( session, setPortForwardingEnabled, d );
1743
1752
}
1744
1753
 
1745
1754
tr_bool
1897
1906
tr_blocklistSetContent( tr_session * session,
1898
1907
                        const char * contentFilename )
1899
1908
{
1900
 
    tr_list *      l;
 
1909
    tr_list * l;
 
1910
    int ruleCount;
1901
1911
    tr_blocklist * b;
1902
 
    const char *   defaultName = "level1.bin";
1903
 
 
1904
 
    assert( tr_isSession( session ) );
 
1912
    const char * defaultName = "level1.bin";
 
1913
    tr_sessionLock( session );
1905
1914
 
1906
1915
    for( b = NULL, l = session->blocklists; !b && l; l = l->next )
1907
1916
        if( tr_stringEndsWith( _tr_blocklistGetFilename( l->data ),
1916
1925
        tr_free( path );
1917
1926
    }
1918
1927
 
1919
 
    return _tr_blocklistSetContent( b, contentFilename );
 
1928
    ruleCount = _tr_blocklistSetContent( b, contentFilename );
 
1929
    tr_sessionUnlock( session );
 
1930
    return ruleCount;
1920
1931
}
1921
1932
 
1922
1933
tr_bool