~ubuntu-branches/ubuntu/jaunty/transmission/jaunty-updates

« back to all changes in this revision

Viewing changes to libtransmission/torrent.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2008-11-28 15:33:48 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20081128153348-it70trfnxiroblmc
Tags: 1.40-0ubuntu1
* New upstream release (LP: #302672)
  - Tracker communication uses fewer resources
  - More accurate bandwidth limits
  - Reduce disk fragmentation by preallocating files (LP: #287726)
  - Stability, security and performance improvements to the RPC /
    Web UI server (closes LP: #290423)
  - Support compression when serving Web UI and RPC responses
  - Simplify the RPC whitelist
  - Fix bug that prevented handshakes with encrypted BitComet peers
  - Fix 1.3x bug that could re-download some data unnecessarily
    (LP: #295040)
  - Option to automatically update the blocklist weekly
  - Added off-hour bandwidth scheduling
  - Simplify file/priority selection in the details dialog
  - Fix a couple of crashes
  - New / updated translations
  - Don't inhibit hibernation by default (LP: #292929)
  - Use "close" animation when sending to notification area (LP: #130811)
  - Fix resize problems (LP: #269872)
  - Support "--version" option when launching from command line
    (LP: #292011)
  - Correctly parse announce URLs that have leading or trailing
    spaces (LP: #262411)
  - Display an error when "Open Torrent" fails (LP: #281463)
* Dropped 10_fix_crasher_from_upstream.dpatch: Fix is in this
  upstream release.
* debian/control: Don't just build-depend on libcurl-dev, which is
  a virtual package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: torrent.c 6469 2008-08-10 15:15:51Z charles $
 
2
 * $Id: torrent.c 7069 2008-11-08 02:49:04Z charles $
3
3
 *
4
4
 * Copyright (c) 2005-2008 Transmission authors and contributors
5
5
 *
46
46
#include "utils.h"
47
47
#include "verify.h"
48
48
 
49
 
#define MAX_BLOCK_SIZE (1024*16)
 
49
#define MAX_BLOCK_SIZE ( 1024 * 16 )
50
50
 
51
51
/***
52
52
****
59
59
}
60
60
 
61
61
tr_torrent*
62
 
tr_torrentFindFromId( tr_handle * handle, int id )
 
62
tr_torrentFindFromId( tr_handle * handle,
 
63
                      int         id )
63
64
{
64
65
    tr_torrent * tor = NULL;
65
66
 
66
 
    while(( tor = tr_torrentNext( handle, tor )))
 
67
    while( ( tor = tr_torrentNext( handle, tor ) ) )
67
68
        if( tor->uniqueId == id )
68
69
            return tor;
69
70
 
71
72
}
72
73
 
73
74
tr_torrent*
74
 
tr_torrentFindFromHashString( tr_handle * handle, const char * str )
 
75
tr_torrentFindFromHashString( tr_handle *  handle,
 
76
                              const char * str )
75
77
{
76
78
    tr_torrent * tor = NULL;
77
79
 
78
 
    while(( tor = tr_torrentNext( handle, tor )))
 
80
    while( ( tor = tr_torrentNext( handle, tor ) ) )
79
81
        if( !strcmp( str, tor->info.hashString ) )
80
82
            return tor;
81
83
 
84
86
 
85
87
int
86
88
tr_torrentExists( const tr_handle * handle,
87
 
                  const uint8_t   * torrentHash )
 
89
                  const uint8_t *   torrentHash )
88
90
{
89
 
    return tr_torrentFindFromHash( (tr_handle*)handle, torrentHash ) != NULL;
 
91
    return tr_torrentFindFromHash( (tr_handle*)handle,
 
92
                                  torrentHash ) != NULL;
90
93
}
91
94
 
92
95
tr_torrent*
93
 
tr_torrentFindFromHash( tr_handle      * handle,
94
 
                        const uint8_t  * torrentHash )
 
96
tr_torrentFindFromHash( tr_handle *     handle,
 
97
                        const uint8_t * torrentHash )
95
98
{
96
99
    tr_torrent * tor = NULL;
97
100
 
98
 
    while(( tor = tr_torrentNext( handle, tor )))
99
 
        if( !memcmp( tor->info.hash, torrentHash, SHA_DIGEST_LENGTH ) )
100
 
            return tor;
 
101
    while( ( tor = tr_torrentNext( handle, tor ) ) )
 
102
        if( *tor->info.hash == *torrentHash )
 
103
            if( !memcmp( tor->info.hash, torrentHash, SHA_DIGEST_LENGTH ) )
 
104
                return tor;
101
105
 
102
106
    return NULL;
103
107
}
104
108
 
105
109
tr_torrent*
106
 
tr_torrentFindFromObfuscatedHash( tr_handle      * handle,
107
 
                                  const uint8_t  * obfuscatedTorrentHash )
 
110
tr_torrentFindFromObfuscatedHash( tr_handle *     handle,
 
111
                                  const uint8_t * obfuscatedTorrentHash )
108
112
{
109
113
    tr_torrent * tor = NULL;
110
114
 
111
 
    while(( tor = tr_torrentNext( handle, tor )))
112
 
        if( !memcmp( tor->obfuscatedHash, obfuscatedTorrentHash, SHA_DIGEST_LENGTH ) )
 
115
    while( ( tor = tr_torrentNext( handle, tor ) ) )
 
116
        if( !memcmp( tor->obfuscatedHash, obfuscatedTorrentHash,
 
117
                     SHA_DIGEST_LENGTH ) )
113
118
            return tor;
114
119
 
115
120
    return NULL;
122
127
void
123
128
tr_torrentLock( const tr_torrent * tor )
124
129
{
125
 
    tr_globalLock( tor->handle );
 
130
    tr_globalLock( tor->session );
126
131
}
127
132
 
128
133
void
129
134
tr_torrentUnlock( const tr_torrent * tor )
130
135
{
131
 
    tr_globalUnlock( tor->handle );
 
136
    tr_globalUnlock( tor->session );
132
137
}
133
138
 
134
139
/***
136
141
***/
137
142
 
138
143
void
139
 
tr_torrentSetSpeedMode( tr_torrent   * tor,
140
 
                        int            up_or_down,
141
 
                        tr_speedlimit  mode )
 
144
tr_torrentSetSpeedMode( tr_torrent *  tor,
 
145
                        tr_direction  direction,
 
146
                        tr_speedlimit mode )
142
147
{
143
 
    tr_speedlimit * limit = up_or_down==TR_UP
144
 
        ? &tor->uploadLimitMode
145
 
        : &tor->downloadLimitMode;
 
148
    tr_speedlimit * limit = direction == TR_UP ? &tor->uploadLimitMode
 
149
                                               : &tor->downloadLimitMode;
 
150
 
146
151
    *limit = mode;
147
152
}
148
153
 
149
154
tr_speedlimit
150
155
tr_torrentGetSpeedMode( const tr_torrent * tor,
151
 
                        int                up_or_down)
 
156
                        tr_direction       direction )
152
157
{
153
 
    return up_or_down==TR_UP ? tor->uploadLimitMode
154
 
                             : tor->downloadLimitMode;
 
158
    return direction == TR_UP ? tor->uploadLimitMode
 
159
                              : tor->downloadLimitMode;
155
160
}
156
161
 
157
162
void
158
 
tr_torrentSetSpeedLimit( tr_torrent   * tor,
159
 
                         int            up_or_down,
160
 
                         int            single_KiB_sec )
161
 
{
162
 
    tr_ratecontrol * rc = up_or_down==TR_UP ? tor->upload : tor->download;
163
 
    tr_rcSetLimit( rc, single_KiB_sec );
164
 
}
165
 
 
166
 
int
167
 
tr_torrentGetSpeedLimit( const tr_torrent  * tor,
168
 
                         int                 up_or_down )
169
 
{
170
 
    tr_ratecontrol * rc = up_or_down==TR_UP ? tor->upload : tor->download;
171
 
    return tr_rcGetLimit( rc );
 
163
tr_torrentSetSpeedLimit( tr_torrent * tor,
 
164
                         tr_direction direction,
 
165
                         int          single_KiB_sec )
 
166
{
 
167
    switch( direction )
 
168
    {
 
169
        case TR_UP:
 
170
            tor->uploadLimit = single_KiB_sec; break;
 
171
 
 
172
        case TR_DOWN:
 
173
            tor->downloadLimit = single_KiB_sec; break;
 
174
 
 
175
        default:
 
176
            assert( 0 );
 
177
    }
 
178
}
 
179
 
 
180
int
 
181
tr_torrentGetSpeedLimit( const tr_torrent * tor,
 
182
                         tr_direction       direction )
 
183
{
 
184
    switch( direction )
 
185
    {
 
186
        case TR_UP:
 
187
            return tor->uploadLimit;
 
188
 
 
189
        case TR_DOWN:
 
190
            return tor->downloadLimit;
 
191
 
 
192
        default:
 
193
            assert( 0 );
 
194
    }
 
195
}
 
196
 
 
197
int
 
198
tr_torrentIsPieceTransferAllowed( const tr_torrent  * tor,
 
199
                                  tr_direction        direction )
 
200
{
 
201
    int isEnabled = FALSE;
 
202
 
 
203
    switch( tr_torrentGetSpeedMode( tor, direction ) )
 
204
    {
 
205
        case TR_SPEEDLIMIT_GLOBAL:
 
206
            isEnabled = !tr_sessionIsSpeedLimitEnabled( tor->session, direction )
 
207
                      || tr_sessionGetSpeedLimit( tor->session, direction ) > 0;
 
208
            break;
 
209
 
 
210
        case TR_SPEEDLIMIT_SINGLE:
 
211
            isEnabled = tr_torrentGetSpeedLimit( tor, direction ) > 0;
 
212
            break;
 
213
 
 
214
        case TR_SPEEDLIMIT_UNLIMITED:
 
215
            isEnabled = TRUE;
 
216
            break;
 
217
 
 
218
        default:
 
219
            assert( 0 && "unhandled speed mode" );
 
220
            break;
 
221
    }
 
222
 
 
223
    return isEnabled;
172
224
}
173
225
 
174
226
/***
176
228
***/
177
229
 
178
230
static void
179
 
onTrackerResponse( void * tracker UNUSED, void * vevent, void * user_data )
 
231
onTrackerResponse( void * tracker UNUSED,
 
232
                   void *         vevent,
 
233
                   void *         user_data )
180
234
{
181
 
    tr_torrent * tor = user_data;
 
235
    tr_torrent *       tor = user_data;
182
236
    tr_tracker_event * event = vevent;
183
237
 
184
238
    switch( event->messageType )
185
239
    {
186
 
        case TR_TRACKER_PEERS: {
187
 
            size_t i, n;
 
240
        case TR_TRACKER_PEERS:
 
241
        {
 
242
            size_t   i, n;
188
243
            tr_pex * pex = tr_peerMgrCompactToPex( event->compact,
189
244
                                                   event->compactLen,
190
245
                                                   NULL, 0, &n );
193
248
            else
194
249
                tr_torinf( tor, _( "Got %d peers from tracker" ), (int)n );
195
250
 
196
 
            for( i=0; i<n; ++i ) {
 
251
            for( i = 0; i < n; ++i )
 
252
            {
197
253
                if( event->allAreSeeds )
198
254
                    pex[i].flags |= ADDED_F_SEED_FLAG;
199
 
                tr_peerMgrAddPex( tor->handle->peerMgr, tor->info.hash,
200
 
                                  TR_PEER_FROM_TRACKER, pex+i );
 
255
                tr_peerMgrAddPex( tor->session->peerMgr, tor->info.hash,
 
256
                                  TR_PEER_FROM_TRACKER, pex + i );
201
257
            }
202
258
 
203
259
            tr_free( pex );
206
262
 
207
263
        case TR_TRACKER_WARNING:
208
264
            tr_torerr( tor, _( "Tracker warning: \"%s\"" ), event->text );
209
 
            tor->error = TR_ERROR_TC_WARNING;
210
 
            tr_strlcpy( tor->errorString, event->text, sizeof(tor->errorString) );
 
265
            tor->error = -1;
 
266
            tr_strlcpy( tor->errorString, event->text,
 
267
                       sizeof( tor->errorString ) );
211
268
            break;
212
269
 
213
270
        case TR_TRACKER_ERROR:
214
271
            tr_torerr( tor, _( "Tracker error: \"%s\"" ), event->text );
215
 
            tor->error = TR_ERROR_TC_ERROR;
216
 
            tr_strlcpy( tor->errorString, event->text, sizeof(tor->errorString) );
 
272
            tor->error = -2;
 
273
            tr_strlcpy( tor->errorString, event->text,
 
274
                       sizeof( tor->errorString ) );
217
275
            break;
218
276
 
219
277
        case TR_TRACKER_ERROR_CLEAR:
230
288
***/
231
289
 
232
290
static int
233
 
getBytePiece( const tr_info * info, uint64_t byteOffset )
 
291
getBytePiece( const tr_info * info,
 
292
              uint64_t        byteOffset )
234
293
{
235
294
    assert( info );
236
295
    assert( info->pieceSize != 0 );
239
298
}
240
299
 
241
300
static void
242
 
initFilePieces ( tr_info * info, tr_file_index_t fileIndex )
 
301
initFilePieces( tr_info *       info,
 
302
                tr_file_index_t fileIndex )
243
303
{
244
304
    tr_file * file;
245
 
    uint64_t firstByte, lastByte;
 
305
    uint64_t  firstByte, lastByte;
246
306
 
247
307
    assert( info );
248
308
    assert( fileIndex < info->fileCount );
249
309
 
250
310
    file = &info->files[fileIndex];
251
311
    firstByte = file->offset;
252
 
    lastByte = firstByte + (file->length ? file->length-1 : 0);
 
312
    lastByte = firstByte + ( file->length ? file->length - 1 : 0 );
253
313
    file->firstPiece = getBytePiece( info, firstByte );
254
314
    file->lastPiece = getBytePiece( info, lastByte );
255
315
}
256
316
 
257
317
static int
258
 
pieceHasFile( tr_piece_index_t piece, const tr_file * file )
 
318
pieceHasFile( tr_piece_index_t piece,
 
319
              const tr_file *  file )
259
320
{
260
321
    return ( file->firstPiece <= piece ) && ( piece <= file->lastPiece );
261
322
}
262
323
 
263
324
static tr_priority_t
264
 
calculatePiecePriority ( const tr_torrent * tor,
265
 
                         tr_piece_index_t   piece,
266
 
                         int                fileHint )
 
325
calculatePiecePriority( const tr_torrent * tor,
 
326
                        tr_piece_index_t   piece,
 
327
                        int                fileHint )
267
328
{
268
329
    tr_file_index_t i;
269
 
    int priority = TR_PRI_LOW;
 
330
    int             priority = TR_PRI_LOW;
270
331
 
271
332
    /* find the first file that has data in this piece */
272
 
    if( fileHint >= 0 ) {
 
333
    if( fileHint >= 0 )
 
334
    {
273
335
        i = fileHint;
274
 
        while( i>0 && pieceHasFile( piece, &tor->info.files[i-1] ) )
 
336
        while( i > 0 && pieceHasFile( piece, &tor->info.files[i - 1] ) )
275
337
            --i;
276
 
    } else {
277
 
        for( i=0; i<tor->info.fileCount; ++i )
 
338
    }
 
339
    else
 
340
    {
 
341
        for( i = 0; i < tor->info.fileCount; ++i )
278
342
            if( pieceHasFile( piece, &tor->info.files[i] ) )
279
343
                break;
280
344
    }
281
345
 
282
346
    /* the piece's priority is the max of the priorities
283
347
     * of all the files in that piece */
284
 
    for( ; i<tor->info.fileCount; ++i )
 
348
    for( ; i < tor->info.fileCount; ++i )
285
349
    {
286
350
        const tr_file * file = &tor->info.files[i];
287
351
 
293
357
        /* when dealing with multimedia files, getting the first and
294
358
           last pieces can sometimes allow you to preview it a bit
295
359
           before it's fully downloaded... */
296
 
        if ( file->priority >= TR_PRI_NORMAL )
297
 
            if ( file->firstPiece == piece || file->lastPiece == piece )
 
360
        if( file->priority >= TR_PRI_NORMAL )
 
361
            if( file->firstPiece == piece || file->lastPiece == piece )
298
362
                priority = TR_PRI_HIGH;
299
363
    }
300
364
 
304
368
static void
305
369
tr_torrentInitFilePieces( tr_torrent * tor )
306
370
{
307
 
    tr_file_index_t ff;
 
371
    tr_file_index_t  ff;
308
372
    tr_piece_index_t pp;
309
 
    uint64_t offset = 0;
310
 
    tr_info * inf = &tor->info;
 
373
    uint64_t         offset = 0;
 
374
    tr_info *        inf = &tor->info;
311
375
 
312
376
    assert( inf );
313
377
 
314
 
    for( ff=0; ff<inf->fileCount; ++ff ) {
315
 
      inf->files[ff].offset = offset;
316
 
      offset += inf->files[ff].length;
317
 
      initFilePieces( inf, ff );
 
378
    for( ff = 0; ff < inf->fileCount; ++ff )
 
379
    {
 
380
        inf->files[ff].offset = offset;
 
381
        offset += inf->files[ff].length;
 
382
        initFilePieces( inf, ff );
318
383
    }
319
384
 
320
 
    for( pp=0; pp<inf->pieceCount; ++pp )
 
385
    for( pp = 0; pp < inf->pieceCount; ++pp )
321
386
        inf->pieces[pp].priority = calculatePiecePriority( tor, pp, -1 );
322
387
}
323
388
 
324
389
int
325
 
tr_torrentPromoteTracker( tr_torrent * tor, int pos )
 
390
tr_torrentPromoteTracker( tr_torrent * tor,
 
391
                          int          pos )
326
392
{
327
393
    int i;
328
394
    int tier;
334
400
    tier = tor->info.trackers[pos].tier;
335
401
 
336
402
    /* find the index of that tier's first tracker */
337
 
    for( i=0; i<tor->info.trackerCount; ++i )
 
403
    for( i = 0; i < tor->info.trackerCount; ++i )
338
404
        if( tor->info.trackers[i].tier == tier )
339
405
            break;
340
406
 
341
407
    assert( i < tor->info.trackerCount );
342
408
 
343
409
    /* promote the tracker at `pos' to the front of the tier */
344
 
    if( i != pos ) {
 
410
    if( i != pos )
 
411
    {
345
412
        const tr_tracker_info tmp = tor->info.trackers[i];
346
413
        tor->info.trackers[i] = tor->info.trackers[pos];
347
414
        tor->info.trackers[pos] = tmp;
353
420
 
354
421
struct RandomTracker
355
422
{
356
 
    tr_tracker_info tracker;
357
 
    int random_value;
 
423
    tr_tracker_info    tracker;
 
424
    int                random_value;
358
425
};
359
426
 
360
427
/* the tiers will be sorted from lowest to highest,
361
428
 * and trackers are randomized within the tiers */
362
429
static int
363
 
compareRandomTracker( const void * va, const void * vb )
 
430
compareRandomTracker( const void * va,
 
431
                      const void * vb )
364
432
{
365
433
    const struct RandomTracker * a = va;
366
434
    const struct RandomTracker * b = vb;
368
436
    if( a->tracker.tier != b->tracker.tier )
369
437
        return a->tracker.tier - b->tracker.tier;
370
438
 
371
 
   return a->random_value - b->random_value;
 
439
    return a->random_value - b->random_value;
372
440
}
373
 
    
 
441
 
374
442
static void
375
443
randomizeTiers( tr_info * info )
376
444
{
377
 
    int i;
378
 
    const int n = info->trackerCount;
 
445
    int                    i;
 
446
    const int              n = info->trackerCount;
379
447
    struct RandomTracker * r = tr_new0( struct RandomTracker, n );
380
 
    for( i=0; i<n; ++i ) {
 
448
 
 
449
    for( i = 0; i < n; ++i )
 
450
    {
381
451
        r[i].tracker = info->trackers[i];
382
 
        r[i].random_value = tr_rand( INT_MAX );
 
452
        r[i].random_value = tr_cryptoRandInt( INT_MAX );
383
453
    }
384
454
    qsort( r, n, sizeof( struct RandomTracker ), compareRandomTracker );
385
 
    for( i=0; i<n; ++i )
 
455
    for( i = 0; i < n; ++i )
386
456
        info->trackers[i] = r[i].tracker;
387
457
    tr_free( r );
388
458
}
389
459
 
390
 
static void torrentStart( tr_torrent * tor, int reloadProgress );
 
460
static void torrentStart( tr_torrent * tor,
 
461
                          int          reloadProgress );
391
462
 
392
463
/**
393
464
 * Decide on a block size.  constraints:
398
469
getBlockSize( uint32_t pieceSize )
399
470
{
400
471
    uint32_t b = pieceSize;
 
472
 
401
473
    while( b > MAX_BLOCK_SIZE )
402
474
        b /= 2u;
 
475
 
403
476
    if( !b || ( pieceSize % b ) ) /* not cleanly divisible */
404
477
        return 0;
405
478
    return b;
406
479
}
407
480
 
408
481
static void
409
 
torrentRealInit( tr_handle     * h,
410
 
                 tr_torrent    * tor,
 
482
torrentRealInit( tr_handle *     h,
 
483
                 tr_torrent *    tor,
411
484
                 const tr_ctor * ctor )
412
485
{
413
 
    int doStart;
414
 
    uint64_t loaded;
415
 
    uint64_t t;
416
 
    tr_info * info = &tor->info;
 
486
    int        doStart;
 
487
    uint64_t   loaded;
 
488
    uint64_t   t;
 
489
    tr_info *  info = &tor->info;
417
490
    static int nextUniqueId = 1;
418
 
   
 
491
 
419
492
    tr_globalLock( h );
420
493
 
421
 
    tor->handle   = h;
 
494
    tor->session   = h;
422
495
    tor->uniqueId = nextUniqueId++;
423
496
 
424
497
    randomizeTiers( info );
425
498
 
 
499
    tor->rawSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
 
500
    tor->rawSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
 
501
    tor->pieceSpeed[TR_CLIENT_TO_PEER] = tr_rcInit( );
 
502
    tor->pieceSpeed[TR_PEER_TO_CLIENT] = tr_rcInit( );
 
503
 
426
504
    tor->blockSize = getBlockSize( info->pieceSize );
427
505
 
428
506
    tor->lastPieceSize = info->totalSize % info->pieceSize;
429
507
 
430
508
    if( !tor->lastPieceSize )
431
 
         tor->lastPieceSize = info->pieceSize;
 
509
        tor->lastPieceSize = info->pieceSize;
432
510
 
433
511
    tor->lastBlockSize = info->totalSize % tor->blockSize;
434
512
 
435
513
    if( !tor->lastBlockSize )
436
 
         tor->lastBlockSize = tor->blockSize;
 
514
        tor->lastBlockSize = tor->blockSize;
437
515
 
438
516
    tor->blockCount =
439
517
        ( info->totalSize + tor->blockSize - 1 ) / tor->blockSize;
463
541
 
464
542
    tr_torrentInitFilePieces( tor );
465
543
 
466
 
    tor->upload         = tr_rcInit();
467
 
    tor->download       = tr_rcInit();
468
 
    tor->swarmSpeed     = tr_rcInit();
 
544
    tor->uploadLimit = 0;
 
545
    tor->downloadLimit = 0;
 
546
    tor->swarmSpeed = tr_rcInit( );
469
547
 
470
548
    tr_sha1( tor->obfuscatedHash, "req2", 4,
471
 
                                  info->hash, SHA_DIGEST_LENGTH,
472
 
                                  NULL );
 
549
             info->hash, SHA_DIGEST_LENGTH,
 
550
             NULL );
473
551
 
474
552
    tr_peerMgrAddTorrent( h->peerMgr, tor );
475
553
 
479
557
    assert( !tor->downloadedCur );
480
558
    assert( !tor->uploadedCur );
481
559
 
482
 
    tor->error   = TR_OK;
 
560
    tor->error   = 0;
483
561
 
484
562
    tor->checkedPieces = tr_bitfieldNew( tor->info.pieceCount );
485
563
    tr_torrentUncheck( tor );
487
565
    tor->addedDate = time( NULL ); /* this is a default value to be
488
566
                                      overwritten by the resume file */
489
567
    loaded = tr_torrentLoadResume( tor, ~0, ctor );
490
 
    
 
568
 
491
569
    doStart = tor->isRunning;
492
570
    tor->isRunning = 0;
493
571
 
494
 
    if( !(loaded & TR_FR_SPEEDLIMIT ) ) {
 
572
    if( !( loaded & TR_FR_SPEEDLIMIT ) )
 
573
    {
495
574
        tr_torrentSetSpeedLimit( tor, TR_UP,
496
 
                tr_sessionGetSpeedLimit( tor->handle, TR_UP ) );
 
575
                                tr_sessionGetSpeedLimit( tor->session, TR_UP ) );
497
576
        tr_torrentSetSpeedLimit( tor, TR_DOWN,
498
 
                tr_sessionGetSpeedLimit( tor->handle, TR_DOWN ) );
 
577
                                tr_sessionGetSpeedLimit( tor->session,
 
578
                                                         TR_DOWN ) );
499
579
    }
500
580
 
501
 
    tor->cpStatus = tr_cpGetStatus( tor->completion );
 
581
    tor->completeness = tr_cpGetStatus( tor->completion );
502
582
 
503
583
    tor->tracker = tr_trackerNew( tor );
504
 
    tor->trackerSubscription = tr_trackerSubscribe( tor->tracker, onTrackerResponse, tor );
 
584
    tor->trackerSubscription =
 
585
        tr_trackerSubscribe( tor->tracker, onTrackerResponse,
 
586
                             tor );
505
587
 
506
588
    {
507
589
        tr_torrent * it = NULL;
508
590
        tr_torrent * last = NULL;
509
 
        while(( it = tr_torrentNext( h, it )))
 
591
        while( ( it = tr_torrentNext( h, it ) ) )
510
592
            last = it;
 
593
 
511
594
        if( !last )
512
595
            h->torrentList = tor;
513
596
        else
518
601
    tr_globalUnlock( h );
519
602
 
520
603
    /* maybe save our own copy of the metainfo */
521
 
    if( tr_ctorGetSave( ctor ) ) {
 
604
    if( tr_ctorGetSave( ctor ) )
 
605
    {
522
606
        const tr_benc * val;
523
 
        if( !tr_ctorGetMetainfo( ctor, &val ) ) {
 
607
        if( !tr_ctorGetMetainfo( ctor, &val ) )
 
608
        {
524
609
            const char * filename = tor->info.torrent;
525
610
            tr_bencSaveFile( filename, val );
526
 
            tr_sessionSetTorrentFile( tor->handle, tor->info.hashString, filename );
 
611
            tr_sessionSetTorrentFile( tor->session, tor->info.hashString,
 
612
                                      filename );
527
613
        }
528
614
    }
529
615
 
534
620
}
535
621
 
536
622
int
537
 
tr_torrentParse( const tr_handle  * handle,
538
 
                 const tr_ctor    * ctor,
539
 
                 tr_info          * setmeInfo )
 
623
tr_torrentParse( const tr_handle * handle,
 
624
                 const tr_ctor *   ctor,
 
625
                 tr_info *         setmeInfo )
540
626
{
541
 
    int err = 0;
542
 
    int doFree;
543
 
    tr_info tmp;
 
627
    int             err = 0;
 
628
    int             doFree;
 
629
    tr_info         tmp;
544
630
    const tr_benc * metainfo;
545
631
 
546
632
    if( setmeInfo == NULL )
566
652
}
567
653
 
568
654
tr_torrent *
569
 
tr_torrentNew( tr_handle      * handle,
570
 
               const tr_ctor  * ctor,
571
 
               int            * setmeError )
 
655
tr_torrentNew( tr_handle *     handle,
 
656
               const tr_ctor * ctor,
 
657
               int *           setmeError )
572
658
{
573
 
    int err;
574
 
    tr_info tmpInfo;
 
659
    int          err;
 
660
    tr_info      tmpInfo;
575
661
    tr_torrent * tor = NULL;
576
662
 
577
663
    err = tr_torrentParse( handle, ctor, &tmpInfo );
578
 
    if( !err ) {
 
664
    if( !err )
 
665
    {
579
666
        tor = tr_new0( tr_torrent, 1 );
580
667
        tor->info = tmpInfo;
581
668
        torrentRealInit( handle, tor, ctor );
582
 
    } else if( setmeError ) {
 
669
    }
 
670
    else if( setmeError )
 
671
    {
583
672
        *setmeError = err;
584
673
    }
585
674
 
591
680
**/
592
681
 
593
682
void
594
 
tr_torrentSetDownloadDir( tr_torrent * tor, const char * path )
 
683
tr_torrentSetDownloadDir( tr_torrent * tor,
 
684
                          const char * path )
595
685
{
596
686
    if( !path || !tor->downloadDir || strcmp( path, tor->downloadDir ) )
597
687
    {
618
708
tr_torrentIsPrivate( const tr_torrent * tor )
619
709
{
620
710
    return tor
621
 
        && tor->info.isPrivate;
 
711
           && tor->info.isPrivate;
622
712
}
623
713
 
624
714
int
625
715
tr_torrentAllowsPex( const tr_torrent * tor )
626
716
{
627
717
    return tor
628
 
        && tor->handle->isPexEnabled
629
 
        && !tr_torrentIsPrivate( tor );
 
718
           && tor->session->isPexEnabled
 
719
           && !tr_torrentIsPrivate( tor );
630
720
}
631
721
 
632
722
static void
633
723
tr_torrentManualUpdateImpl( void * vtor )
634
724
{
635
725
    tr_torrent * tor = vtor;
 
726
 
636
727
    if( tor->isRunning )
637
728
        tr_trackerReannounce( tor->tracker );
638
729
}
 
730
 
639
731
void
640
732
tr_torrentManualUpdate( tr_torrent * tor )
641
733
{
642
 
    tr_runInEventThread( tor->handle, tr_torrentManualUpdateImpl, tor );
 
734
    tr_runInEventThread( tor->session, tr_torrentManualUpdateImpl, tor );
643
735
}
 
736
 
644
737
int
645
738
tr_torrentCanManualUpdate( const tr_torrent * tor )
646
739
{
647
740
    return ( tor )
648
 
        && ( tor->isRunning )
649
 
        && ( tr_trackerCanManualAnnounce( tor->tracker ) );
650
 
}
651
 
 
652
 
/* rcRate's averaging code can make it appear that we're
653
 
 * still sending bytes after a torrent stops or all the
654
 
 * peers disconnect, so short-circuit that appearance here */
655
 
void
656
 
tr_torrentGetRates( const tr_torrent * tor,
657
 
                    float            * toClient,
658
 
                    float            * toPeer)
659
 
{
660
 
    const int showSpeed = tor->isRunning
661
 
        && tr_peerMgrHasConnections( tor->handle->peerMgr, tor->info.hash );
662
 
 
663
 
    if( toClient )
664
 
        *toClient = showSpeed ? tr_rcRate( tor->download ) : 0.0;
665
 
    if( toPeer )
666
 
        *toPeer = showSpeed ? tr_rcRate( tor->upload ) : 0.0;
667
 
}
 
741
           && ( tor->isRunning )
 
742
           && ( tr_trackerCanManualAnnounce( tor->tracker ) );
 
743
}
 
744
 
668
745
const tr_info *
669
746
tr_torrentInfo( const tr_torrent * tor )
670
747
{
677
754
    const time_t now = time( NULL );
678
755
 
679
756
    return tor && ( now == tor->lastStatTime ) ? &tor->stats
680
 
                                               : tr_torrentStat( tor );
 
757
           : tr_torrentStat( tor );
681
758
}
682
759
 
683
 
tr_torrent_status
684
 
tr_torrentGetStatus( tr_torrent * tor )
 
760
tr_torrent_activity
 
761
tr_torrentGetActivity( tr_torrent * tor )
685
762
{
686
763
    tr_torrentRecheckCompleteness( tor );
687
764
 
691
768
        return TR_STATUS_CHECK_WAIT;
692
769
    if( !tor->isRunning )
693
770
        return TR_STATUS_STOPPED;
694
 
    if( tor->cpStatus == TR_CP_INCOMPLETE )
 
771
    if( tor->completeness == TR_CP_INCOMPLETE )
695
772
        return TR_STATUS_DOWNLOAD;
696
773
 
697
774
    return TR_STATUS_SEED;
700
777
const tr_stat *
701
778
tr_torrentStat( tr_torrent * tor )
702
779
{
703
 
    tr_stat * s;
704
 
    struct tr_tracker * tc;
 
780
    tr_stat *               s;
 
781
    struct tr_tracker *     tc;
705
782
    const tr_tracker_info * ti;
706
 
    int usableSeeds = 0;
 
783
    int                     usableSeeds = 0;
707
784
 
708
785
    if( !tor )
709
786
        return NULL;
714
791
 
715
792
    s = &tor->stats;
716
793
    s->id = tor->uniqueId;
717
 
    s->status = tr_torrentGetStatus( tor );
 
794
    s->activity = tr_torrentGetActivity( tor );
718
795
    s->error  = tor->error;
719
796
    memcpy( s->errorString, tor->errorString,
720
 
            sizeof( s->errorString ) );
 
797
           sizeof( s->errorString ) );
721
798
 
722
799
    tc = tor->tracker;
723
800
    ti = tr_trackerGetAddress( tor->tracker );
725
802
    s->scrapeURL   = ti ? ti->scrape   : NULL;
726
803
    tr_trackerStat( tc, s );
727
804
    tr_trackerGetCounts( tc, &s->timesCompleted,
728
 
                             &s->leechers, 
729
 
                             &s->seeders );
730
 
    tr_peerMgrTorrentStats( tor->handle->peerMgr,
 
805
                         &s->leechers,
 
806
                         &s->seeders );
 
807
    tr_peerMgrTorrentStats( tor->session->peerMgr,
731
808
                            tor->info.hash,
732
809
                            &s->peersKnown,
733
810
                            &s->peersConnected,
734
 
                               &usableSeeds,
 
811
                            &usableSeeds,
735
812
                            &s->webseedsSendingToUs,
736
813
                            &s->peersSendingToUs,
737
814
                            &s->peersGettingFromUs,
738
 
                             s->peersFrom );
 
815
                            s->peersFrom );
 
816
 
 
817
    s->rawUploadSpeed     = tr_rcRate( tor->rawSpeed[TR_UP] );
 
818
    s->rawDownloadSpeed   = tr_rcRate( tor->rawSpeed[TR_DOWN] );
 
819
    s->pieceUploadSpeed   = tr_rcRate( tor->pieceSpeed[TR_UP] );
 
820
    s->pieceDownloadSpeed = tr_rcRate( tor->pieceSpeed[TR_DOWN] );
739
821
 
740
822
    usableSeeds += tor->info.webseedCount;
741
823
 
745
827
    s->leftUntilDone = tr_cpLeftUntilDone( tor->completion );
746
828
    s->sizeWhenDone = tr_cpSizeWhenDone( tor->completion );
747
829
 
748
 
    s->recheckProgress = s->status == TR_STATUS_CHECK
749
 
        ? 1.0 - (tr_torrentCountUncheckedPieces( tor ) / (double) tor->info.pieceCount)
750
 
        : 0.0;
751
 
 
752
 
    tr_torrentGetRates( tor, &s->rateDownload, &s->rateUpload );
 
830
    s->recheckProgress = s->activity == TR_STATUS_CHECK
 
831
                       ? 1.0 -
 
832
                         ( tr_torrentCountUncheckedPieces( tor ) /
 
833
                           (double) tor->info.pieceCount )
 
834
                       : 0.0;
753
835
 
754
836
    s->swarmSpeed = tr_rcRate( tor->swarmSpeed );
755
 
    
 
837
 
756
838
    s->activityDate = tor->activityDate;
757
839
    s->addedDate    = tor->addedDate;
758
840
    s->doneDate     = tor->doneDate;
776
858
    else
777
859
    {
778
860
        tr_piece_index_t i;
779
 
        tr_bitfield * peerPieces = tr_peerMgrGetAvailable( tor->handle->peerMgr,
780
 
                                                           tor->info.hash );
 
861
        tr_bitfield *    peerPieces = tr_peerMgrGetAvailable(
 
862
            tor->session->peerMgr,
 
863
            tor->info.
 
864
            hash );
781
865
        s->desiredAvailable = 0;
782
 
        for( i=0; i<tor->info.pieceCount; ++i )
 
866
        for( i = 0; i < tor->info.pieceCount; ++i )
783
867
            if( !tor->info.pieces[i].dnd && tr_bitfieldHas( peerPieces, i ) )
784
 
                s->desiredAvailable += tr_cpMissingBlocksInPiece( tor->completion, i );
 
868
                s->desiredAvailable += tr_cpMissingBlocksInPiece(
 
869
                    tor->completion, i );
785
870
        s->desiredAvailable *= tor->blockSize;
786
871
        tr_bitfieldFree( peerPieces );
787
872
    }
788
873
 
789
874
    if( s->leftUntilDone > s->desiredAvailable )
790
875
        s->eta = TR_ETA_NOT_AVAIL;
791
 
    else if( s->rateDownload < 0.1 )
 
876
    else if( s->pieceDownloadSpeed < 0.1 )
792
877
        s->eta = TR_ETA_UNKNOWN;
793
878
    else
794
 
        s->eta = s->leftUntilDone / s->rateDownload / 1024.0;
795
 
 
796
 
    s->ratio = tr_getRatio( s->uploadedEver,
797
 
                            s->downloadedEver ? s->downloadedEver : s->haveValid );
798
 
    
 
879
        s->eta = s->leftUntilDone / s->pieceDownloadSpeed / 1024.0;
 
880
 
 
881
    s->ratio = tr_getRatio(
 
882
        s->uploadedEver,
 
883
        s->downloadedEver ? s->downloadedEver : s->
 
884
        haveValid );
 
885
 
799
886
    tr_torrentUnlock( tor );
800
887
 
801
888
    return s;
806
893
***/
807
894
 
808
895
static uint64_t
809
 
fileBytesCompleted ( const tr_torrent * tor, tr_file_index_t fileIndex )
 
896
fileBytesCompleted( const tr_torrent * tor,
 
897
                    tr_file_index_t    fileIndex )
810
898
{
811
 
    const tr_file * file     =  &tor->info.files[fileIndex];
812
 
    const tr_block_index_t firstBlock       =  file->offset / tor->blockSize;
813
 
    const uint64_t firstBlockOffset =  file->offset % tor->blockSize;
814
 
    const uint64_t lastOffset       =  file->length ? (file->length-1) : 0;
815
 
    const tr_block_index_t lastBlock        = (file->offset + lastOffset) / tor->blockSize;
816
 
    const uint64_t lastBlockOffset  = (file->offset + lastOffset) % tor->blockSize;
817
 
    uint64_t haveBytes = 0;
 
899
    const tr_file *        file     =  &tor->info.files[fileIndex];
 
900
    const tr_block_index_t firstBlock       =  file->offset /
 
901
                                              tor->blockSize;
 
902
    const uint64_t         firstBlockOffset =  file->offset %
 
903
                                              tor->blockSize;
 
904
    const uint64_t         lastOffset       =
 
905
        file->length ? ( file->length - 1 ) : 0;
 
906
    const tr_block_index_t lastBlock        =
 
907
        ( file->offset + lastOffset ) / tor->blockSize;
 
908
    const uint64_t         lastBlockOffset  =
 
909
        ( file->offset + lastOffset ) % tor->blockSize;
 
910
    uint64_t               haveBytes = 0;
818
911
 
819
912
    assert( tor );
820
913
    assert( fileIndex < tor->info.fileCount );
821
914
    assert( file->offset + file->length <= tor->info.totalSize );
822
 
    assert( ( firstBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
823
 
    assert( ( lastBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
 
915
    assert( ( firstBlock < tor->blockCount )
 
916
          || ( !file->length && file->offset == tor->info.totalSize ) );
 
917
    assert( ( lastBlock < tor->blockCount )
 
918
          || ( !file->length && file->offset == tor->info.totalSize ) );
824
919
    assert( firstBlock <= lastBlock );
825
920
    assert( tr_torBlockPiece( tor, firstBlock ) == file->firstPiece );
826
921
    assert( tr_torBlockPiece( tor, lastBlock ) == file->lastPiece );
837
932
        if( tr_cpBlockIsComplete( tor->completion, firstBlock ) )
838
933
            haveBytes += tor->blockSize - firstBlockOffset;
839
934
 
840
 
        for( i=firstBlock+1; i<lastBlock; ++i )
 
935
        for( i = firstBlock + 1; i < lastBlock; ++i )
841
936
            if( tr_cpBlockIsComplete( tor->completion, i ) )
842
 
               haveBytes += tor->blockSize;
 
937
                haveBytes += tor->blockSize;
843
938
 
844
939
        if( tr_cpBlockIsComplete( tor->completion, lastBlock ) )
845
940
            haveBytes += lastBlockOffset + 1;
849
944
}
850
945
 
851
946
tr_file_stat *
852
 
tr_torrentFiles( const tr_torrent * tor, tr_file_index_t * fileCount )
 
947
tr_torrentFiles( const tr_torrent * tor,
 
948
                 tr_file_index_t *  fileCount )
853
949
{
854
 
    tr_file_index_t i;
 
950
    tr_file_index_t       i;
855
951
    const tr_file_index_t n = tor->info.fileCount;
856
 
    tr_file_stat * files = tr_new0( tr_file_stat, n );
857
 
    tr_file_stat * walk = files;
 
952
    tr_file_stat *        files = tr_new0( tr_file_stat, n );
 
953
    tr_file_stat *        walk = files;
858
954
 
859
 
    for( i=0; i<n; ++i, ++walk ) {
 
955
    for( i = 0; i < n; ++i, ++walk )
 
956
    {
860
957
        const uint64_t b = fileBytesCompleted( tor, i );
861
958
        walk->bytesCompleted = b;
862
959
        walk->progress = tr_getRatio( b, tor->info.files[i].length );
869
966
}
870
967
 
871
968
void
872
 
tr_torrentFilesFree( tr_file_stat * files, tr_file_index_t fileCount UNUSED )
 
969
tr_torrentFilesFree( tr_file_stat *            files,
 
970
                     tr_file_index_t fileCount UNUSED )
873
971
{
874
972
    tr_free( files );
875
973
}
881
979
float*
882
980
tr_torrentWebSpeeds( const tr_torrent * tor )
883
981
{
884
 
    return tor ? tr_peerMgrWebSpeeds( tor->handle->peerMgr, tor->info.hash )
885
 
               : NULL;
 
982
    return tor ? tr_peerMgrWebSpeeds( tor->session->peerMgr, tor->info.hash )
 
983
           : NULL;
886
984
}
887
 
    
888
985
 
889
986
tr_peer_stat *
890
 
tr_torrentPeers( const tr_torrent * tor, int * peerCount )
 
987
tr_torrentPeers( const tr_torrent * tor,
 
988
                 int *              peerCount )
891
989
{
892
990
    tr_peer_stat * ret = NULL;
893
991
 
894
992
    if( tor )
895
 
        ret = tr_peerMgrPeerStats( tor->handle->peerMgr,
 
993
        ret = tr_peerMgrPeerStats( tor->session->peerMgr,
896
994
                                   tor->info.hash, peerCount );
897
995
 
898
996
    return ret;
899
997
}
900
998
 
901
999
void
902
 
tr_torrentPeersFree( tr_peer_stat * peers, int peerCount UNUSED )
 
1000
tr_torrentPeersFree( tr_peer_stat * peers,
 
1001
                     int peerCount  UNUSED )
903
1002
{
904
1003
    tr_free( peers );
905
1004
}
906
1005
 
907
1006
void
908
 
tr_torrentAvailability( const tr_torrent * tor, int8_t * tab, int size )
 
1007
tr_torrentAvailability( const tr_torrent * tor,
 
1008
                        int8_t *           tab,
 
1009
                        int                size )
909
1010
{
910
 
    tr_peerMgrTorrentAvailability( tor->handle->peerMgr,
 
1011
    tr_peerMgrTorrentAvailability( tor->session->peerMgr,
911
1012
                                   tor->info.hash,
912
1013
                                   tab, size );
913
1014
}
914
1015
 
915
1016
void
916
 
tr_torrentAmountFinished( const tr_torrent * tor, float * tab, int size )
 
1017
tr_torrentAmountFinished( const tr_torrent * tor,
 
1018
                          float *            tab,
 
1019
                          int                size )
917
1020
{
918
1021
    tr_torrentLock( tor );
919
1022
    tr_cpGetAmountDone( tor->completion, tab, size );
935
1038
    tr_torrentUnlock( tor );
936
1039
}
937
1040
 
938
 
 
939
1041
void
940
 
tr_torrentSetHasPiece( tr_torrent * tor, tr_piece_index_t pieceIndex, int has )
 
1042
tr_torrentSetHasPiece( tr_torrent *     tor,
 
1043
                       tr_piece_index_t pieceIndex,
 
1044
                       int              has )
941
1045
{
942
1046
    tr_torrentLock( tor );
943
1047
 
960
1064
freeTorrent( tr_torrent * tor )
961
1065
{
962
1066
    tr_torrent * t;
963
 
    tr_handle * h = tor->handle;
964
 
    tr_info * inf = &tor->info;
 
1067
    tr_handle *  h = tor->session;
 
1068
    tr_info *    inf = &tor->info;
965
1069
 
966
1070
    assert( tor );
967
1071
    assert( !tor->isRunning );
972
1076
 
973
1077
    tr_cpClose( tor->completion );
974
1078
 
975
 
    tr_rcClose( tor->upload );
976
 
    tr_rcClose( tor->download );
977
1079
    tr_rcClose( tor->swarmSpeed );
978
1080
 
979
1081
    tr_trackerUnsubscribe( tor->tracker, tor->trackerSubscription );
986
1088
 
987
1089
    if( tor == h->torrentList )
988
1090
        h->torrentList = tor->next;
989
 
    else for( t=h->torrentList; t!=NULL; t=t->next ) {
990
 
        if( t->next == tor ) {
991
 
            t->next = tor->next;
992
 
            break;
 
1091
    else for( t = h->torrentList; t != NULL; t = t->next )
 
1092
        {
 
1093
            if( t->next == tor )
 
1094
            {
 
1095
                t->next = tor->next;
 
1096
                break;
 
1097
            }
993
1098
        }
994
 
    }
995
1099
 
996
1100
    assert( h->torrentCount >= 1 );
997
1101
    h->torrentCount--;
998
1102
 
 
1103
    tr_rcClose( tor->pieceSpeed[TR_PEER_TO_CLIENT] );
 
1104
    tr_rcClose( tor->pieceSpeed[TR_CLIENT_TO_PEER] );
 
1105
    tr_rcClose( tor->rawSpeed[TR_PEER_TO_CLIENT] );
 
1106
    tr_rcClose( tor->rawSpeed[TR_CLIENT_TO_PEER] );
 
1107
 
999
1108
    tr_metainfoFree( inf );
1000
1109
    tr_free( tor );
1001
1110
 
1011
1120
{
1012
1121
    tr_torrent * tor = vtor;
1013
1122
 
1014
 
    tr_globalLock( tor->handle );
 
1123
    tr_globalLock( tor->session );
1015
1124
 
1016
1125
    tor->isRunning  = 1;
1017
1126
    *tor->errorString = '\0';
1018
1127
    tr_torrentResetTransferStats( tor );
1019
 
    tor->cpStatus = tr_cpGetStatus( tor->completion );
 
1128
    tor->completeness = tr_cpGetStatus( tor->completion );
1020
1129
    tr_torrentSaveResume( tor );
1021
1130
    tor->startDate = time( NULL );
1022
1131
    tr_trackerStart( tor->tracker );
1023
 
    tr_peerMgrStartTorrent( tor->handle->peerMgr, tor->info.hash );
 
1132
    tr_peerMgrStartTorrent( tor->session->peerMgr, tor->info.hash );
1024
1133
 
1025
 
    tr_globalUnlock( tor->handle );
 
1134
    tr_globalUnlock( tor->session );
1026
1135
}
1027
1136
 
1028
1137
static void
1029
1138
checkAndStartCB( tr_torrent * tor )
1030
1139
{
1031
 
    tr_runInEventThread( tor->handle, checkAndStartImpl, tor );
 
1140
    tr_runInEventThread( tor->session, checkAndStartImpl, tor );
1032
1141
}
1033
1142
 
1034
1143
static void
1035
 
torrentStart( tr_torrent * tor, int reloadProgress )
 
1144
torrentStart( tr_torrent * tor,
 
1145
              int          reloadProgress )
1036
1146
{
1037
 
    tr_globalLock( tor->handle );
 
1147
    tr_globalLock( tor->session );
1038
1148
 
1039
1149
    if( !tor->isRunning )
1040
1150
    {
1041
 
        if( reloadProgress )
 
1151
        const int isVerifying = tr_verifyInProgress( tor );
 
1152
 
 
1153
        if( !isVerifying && reloadProgress )
1042
1154
            tr_torrentLoadResume( tor, TR_FR_PROGRESS, NULL );
 
1155
 
1043
1156
        tor->isRunning = 1;
1044
 
        tr_verifyAdd( tor, checkAndStartCB );
 
1157
 
 
1158
        if( !isVerifying )
 
1159
            tr_verifyAdd( tor, checkAndStartCB );
1045
1160
    }
1046
1161
 
1047
 
    tr_globalUnlock( tor->handle );
 
1162
    tr_globalUnlock( tor->session );
1048
1163
}
1049
1164
 
1050
1165
void
1059
1174
{
1060
1175
    tr_torrentRecheckCompleteness( vtor );
1061
1176
}
 
1177
 
1062
1178
static void
1063
1179
torrentRecheckDoneCB( tr_torrent * tor )
1064
1180
{
1065
 
    tr_runInEventThread( tor->handle, torrentRecheckDoneImpl, tor );
 
1181
    tr_runInEventThread( tor->session, torrentRecheckDoneImpl, tor );
1066
1182
}
 
1183
 
1067
1184
void
1068
1185
tr_torrentVerify( tr_torrent * tor )
1069
1186
{
1070
1187
    tr_verifyRemove( tor );
1071
1188
 
1072
 
    tr_globalLock( tor->handle );
 
1189
    tr_globalLock( tor->session );
1073
1190
 
1074
1191
    tr_torrentUncheck( tor );
1075
1192
    tr_verifyAdd( tor, torrentRecheckDoneCB );
1076
1193
 
1077
 
    tr_globalUnlock( tor->handle );
 
1194
    tr_globalUnlock( tor->session );
1078
1195
}
1079
1196
 
1080
 
 
1081
1197
static void
1082
1198
stopTorrent( void * vtor )
1083
1199
{
1084
1200
    tr_file_index_t i;
1085
1201
 
1086
 
    tr_torrent * tor = vtor;
 
1202
    tr_torrent *    tor = vtor;
 
1203
 
1087
1204
    tr_verifyRemove( tor );
1088
 
    tr_peerMgrStopTorrent( tor->handle->peerMgr, tor->info.hash );
 
1205
    tr_peerMgrStopTorrent( tor->session->peerMgr, tor->info.hash );
1089
1206
    tr_trackerStop( tor->tracker );
1090
1207
 
1091
 
    for( i=0; i<tor->info.fileCount; ++i )
 
1208
    for( i = 0; i < tor->info.fileCount; ++i )
1092
1209
    {
1093
 
        char path[MAX_PATH_LENGTH];
1094
1210
        const tr_file * file = &tor->info.files[i];
1095
 
        tr_buildPath( path, sizeof(path), tor->downloadDir, file->name, NULL );
 
1211
        char * path = tr_buildPath( tor->downloadDir, file->name, NULL );
1096
1212
        tr_fdFileClose( path );
 
1213
        tr_free( path );
1097
1214
    }
1098
1215
}
1099
1216
 
1102
1219
{
1103
1220
    if( tor )
1104
1221
    {
1105
 
        tr_globalLock( tor->handle );
 
1222
        tr_globalLock( tor->session );
1106
1223
 
1107
1224
        tor->isRunning = 0;
1108
1225
        if( !tor->isDeleting )
1109
1226
            tr_torrentSaveResume( tor );
1110
 
        tr_runInEventThread( tor->handle, stopTorrent, tor );
 
1227
        tr_runInEventThread( tor->session, stopTorrent, tor );
1111
1228
 
1112
 
        tr_globalUnlock( tor->handle );
 
1229
        tr_globalUnlock( tor->session );
1113
1230
    }
1114
1231
}
1115
1232
 
1117
1234
closeTorrent( void * vtor )
1118
1235
{
1119
1236
    tr_torrent * tor = vtor;
 
1237
 
1120
1238
    tr_torrentSaveResume( tor );
1121
1239
    tor->isRunning = 0;
1122
1240
    stopTorrent( tor );
1123
 
    if( tor->isDeleting ) {
1124
 
        tr_metainfoRemoveSaved( tor->handle, &tor->info );
 
1241
    if( tor->isDeleting )
 
1242
    {
 
1243
        tr_metainfoRemoveSaved( tor->session, &tor->info );
1125
1244
        tr_torrentRemoveResume( tor );
1126
1245
    }
1127
1246
    freeTorrent( tor );
1132
1251
{
1133
1252
    if( tor )
1134
1253
    {
1135
 
        tr_handle * handle = tor->handle;
 
1254
        tr_handle * handle = tor->session;
1136
1255
        tr_globalLock( handle );
1137
1256
 
1138
 
        tr_torrentClearStatusCallback( tor );
 
1257
        tr_torrentClearCompletenessCallback( tor );
1139
1258
        tr_runInEventThread( handle, closeTorrent, tor );
1140
1259
 
1141
1260
        tr_globalUnlock( handle );
1149
1268
    tr_torrentFree( tor );
1150
1269
}
1151
1270
 
1152
 
 
1153
1271
/**
1154
1272
***  Completeness
1155
1273
**/
1162
1280
        /* Translators: this is a minor point that's safe to skip over, but FYI:
1163
1281
           "Complete" and "Done" are specific, different terms in Transmission:
1164
1282
           "Complete" means we've downloaded every file in the torrent.
1165
 
           "Done" means we're done downloading the files we wanted, but NOT all that exist */
1166
 
        case TR_CP_DONE:     return _( "Done" );
1167
 
        case TR_CP_COMPLETE: return _( "Complete" );
1168
 
        default:             return _( "Incomplete" );
 
1283
           "Done" means we're done downloading the files we wanted, but NOT all
 
1284
           that exist */
 
1285
        case TR_CP_DONE:
 
1286
            return _( "Done" );
 
1287
 
 
1288
        case TR_CP_COMPLETE:
 
1289
            return _( "Complete" );
 
1290
 
 
1291
        default:
 
1292
            return _( "Incomplete" );
1169
1293
    }
1170
1294
}
1171
1295
 
1172
1296
static void
1173
 
fireStatusChange( tr_torrent * tor, cp_status_t status )
1174
 
{
1175
 
    assert( tor );
1176
 
    assert( status==TR_CP_INCOMPLETE || status==TR_CP_DONE || status==TR_CP_COMPLETE );
1177
 
 
1178
 
    if( tor->status_func )
1179
 
        tor->status_func( tor, status, tor->status_func_user_data );
1180
 
}
1181
 
 
1182
 
void
1183
 
tr_torrentSetStatusCallback( tr_torrent             * tor,
1184
 
                             tr_torrent_status_func   func,
1185
 
                             void                   * user_data )
1186
 
{
1187
 
    assert( tor );
1188
 
    tor->status_func = func;
1189
 
    tor->status_func_user_data = user_data;
1190
 
}
1191
 
 
1192
 
void
1193
 
tr_torrentClearStatusCallback( tr_torrent * torrent )
1194
 
{
1195
 
    tr_torrentSetStatusCallback( torrent, NULL, NULL );
 
1297
fireCompletenessChange( tr_torrent       * tor,
 
1298
                        tr_completeness    status )
 
1299
{
 
1300
    assert( tor );
 
1301
    assert( ( status == TR_CP_INCOMPLETE )
 
1302
         || ( status == TR_CP_DONE )
 
1303
         || ( status == TR_CP_COMPLETE ) );
 
1304
 
 
1305
    if( tor->completeness_func )
 
1306
        tor->completeness_func( tor, status, tor->completeness_func_user_data );
 
1307
}
 
1308
 
 
1309
void
 
1310
tr_torrentSetCompletenessCallback( tr_torrent                    * tor,
 
1311
                                   tr_torrent_completeness_func    func,
 
1312
                                   void                          * user_data )
 
1313
{
 
1314
    assert( tor );
 
1315
    tor->completeness_func = func;
 
1316
    tor->completeness_func_user_data = user_data;
 
1317
}
 
1318
 
 
1319
void
 
1320
tr_torrentClearCompletenessCallback( tr_torrent * torrent )
 
1321
{
 
1322
    tr_torrentSetCompletenessCallback( torrent, NULL, NULL );
1196
1323
}
1197
1324
 
1198
1325
void
1199
1326
tr_torrentRecheckCompleteness( tr_torrent * tor )
1200
1327
{
1201
 
    cp_status_t cpStatus;
 
1328
    tr_completeness completeness;
1202
1329
 
1203
1330
    tr_torrentLock( tor );
1204
1331
 
1205
 
    cpStatus = tr_cpGetStatus( tor->completion );
 
1332
    completeness = tr_cpGetStatus( tor->completion );
1206
1333
 
1207
 
    if( cpStatus != tor->cpStatus )
 
1334
    if( completeness != tor->completeness )
1208
1335
    {
1209
1336
        const int recentChange = tor->downloadedCur != 0;
1210
1337
 
1211
1338
        if( recentChange )
1212
1339
        {
1213
1340
            tr_torinf( tor, _( "State changed from \"%1$s\" to \"%2$s\"" ),
1214
 
                            getCompletionString( tor->cpStatus ),
1215
 
                            getCompletionString( cpStatus ) );
 
1341
                      getCompletionString( tor->completeness ),
 
1342
                      getCompletionString( completeness ) );
1216
1343
        }
1217
1344
 
1218
 
        tor->cpStatus = cpStatus;
1219
 
        fireStatusChange( tor, cpStatus );
 
1345
        tor->completeness = completeness;
 
1346
        fireCompletenessChange( tor, completeness );
1220
1347
 
1221
 
        if( recentChange && ( cpStatus == TR_CP_COMPLETE ) )
 
1348
        if( recentChange && ( completeness == TR_CP_COMPLETE ) )
1222
1349
        {
1223
1350
            tr_trackerCompleted( tor->tracker );
1224
1351
 
1234
1361
int
1235
1362
tr_torrentIsSeed( const tr_torrent * tor )
1236
1363
{
1237
 
    return tor->cpStatus==TR_CP_COMPLETE || tor->cpStatus==TR_CP_DONE;
 
1364
    return tor->completeness == TR_CP_COMPLETE || tor->completeness == TR_CP_DONE;
1238
1365
}
1239
1366
 
1240
1367
/**
1242
1369
**/
1243
1370
 
1244
1371
void
1245
 
tr_torrentInitFilePriority( tr_torrent      * tor,
1246
 
                            tr_file_index_t   fileIndex,
1247
 
                            tr_priority_t     priority )
 
1372
tr_torrentInitFilePriority( tr_torrent *    tor,
 
1373
                            tr_file_index_t fileIndex,
 
1374
                            tr_priority_t   priority )
1248
1375
{
1249
1376
    tr_piece_index_t i;
1250
 
    tr_file * file;
 
1377
    tr_file *        file;
1251
1378
 
1252
1379
    assert( tor );
1253
1380
    assert( fileIndex < tor->info.fileCount );
1254
 
    assert( priority==TR_PRI_LOW || priority==TR_PRI_NORMAL || priority==TR_PRI_HIGH );
 
1381
    assert(
 
1382
        priority == TR_PRI_LOW || priority == TR_PRI_NORMAL || priority ==
 
1383
        TR_PRI_HIGH );
1255
1384
 
1256
1385
    file = &tor->info.files[fileIndex];
1257
1386
    file->priority = priority;
1258
 
    for( i=file->firstPiece; i<=file->lastPiece; ++i )
1259
 
      tor->info.pieces[i].priority = calculatePiecePriority( tor, i, fileIndex );
 
1387
    for( i = file->firstPiece; i <= file->lastPiece; ++i )
 
1388
        tor->info.pieces[i].priority = calculatePiecePriority( tor, i,
 
1389
                                                               fileIndex );
1260
1390
}
1261
1391
 
1262
1392
void
1263
 
tr_torrentSetFilePriorities( tr_torrent       * tor,
1264
 
                             tr_file_index_t  * files,
1265
 
                             tr_file_index_t    fileCount,
1266
 
                             tr_priority_t      priority )
 
1393
tr_torrentSetFilePriorities( tr_torrent *      tor,
 
1394
                             tr_file_index_t * files,
 
1395
                             tr_file_index_t   fileCount,
 
1396
                             tr_priority_t     priority )
1267
1397
{
1268
1398
    tr_file_index_t i;
 
1399
 
1269
1400
    tr_torrentLock( tor );
1270
1401
 
1271
 
    for( i=0; i<fileCount; ++i )
 
1402
    for( i = 0; i < fileCount; ++i )
1272
1403
        tr_torrentInitFilePriority( tor, files[i], priority );
1273
1404
 
1274
1405
    tr_torrentSaveResume( tor );
1276
1407
}
1277
1408
 
1278
1409
tr_priority_t
1279
 
tr_torrentGetFilePriority( const tr_torrent *  tor, tr_file_index_t file )
 
1410
tr_torrentGetFilePriority( const tr_torrent * tor,
 
1411
                           tr_file_index_t    file )
1280
1412
{
1281
1413
    tr_priority_t ret;
1282
1414
 
1297
1429
 
1298
1430
    tr_torrentLock( tor );
1299
1431
    p = tr_new0( tr_priority_t, tor->info.fileCount );
1300
 
    for( i=0; i<tor->info.fileCount; ++i )
 
1432
    for( i = 0; i < tor->info.fileCount; ++i )
1301
1433
        p[i] = tor->info.files[i].priority;
1302
1434
    tr_torrentUnlock( tor );
1303
1435
 
1313
1445
                     tr_file_index_t    file )
1314
1446
{
1315
1447
    int doDownload;
 
1448
 
1316
1449
    tr_torrentLock( tor );
1317
1450
 
1318
1451
    assert( file < tor->info.fileCount );
1323
1456
}
1324
1457
 
1325
1458
static void
1326
 
setFileDND( tr_torrent      * tor,
1327
 
            tr_file_index_t   fileIndex,
1328
 
            int               doDownload )
 
1459
setFileDND( tr_torrent *    tor,
 
1460
            tr_file_index_t fileIndex,
 
1461
            int             doDownload )
1329
1462
{
1330
 
    tr_file * file;
1331
 
    const int dnd = !doDownload;
 
1463
    tr_file *        file;
 
1464
    const int        dnd = !doDownload;
1332
1465
    tr_piece_index_t firstPiece, firstPieceDND;
1333
1466
    tr_piece_index_t lastPiece, lastPieceDND;
1334
 
    tr_file_index_t i;
 
1467
    tr_file_index_t  i;
1335
1468
 
1336
1469
    file = &tor->info.files[fileIndex];
1337
1470
    file->dnd = dnd;
1341
1474
    /* can't set the first piece to DND unless
1342
1475
       every file using that piece is DND */
1343
1476
    firstPieceDND = dnd;
1344
 
    if( fileIndex > 0 ) {
1345
 
        for( i=fileIndex-1; firstPieceDND; --i ) {
 
1477
    if( fileIndex > 0 )
 
1478
    {
 
1479
        for( i = fileIndex - 1; firstPieceDND; --i )
 
1480
        {
1346
1481
            if( tor->info.files[i].lastPiece != firstPiece )
1347
1482
                break;
1348
1483
            firstPieceDND = tor->info.files[i].dnd;
1354
1489
    /* can't set the last piece to DND unless
1355
1490
       every file using that piece is DND */
1356
1491
    lastPieceDND = dnd;
1357
 
    for( i=fileIndex+1; lastPieceDND && i<tor->info.fileCount; ++i ) {
 
1492
    for( i = fileIndex + 1; lastPieceDND && i < tor->info.fileCount; ++i )
 
1493
    {
1358
1494
        if( tor->info.files[i].firstPiece != lastPiece )
1359
1495
            break;
1360
1496
        lastPieceDND = tor->info.files[i].dnd;
1369
1505
        tr_piece_index_t pp;
1370
1506
        tor->info.pieces[firstPiece].dnd = firstPieceDND;
1371
1507
        tor->info.pieces[lastPiece].dnd = lastPieceDND;
1372
 
        for( pp=firstPiece+1; pp<lastPiece; ++pp )
 
1508
        for( pp = firstPiece + 1; pp < lastPiece; ++pp )
1373
1509
            tor->info.pieces[pp].dnd = dnd;
1374
1510
    }
1375
1511
}
1376
1512
 
1377
1513
void
1378
 
tr_torrentInitFileDLs ( tr_torrent       * tor,
1379
 
                        tr_file_index_t  * files,
1380
 
                        tr_file_index_t    fileCount,
1381
 
                        int                doDownload )
1382
 
{
1383
 
    tr_file_index_t i;
1384
 
    tr_torrentLock( tor );
1385
 
 
1386
 
    for( i=0; i<fileCount; ++i )
1387
 
        setFileDND( tor, files[i], doDownload );
1388
 
    tr_cpInvalidateDND ( tor->completion );
1389
 
 
1390
 
    tr_torrentUnlock( tor );
1391
 
}
1392
 
 
1393
 
void
1394
 
tr_torrentSetFileDLs ( tr_torrent      * tor,
 
1514
tr_torrentInitFileDLs( tr_torrent *      tor,
1395
1515
                       tr_file_index_t * files,
1396
1516
                       tr_file_index_t   fileCount,
1397
1517
                       int               doDownload )
1398
1518
{
 
1519
    tr_file_index_t i;
 
1520
 
 
1521
    tr_torrentLock( tor );
 
1522
 
 
1523
    for( i = 0; i < fileCount; ++i )
 
1524
        setFileDND( tor, files[i], doDownload );
 
1525
    tr_cpInvalidateDND ( tor->completion );
 
1526
 
 
1527
    tr_torrentUnlock( tor );
 
1528
}
 
1529
 
 
1530
void
 
1531
tr_torrentSetFileDLs( tr_torrent *      tor,
 
1532
                      tr_file_index_t * files,
 
1533
                      tr_file_index_t   fileCount,
 
1534
                      int               doDownload )
 
1535
{
1399
1536
    tr_torrentLock( tor );
1400
1537
    tr_torrentInitFileDLs( tor, files, fileCount, doDownload );
1401
1538
    tr_torrentSaveResume( tor );
1407
1544
***/
1408
1545
 
1409
1546
void
1410
 
tr_torrentSetPeerLimit( tr_torrent  * tor,
1411
 
                        uint16_t      maxConnectedPeers )
 
1547
tr_torrentSetPeerLimit( tr_torrent * tor,
 
1548
                        uint16_t     maxConnectedPeers )
1412
1549
{
1413
1550
    tor->maxConnectedPeers = maxConnectedPeers;
1414
1551
}
1415
1552
 
1416
1553
uint16_t
1417
 
tr_torrentGetPeerLimit( const tr_torrent  * tor )
 
1554
tr_torrentGetPeerLimit( const tr_torrent * tor )
1418
1555
{
1419
1556
    return tor->maxConnectedPeers;
1420
1557
}
1424
1561
***/
1425
1562
 
1426
1563
tr_block_index_t
1427
 
_tr_block( const tr_torrent  * tor,
1428
 
           tr_piece_index_t    index,
1429
 
           uint32_t            offset )
 
1564
_tr_block( const tr_torrent * tor,
 
1565
           tr_piece_index_t   index,
 
1566
           uint32_t           offset )
1430
1567
{
1431
 
    const tr_info * inf = &tor->info;
 
1568
    const tr_info *  inf = &tor->info;
1432
1569
    tr_block_index_t ret;
 
1570
 
1433
1571
    ret = index;
1434
1572
    ret *= ( inf->pieceSize / tor->blockSize );
1435
1573
    ret += offset / tor->blockSize;
1446
1584
 
1447
1585
    if( index >= tor->info.pieceCount )
1448
1586
        err = 1;
1449
 
    else if ( offset >= tr_torPieceCountBytes( tor, index ) )
 
1587
    else if( length < 1 )
1450
1588
        err = 2;
 
1589
    else if( ( offset + length ) > tr_torPieceCountBytes( tor, index ) )
 
1590
        err = 3;
1451
1591
    else if( length > MAX_BLOCK_SIZE )
1452
 
        err = 3;
 
1592
        err = 4;
1453
1593
    else if( tr_pieceOffset( tor, index, offset, length ) > tor->info.totalSize )
1454
 
        err = 4;
 
1594
        err = 5;
1455
1595
 
1456
 
if( err ) fprintf( stderr, "index %lu offset %lu length %lu err %d\n", (unsigned long)index, (unsigned long)offset, (unsigned long)length, err );
 
1596
    if( err ) fprintf( stderr, "index %lu offset %lu length %lu err %d\n",
 
1597
                       (unsigned long)index, (unsigned long)offset,
 
1598
                       (unsigned long)length,
 
1599
                       err );
1457
1600
 
1458
1601
    return !err;
1459
1602
}
1460
1603
 
1461
 
 
1462
1604
uint64_t
1463
1605
tr_pieceOffset( const tr_torrent * tor,
1464
1606
                tr_piece_index_t   index,
1466
1608
                uint32_t           length )
1467
1609
{
1468
1610
    uint64_t ret;
 
1611
 
1469
1612
    ret = tor->info.pieceSize;
1470
1613
    ret *= index;
1471
1614
    ret += offset;
1478
1621
***/
1479
1622
 
1480
1623
int
1481
 
tr_torrentIsPieceChecked( const tr_torrent * tor, tr_piece_index_t piece )
 
1624
tr_torrentIsPieceChecked( const tr_torrent * tor,
 
1625
                          tr_piece_index_t   piece )
1482
1626
{
1483
1627
    return tr_bitfieldHas( tor->checkedPieces, piece );
1484
1628
}
1485
1629
 
1486
1630
void
1487
 
tr_torrentSetPieceChecked( tr_torrent * tor, tr_piece_index_t piece, int isChecked )
 
1631
tr_torrentSetPieceChecked( tr_torrent *     tor,
 
1632
                           tr_piece_index_t piece,
 
1633
                           int              isChecked )
1488
1634
{
1489
1635
    if( isChecked )
1490
1636
        tr_bitfieldAdd( tor->checkedPieces, piece );
1493
1639
}
1494
1640
 
1495
1641
void
1496
 
tr_torrentSetFileChecked( tr_torrent * tor, tr_file_index_t fileIndex, int isChecked )
 
1642
tr_torrentSetFileChecked( tr_torrent *    tor,
 
1643
                          tr_file_index_t fileIndex,
 
1644
                          int             isChecked )
1497
1645
{
1498
 
    const tr_file * file = &tor->info.files[fileIndex];
 
1646
    const tr_file *        file = &tor->info.files[fileIndex];
1499
1647
    const tr_piece_index_t begin = file->firstPiece;
1500
1648
    const tr_piece_index_t end = file->lastPiece + 1;
1501
1649
 
1506
1654
}
1507
1655
 
1508
1656
int
1509
 
tr_torrentIsFileChecked( const tr_torrent * tor, tr_file_index_t fileIndex )
 
1657
tr_torrentIsFileChecked( const tr_torrent * tor,
 
1658
                         tr_file_index_t    fileIndex )
1510
1659
{
1511
 
    const tr_file * file = &tor->info.files[fileIndex];
 
1660
    const tr_file *        file = &tor->info.files[fileIndex];
1512
1661
    const tr_piece_index_t begin = file->firstPiece;
1513
1662
    const tr_piece_index_t end = file->lastPiece + 1;
1514
 
    tr_piece_index_t i;
1515
 
    int isChecked = TRUE;
 
1663
    tr_piece_index_t       i;
 
1664
    int                    isChecked = TRUE;
1516
1665
 
1517
 
    for( i=begin; isChecked && i<end; ++i )
 
1666
    for( i = begin; isChecked && i < end; ++i )
1518
1667
        if( !tr_torrentIsPieceChecked( tor, i ) )
1519
1668
            isChecked = FALSE;
1520
1669
 
1530
1679
int
1531
1680
tr_torrentCountUncheckedPieces( const tr_torrent * tor )
1532
1681
{
1533
 
    return tor->info.pieceCount - tr_bitfieldCountTrueBits( tor->checkedPieces );
 
1682
    return tor->info.pieceCount - tr_bitfieldCountTrueBits(
 
1683
               tor->checkedPieces );
1534
1684
}
1535
1685
 
1536
1686
time_t*
1537
 
tr_torrentGetMTimes( const tr_torrent * tor, int * setme_n )
 
1687
tr_torrentGetMTimes( const tr_torrent * tor,
 
1688
                     size_t *           setme_n )
1538
1689
{
1539
 
    int i;
1540
 
    const int n = tor->info.fileCount;
1541
 
    time_t * m = tr_new0( time_t, n );
 
1690
    size_t       i;
 
1691
    const size_t n = tor->info.fileCount;
 
1692
    time_t *     m = tr_new0( time_t, n );
1542
1693
 
1543
 
    for( i=0; i<n; ++i ) {
1544
 
        char fname[MAX_PATH_LENGTH];
 
1694
    for( i = 0; i < n; ++i )
 
1695
    {
1545
1696
        struct stat sb;
1546
 
        tr_buildPath( fname, sizeof(fname),
1547
 
                      tor->downloadDir, tor->info.files[i].name, NULL );
1548
 
        if ( !stat( fname, &sb ) ) {
 
1697
        char * path = tr_buildPath( tor->downloadDir, tor->info.files[i].name, NULL );
 
1698
        if( !stat( path, &sb ) )
 
1699
        {
1549
1700
#ifdef SYS_DARWIN
1550
1701
            m[i] = sb.st_mtimespec.tv_sec;
1551
1702
#else
1552
1703
            m[i] = sb.st_mtime;
1553
1704
#endif
1554
1705
        }
 
1706
        tr_free( path );
1555
1707
    }
1556
1708
 
1557
1709
    *setme_n = n;
1563
1715
***/
1564
1716
 
1565
1717
void
1566
 
tr_torrentSetAnnounceList( tr_torrent             * tor,
1567
 
                           const tr_tracker_info  * trackers,
1568
 
                           int                      trackerCount )
 
1718
tr_torrentSetAnnounceList( tr_torrent *            tor,
 
1719
                           const tr_tracker_info * trackers,
 
1720
                           int                     trackerCount )
1569
1721
{
1570
1722
    tr_benc metainfo;
1571
1723
 
1572
1724
    /* save to the .torrent file */
1573
1725
    if( !tr_bencLoadFile( tor->info.torrent, &metainfo ) )
1574
1726
    {
1575
 
        int i;
1576
 
        int prevTier = -1;
 
1727
        int       i;
 
1728
        int       prevTier = -1;
1577
1729
        tr_benc * tier = NULL;
1578
1730
        tr_benc * announceList;
1579
 
        tr_info tmpInfo;
 
1731
        tr_info   tmpInfo;
1580
1732
 
1581
1733
        /* remove the old fields */
1582
1734
        tr_bencDictRemove( &metainfo, "announce" );
1585
1737
        /* add the new fields */
1586
1738
        tr_bencDictAddStr( &metainfo, "announce", trackers[0].announce );
1587
1739
        announceList = tr_bencDictAddList( &metainfo, "announce-list", 0 );
1588
 
        for( i=0; i<trackerCount; ++i ) {
1589
 
            if( prevTier != trackers[i].tier ) {
 
1740
        for( i = 0; i < trackerCount; ++i )
 
1741
        {
 
1742
            if( prevTier != trackers[i].tier )
 
1743
            {
1590
1744
                prevTier = trackers[i].tier;
1591
1745
                tier = tr_bencListAddList( announceList, 0 );
1592
1746
            }
1595
1749
 
1596
1750
        /* try to parse it back again, to make sure it's good */
1597
1751
        memset( &tmpInfo, 0, sizeof( tr_info ) );
1598
 
        if( !tr_metainfoParse( tor->handle, &tmpInfo, &metainfo ) )
 
1752
        if( !tr_metainfoParse( tor->session, &tmpInfo, &metainfo ) )
1599
1753
        {
1600
1754
            /* if it's good, save it and use it */
1601
1755
            tr_metainfoFree( &tor->info );
1604
1758
            tr_bencSaveFile( tor->info.torrent, &metainfo );
1605
1759
        }
1606
1760
 
1607
 
        /* cleanup */ 
 
1761
        /* cleanup */
1608
1762
        tr_bencFree( &metainfo );
1609
1763
    }
1610
1764
}
1615
1769
 
1616
1770
/** @deprecated this method will be removed in 1.40 */
1617
1771
void
1618
 
tr_torrentSetAddedDate( tr_torrent * tor, time_t t )
 
1772
tr_torrentSetAddedDate( tr_torrent * tor,
 
1773
                        time_t       t )
1619
1774
{
1620
1775
    tor->addedDate = t;
1621
1776
}
1622
1777
 
1623
1778
/** @deprecated this method will be removed in 1.40 */
1624
1779
void
1625
 
tr_torrentSetActivityDate( tr_torrent * tor, time_t t )
 
1780
tr_torrentSetActivityDate( tr_torrent * tor,
 
1781
                           time_t       t )
1626
1782
{
1627
1783
    tor->activityDate = t;
1628
1784
}
1629
1785
 
1630
1786
/** @deprecated this method will be removed in 1.40 */
1631
1787
void
1632
 
tr_torrentSetDoneDate( tr_torrent * tor, time_t t )
 
1788
tr_torrentSetDoneDate( tr_torrent * tor,
 
1789
                       time_t       t )
1633
1790
{
1634
1791
    tor->doneDate = t;
1635
1792
}
 
1793
 
 
1794
/**
 
1795
***
 
1796
**/
 
1797
 
 
1798
uint64_t
 
1799
tr_torrentGetBytesLeftToAllocate( const tr_torrent * tor )
 
1800
{
 
1801
    const tr_file * it;
 
1802
    const tr_file * end;
 
1803
    struct stat sb;
 
1804
    uint64_t bytesLeft = 0;
 
1805
 
 
1806
    for( it=tor->info.files, end=it+tor->info.fileCount; it!=end; ++it )
 
1807
    {
 
1808
        if( !it->dnd )
 
1809
        {
 
1810
            char * path = tr_buildPath( tor->downloadDir, it->name, NULL );
 
1811
 
 
1812
            bytesLeft += it->length;
 
1813
 
 
1814
            if( !stat( path, &sb )
 
1815
                    && S_ISREG( sb.st_mode )
 
1816
                    && ( (uint64_t)sb.st_size <= it->length ) )
 
1817
                bytesLeft -= sb.st_size;
 
1818
 
 
1819
            tr_free( path );
 
1820
        }
 
1821
    }
 
1822
 
 
1823
    return bytesLeft;
 
1824
}