Changeset 1405


Ignore:
Timestamp:
Jan 19, 2007, 8:36:49 AM (15 years ago)
Author:
titer
Message:

Another split

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Transmission.xcodeproj/project.pbxproj

    r1403 r1405  
    5757                4D9A55700B607ED80086C2A4 /* shared.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D9A556E0B607ED80086C2A4 /* shared.c */; };
    5858                4D9A55710B607ED80086C2A4 /* shared.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D9A556F0B607ED80086C2A4 /* shared.h */; };
     59                4D9A559C0B60BA5B0086C2A4 /* torrent.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D9A559B0B60BA5B0086C2A4 /* torrent.c */; };
    5960                4DA6FDBA0911233800450CB1 /* PauseOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDB80911233800450CB1 /* PauseOn.png */; };
    6061                4DA6FDBB0911233800450CB1 /* PauseOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDB90911233800450CB1 /* PauseOff.png */; };
     
    256257                4D9A556E0B607ED80086C2A4 /* shared.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = shared.c; path = libtransmission/shared.c; sourceTree = "<group>"; };
    257258                4D9A556F0B607ED80086C2A4 /* shared.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = shared.h; path = libtransmission/shared.h; sourceTree = "<group>"; };
     259                4D9A559B0B60BA5B0086C2A4 /* torrent.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = torrent.c; path = libtransmission/torrent.c; sourceTree = "<group>"; };
    258260                4DA6FDB80911233800450CB1 /* PauseOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PauseOn.png; path = macosx/Images/PauseOn.png; sourceTree = "<group>"; };
    259261                4DA6FDB90911233800450CB1 /* PauseOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PauseOff.png; path = macosx/Images/PauseOff.png; sourceTree = "<group>"; };
     
    646648                                4D9A556F0B607ED80086C2A4 /* shared.h */,
    647649                                4D9A556E0B607ED80086C2A4 /* shared.c */,
     650                                4D9A559B0B60BA5B0086C2A4 /* torrent.c */,
    648651                        );
    649652                        name = libtransmission;
     
    906909                                4DAB87CC0ABE1F730081CF7E /* http.c in Sources */,
    907910                                4D9A55700B607ED80086C2A4 /* shared.c in Sources */,
     911                                4D9A559C0B60BA5B0086C2A4 /* torrent.c in Sources */,
    908912                        );
    909913                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/libtransmission/transmission.c

    r1404 r1405  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    2525#include "transmission.h"
    2626#include "shared.h"
    27 
    28 /***********************************************************************
    29  * Local prototypes
    30  **********************************************************************/
    31 static tr_torrent_t * torrentRealInit( tr_handle_t *, tr_torrent_t * tor,
    32                                        int flags, int * error );
    33 static void torrentReallyStop( tr_torrent_t * );
    34 static void downloadLoop( void * );
    3527
    3628/***********************************************************************
     
    111103}
    112104
    113 void tr_setUseCustomLimit( tr_torrent_t * tor, int limit )
    114 {
    115     tor->customSpeedLimit = limit;
    116 }
    117 
    118 void tr_setUploadLimit( tr_torrent_t * tor, int limit )
    119 {
    120     tr_rcSetLimit( tor->upload, limit );
    121 }
    122 
    123 void tr_setDownloadLimit( tr_torrent_t * tor, int limit )
    124 {
    125     tr_rcSetLimit( tor->download, limit );
    126 }
    127 
    128105void tr_torrentRates( tr_handle_t * h, float * dl, float * ul )
    129106{
     
    142119}
    143120
    144 tr_torrent_t * tr_torrentInit( tr_handle_t * h, const char * path,
    145                                int flags, int * error )
    146 {
    147     tr_torrent_t  * tor = calloc( sizeof( tr_torrent_t ), 1 );
    148     int             saveCopy = ( TR_FSAVEPRIVATE & flags );
    149 
    150     /* Parse torrent file */
    151     if( tr_metainfoParse( &tor->info, path, NULL, saveCopy ) )
    152     {
    153         *error = TR_EINVALID;
    154         free( tor );
    155         return NULL;
    156     }
    157 
    158     return torrentRealInit( h, tor, flags, error );
    159 }
    160 
    161 tr_torrent_t * tr_torrentInitSaved( tr_handle_t * h, const char * hashStr,
    162                                     int flags, int * error )
    163 {
    164     tr_torrent_t  * tor = calloc( sizeof( tr_torrent_t ), 1 );
    165 
    166     /* Parse torrent file */
    167     if( tr_metainfoParse( &tor->info, NULL, hashStr, 0 ) )
    168     {
    169         *error = TR_EINVALID;
    170         free( tor );
    171         return NULL;
    172     }
    173 
    174     return torrentRealInit( h, tor, ( TR_FSAVEPRIVATE | flags ), error );
    175 }
    176 
    177 /***********************************************************************
    178  * tr_torrentInit
    179  ***********************************************************************
    180  * Allocates a tr_torrent_t structure, then relies on tr_metainfoParse
    181  * to fill it.
    182  **********************************************************************/
    183 static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor,
    184                                        int flags, int * error )
    185 {
    186     tr_torrent_t  * tor_tmp;
    187     tr_info_t     * inf;
    188     int             i;
    189    
    190     inf        = &tor->info;
    191     inf->flags = flags;
    192 
    193     /* Make sure this torrent is not already open */
    194     for( tor_tmp = h->torrentList; tor_tmp; tor_tmp = tor_tmp->next )
    195     {
    196         if( !memcmp( tor->info.hash, tor_tmp->info.hash,
    197                      SHA_DIGEST_LENGTH ) )
    198         {
    199             *error = TR_EDUPLICATE;
    200             tr_metainfoFree( &tor->info );
    201             free( tor );
    202             return NULL;
    203         }
    204     }
    205 
    206     tor->handle = h;
    207     tor->status = TR_STATUS_PAUSE;
    208     tor->id     = h->id;
    209     tor->key    = h->key;
    210     tor->bindPort = &h->bindPort;
    211         tor->finished = 0;
    212 
    213     /* Escaped info hash for HTTP queries */
    214     for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
    215     {
    216         sprintf( &tor->escapedHashString[3*i], "%%%02x", inf->hash[i] );
    217     }
    218 
    219     /* Block size: usually 16 ko, or less if we have to */
    220     tor->blockSize  = MIN( inf->pieceSize, 1 << 14 );
    221     tor->blockCount = ( inf->totalSize + tor->blockSize - 1 ) /
    222                         tor->blockSize;
    223     tor->completion = tr_cpInit( tor );
    224 
    225     tr_lockInit( &tor->lock );
    226 
    227     tor->fdlimit        = h->fdlimit;
    228     tor->upload         = tr_rcInit();
    229     tor->download       = tr_rcInit();
    230     tor->swarmspeed     = tr_rcInit();
    231  
    232     /* We have a new torrent */
    233     tr_sharedLock( h->shared );
    234     tor->prev = NULL;
    235     tor->next = h->torrentList;
    236     if( tor->next )
    237     {
    238         tor->next->prev = tor;
    239     }
    240     h->torrentList = tor;
    241     (h->torrentCount)++;
    242     tr_sharedUnlock( h->shared );
    243 
    244     if( 0 > h->bindPort )
    245     {
    246         tr_setBindPort( h, TR_DEFAULT_PORT );
    247     }
    248 
    249     return tor;
    250 }
    251 
    252 tr_info_t * tr_torrentInfo( tr_torrent_t * tor )
    253 {
    254     return &tor->info;
    255 }
    256 
    257 /***********************************************************************
    258  * tr_torrentScrape     
    259  **********************************************************************/
    260 int tr_torrentScrape( tr_torrent_t * tor, int * s, int * l, int * d )
    261 {
    262     return tr_trackerScrape( tor, s, l, d );
    263 }
    264 
    265 void tr_torrentSetFolder( tr_torrent_t * tor, const char * path )
    266 {
    267     tor->destination = strdup( path );
    268     tr_ioLoadResume( tor );
    269 }
    270 
    271 char * tr_torrentGetFolder( tr_torrent_t * tor )
    272 {
    273     return tor->destination;
    274 }
    275 
    276 void tr_torrentStart( tr_torrent_t * tor )
    277 {
    278     char name[32];
    279 
    280     if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
    281     {
    282         /* Join the thread first */
    283         torrentReallyStop( tor );
    284     }
    285 
    286     tor->downloadedPrev += tor->downloadedCur;
    287     tor->downloadedCur   = 0;
    288     tor->uploadedPrev   += tor->uploadedCur;
    289     tor->uploadedCur     = 0;
    290 
    291     tor->status  = TR_STATUS_CHECK;
    292     tor->error   = TR_OK;
    293     tor->tracker = tr_trackerInit( tor );
    294 
    295     tor->date = tr_date();
    296     tor->die = 0;
    297     snprintf( name, sizeof( name ), "torrent %p", tor );
    298     tr_threadCreate( &tor->thread, downloadLoop, tor, name );
    299 }
    300 
    301 static void torrentStop( tr_torrent_t * tor )
    302 {
    303     tr_trackerStopped( tor->tracker );
    304     tr_rcReset( tor->download );
    305     tr_rcReset( tor->upload );
    306     tr_rcReset( tor->swarmspeed );
    307     tor->status = TR_STATUS_STOPPING;
    308     tor->stopDate = tr_date();
    309 }
    310 
    311 void tr_torrentStop( tr_torrent_t * tor )
    312 {
    313     tr_lockLock( &tor->lock );
    314     torrentStop( tor );
    315     tr_lockUnlock( &tor->lock );
    316 }
    317 
    318 /***********************************************************************
    319  * torrentReallyStop
    320  ***********************************************************************
    321  * Joins the download thread and frees/closes everything related to it.
    322  **********************************************************************/
    323 static void torrentReallyStop( tr_torrent_t * tor )
    324 {
    325     tor->die = 1;
    326     tr_threadJoin( &tor->thread );
    327 
    328     tr_trackerClose( tor->tracker );
    329     tor->tracker = NULL;
    330 
    331     tr_lockLock( &tor->lock );
    332     while( tor->peerCount > 0 )
    333     {
    334         tr_peerRem( tor, 0 );
    335     }
    336     tr_lockUnlock( &tor->lock );
    337 }
    338 
    339 /***********************************************************************
    340  * tr_torrentCount
    341  ***********************************************************************
    342  *
    343  **********************************************************************/
    344121int tr_torrentCount( tr_handle_t * h )
    345122{
     
    358135}
    359136
    360 int tr_getFinished( tr_torrent_t * tor )
    361 {
    362     if( tor->finished )
    363     {
    364         tor->finished = 0;
    365         return 1;
    366     }
    367     return 0;
    368 }
    369 
    370 void tr_manualUpdate( tr_torrent_t * tor )
    371 {
    372     if( !( tor->status & TR_STATUS_ACTIVE ) )
    373         return;
    374    
    375     tr_lockLock( &tor->lock );
    376     tr_trackerAnnouncePulse( tor->tracker, 1 );
    377     tr_lockUnlock( &tor->lock );
    378 }
    379 
    380 tr_stat_t * tr_torrentStat( tr_torrent_t * tor )
    381 {
    382     tr_stat_t * s;
    383     tr_peer_t * peer;
    384     tr_info_t * inf = &tor->info;
    385     tr_tracker_t * tc;
    386     int i;
    387 
    388     tor->statCur = ( tor->statCur + 1 ) % 2;
    389     s = &tor->stats[tor->statCur];
    390 
    391     if( ( tor->status & TR_STATUS_STOPPED ) ||
    392         ( ( tor->status & TR_STATUS_STOPPING ) &&
    393           tr_date() > tor->stopDate + 60000 ) )
    394     {
    395         torrentReallyStop( tor );
    396         tor->status = TR_STATUS_PAUSE;
    397     }
    398 
    399     tr_lockLock( &tor->lock );
    400 
    401     s->status = tor->status;
    402     s->error  = tor->error;
    403     memcpy( s->errorString, tor->errorString,
    404             sizeof( s->errorString ) );
    405 
    406     tc = tor->tracker;
    407     s->cannotConnect = tr_trackerCannotConnect( tc );
    408    
    409     if( tc )
    410     {
    411         s->trackerAddress  = tr_trackerAddress(  tc );
    412         s->trackerPort     = tr_trackerPort(     tc );
    413         s->trackerAnnounce = tr_trackerAnnounce( tc );
    414     }
    415     else
    416     {
    417         s->trackerAddress  = inf->trackerList[0].list[0].address;
    418         s->trackerPort     = inf->trackerList[0].list[0].port;
    419         s->trackerAnnounce = inf->trackerList[0].list[0].announce;
    420     }
    421 
    422     s->peersTotal       = 0;
    423     s->peersIncoming    = 0;
    424     s->peersUploading   = 0;
    425     s->peersDownloading = 0;
    426    
    427     for( i = 0; i < tor->peerCount; i++ )
    428     {
    429         peer = tor->peers[i];
    430    
    431         if( tr_peerIsConnected( peer ) )
    432         {
    433             (s->peersTotal)++;
    434            
    435             if( tr_peerIsIncoming( peer ) )
    436             {
    437                 (s->peersIncoming)++;
    438             }
    439             if( !tr_peerIsChoking( peer ) )
    440             {
    441                 (s->peersUploading)++;
    442             }
    443             if( tr_peerIsUnchoked( peer ) )
    444             {
    445                 (s->peersDownloading)++;
    446             }
    447         }
    448     }
    449 
    450     s->progress = tr_cpCompletionAsFloat( tor->completion );
    451     if( tor->status & TR_STATUS_DOWNLOAD )
    452     {
    453         s->rateDownload = tr_rcRate( tor->download );
    454     }
    455     else
    456     {
    457         /* tr_rcRate() doesn't make the difference between 'piece'
    458            messages and other messages, which causes a non-zero
    459            download rate even tough we are not downloading. So we
    460            force it to zero not to confuse the user. */
    461         s->rateDownload = 0.0;
    462     }
    463     s->rateUpload = tr_rcRate( tor->upload );
    464    
    465     s->seeders  = tr_trackerSeeders( tc );
    466     s->leechers = tr_trackerLeechers( tc );
    467     s->completedFromTracker = tr_trackerDownloaded( tc );
    468 
    469     s->swarmspeed = tr_rcRate( tor->swarmspeed );
    470 
    471     if( s->rateDownload < 0.1 )
    472     {
    473         s->eta = -1;
    474     }
    475     else
    476     {
    477         s->eta = ( 1.0 - s->progress ) *
    478             (float) inf->totalSize / s->rateDownload / 1024.0;
    479     }
    480 
    481     s->downloaded = tor->downloadedCur + tor->downloadedPrev;
    482     s->uploaded   = tor->uploadedCur   + tor->uploadedPrev;
    483    
    484     if( s->downloaded == 0 )
    485     {
    486         s->ratio = s->uploaded == 0 ? TR_RATIO_NA : TR_RATIO_INF;
    487     }
    488     else
    489     {
    490         s->ratio = (float)s->uploaded / (float)s->downloaded;
    491     }
    492    
    493     tr_lockUnlock( &tor->lock );
    494 
    495     return s;
    496 }
    497 
    498 tr_peer_stat_t * tr_torrentPeers( tr_torrent_t * tor, int * peerCount )
    499 {
    500     tr_peer_stat_t * peers;
    501 
    502     tr_lockLock( &tor->lock );
    503 
    504     *peerCount = tor->peerCount;
    505    
    506     peers = (tr_peer_stat_t *) calloc( tor->peerCount, sizeof( tr_peer_stat_t ) );
    507     if (peers != NULL)
    508     {
    509         tr_peer_t * peer;
    510         struct in_addr * addr;
    511         int i;
    512         for( i = 0; i < tor->peerCount; i++ )
    513         {
    514             peer = tor->peers[i];
    515            
    516             addr = tr_peerAddress( peer );
    517             if( NULL != addr )
    518             {
    519                 tr_netNtop( addr, peers[i].addr,
    520                            sizeof( peers[i].addr ) );
    521             }
    522            
    523             peers[i].client = tr_clientForId(tr_peerId(peer));
    524            
    525             peers[i].isConnected   = tr_peerIsConnected( peer );
    526             peers[i].isIncoming    = tr_peerIsIncoming( peer );
    527             peers[i].progress      = tr_peerProgress( peer );
    528             peers[i].port          = tr_peerPort( peer );
    529            
    530             if( ( peers[i].isDownloading = tr_peerIsUnchoked( peer ) ) )
    531             {
    532                 peers[i].uploadToRate = tr_peerUploadRate( peer );
    533             }
    534             if( ( peers[i].isUploading = !tr_peerIsChoking( peer ) ) )
    535             {
    536                 peers[i].downloadFromRate = tr_peerDownloadRate( peer );
    537             }
    538         }
    539     }
    540    
    541     tr_lockUnlock( &tor->lock );
    542    
    543     return peers;
    544 }
    545 
    546 void tr_torrentPeersFree( tr_peer_stat_t * peers, int peerCount )
    547 {
    548     int i;
    549 
    550     if (peers == NULL)
    551         return;
    552 
    553     for (i = 0; i < peerCount; i++)
    554         free( peers[i].client );
    555 
    556     free( peers );
    557 }
    558 
    559 void tr_torrentAvailability( tr_torrent_t * tor, int8_t * tab, int size )
    560 {
    561     int i, j, piece;
    562 
    563     tr_lockLock( &tor->lock );
    564     for( i = 0; i < size; i++ )
    565     {
    566         piece = i * tor->info.pieceCount / size;
    567 
    568         if( tr_cpPieceIsComplete( tor->completion, piece ) )
    569         {
    570             tab[i] = -1;
    571             continue;
    572         }
    573 
    574         tab[i] = 0;
    575         for( j = 0; j < tor->peerCount; j++ )
    576         {
    577             if( tr_peerBitfield( tor->peers[j] ) &&
    578                 tr_bitfieldHas( tr_peerBitfield( tor->peers[j] ), piece ) )
    579             {
    580                 (tab[i])++;
    581             }
    582         }
    583     }
    584     tr_lockUnlock( &tor->lock );
    585 }
    586 
    587 void tr_torrentAmountFinished( tr_torrent_t * tor, float * tab, int size )
    588 {
    589     int i, piece;
    590 
    591     tr_lockLock( &tor->lock );
    592     for( i = 0; i < size; i++ )
    593     {
    594         piece = i * tor->info.pieceCount / size;
    595         tab[i] = tr_cpPercentBlocksInPiece( tor->completion, piece );
    596     }
    597     tr_lockUnlock( &tor->lock );
    598 }
    599 
    600 void tr_torrentRemoveSaved( tr_torrent_t * tor ) {
    601     tr_metainfoRemoveSaved( tor->info.hashString );
    602 }
    603 
    604 /***********************************************************************
    605  * tr_torrentClose
    606  ***********************************************************************
    607  * Frees memory allocated by tr_torrentInit.
    608  **********************************************************************/
    609 void tr_torrentClose( tr_handle_t * h, tr_torrent_t * tor )
    610 {
    611     tr_info_t * inf = &tor->info;
    612 
    613     if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
    614     {
    615         /* Join the thread first */
    616         torrentReallyStop( tor );
    617     }
    618 
    619     tr_sharedLock( h->shared );
    620 
    621     h->torrentCount--;
    622 
    623     tr_lockClose( &tor->lock );
    624     tr_cpClose( tor->completion );
    625 
    626     tr_rcClose( tor->upload );
    627     tr_rcClose( tor->download );
    628     tr_rcClose( tor->swarmspeed );
    629 
    630     if( tor->destination )
    631     {
    632         free( tor->destination );
    633     }
    634 
    635     tr_metainfoFree( inf );
    636 
    637     if( tor->prev )
    638     {
    639         tor->prev->next = tor->next;
    640     }
    641     else
    642     {
    643         h->torrentList = tor->next;
    644     }
    645     if( tor->next )
    646     {
    647         tor->next->prev = tor->prev;
    648     }
    649     free( tor );
    650 
    651     tr_sharedUnlock( h->shared );
    652 }
    653 
    654137void tr_close( tr_handle_t * h )
    655138{
     
    661144}
    662145
    663 /***********************************************************************
    664  * downloadLoop
    665  **********************************************************************/
    666 static void downloadLoop( void * _tor )
    667 {
    668     tr_torrent_t * tor = _tor;
    669     uint64_t       date1, date2;
    670     int            ret;
    671 
    672     tr_lockLock( &tor->lock );
    673 
    674     tr_cpReset( tor->completion );
    675     tor->io     = tr_ioInit( tor );
    676     tor->status = tr_cpIsSeeding( tor->completion ) ?
    677                       TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
    678 
    679     while( !tor->die )
    680     {
    681         date1 = tr_date();
    682 
    683         /* Are we finished ? */
    684         if( ( tor->status & TR_STATUS_DOWNLOAD ) &&
    685             tr_cpIsSeeding( tor->completion ) )
    686         {
    687             /* Done */
    688             tor->status = TR_STATUS_SEED;
    689                         tor->finished = 1;
    690             tr_trackerCompleted( tor->tracker );
    691             tr_ioSync( tor->io );
    692         }
    693 
    694         /* Receive/send messages */
    695         if( ( ret = tr_peerPulse( tor ) ) )
    696         {
    697             tr_err( "Fatal error, stopping download (%d)", ret );
    698             torrentStop( tor );
    699             tor->error = ret;
    700             snprintf( tor->errorString, sizeof( tor->errorString ),
    701                       "%s", tr_errorString( ret ) );
    702         }
    703 
    704         /* Try to get new peers or to send a message to the tracker */
    705         tr_trackerPulse( tor->tracker );
    706 
    707         if( tor->status & TR_STATUS_STOPPED )
    708         {
    709             break;
    710         }
    711 
    712         /* Wait up to 20 ms */
    713         date2 = tr_date();
    714         if( date2 < date1 + 20 )
    715         {
    716             tr_lockUnlock( &tor->lock );
    717             tr_wait( date1 + 20 - date2 );
    718             tr_lockLock( &tor->lock );
    719         }
    720     }
    721 
    722     tr_lockUnlock( &tor->lock );
    723 
    724     tr_ioClose( tor->io );
    725 
    726     tor->status = TR_STATUS_STOPPED;
    727 }
    728 
  • trunk/mk/lib.mk

    r1403 r1405  
    77       metainfo.c sha1.c utils.c fdlimit.c clients.c completion.c \
    88       platform.c ratecontrol.c choking.c natpmp.c upnp.c http.c xml.c \
    9        shared.c
     9       shared.c torrent.c
    1010
    1111OBJS = $(SRCS:%.c=%.o)
Note: See TracChangeset for help on using the changeset viewer.