Changeset 2 for trunk/libtransmission


Ignore:
Timestamp:
Jan 12, 2006, 6:20:48 PM (16 years ago)
Author:
root
Message:

Update 2005-11-01

Location:
trunk/libtransmission
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/fastresume.h

    r1 r2  
    3131 *    been completed or started in each slot
    3232 *
    33  * The resume file is located in ~/.transmission/. Its name is
    34  * "resume.<hash>".
     33 * The name of the resume file is "resume.<hash>".
    3534 *
    3635 * All values are stored in the native endianness. Moving a
     
    4039 **********************************************************************/
    4140
    42 static char * fastResumeFolderName()
    43 {
    44     char * ret;
    45     asprintf( &ret, "%s/.transmission", getenv( "HOME" ) );
    46     return ret;
    47 }
    48 
    4941static char * fastResumeFileName( tr_io_t * io )
    5042{
     43    tr_torrent_t * tor = io->tor;
    5144    char * ret, * p;
    5245    int i;
    5346
    54     p = fastResumeFolderName();
    55     asprintf( &ret, "%s/resume.%40d", p, 0 );
    56     free( p );
     47    asprintf( &ret, "%s/resume.%40d", tor->prefsDirectory, 0 );
    5748
    5849    p = &ret[ strlen( ret ) - 2 * SHA_DIGEST_LENGTH ];
     
    122113    }
    123114
    124     /* Create folder if missing */
    125     path = fastResumeFolderName();
    126     mkdir( path, 0755 );
    127     free( path );
    128 
    129115    /* Create/overwrite the resume file */
    130116    path = fastResumeFileName( io );
     
    136122        return;
    137123    }
    138     free( path );
    139124   
    140125    /* Write format version */
     
    161146
    162147    fclose( file );
     148
     149    tr_dbg( "Resume file '%s' written", path );
     150    free( path );
    163151}
    164152
     
    185173        return 1;
    186174    }
     175    tr_dbg( "Resume file '%s' loaded", path );
    187176    free( path );
    188177
  • trunk/libtransmission/internal.h

    r1 r2  
    156156    tr_tracker_t    * tracker;
    157157    tr_io_t         * io;
     158    uint64_t          stopDate;
    158159
    159160    int               bindSocket;
     
    165166    uint64_t          downloaded[10];
    166167    uint64_t          uploaded[10];
     168
     169    char            * prefsDirectory;
    167170};
    168171
     
    180183
    181184    char           id[21];
     185    char           prefsDirectory[256];
    182186};
    183187
  • trunk/libtransmission/peer.c

    r1 r2  
    101101#include "peermessages.h"
    102102#include "peerutils.h"
     103#include "peerparse.h"
    103104
    104105/***********************************************************************
     
    233234    }
    234235
     236    if( tor->status & TR_STATUS_STOPPING )
     237    {
     238        return;
     239    }
     240
    235241    /* Check for incoming connections */
    236242    if( tor->bindSocket > -1 &&
     
    332338                peer->date  = tr_date();
    333339                peer->pos  += ret;
    334                 if( parseMessage( tor, peer, ret ) )
     340                if( parseBuf( tor, peer, ret ) )
    335341                {
    336342                    goto dropPeer;
  • trunk/libtransmission/peermessages.h

    r1 r2  
    2121 *****************************************************************************/
    2222
     23/***********************************************************************
     24 * This file handles all outgoing messages
     25 **********************************************************************/
     26
    2327static uint8_t * messagesPending( tr_peer_t * peer, int * size )
    2428{
  • trunk/libtransmission/peerutils.h

    r1 r2  
    123123    }
    124124
     125    /* TODO: check for bad downloaders */
     126
    125127#if 0
    126128    /* Choke unchoked peers we are not sending anything to */
     
    161163        }
    162164    }
    163 
    164     return 0;
    165 }
    166 
    167 static int parseMessage( tr_torrent_t * tor, tr_peer_t * peer,
    168                          int newBytes )
    169 {
    170     tr_info_t * inf = &tor->info;
    171 
    172     int       i, j;
    173     int       len;
    174     char      id;
    175     uint8_t * p   = peer->buf;
    176     uint8_t * end = &p[peer->pos];
    177    
    178     for( ;; )
    179     {
    180         if( peer->pos < 4 )
    181         {
    182             break;
    183         }
    184 
    185         if( peer->status & PEER_STATUS_HANDSHAKE )
    186         {
    187             char * client;
    188 
    189             if( p[0] != 19 || memcmp( &p[1], "Bit", 3 ) )
    190             {
    191                 /* Don't wait until we get 68 bytes, this is wrong
    192                    already */
    193                 peer_dbg( "GET  handshake, invalid" );
    194                 tr_netSend( peer->socket, (uint8_t *) "Nice try...\r\n", 13 );
    195                 return 1;
    196             }
    197 
    198             if( peer->pos < 68 )
    199             {
    200                 break;
    201             }
    202 
    203             if( memcmp( &p[4], "Torrent protocol", 16 ) )
    204             {
    205                 peer_dbg( "GET  handshake, invalid" );
    206                 return 1;
    207             }
    208 
    209             if( memcmp( &p[28], inf->hash, 20 ) )
    210             {
    211                 peer_dbg( "GET  handshake, wrong torrent hash" );
    212                 return 1;
    213             }
    214 
    215             if( !memcmp( &p[48], tor->id, 20 ) )
    216             {
    217                 /* We are connected to ourselves... */
    218                 peer_dbg( "GET  handshake, that is us" );
    219                 return 1;
    220             }
    221 
    222             peer->status  = PEER_STATUS_CONNECTED;
    223             memcpy( peer->id, &p[48], 20 );
    224             p            += 68;
    225             peer->pos    -= 68;
    226 
    227             for( i = 0; i < tor->peerCount; i++ )
    228             {
    229                 if( tor->peers[i] == peer )
    230                 {
    231                     continue;
    232                 }
    233                 if( !peerCmp( peer, tor->peers[i] ) )
    234                 {
    235                     peer_dbg( "GET  handshake, duplicate" );
    236                     return 1;
    237                 }
    238             }
    239 
    240             client = tr_clientForId( (uint8_t *) peer->id );
    241             peer_dbg( "GET  handshake, ok (%s)", client );
    242             free( client );
    243 
    244             sendBitfield( tor, peer );
    245 
    246             continue;
    247         }
    248        
    249         /* Get payload size */
    250         TR_NTOHL( p, len );
    251         p += 4;
    252 
    253         if( len > 9 + tor->blockSize )
    254         {
    255             /* This shouldn't happen. Forget about that peer */
    256             peer_dbg( "message too large" );
    257             return 1;
    258         }
    259 
    260         if( !len )
    261         {
    262             /* keep-alive */
    263             peer_dbg( "GET  keep-alive" );
    264             peer->pos -= 4;
    265             continue;
    266         }
    267 
    268         /* That's a piece coming */
    269         if( p < end && *p == 7 )
    270         {
    271             /* XXX */
    272             tor->downloaded[9] += newBytes;
    273             peer->inTotal      += newBytes;
    274             newBytes            = 0;
    275         }
    276 
    277         if( &p[len] > end )
    278         {
    279             /* We do not have the entire message */
    280             p -= 4;
    281             break;
    282         }
    283 
    284         /* Remaining data after this message */
    285         peer->pos -= 4 + len;
    286 
    287         /* Type of the message */
    288         id = *(p++);
    289 
    290         switch( id )
    291         {
    292             case 0: /* choke */
    293             {
    294                 tr_request_t * r;
    295 
    296                 if( len != 1 )
    297                 {
    298                     peer_dbg( "GET  choke, invalid" );
    299                     return 1;
    300                 }
    301 
    302                 peer_dbg( "GET  choke" );
    303                 peer->peerChoking    = 1;
    304 
    305                 for( i = 0; i < peer->inRequestCount; i++ )
    306                 {
    307                     r = &peer->inRequests[i];
    308                     if( tor->blockHave[tr_block(r->index,r->begin)] > 0 )
    309                     {
    310                         tor->blockHave[tr_block(r->index,r->begin)]--;
    311                     }
    312                 }
    313                 peer->inRequestCount = 0;
    314 
    315                 break;
    316             }
    317             case 1: /* unchoke */
    318                 if( len != 1 )
    319                 {
    320                     peer_dbg( "GET  unchoke, invalid" );
    321                     return 1;
    322                 }
    323                 peer_dbg( "GET  unchoke" );
    324                 peer->peerChoking = 0;
    325                 break;
    326             case 2: /* interested */
    327                 if( len != 1 )
    328                 {
    329                     peer_dbg( "GET  interested, invalid" );
    330                     return 1;
    331                 }
    332                 peer_dbg( "GET  interested" );
    333                 peer->peerInterested = 1;
    334                 break;
    335             case 3: /* uninterested */
    336                 if( len != 1 )
    337                 {
    338                     peer_dbg( "GET  uninterested, invalid" );
    339                     return 1;
    340                 }
    341                 peer_dbg( "GET  uninterested" );
    342                 peer->peerInterested = 0;
    343                 break;
    344             case 4: /* have */
    345             {
    346                 uint32_t piece;
    347                 if( len != 5 )
    348                 {
    349                     peer_dbg( "GET  have, invalid" );
    350                     return 1;
    351                 }
    352                 TR_NTOHL( p, piece );
    353                 if( !peer->bitfield )
    354                 {
    355                     peer->bitfield = calloc( ( inf->pieceCount + 7 ) / 8, 1 );
    356                 }
    357                 tr_bitfieldAdd( peer->bitfield, piece );
    358 
    359                 updateInterest( tor, peer );
    360 
    361                 peer_dbg( "GET  have %d", piece );
    362                 break;
    363             }
    364             case 5: /* bitfield */
    365             {
    366                 int bitfieldSize;
    367 
    368                 bitfieldSize = ( inf->pieceCount + 7 ) / 8;
    369                
    370                 if( len != 1 + bitfieldSize )
    371                 {
    372                     peer_dbg( "GET  bitfield, wrong size" );
    373                     return 1;
    374                 }
    375 
    376                 /* Make sure the spare bits are unset */
    377                 if( ( inf->pieceCount & 0x7 ) )
    378                 {
    379                     uint8_t lastByte;
    380                    
    381                     lastByte   = p[bitfieldSize-1];
    382                     lastByte <<= inf->pieceCount & 0x7;
    383                     lastByte  &= 0xFF;
    384 
    385                     if( lastByte )
    386                     {
    387                         peer_dbg( "GET  bitfield, spare bits set" );
    388                         return 1;
    389                     }
    390                 }
    391 
    392                 if( !peer->bitfield )
    393                 {
    394                     peer->bitfield = malloc( bitfieldSize );
    395                 }
    396                 memcpy( peer->bitfield, p, bitfieldSize );
    397 
    398                 updateInterest( tor, peer );
    399 
    400                 peer_dbg( "GET  bitfield, ok" );
    401                 break;
    402             }
    403             case 6: /* request */
    404             {
    405                 int index, begin, length;
    406 
    407                 if( peer->amChoking )
    408                 {
    409                     /* Didn't he get it? */
    410                     sendChoke( peer, 1 );
    411                     break;
    412                 }
    413                
    414                 TR_NTOHL( p,     index );
    415                 TR_NTOHL( &p[4], begin );
    416                 TR_NTOHL( &p[8], length );
    417 
    418                 peer_dbg( "GET  request %d/%d (%d bytes)",
    419                           index, begin, length );
    420 
    421                 /* TODO sanity checks (do we have the piece, etc) */
    422 
    423                 if( length > 16384 )
    424                 {
    425                     /* Sorry mate */
    426                     return 1;
    427                 }
    428 
    429                 if( peer->outRequestCount < MAX_REQUEST_COUNT )
    430                 {
    431                     tr_request_t * r;
    432                    
    433                     r         = &peer->outRequests[peer->outRequestCount];
    434                     r->index  = index;
    435                     r->begin  = begin;
    436                     r->length = length;
    437 
    438                     (peer->outRequestCount)++;
    439                 }
    440                 else
    441                 {
    442                     tr_err( "Too many requests" );
    443                     return 1;
    444                 }
    445                 break;
    446             }
    447             case 7: /* piece */
    448             {
    449                 int index, begin;
    450                 int block;
    451                 tr_request_t * r;
    452 
    453                 TR_NTOHL( p,     index );
    454                 TR_NTOHL( &p[4], begin );
    455 
    456                 peer_dbg( "GET  piece %d/%d (%d bytes)",
    457                           index, begin, len - 9 );
    458 
    459                 if( peer->inRequestCount < 1 )
    460                 {
    461                     /* Our "cancel" was probably late */
    462                     peer_dbg( "not expecting a block" );
    463                     break;
    464                 }
    465                
    466                 r = &peer->inRequests[0];
    467                 if( index != r->index || begin != r->begin )
    468                 {
    469                     int suckyClient;
    470 
    471                     /* Either our "cancel" was late, or this is a sucky
    472                        client that cannot deal with multiple requests */
    473                     suckyClient = 0;
    474                     for( i = 0; i < peer->inRequestCount; i++ )
    475                     {
    476                         r = &peer->inRequests[i];
    477 
    478                         if( index != r->index || begin != r->begin )
    479                         {
    480                             continue;
    481                         }
    482 
    483                         /* Sucky client, he dropped the previous requests */
    484                         peer_dbg( "block was expected later" );
    485                         for( j = 0; j < i; j++ )
    486                         {
    487                             r = &peer->inRequests[j];
    488                             if( tor->blockHave[tr_block(r->index,r->begin)] > 0 )
    489                             {
    490                                 tor->blockHave[tr_block(r->index,r->begin)]--;
    491                             }
    492                         }
    493                         suckyClient = 1;
    494                         peer->inRequestCount -= i;
    495                         memmove( &peer->inRequests[0], &peer->inRequests[i],
    496                                  peer->inRequestCount * sizeof( tr_request_t ) );
    497                         r = &peer->inRequests[0];
    498                         break;
    499                     }
    500 
    501                     if( !suckyClient )
    502                     {
    503                         r = &peer->inRequests[0];
    504                         peer_dbg( "wrong block (expecting %d/%d)",
    505                                   r->index, r->begin );
    506                         break;
    507                     }
    508                 }
    509 
    510                 if( len - 9 != r->length )
    511                 {
    512                     peer_dbg( "wrong size (expecting %d)", r->length );
    513                     return 1;
    514                 }
    515 
    516                 block = tr_block( r->index, r->begin );
    517                 if( tor->blockHave[block] < 0 )
    518                 {
    519                     peer_dbg( "have this block already" );
    520                     (peer->inRequestCount)--;
    521                     memmove( &peer->inRequests[0], &peer->inRequests[1],
    522                              peer->inRequestCount * sizeof( tr_request_t ) );
    523                     break;
    524                 }
    525 
    526                 tor->blockHave[block]  = -1;
    527                 tor->blockHaveCount   +=  1;
    528                 tr_ioWrite( tor->io, index, begin, len - 9, &p[8] );
    529 
    530                 sendCancel( tor, block );
    531 
    532                 if( tr_bitfieldHas( tor->bitfield, index ) )
    533                 {
    534                     tr_peer_t * otherPeer;
    535 
    536                     for( i = 0; i < tor->peerCount; i++ )
    537                     {
    538                         otherPeer = tor->peers[i];
    539 
    540                         if( otherPeer->status < PEER_STATUS_CONNECTED )
    541                         {
    542                             continue;
    543                         }
    544 
    545                         sendHave( otherPeer, index );
    546                         updateInterest( tor, otherPeer );
    547                     }
    548                 }
    549 
    550                 (peer->inRequestCount)--;
    551                 memmove( &peer->inRequests[0], &peer->inRequests[1],
    552                          peer->inRequestCount * sizeof( tr_request_t ) );
    553                 break;
    554             }
    555             case 8: /* cancel */
    556             {
    557                 int index, begin, length;
    558                 int i;
    559                 tr_request_t * r;
    560 
    561                 TR_NTOHL( p,     index );
    562                 TR_NTOHL( &p[4], begin );
    563                 TR_NTOHL( &p[8], length );
    564 
    565                 peer_dbg( "GET  cancel %d/%d (%d bytes)",
    566                           index, begin, length );
    567 
    568                 for( i = 0; i < peer->outRequestCount; i++ )
    569                 {
    570                     r = &peer->outRequests[i];
    571                     if( r->index == index && r->begin == begin &&
    572                         r->length == length )
    573                     {
    574                         (peer->outRequestCount)--;
    575                         memmove( &r[0], &r[1], sizeof( tr_request_t ) *
    576                                 ( peer->outRequestCount - i ) );
    577                         break;
    578                     }
    579                 }
    580 
    581                 break;
    582             }
    583             case 9:
    584             {
    585                 in_port_t port;
    586 
    587                 if( len != 3 )
    588                 {
    589                     peer_dbg( "GET  port, invalid" );
    590                     return 1;
    591                 }
    592 
    593                 port = *( (in_port_t *) p );
    594                 peer_dbg( "GET  port %d", ntohs( port ) );
    595 
    596                 break;
    597             }
    598             default:
    599             {
    600                 peer_dbg( "Unknown message '%d'", id );
    601                 return 1;
    602             }
    603         }
    604 
    605         p += len - 1;
    606     }
    607 
    608     memmove( peer->buf, p, peer->pos );
    609165
    610166    return 0;
     
    663219 * missing less blocks.
    664220 **********************************************************************/
    665 static int chooseBlock( tr_torrent_t * tor, tr_peer_t * peer )
     221static inline int chooseBlock( tr_torrent_t * tor, tr_peer_t * peer )
    666222{
    667223    tr_info_t * inf = &tor->info;
     
    799355    {
    800356        /* TODO: optimize */
    801         if( tor->blockHave[i] > 0 && tor->blockHave[i] < minDownloading )
     357        if( tr_bitfieldHas( peer->bitfield, tr_blockPiece( i ) ) &&
     358            tor->blockHave[i] >= 0 && tor->blockHave[i] < minDownloading )
    802359        {
    803360            block          = i;
  • trunk/libtransmission/transmission.c

    r1 r2  
    6060
    6161    h->bindPort = 9090;
     62
     63    snprintf( h->prefsDirectory, sizeof( h->prefsDirectory ),
     64              "%s/.transmission", getenv( "HOME" ) );
     65    mkdir( h->prefsDirectory, 0755 );
    6266   
    6367    return h;
     68}
     69
     70/***********************************************************************
     71 * tr_getPrefsDirectory
     72 ***********************************************************************
     73 *
     74 **********************************************************************/
     75char * tr_getPrefsDirectory( tr_handle_t * h )
     76{
     77    return (char *) h->prefsDirectory;
    6478}
    6579
     
    185199    tor->upload  = h->upload;
    186200    tor->fdlimit = h->fdlimit;
     201    tor->prefsDirectory = (char *) h->prefsDirectory;
    187202 
    188203    /* We have a new torrent */
     
    253268    tr_trackerStopped( tor->tracker );
    254269    tor->status = TR_STATUS_STOPPING;
     270    tor->stopDate = tr_date();
    255271    tr_lockUnlock( tor->lock );
    256272}
     
    317333        tr_lockLock( tor->lock );
    318334
    319         if( tor->status & TR_STATUS_STOPPED )
     335        if( ( tor->status & TR_STATUS_STOPPED ) ||
     336            ( ( tor->status & TR_STATUS_STOPPING ) &&
     337              tr_date() > tor->stopDate + 60000 ) )
    320338        {
    321339            torrentReallyStop( h, i );
     
    479497
    480498        /* Receive/send messages */
    481         if( !( tor->status & TR_STATUS_STOPPING ) )
    482         {
    483             tr_peerPulse( tor );
    484         }
     499        tr_peerPulse( tor );
    485500
    486501        /* Try to get new peers or to send a message to the tracker */
  • trunk/libtransmission/transmission.h

    r1 r2  
    4141
    4242/***********************************************************************
     43 * tr_getPrefsDirectory
     44 ***********************************************************************
     45 * Returns the full path to the directory used by libtransmission to
     46 * store the resume files. The string belongs to libtransmission, do
     47 * not free it.
     48 **********************************************************************/
     49char * tr_getPrefsDirectory( tr_handle_t * );
     50
     51/***********************************************************************
    4352 * tr_setBindPort
    4453 ***********************************************************************
Note: See TracChangeset for help on using the changeset viewer.