Changeset 1356


Ignore:
Timestamp:
Jan 14, 2007, 12:00:21 PM (14 years ago)
Author:
titer
Message:

Merge io branch into trunk

Location:
trunk
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/cli/transmissioncli.c

    r1287 r1356  
    5656static int           downloadLimit = -1;
    5757static char          * torrentPath = NULL;
    58 static volatile char mustDie       = 0;
    5958static int           natTraversal  = 0;
     59static tr_torrent_t  * tor;
    6060
    6161static char          * finishCall   = NULL;
     
    6868    int i, error, nat;
    6969    tr_handle_t  * h;
    70     tr_torrent_t * tor;
    7170    tr_stat_t    * s;
    7271
     
    190189    tr_torrentStart( tor );
    191190
    192     while( !mustDie )
     191    for( ;; )
    193192    {
    194193        char string[80];
     
    200199        s = tr_torrentStat( tor );
    201200
    202         if( s->status & TR_STATUS_CHECK )
     201        if( s->status & TR_STATUS_PAUSE )
     202        {
     203            break;
     204        }
     205        else if( s->status & TR_STATUS_CHECK )
    203206        {
    204207            chars = snprintf( string, 80,
     
    225228        fprintf( stderr, "\r%s", string );
    226229
    227         if( s->error & TR_ETRACKER )
    228         {
    229             fprintf( stderr, "\n%s\n", s->trackerError );
     230        if( s->error )
     231        {
     232            fprintf( stderr, "\n%s\n", s->errorString );
    230233        }
    231234        else if( verboseLevel > 0 )
     
    241244    fprintf( stderr, "\n" );
    242245
    243     /* Try for 5 seconds to notify the tracker that we are leaving
    244        and to delete any port mappings for nat traversal */
    245     tr_torrentStop( tor );
     246    /* Try for 5 seconds to delete any port mappings for nat traversal */
    246247    tr_natTraversalDisable( h );
    247248    for( i = 0; i < 10; i++ )
    248249    {
    249         s = tr_torrentStat( tor );
    250250        nat = tr_natTraversalStatus( h );
    251         if( s->status & TR_STATUS_PAUSE && TR_NAT_TRAVERSAL_DISABLED == nat )
    252         {
    253             /* The 'stopped' tracker message was sent
    254                and port mappings were deleted */
     251        if( TR_NAT_TRAVERSAL_DISABLED == nat )
     252        {
     253            /* Port mappings were deleted */
    255254            break;
    256255        }
     
    338337    {
    339338        case SIGINT:
    340             mustDie = 1;
     339            tr_torrentStop( tor );
    341340            break;
    342341
  • trunk/gtk/main.c

    r1018 r1356  
    427427makewind_list(struct cbdata *data, GObject **sizehack) {
    428428  GType types[] = {
    429     /* info->name, info->totalSize, status,     error,      trackerError, */
     429    /* info->name, info->totalSize, status,     error,      errorString, */
    430430    G_TYPE_STRING, G_TYPE_UINT64,   G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING,
    431431    /* progress,  rateDownload, rateUpload,   eta,        peersTotal, */
     
    731731  }
    732732
    733   if(TR_NOERROR != err) {
     733  if(TR_OK != err) {
    734734    gtk_tree_model_get(model, iter, MC_TERR, &terr, -1);
    735735    bottom = g_strconcat(_("Error: "), terr, NULL);
     
    808808      gtk_list_store_set(GTK_LIST_STORE(data->model), &iter, MC_NAME, in->name,
    809809        MC_SIZE, in->totalSize, MC_STAT, st->status, MC_ERR, st->error,
    810         MC_TERR, st->trackerError, MC_PROG, st->progress,
     810        MC_TERR, st->errorString, MC_PROG, st->progress,
    811811        MC_DRATE, st->rateDownload, MC_URATE, st->rateUpload, MC_ETA, st->eta,
    812812        MC_PEERS, st->peersTotal, MC_UPEERS, st->peersUploading,
  • trunk/libtransmission/completion.c

    r1197 r1356  
    8686
    8787/* Pieces */
     88int tr_cpPieceHasAllBlocks( tr_completion_t * cp, int piece )
     89{
     90    tr_torrent_t * tor = cp->tor;
     91    int startBlock  = tr_pieceStartBlock( piece );
     92    int endBlock    = startBlock + tr_pieceCountBlocks( piece );
     93    int i;
     94
     95    for( i = startBlock; i < endBlock; i++ )
     96    {
     97        if( !tr_bitfieldHas( cp->blockBitfield, i ) )
     98        {
     99            return 0;
     100        }
     101    }   
     102    return 1;
     103}
    88104int tr_cpPieceIsComplete( tr_completion_t * cp, int piece )
    89105{
     
    109125
    110126    tr_bitfieldAdd( cp->pieceBitfield, piece );
     127}
     128
     129void tr_cpPieceRem( tr_completion_t * cp, int piece )
     130{
     131    tr_torrent_t * tor = cp->tor;
     132    int startBlock, endBlock, i;
     133
     134    startBlock = tr_pieceStartBlock( piece );
     135    endBlock   = startBlock + tr_pieceCountBlocks( piece );
     136    for( i = startBlock; i < endBlock; i++ )
     137    {
     138        tr_cpBlockRem( cp, i );
     139    }
     140
     141    tr_bitfieldRem( cp->pieceBitfield, piece );
    111142}
    112143
  • trunk/libtransmission/completion.h

    r996 r1356  
    4646
    4747/* Pieces */
     48int               tr_cpPieceHasAllBlocks( tr_completion_t *, int piece );
    4849int               tr_cpPieceIsComplete( tr_completion_t *, int piece );
    4950uint8_t         * tr_cpPieceBitfield( tr_completion_t * );
    5051void              tr_cpPieceAdd( tr_completion_t *, int piece );
     52void              tr_cpPieceRem( tr_completion_t *, int piece );
    5153
    5254/* Blocks */
  • trunk/libtransmission/fastresume.h

    r1074 r1356  
    8888        if( stat( path, &sb ) )
    8989        {
    90             tr_err( "Could not stat '%s'", path );
    91             free( path );
    92             return 1;
     90            tab[i] = 0xFFFFFFFF;
    9391        }
    94         if( ( sb.st_mode & S_IFMT ) == S_IFREG )
     92        else if( !S_ISREG( sb.st_mode ) )
    9593        {
    9694#ifdef SYS_DARWIN
  • trunk/libtransmission/fdlimit.c

    r261 r1356  
    3131typedef struct tr_openFile_s
    3232{
    33     char       path[MAX_PATH_LENGTH];
     33    char       folder[MAX_PATH_LENGTH];
     34    char       name[MAX_PATH_LENGTH];
    3435    int        file;
     36    int        write;
    3537
    3638#define STATUS_INVALID 1
     
    4749{
    4850    tr_lock_t       lock;
     51    tr_cond_t       cond;
    4952   
    5053    int             reserved;
     
    5760
    5861/***********************************************************************
     62 * Local prototypes
     63 **********************************************************************/
     64static int  ErrorFromErrno();
     65static int  OpenFile( tr_fd_t * f, int i, char * folder, char * name,
     66                      int write );
     67static void CloseFile( tr_fd_t * f, int i );
     68
     69
     70/***********************************************************************
    5971 * tr_fdInit
    6072 **********************************************************************/
     
    6678    f = calloc( sizeof( tr_fd_t ), 1 );
    6779
    68     /* Init lock */
     80    /* Init lock and cond */
    6981    tr_lockInit( &f->lock );
     82    tr_condInit( &f->cond );
    7083
    7184    /* Detect the maximum number of open files or sockets */
     
    102115 * tr_fdFileOpen
    103116 **********************************************************************/
    104 int tr_fdFileOpen( tr_fd_t * f, char * path )
    105 {
    106     int i, winner;
     117int tr_fdFileOpen( tr_fd_t * f, char * folder, char * name, int write )
     118{
     119    int i, winner, ret;
    107120    uint64_t date;
    108121
     
    112125    for( i = 0; i < TR_MAX_OPEN_FILES; i++ )
    113126    {
    114         if( f->open[i].status > STATUS_INVALID &&
    115             !strcmp( path, f->open[i].path ) )
    116         {
    117             if( f->open[i].status & STATUS_CLOSING )
    118             {
    119                 /* Wait until the file is closed */
    120                 tr_lockUnlock( &f->lock );
    121                 tr_wait( 10 );
    122                 tr_lockLock( &f->lock );
    123                 i = -1;
    124                 continue;
    125             }
    126             winner = i;
    127             goto done;
    128         }
     127        if( f->open[i].status & STATUS_INVALID ||
     128            strcmp( folder, f->open[i].folder ) ||
     129            strcmp( name, f->open[i].name ) )
     130        {
     131            continue;
     132        }
     133        if( f->open[i].status & STATUS_CLOSING )
     134        {
     135            /* File is being closed by another thread, wait until
     136             * it's done before we reopen it */
     137            tr_condWait( &f->cond, &f->lock );
     138            i = -1;
     139            continue;
     140        }
     141        if( f->open[i].write < write )
     142        {
     143            /* File is open read-only and needs to be closed then
     144             * re-opened read-write */
     145            CloseFile( f, i );
     146            continue;
     147        }
     148        winner = i;
     149        goto done;
    129150    }
    130151
     
    139160    }
    140161
     162    /* All slots taken - close the oldest currently unused file */
    141163    for( ;; )
    142164    {
    143         /* Close the oldest currently unused file */
    144165        date   = tr_date() + 1;
    145166        winner = -1;
     
    160181        if( winner >= 0 )
    161182        {
    162             /* Close the file: we mark it as closing then release the
    163                lock while doing so, because close may take same time
    164                and we don't want to block other threads */
    165             tr_dbg( "Closing %s", f->open[winner].path );
    166             f->open[winner].status = STATUS_CLOSING;
    167             tr_lockUnlock( &f->lock );
    168             close( f->open[winner].file );
    169             tr_lockLock( &f->lock );
     183            CloseFile( f, winner );
    170184            goto open;
    171185        }
    172186
    173187        /* All used! Wait a bit and try again */
     188        tr_condWait( &f->cond, &f->lock );
     189    }
     190
     191open:
     192    if( ( ret = OpenFile( f, winner, folder, name, write ) ) )
     193    {
    174194        tr_lockUnlock( &f->lock );
    175         tr_wait( 10 );
    176         tr_lockLock( &f->lock );
    177     }
    178 
    179 open:
    180     tr_dbg( "Opening %s", path );
    181     snprintf( f->open[winner].path, MAX_PATH_LENGTH, "%s", path );
    182     f->open[winner].file = open( path, O_RDWR, 0 );
     195        return ret;
     196    }
     197    snprintf( f->open[winner].folder, MAX_PATH_LENGTH, "%s", folder );
     198    snprintf( f->open[winner].name, MAX_PATH_LENGTH, "%s", name );
     199    f->open[winner].write = write;
    183200
    184201done:
     
    207224    }
    208225   
     226    tr_condSignal( &f->cond );
    209227    tr_lockUnlock( &f->lock );
    210228}
     
    213231 * tr_fdFileClose
    214232 **********************************************************************/
    215 void tr_fdFileClose( tr_fd_t * f, char * path )
     233void tr_fdFileClose( tr_fd_t * f, char * folder, char * name )
    216234{
    217235    int i;
     
    219237    tr_lockLock( &f->lock );
    220238
    221     /* Is it already open? */
    222239    for( i = 0; i < TR_MAX_OPEN_FILES; i++ )
    223240    {
     
    226243            continue;
    227244        }
    228         if( !strcmp( path, f->open[i].path ) )
    229         {
    230             tr_dbg( "Closing %s", path );
    231             close( f->open[i].file );
    232             f->open[i].status = STATUS_INVALID;
    233             break;
    234         }
    235     }
    236 
    237     tr_lockUnlock( &f->lock );
    238 }
    239 
     245        if( !strcmp( folder, f->open[i].folder ) &&
     246            !strcmp( name, f->open[i].name ) )
     247        {
     248            CloseFile( f, i );
     249        }
     250    }
     251
     252    tr_lockUnlock( &f->lock );
     253}
     254
     255/***********************************************************************
     256 * tr_fdSocketWillCreate
     257 **********************************************************************/
    240258int tr_fdSocketWillCreate( tr_fd_t * f, int reserved )
    241259{
     
    274292}
    275293
     294/***********************************************************************
     295 * tr_fdSocketClosed
     296 **********************************************************************/
    276297void tr_fdSocketClosed( tr_fd_t * f, int reserved )
    277298{
     
    290311}
    291312
     313/***********************************************************************
     314 * tr_fdClose
     315 **********************************************************************/
    292316void tr_fdClose( tr_fd_t * f )
    293317{
    294318    tr_lockClose( &f->lock );
     319    tr_condClose( &f->cond );
    295320    free( f );
    296321}
    297322
     323
     324/***********************************************************************
     325 * Local functions
     326 **********************************************************************/
     327
     328/***********************************************************************
     329 * ErrorFromErrno
     330 **********************************************************************/
     331static int ErrorFromErrno()
     332{
     333    if( errno == EACCES || errno == EROFS )
     334        return TR_ERROR_IO_PERMISSIONS;
     335    return TR_ERROR_IO_OTHER;
     336}
     337
     338/***********************************************************************
     339 * CheckFolder
     340 ***********************************************************************
     341 *
     342 **********************************************************************/
     343static int OpenFile( tr_fd_t * f, int i, char * folder, char * name,
     344                     int write )
     345{
     346    tr_openFile_t * file = &f->open[i];
     347    struct stat sb;
     348    char * path;
     349
     350    tr_dbg( "Opening %s in %s (%d)", name, folder, write );
     351
     352    /* Make sure the parent folder exists */
     353    if( stat( folder, &sb ) || !S_ISDIR( sb.st_mode ) )
     354    {
     355        return TR_ERROR_IO_PARENT;
     356    }
     357
     358    asprintf( &path, "%s/%s", folder, name );
     359
     360    /* Create subfolders, if any */
     361    if( write )
     362    {
     363        char * p = path + strlen( folder ) + 1;
     364        char * s;
     365
     366        while( ( s = strchr( p, '/' ) ) )
     367        {
     368            *s = '\0';
     369            if( stat( path, &sb ) )
     370            {
     371                if( mkdir( path, 0777 ) )
     372                {
     373                    free( path );
     374                    return ErrorFromErrno();
     375                }
     376            }
     377            else
     378            {
     379                if( !S_ISDIR( sb.st_mode ) )
     380                {
     381                    free( path );
     382                    return TR_ERROR_IO_OTHER;
     383                }
     384            }
     385            *s = '/';
     386            p = s + 1;
     387        }
     388    }
     389
     390    /* Now try to really open the file */
     391    file->file = open( path, write ? ( O_RDWR | O_CREAT ) : O_RDONLY, 0666 );
     392    free( path );
     393
     394    if( file->file < 0 )
     395    {
     396        int ret = ErrorFromErrno();
     397        tr_err( "Could not open %s in %s (%d, %d)", name, folder, write, ret );
     398        return ret;
     399    }
     400
     401    return TR_OK;
     402}
     403
     404/***********************************************************************
     405 * CloseFile
     406 ***********************************************************************
     407 * We first mark it as closing then release the lock while doing so,
     408 * because close() may take same time and we don't want to block other
     409 * threads.
     410 **********************************************************************/
     411static void CloseFile( tr_fd_t * f, int i )
     412{
     413    tr_openFile_t * file = &f->open[i];
     414
     415    /* If it's already being closed by another thread, just wait till
     416     * it is done */
     417    while( file->status & STATUS_CLOSING )
     418    {
     419        tr_condWait( &f->cond, &f->lock );
     420    }
     421    if( file->status & STATUS_INVALID )
     422    {
     423        return;
     424    }
     425
     426    /* Nobody is closing it already, so let's do it */
     427    if( file->status & STATUS_USED )
     428    {
     429        tr_err( "CloseFile: closing a file that's being used!" );
     430    }
     431    tr_dbg( "Closing %s in %s (%d)", file->name, file->folder, file->write );
     432    file->status = STATUS_CLOSING;
     433    tr_lockUnlock( &f->lock );
     434    close( file->file );
     435    tr_lockLock( &f->lock );
     436    file->status = STATUS_INVALID;
     437    tr_condSignal( &f->cond );
     438}
     439
  • trunk/libtransmission/fdlimit.h

    r261 r1356  
    2525typedef struct tr_fd_s tr_fd_t;
    2626
     27/***********************************************************************
     28 * tr_fdInit
     29 ***********************************************************************
     30 * Detect the maximum number of open files and initializes things.
     31 **********************************************************************/
    2732tr_fd_t * tr_fdInit();
    2833
    29 int       tr_fdFileOpen         ( tr_fd_t *, char * );
    30 void      tr_fdFileRelease      ( tr_fd_t *, int );
    31 void      tr_fdFileClose        ( tr_fd_t *, char * );
     34/***********************************************************************
     35 * tr_fdFileOpen
     36 ***********************************************************************
     37 * If it isn't open already, tries to open the file 'name' in the
     38 * directory 'folder'. If 'name' itself contains '/'s, required
     39 * subfolders are created. The file is open read-write if 'write' is 1
     40 * (created if necessary), read-only if 0.
     41 * Returns the file descriptor if successful, otherwise returns
     42 * one of the TR_ERROR_IO_*.
     43 **********************************************************************/
     44int tr_fdFileOpen( tr_fd_t *, char * folder, char * name, int write );
    3245
    33 int       tr_fdSocketWillCreate ( tr_fd_t *, int );
    34 void      tr_fdSocketClosed     ( tr_fd_t *, int );
     46/***********************************************************************
     47 * tr_fdFileRelease
     48 ***********************************************************************
     49 * Indicates that the file whose descriptor is 'file' is unused at the
     50 * moment and can safely be closed.
     51 **********************************************************************/
     52void tr_fdFileRelease( tr_fd_t *, int file );
    3553
    36 void      tr_fdClose            ( tr_fd_t * );
     54/***********************************************************************
     55 * tr_fdFileClose
     56 ***********************************************************************
     57 * If the file 'name' in directory 'folder' was open, closes it,
     58 * flushing data on disk.
     59 **********************************************************************/
     60void tr_fdFileClose( tr_fd_t *, char * folder, char * name );
     61
     62/***********************************************************************
     63 * tr_fdSocketWillCreate
     64 ***********************************************************************
     65 *
     66 **********************************************************************/
     67int tr_fdSocketWillCreate( tr_fd_t *, int );
     68
     69/***********************************************************************
     70 * tr_fdSocketClosed
     71 ***********************************************************************
     72 *
     73 **********************************************************************/
     74void tr_fdSocketClosed( tr_fd_t *, int );
     75
     76
     77/***********************************************************************
     78 * tr_fdClose
     79 ***********************************************************************
     80 * Frees resources allocated by tr_fdInit.
     81 **********************************************************************/
     82void tr_fdClose( tr_fd_t * );
  • trunk/libtransmission/http.c

    r1293 r1356  
    561561            switch( tr_netResolvePulse( http->resolve, &addr ) )
    562562            {
    563                 case TR_WAIT:
    564                     return TR_WAIT;
    565                 case TR_ERROR:
     563                case TR_NET_WAIT:
     564                    return TR_NET_WAIT;
     565                case TR_NET_ERROR:
    566566                    goto err;
    567                 case TR_OK:
     567                case TR_NET_OK:
    568568                    tr_netResolveClose( http->resolve );
    569569                    http->resolve = NULL;
     
    576576            switch( sendrequest( http ) )
    577577            {
    578                 case TR_WAIT:
    579                     return TR_WAIT;
    580                 case TR_ERROR:
     578                case TR_NET_WAIT:
     579                    return TR_NET_WAIT;
     580                case TR_NET_ERROR:
    581581                    goto err;
    582                 case TR_OK:
     582                case TR_NET_OK:
    583583                    http->state = HTTP_STATE_RECEIVE;
    584584            }
     
    588588            switch( receiveresponse( http ) )
    589589            {
    590                 case TR_WAIT:
    591                     return TR_WAIT;
    592                 case TR_ERROR:
     590                case TR_NET_WAIT:
     591                    return TR_NET_WAIT;
     592                case TR_NET_ERROR:
    593593                    goto err;
    594                 case TR_OK:
     594                case TR_NET_OK:
    595595                    goto ok;
    596596            }
     
    604604    }
    605605
    606     return TR_WAIT;
     606    return TR_NET_WAIT;
    607607
    608608  err:
    609609    http->state = HTTP_STATE_ERROR;
    610     return TR_ERROR;
     610    return TR_NET_ERROR;
    611611
    612612  ok:
     
    620620        *len = http->header.used;
    621621    }
    622     return TR_OK;
     622    return TR_NET_OK;
    623623}
    624624
     
    636636    if( 0 > http->sock || tr_date() > http->date + HTTP_TIMEOUT )
    637637    {
    638         return TR_ERROR;
     638        return TR_NET_ERROR;
    639639    }
    640640
     
    645645        if( ret & TR_NET_CLOSE )
    646646        {
    647             return TR_ERROR;
     647            return TR_NET_ERROR;
    648648        }
    649649        else if( ret & TR_NET_BLOCK )
    650650        {
    651             return TR_WAIT;
     651            return TR_NET_WAIT;
    652652        }
    653653        buf->used = 0;
     
    660660    http->date = 0;
    661661
    662     return TR_OK;
     662    return TR_NET_OK;
    663663}
    664664
     
    683683            if( NULL == newbuf )
    684684            {
    685                 return TR_ERROR;
     685                return TR_NET_ERROR;
    686686            }
    687687            http->header.buf = newbuf;
     
    695695        {
    696696            checklength( http );
    697             return TR_OK;
     697            return TR_NET_OK;
    698698        }
    699699        else if( ret & TR_NET_BLOCK )
     
    709709    if( before < http->header.used && checklength( http ) )
    710710    {
    711         return TR_OK;
     711        return TR_NET_OK;
    712712    }
    713713
    714714    if( tr_date() > HTTP_TIMEOUT + http->date )
    715715    {
    716         return TR_ERROR;
    717     }
    718 
    719     return TR_WAIT;
     716        return TR_NET_ERROR;
     717    }
     718
     719    return TR_NET_WAIT;
    720720}
    721721
  • trunk/libtransmission/inout.c

    r1074 r1356  
    4747 * Local prototypes
    4848 **********************************************************************/
    49 static int  createFiles( tr_io_t * );
    5049static int  checkFiles( tr_io_t * );
    5150static void closeFiles( tr_io_t * );
     
    9695    io->tor = tor;
    9796
    98     if( createFiles( io ) || checkFiles( io ) )
     97    if( checkFiles( io ) )
    9998    {
    10099        free( io );
     
    107106/***********************************************************************
    108107 * tr_ioRead
    109  ***********************************************************************
    110  *
    111108 **********************************************************************/
    112109int tr_ioRead( tr_io_t * io, int index, int begin, int length,
    113110               uint8_t * buf )
    114111{
     112    tr_info_t * inf = &io->tor->info;
    115113    uint64_t    offset;
    116     tr_info_t * inf = &io->tor->info;
    117114
    118115    offset = (uint64_t) io->pieceSlot[index] *
     
    124121/***********************************************************************
    125122 * tr_ioWrite
    126  ***********************************************************************
    127  *
    128123 **********************************************************************/
    129124int tr_ioWrite( tr_io_t * io, int index, int begin, int length,
    130125                uint8_t * buf )
    131126{
    132     tr_torrent_t * tor = io->tor;
    133127    tr_info_t    * inf = &io->tor->info;
    134128    uint64_t       offset;
    135     int            i, hashFailed;
    136     uint8_t        hash[SHA_DIGEST_LENGTH];
    137     uint8_t      * pieceBuf;
    138     int            pieceSize;
    139     int            startBlock, endBlock;
    140129
    141130    if( io->pieceSlot[index] < 0 )
     
    149138        (uint64_t) inf->pieceSize + (uint64_t) begin;
    150139
    151     if( writeBytes( io, offset, length, buf ) )
    152     {
    153         return 1;
    154     }
    155 
    156     startBlock = tr_pieceStartBlock( index );
    157     endBlock   = startBlock + tr_pieceCountBlocks( index );
    158     for( i = startBlock; i < endBlock; i++ )
    159     {
    160         if( !tr_cpBlockIsComplete( tor->completion, i ) )
    161         {
    162             /* The piece is not complete */
    163             return 0;
    164         }
    165     }
    166 
    167     /* The piece is complete, check the hash */
     140    return writeBytes( io, offset, length, buf );
     141}
     142
     143/***********************************************************************
     144 * tr_ioHash
     145 **********************************************************************/
     146int tr_ioHash( tr_io_t * io, int index )
     147{
     148    tr_torrent_t * tor = io->tor;
     149    tr_info_t    * inf = &io->tor->info;
     150    int            pieceSize;
     151    uint8_t      * pieceBuf;
     152    uint8_t        hash[SHA_DIGEST_LENGTH];
     153    int            hashFailed;
     154    int            ret;
     155    int            i;
     156
     157    if( !tr_cpPieceIsComplete( tor->completion, index ) )
     158    {
     159        return TR_ERROR_ASSERT;
     160    }
     161
    168162    pieceSize = tr_pieceSize( index );
    169163    pieceBuf  = malloc( pieceSize );
    170     readBytes( io, (uint64_t) io->pieceSlot[index] *
    171                (uint64_t) inf->pieceSize, pieceSize, pieceBuf );
     164    if( ( ret = readBytes( io, (uint64_t) io->pieceSlot[index] *
     165                    (uint64_t) inf->pieceSize, pieceSize, pieceBuf ) ) )
     166    {
     167        free( pieceBuf );
     168        return ret;
     169    }
    172170    SHA1( pieceBuf, pieceSize, hash );
    173171    free( pieceBuf );
     
    178176        tr_inf( "Piece %d (slot %d): hash FAILED", index,
    179177                io->pieceSlot[index] );
    180 
    181         /* We will need to reload the whole piece */
    182         for( i = startBlock; i < endBlock; i++ )
    183         {
    184             tr_cpBlockRem( tor->completion, i );
    185         }
     178        tr_cpPieceRem( tor->completion, index );
    186179    }
    187180    else
     
    201194}
    202195
     196/***********************************************************************
     197 * tr_ioSync
     198 **********************************************************************/
     199void tr_ioSync( tr_io_t * io )
     200{
     201    closeFiles( io );
     202    fastResumeSave( io );
     203}
     204
     205/***********************************************************************
     206 * tr_ioClose
     207 **********************************************************************/
    203208void tr_ioClose( tr_io_t * io )
    204209{
    205     closeFiles( io );
    206 
    207     fastResumeSave( io );
     210    tr_ioSync( io );
    208211
    209212    free( io->pieceSlot );
    210213    free( io->slotPiece );
    211214    free( io );
    212 }
    213 
    214 void tr_ioSaveResume( tr_io_t * io )
    215 {
    216     fastResumeSave( io );
    217 }
    218 
    219 /***********************************************************************
    220  * createFiles
    221  ***********************************************************************
    222  * Make sure the existing folders/files have correct types and
    223  * permissions, and create missing folders and files
    224  **********************************************************************/
    225 static int createFiles( tr_io_t * io )
    226 {
    227     tr_torrent_t * tor = io->tor;
    228     tr_info_t    * inf = &tor->info;
    229 
    230     int           i;
    231     char        * path, * p;
    232     struct stat   sb;
    233     int           file;
    234 
    235     tr_dbg( "Creating files..." );
    236 
    237     for( i = 0; i < inf->fileCount; i++ )
    238     {
    239         asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
    240 
    241         /* Create folders */
    242         if( NULL != ( p = strrchr( path, '/' ) ) )
    243         {
    244             *p = '\0';
    245             if( tr_mkdir( path ) )
    246             {
    247                 free( path );
    248                 return 1;
    249             }
    250             *p = '/';
    251         }
    252 
    253         /* Empty folders use a dummy "" file, skip those */
    254         if( p == &path[strlen( path ) - 1] )
    255         {
    256             free( path );
    257             continue;
    258         }
    259 
    260         if( stat( path, &sb ) )
    261         {
    262             /* File doesn't exist yet */
    263             if( ( file = open( path, O_WRONLY|O_CREAT|O_TRUNC, 0666 ) ) < 0 )
    264             {
    265                 tr_err( "Could not create `%s' (%s)", path,
    266                         strerror( errno ) );
    267                 free( path );
    268                 return 1;
    269             }
    270             close( file );
    271         }
    272         else if( ( sb.st_mode & S_IFMT ) != S_IFREG )
    273         {
    274             /* Node exists but isn't a file */
    275             /* XXX this should be reported to the frontend somehow */
    276             tr_err( "Remove %s, it's in the way.", path );
    277             free( path );
    278             return 1;
    279         }
    280 
    281         free( path );
    282     }
    283 
    284     return 0;
    285215}
    286216
     
    370300
    371301    int i;
    372     char * path;
    373302
    374303    for( i = 0; i < inf->fileCount; i++ )
    375304    {
    376         asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
    377         tr_fdFileClose( tor->fdlimit, path );
    378         free( path );
     305        tr_fdFileClose( tor->fdlimit, tor->destination,
     306                        inf->files[i].name );
    379307    }
    380308}
     
    396324    int    i;
    397325    size_t cur;
    398     char * path;
    399326    int    file;
    400327    iofunc readOrWrite = isWrite ? (iofunc) write : (iofunc) read;
     328    int    ret = 0;
    401329
    402330    /* Release the torrent lock so the UI can still update itself if
     
    408336    {
    409337        tr_err( "readOrWriteBytes: trying to write more than a piece" );
    410         goto fail;
     338        ret = TR_ERROR_ASSERT;
     339        goto cleanup;
    411340    }
    412341
     
    426355        tr_err( "readOrWriteBytes: offset out of range (%"PRIu64", %d, %d)",
    427356                offset, size, isWrite );
    428         goto fail;
     357        ret = TR_ERROR_ASSERT;
     358        goto cleanup;
    429359    }
    430360
     
    443373        if( cur > 0 )
    444374        {
    445             /* Now let's get a stream on the file... */
    446             asprintf( &path, "%s/%s", tor->destination, inf->files[i].name );
    447             file = tr_fdFileOpen( tor->fdlimit, path );
     375            /* Now let's get a descriptor on the file... */
     376            file = tr_fdFileOpen( tor->fdlimit, tor->destination,
     377                                  inf->files[i].name, isWrite );
    448378            if( file < 0 )
    449379            {
    450                 tr_err( "readOrWriteBytes: could not open file '%s'", path );
    451                 free( path );
    452                 goto fail;
    453             }
    454             free( path );
     380                ret = file;
     381                goto cleanup;
     382            }
    455383
    456384            /* seek to the right offset... */
    457385            if( lseek( file, offset, SEEK_SET ) < 0 )
    458386            {
    459                 goto fail;
     387                tr_fdFileRelease( tor->fdlimit, file );
     388                ret = TR_ERROR_IO_OTHER;
     389                goto cleanup;
    460390            }
    461391
     
    463393            if( readOrWrite( file, buf, cur ) != cur )
    464394            {
    465                 goto fail;
    466             }
    467 
    468             /* and close the stream. */
     395                tr_fdFileRelease( tor->fdlimit, file );
     396                ret = TR_ERROR_IO_OTHER;
     397                goto cleanup;
     398            }
     399
     400            /* and release the descriptor. */
    469401            tr_fdFileRelease( tor->fdlimit, file );
    470402        }
     
    477409    }
    478410
     411cleanup:
    479412    tr_lockLock( &tor->lock );
    480     return 0;
    481 
    482 fail:
    483     tr_lockLock( &tor->lock );
    484     return 1;
     413    return ret;
    485414}
    486415
  • trunk/libtransmission/inout.h

    r346 r1356  
    3131
    3232tr_io_t * tr_ioInit        ( tr_torrent_t * );
    33 int       tr_ioRead        ( tr_io_t *, int, int, int, uint8_t * );
    34 int       tr_ioWrite       ( tr_io_t *, int, int, int, uint8_t * );
     33
     34/***********************************************************************
     35 * tr_ioRead, tr_ioWrite
     36 ***********************************************************************
     37 * Reads or writes the block specified by the piece index, the offset in
     38 * that piece and the size of the block. Returns 0 if successful,
     39 * TR_ERROR_ASSERT if the parameters are incorrect, one of the
     40 * TR_ERROR_IO_* otherwise.
     41 **********************************************************************/
     42int tr_ioRead  ( tr_io_t *, int index, int begin, int len, uint8_t * );
     43int tr_ioWrite ( tr_io_t *, int index, int begin, int len, uint8_t * );
     44
     45/***********************************************************************
     46 * tr_ioHash
     47 ***********************************************************************
     48 * Hashes the specified piece and updates the completion accordingly.
     49 **********************************************************************/
     50int tr_ioHash ( tr_io_t *, int piece );
     51
     52/***********************************************************************
     53 * tr_ioSync
     54 ***********************************************************************
     55 * Flush all data on disc by closing all files, and update the cache
     56 * file.
     57 **********************************************************************/
     58void tr_ioSync( tr_io_t * );
     59
    3560void      tr_ioClose       ( tr_io_t * );
    36 void      tr_ioSaveResume  ( tr_io_t * );
    3761
    3862#endif
  • trunk/libtransmission/internal.h

    r1320 r1356  
    120120typedef struct tr_completion_s tr_completion_t;
    121121
    122 typedef enum { TR_OK, TR_ERROR, TR_WAIT } tr_tristate_t;
     122typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;
    123123
    124124#include "platform.h"
     
    151151    int               status;
    152152    int               error;
    153     char              trackerError[128];
     153    char              errorString[128];
    154154    int               finished;
    155155
  • trunk/libtransmission/natpmp.c

    r920 r1356  
    332332                    switch( pulsereq( pmp->req, &pmp->renew ) )
    333333                    {
    334                         case TR_ERROR:
     334                        case TR_NET_ERROR:
    335335                            if( pmp->req->nobodyhome )
    336336                            {
     
    354354                            killreq( &pmp->req );
    355355                            break;
    356                         case TR_OK:
     356                        case TR_NET_OK:
    357357                            pmp->mappedport = pmp->req->port;
    358358                            killreq( &pmp->req );
     
    362362                            tr_inf( "nat-pmp mapped port %i", pmp->mappedport );
    363363                            break;
    364                         case TR_WAIT:
     364                        case TR_NET_WAIT:
    365365                            break;
    366366                    }
     
    384384                    switch( pulsereq( pmp->req, &pmp->renew ) )
    385385                    {
    386                         case TR_ERROR:
     386                        case TR_NET_ERROR:
    387387                            if( pmp->req->nobodyhome )
    388388                            {
     
    403403                            killreq( &pmp->req );
    404404                            break;
    405                         case TR_OK:
     405                        case TR_NET_OK:
    406406                            tr_dbg( "nat-pmp state del -> idle with port %i",
    407407                                    pmp->req->port);
     
    411411                            pmp->state = PMP_STATE_IDLE;
    412412                            break;
    413                         case TR_WAIT:
     413                        case TR_NET_WAIT:
    414414                            break;
    415415                    }
     
    542542        tr_dbg( "nat-pmp request timed out" );
    543543        req->nobodyhome = 1;
    544         return TR_ERROR;
     544        return TR_NET_ERROR;
    545545    }
    546546
     
    549549        if( sendrequest( req->adding, req->fd, req->port ) )
    550550        {
    551             return TR_ERROR;
     551            return TR_NET_ERROR;
    552552        }
    553553        req->delay *= 2;
     
    558558    if( TR_NET_BLOCK & res )
    559559    {
    560         return TR_WAIT;
     560        return TR_NET_WAIT;
    561561    }
    562562    else if( TR_NET_CLOSE & res )
     
    571571            tr_inf( "error reading nat-pmp response (%s)", strerror( errno ) );
    572572        }
    573         return TR_ERROR;
     573        return TR_NET_ERROR;
    574574    }
    575575
     
    636636    }
    637637
    638     if( TR_OK == readrequest( buf, res, 0, -1, &pmp->uptime, &pmp->renew, NULL ) &&
     638    if( TR_NET_OK == readrequest( buf, res, 0, -1, &pmp->uptime, &pmp->renew, NULL ) &&
    639639        PMP_STATE_NOBODYHOME == pmp->state )
    640640    {
     
    701701    {
    702702        tr_err( "read truncated %i byte nat-pmp response packet", len );
    703         return TR_ERROR;
     703        return TR_NET_ERROR;
    704704    }
    705705    version      = buf[0];
     
    711711    {
    712712        tr_dbg( "nat-pmp ignoring request packet" );
    713         return TR_WAIT;
     713        return TR_NET_WAIT;
    714714    }
    715715    opcode = PMP_OPCODE_FROM_RESPONSE( opcode );
     
    718718    {
    719719        tr_err( "bad nat-pmp version %hhu", buf[0] );
    720         return TR_ERROR;
     720        return TR_NET_ERROR;
    721721    }
    722722    if( wantedopcode != opcode )
    723723    {
    724724        tr_err( "bad nat-pmp opcode %hhu", opcode );
    725         return TR_ERROR;
     725        return TR_NET_ERROR;
    726726    }
    727727    switch( rescode )
     
    739739        default:
    740740            tr_err( "bad nat-pmp result code %hu", rescode );
    741             return TR_ERROR;
     741            return TR_NET_ERROR;
    742742    }
    743743
     
    745745    {
    746746        tr_err( "read truncated %i byte nat-pmp response packet", len );
    747         return TR_ERROR;
     747        return TR_NET_ERROR;
    748748    }
    749749    seconds = PMP_FROMBUF32( buf + 4 );
     
    754754        tr_inf( "detected nat-pmp device reset" );
    755755        /* XXX should reset retry counter here */
    756         return TR_WAIT;
     756        return TR_NET_WAIT;
    757757    }
    758758
     
    763763        {
    764764            tr_err( "read truncated %i byte nat-pmp response packet", len );
    765             return TR_ERROR;
     765            return TR_NET_ERROR;
    766766        }
    767767        privport = PMP_FROMBUF16( buf + 8 );
     
    774774            tr_dbg( "nat-pmp ignoring message for port %i, expected port %i",
    775775                    privport, port );
    776             return TR_WAIT;
     776            return TR_NET_WAIT;
    777777        }
    778778
     
    783783                *tmpfail = 1;
    784784                /* XXX should just start announcing the pub port we're given */
    785                 return TR_ERROR;
     785                return TR_NET_ERROR;
    786786            }
    787787            tr_dbg( "nat-pmp set renew to half of %u", lifetime );
     
    790790    }
    791791
    792     return TR_OK;
    793 }
     792    return TR_NET_OK;
     793}
  • trunk/libtransmission/net.c

    r920 r1356  
    100100
    101101    r           = malloc( sizeof( tr_resolve_t ) );
    102     r->status   = TR_WAIT;
     102    r->status   = TR_NET_WAIT;
    103103    r->address  = strdup( address );
    104104    r->refcount = 2;
     
    132132    tr_lockLock( &resolveLock );
    133133    ret = r->status;
    134     if( ret == TR_OK )
     134    if( ret == TR_NET_OK )
    135135    {
    136136        *addr = r->addr;
     
    202202        {
    203203            memcpy( &r->addr, host->h_addr, host->h_length );
    204             r->status = TR_OK;
     204            r->status = TR_NET_OK;
    205205        }
    206206        else
    207207        {
    208             r->status = TR_ERROR;
     208            r->status = TR_NET_ERROR;
    209209        }
    210210       
  • trunk/libtransmission/peer.c

    r1320 r1356  
    290290        {
    291291            peer_dbg( "connection closed" );
    292             return 1;
     292            return TR_ERROR;
    293293        }
    294294        else if( ret & TR_NET_BLOCK )
     
    302302            tr_rcTransferred( peer->download, ret );
    303303            tr_rcTransferred( tor->download, ret );
    304             if( parseBuf( tor, peer ) )
    305             {
    306                 return 1;
     304            if( ( ret = parseBuf( tor, peer ) ) )
     305            {
     306                return ret;
    307307            }
    308308        }
    309309        else
    310310        {
    311             if( parseBufHeader( peer ) )
    312             {
    313                 return 1;
     311            if( ( ret = parseBufHeader( peer ) ) )
     312            {
     313                return ret;
    314314            }
    315315        }
     
    359359 *
    360360 **********************************************************************/
    361 void tr_peerPulse( tr_torrent_t * tor )
     361int tr_peerPulse( tr_torrent_t * tor )
    362362{
    363363    int i, ret, size;
     
    382382    if( tor->status & TR_STATUS_STOPPING )
    383383    {
    384         return;
     384        return 0;
    385385    }
    386386   
     
    405405        }
    406406
    407         if( tr_peerRead( tor, tor->peers[i] ) )
    408         {
     407        ret = tr_peerRead( tor, tor->peers[i] );
     408        if( ret & TR_ERROR_IO_MASK )
     409            return ret;
     410        if( ret )
    409411            goto dropPeer;
    410         }
    411412
    412413        if( peer->status < PEER_STATUS_CONNECTED )
     
    498499        tr_peerRem( tor, i );
    499500    }
     501    return 0;
    500502}
    501503
  • trunk/libtransmission/peer.h

    r1251 r1356  
    3939uint8_t *   tr_peerId            ( tr_peer_t * );
    4040uint8_t *   tr_peerHash          ( tr_peer_t * );
    41 void        tr_peerPulse         ( tr_torrent_t * );
     41int         tr_peerPulse         ( tr_torrent_t * );
    4242int         tr_peerIsConnected   ( tr_peer_t * );
    4343int         tr_peerIsIncoming    ( tr_peer_t * );
  • trunk/libtransmission/peermessages.h

    r261 r1356  
    255255    r->begin  = ( block % ( inf->pieceSize / tor->blockSize ) ) *
    256256                    tor->blockSize;
    257     r->length = tor->blockSize;
    258     if( block == tor->blockCount - 1 )
    259     {
    260         int lastSize = inf->totalSize % tor->blockSize;
    261         if( lastSize )
    262         {
    263             r->length = lastSize;
    264         }
    265     }
     257    r->length = tr_blockSize( block );
    266258    (peer->inRequestCount)++;
    267259
  • trunk/libtransmission/peerparse.h

    r1064 r1356  
    4141    {
    4242        peer_dbg( "GET  %schoke, invalid", choking ? "" : "un" );
    43         return 1;
     43        return TR_ERROR_ASSERT;
    4444    }
    4545
     
    5959    }
    6060
    61     return 0;
     61    return TR_OK;
    6262}
    6363
     
    7373    {
    7474        peer_dbg( "GET  %sinterested, invalid", interested ? "" : "un" );
    75         return 1;
     75        return TR_ERROR_ASSERT;
    7676    }
    7777
     
    8080    peer->peerInterested = interested;
    8181
    82     return 0;
     82    return TR_OK;
    8383}
    8484
     
    9696    {
    9797        peer_dbg( "GET  have, invalid" );
    98         return 1;
     98        return TR_ERROR_ASSERT;
    9999    }
    100100
     
    117117    tr_rcTransferred( tor->swarmspeed, tor->info.pieceSize );
    118118
    119     return 0;
     119    return TR_OK;
    120120}
    121121
     
    132132    {
    133133        peer_dbg( "GET  bitfield, wrong size" );
    134         return 1;
     134        return TR_ERROR_ASSERT;
    135135    }
    136136
     
    147147        {
    148148            peer_dbg( "GET  bitfield, spare bits set" );
    149             return 1;
     149            return TR_ERROR_ASSERT;
    150150        }
    151151    }
     
    171171    updateInterest( tor, peer );
    172172
    173     return 0;
     173    return TR_OK;
    174174}
    175175
     
    182182    {
    183183        peer_dbg( "GET  request, invalid" );
    184         return 1;
     184        return TR_ERROR_ASSERT;
    185185    }
    186186
     
    189189        /* Didn't he get it? */
    190190        sendChoke( peer, 1 );
    191         return 0;
     191        return TR_OK;
    192192    }
    193193   
     
    204204    {
    205205        /* Sorry mate */
    206         return 1;
     206        return TR_ERROR;
    207207    }
    208208
     
    210210    {
    211211        tr_err( "Too many requests" );
    212         return 1;
     212        return TR_ERROR;
    213213    }
    214214
     
    220220    (peer->outRequestCount)++;
    221221
    222     return 0;
     222    return TR_OK;
     223}
     224
     225static inline void updateRequests( tr_torrent_t * tor, tr_peer_t * peer,
     226                                   int index, int begin )
     227{
     228    tr_request_t * r;
     229    int i, j;
     230
     231    /* Find this block in the requests list */
     232    for( i = 0; i < peer->inRequestCount; i++ )
     233    {
     234        r = &peer->inRequests[i];
     235        if( index == r->index && begin == r->begin )
     236        {
     237            break;
     238        }
     239    }
     240
     241    /* Usually i should be 0, but some clients don't handle multiple
     242       request well and drop previous requests */
     243    if( i < peer->inRequestCount )
     244    {
     245        if( i > 0 )
     246        {
     247            peer_dbg( "not expecting this block yet (%d requests dropped)", i );
     248        }
     249        i++;
     250        for( j = 0; j < i; j++ )
     251        {
     252            r = &peer->inRequests[j];
     253            tr_cpDownloaderRem( tor->completion,
     254                                tr_block( r->index, r->begin ) );
     255        }
     256        peer->inRequestCount -= i;
     257        memmove( &peer->inRequests[0], &peer->inRequests[i],
     258                 peer->inRequestCount * sizeof( tr_request_t ) );
     259    }
     260    else
     261    {
     262        /* Not in the list. Probably because of a cancel that arrived
     263           too late */
     264    }
    223265}
    224266
     
    226268                              uint8_t * p, int len )
    227269{
    228     int index, begin, block, i, j;
    229     tr_request_t * r;
     270    int index, begin, block, i, ret;
    230271
    231272    TR_NTOHL( p,     index );
    232273    TR_NTOHL( &p[4], begin );
     274    block = tr_block( index, begin );
    233275
    234276    peer_dbg( "GET  piece %d/%d (%d bytes)",
    235277              index, begin, len - 9 );
    236278
    237     if( peer->inRequestCount < 1 )
    238     {
    239         /* Our "cancel" was probably late */
    240         peer_dbg( "not expecting a block" );
    241         return 0;
    242     }
    243    
    244     r = &peer->inRequests[0];
    245     if( index != r->index || begin != r->begin )
    246     {
    247         int suckyClient;
    248 
    249         /* Either our "cancel" was late, or this is a sucky
    250            client that cannot deal with multiple requests */
    251         suckyClient = 0;
    252         for( i = 0; i < peer->inRequestCount; i++ )
    253         {
    254             r = &peer->inRequests[i];
    255 
    256             if( index != r->index || begin != r->begin )
    257             {
    258                 continue;
    259             }
    260 
    261             /* Sucky client, he dropped the previous requests */
    262             peer_dbg( "block was expected later" );
    263             for( j = 0; j < i; j++ )
    264             {
    265                 r = &peer->inRequests[j];
    266                 tr_cpDownloaderRem( tor->completion,
    267                                     tr_block(r->index,r->begin) );
    268             }
    269             suckyClient = 1;
    270             peer->inRequestCount -= i;
    271             memmove( &peer->inRequests[0], &peer->inRequests[i],
    272                      peer->inRequestCount * sizeof( tr_request_t ) );
    273             r = &peer->inRequests[0];
    274             break;
    275         }
    276 
    277         if( !suckyClient )
    278         {
    279             r = &peer->inRequests[0];
    280             peer_dbg( "wrong block (expecting %d/%d)",
    281                       r->index, r->begin );
    282             return 0;
    283         }
    284     }
    285 
    286     if( len - 9 != r->length )
    287     {
    288         peer_dbg( "wrong size (expecting %d)", r->length );
    289         return 1;
    290     }
    291 
    292     tor->downloadedCur += r->length;
    293 
    294     block = tr_block( r->index, r->begin );
     279    updateRequests( tor, peer, index, begin );
     280    tor->downloadedCur += len;
     281
     282    /* Sanity checks */
     283    if( len - 9 != tr_blockSize( block ) )
     284    {
     285        peer_dbg( "wrong size (expecting %d)", tr_blockSize( block ) );
     286        return TR_ERROR_ASSERT;
     287    }
    295288    if( tr_cpBlockIsComplete( tor->completion, block ) )
    296289    {
    297290        peer_dbg( "have this block already" );
    298         (peer->inRequestCount)--;
    299         memmove( &peer->inRequests[0], &peer->inRequests[1],
    300                  peer->inRequestCount * sizeof( tr_request_t ) );
    301         return 0;
    302     }
    303 
    304     /* set blame/credit for this piece */
     291        return TR_OK;
     292    }
     293
     294    /* Set blame/credit for this piece */
    305295    if( !peer->blamefield )
    306296    {
     
    309299    tr_bitfieldAdd( peer->blamefield, index );
    310300
     301    /* Write to disk */
     302    if( ( ret = tr_ioWrite( tor->io, index, begin, len - 9, &p[8] ) ) )
     303    {
     304        return ret;
     305    }
    311306    tr_cpBlockAdd( tor->completion, block );
    312     tr_ioWrite( tor->io, index, begin, len - 9, &p[8] );
    313     tr_cpDownloaderRem( tor->completion, block );
    314 
    315307    sendCancel( tor, block );
    316308
    317     if( tr_cpPieceIsComplete( tor->completion, index ) )
     309    if( !tr_cpPieceHasAllBlocks( tor->completion, index ) )
     310    {
     311        return TR_OK;
     312    }
     313
     314    /* Piece is complete, check it */
     315    if( ( ret = tr_ioHash( tor->io, index ) ) )
     316    {
     317        return ret;
     318    }
     319    if( !tr_cpPieceIsComplete( tor->completion, index ) )
     320    {
     321        return TR_OK;
     322    }
     323
     324    /* Hash OK */
     325    for( i = 0; i < tor->peerCount; i++ )
    318326    {
    319327        tr_peer_t * otherPeer;
    320 
    321         for( i = 0; i < tor->peerCount; i++ )
    322         {
    323             otherPeer = tor->peers[i];
    324 
    325             if( otherPeer->status < PEER_STATUS_CONNECTED )
    326             {
    327                 continue;
    328             }
    329 
    330             sendHave( otherPeer, index );
    331             updateInterest( tor, otherPeer );
    332         }
    333     }
    334 
    335     (peer->inRequestCount)--;
    336     memmove( &peer->inRequests[0], &peer->inRequests[1],
    337              peer->inRequestCount * sizeof( tr_request_t ) );
    338 
    339     return 0;
     328        otherPeer = tor->peers[i];
     329
     330        if( otherPeer->status < PEER_STATUS_CONNECTED )
     331            continue;
     332
     333        sendHave( otherPeer, index );
     334        updateInterest( tor, otherPeer );
     335    }
     336
     337    return TR_OK;
    340338}
    341339
     
    349347    {
    350348        peer_dbg( "GET  cancel, invalid" );
    351         return 1;
     349        return TR_ERROR_ASSERT;
    352350    }
    353351
     
    372370    }
    373371
    374     return 0;
     372    return TR_OK;
    375373}
    376374
     
    382380    {
    383381        peer_dbg( "GET  port, invalid" );
    384         return 1;
     382        return TR_ERROR_ASSERT;
    385383    }
    386384
     
    388386    peer_dbg( "GET  port %d", ntohs( port ) );
    389387
    390     return 0;
     388    return TR_OK;
    391389}
    392390
     
    424422
    425423    peer_dbg( "Unknown message '%d'", id );
    426     return 1;
     424    return TR_ERROR;
    427425}
    428426
     
    433431    if( 4 > peer->pos )
    434432    {
    435         return 0;
     433        return TR_OK;
    436434    }
    437435
     
    442440        peer_dbg( "GET  handshake, invalid" );
    443441        tr_netSend( peer->socket, (uint8_t *) "Nice try...\r\n", 13 );
    444         return 1;
     442        return TR_ERROR;
    445443    }
    446444    if( peer->pos < 68 )
    447445    {
    448         return 0;
     446        return TR_OK;
    449447    }
    450448    if( memcmp( &p[4], "Torrent protocol", 16 ) )
    451449    {
    452450        peer_dbg( "GET  handshake, invalid" );
    453         return 1;
    454     }
    455 
    456     return 0;
     451        return TR_ERROR;
     452    }
     453
     454    return TR_OK;
    457455}
    458456
     
    477475    uint8_t * p   = peer->buf;
    478476    uint8_t * end = &p[peer->pos];
     477    int       ret;
    479478
    480479    if( peer->banned )
     
    482481        /* Don't even parse, we only stay connected */
    483482        peer->pos = 0;
    484         return 0;
     483        return TR_OK;
    485484    }
    486485
     
    491490            char * client;
    492491
    493             if( parseBufHeader( peer ) )
     492            if( ( ret = parseBufHeader( peer ) ) )
    494493            {
    495                 return 1;
     494                return ret;
    496495            }
    497496
     
    504503            {
    505504                peer_dbg( "GET  handshake, wrong torrent hash" );
    506                 return 1;
     505                return TR_ERROR;
    507506            }
    508507
     
    511510                /* We are connected to ourselves... */
    512511                peer_dbg( "GET  handshake, that is us" );
    513                 return 1;
     512                return TR_ERROR;
    514513            }
    515514
     
    528527                {
    529528                    peer_dbg( "GET  handshake, duplicate" );
    530                     return 1;
     529                    return TR_ERROR;
    531530                }
    532531            }
     
    549548            /* This should never happen. Drop that peer */
    550549            peer_dbg( "message too large (%d bytes)", len );
    551             return 1;
     550            return TR_ERROR;
    552551        }
    553552
     
    570569        peer->pos -= 4 + len;
    571570
    572         if( parseMessage( tor, peer, p, len ) )
    573         {
    574             return 1;
     571        if( ( ret = parseMessage( tor, peer, p, len ) ) )
     572        {
     573            return ret;
    575574        }
    576575
     
    580579    memmove( peer->buf, p, peer->pos );
    581580
    582     return 0;
    583 }
     581    return TR_OK;
     582}
  • trunk/libtransmission/platform.c

    r1000 r1356  
    233233}
    234234
     235
     236void tr_condInit( tr_cond_t * c )
     237{
     238#ifdef SYS_BEOS
     239    *c = -1;
     240#else
     241    pthread_cond_init( c, NULL );
     242#endif
     243}
     244
     245void tr_condWait( tr_cond_t * c, tr_lock_t * l )
     246{
     247#ifdef SYS_BEOS
     248    *c = find_thread( NULL );
     249    release_sem( *l );
     250    suspend_thread( *c );
     251    acquire_sem( *l );
     252    *c = -1;
     253#else
     254    pthread_cond_wait( c, l );
     255#endif
     256}
     257
     258void tr_condSignal( tr_cond_t * c )
     259{
     260#ifdef SYS_BEOS
     261    while( *c != -1 )
     262    {
     263        thread_info info;
     264        get_thread_info( *c, &info );
     265        if( info.state == B_THREAD_SUSPENDED )
     266        {
     267            resume_thread( *c );
     268            break;
     269        }
     270        snooze( 5000 );
     271    }
     272#else
     273    pthread_cond_signal( c );
     274#endif
     275}
     276
     277void tr_condClose( tr_cond_t * c )
     278{
     279#ifndef SYS_BEOS
     280    pthread_cond_destroy( c );
     281#endif
     282}
     283
     284
    235285#if defined( BSD )
    236286
  • trunk/libtransmission/platform.h

    r920 r1356  
    2929  typedef thread_id tr_thread_t;
    3030  typedef sem_id    tr_lock_t;
     31  typedef int       tr_cond_t;
    3132#else
    3233  #include <pthread.h>
    3334  typedef pthread_t       tr_thread_t;
    3435  typedef pthread_mutex_t tr_lock_t;
     36  typedef pthread_cond_t  tr_cond_t;
    3537#endif
    3638
     
    6163}
    6264
     65void tr_condInit( tr_cond_t * );
     66void tr_condWait( tr_cond_t *, tr_lock_t * );
     67void tr_condSignal( tr_cond_t * );
     68void tr_condClose( tr_cond_t * );
     69
    6370int
    6471tr_getDefaultRoute( struct in_addr * addr );
  • trunk/libtransmission/tracker.c

    r1353 r1356  
    435435        switch( tr_httpPulse( tc->http, &data, &len ) )
    436436        {
    437             case TR_WAIT:
     437            case TR_NET_WAIT:
    438438                break;
    439439
    440             case TR_ERROR:
     440            case TR_NET_ERROR:
    441441                killHttp( &tc->http, tor->fdlimit );
    442442                tc->dateTry = tr_date();
     
    454454                break;
    455455
    456             case TR_OK:
     456            case TR_NET_OK:
    457457                readAnswer( tc, data, len );
    458458                killHttp( &tc->http, tor->fdlimit );
     
    505505        switch( tr_httpPulse( tc->httpScrape, &data, &len ) )
    506506        {
    507             case TR_WAIT:
     507            case TR_NET_WAIT:
    508508                break;
    509509
    510             case TR_ERROR:
     510            case TR_NET_ERROR:
    511511                killHttp( &tc->httpScrape, tor->fdlimit );
    512512                tc->lastScrapeFailed = 1;
    513513                break;
    514514
    515             case TR_OK:
     515            case TR_NET_OK:
    516516                readScrapeAnswer( tc, data, len );
    517517                killHttp( &tc->httpScrape, tor->fdlimit );
     
    732732    {
    733733        tr_err( "Tracker: Error - %s", bePeers->val.s.s );
    734         tor->error |= TR_ETRACKER;
    735         snprintf( tor->trackerError, sizeof( tor->trackerError ),
     734        tor->error = TR_ERROR_TC_ERROR;
     735        snprintf( tor->errorString, sizeof( tor->errorString ),
    736736                  "%s", bePeers->val.s.s );
    737737        tc->lastError = 1;
     
    743743    {
    744744        tr_err( "Tracker: Warning - %s", bePeers->val.s.s );
    745         snprintf( tor->trackerError, sizeof( tor->trackerError ),
     745        tor->error = TR_ERROR_TC_WARNING;
     746        snprintf( tor->errorString, sizeof( tor->errorString ),
    746747                  "%s", bePeers->val.s.s );
    747748    }
    748     else
    749     {
    750         tor->trackerError[0] = '\0';
    751     }
    752 
    753     tor->error &= ~TR_ETRACKER;
     749    else if( tor->error & TR_ERROR_TC_MASK )
     750    {
     751        tor->error = TR_OK;
     752    }
     753
    754754    tc->lastError = 0;
    755755    tc->allUnreachIfError = 0;
     
    11291129        switch( tr_httpPulse( http, &data, &len ) )
    11301130        {
    1131             case TR_WAIT:
     1131            case TR_NET_WAIT:
    11321132                break;
    11331133
    1134             case TR_ERROR:
     1134            case TR_NET_ERROR:
    11351135                goto scrapeDone;
    11361136
    1137             case TR_OK:
     1137            case TR_NET_OK:
    11381138                readScrapeAnswer( tc, data, len );
    11391139                goto scrapeDone;
  • trunk/libtransmission/transmission.c

    r1320 r1356  
    380380
    381381    tor->status  = TR_STATUS_CHECK;
     382    tor->error   = TR_OK;
    382383    tor->tracker = tr_trackerInit( tor );
    383384
     
    387388}
    388389
    389 void tr_torrentStop( tr_torrent_t * tor )
    390 {
    391     tr_lockLock( &tor->lock );
     390static void torrentStop( tr_torrent_t * tor )
     391{
    392392    tr_trackerStopped( tor->tracker );
    393393    tr_rcReset( tor->download );
     
    396396    tor->status = TR_STATUS_STOPPING;
    397397    tor->stopDate = tr_date();
     398}
     399
     400void tr_torrentStop( tr_torrent_t * tor )
     401{
     402    tr_lockLock( &tor->lock );
     403    torrentStop( tor );
    398404    tr_lockUnlock( &tor->lock );
    399405}
     
    485491    s->status = tor->status;
    486492    s->error  = tor->error;
    487     memcpy( s->trackerError, tor->trackerError,
    488             sizeof( s->trackerError ) );
     493    memcpy( s->errorString, tor->errorString,
     494            sizeof( s->errorString ) );
    489495
    490496    tc = tor->tracker;
     
    756762    tr_torrent_t * tor = _tor;
    757763    uint64_t       date1, date2;
     764    int            ret;
    758765
    759766    tr_dbg( "Thread started" );
     
    784791                        tor->finished = 1;
    785792            tr_trackerCompleted( tor->tracker );
    786             tr_ioSaveResume( tor->io );
    787 #ifndef __AMIGAOS4__
    788             sync(); /* KLUDGE: all files should be closed and
    789                        re-opened in read-only mode instead */
    790 #endif
     793            tr_ioSync( tor->io );
    791794        }
    792795
    793796        /* Receive/send messages */
    794         tr_peerPulse( tor );
     797        if( ( ret = tr_peerPulse( tor ) ) )
     798        {
     799            tr_err( "Fatal error, stopping download (%d)", ret );
     800            torrentStop( tor );
     801            tor->error = ret;
     802            snprintf( tor->errorString, sizeof( tor->errorString ),
     803                      "%s", tr_errorString( ret ) );
     804        }
    795805
    796806        /* Try to get new peers or to send a message to the tracker */
  • trunk/libtransmission/transmission.h

    r1320 r1356  
    5151
    5252#define TR_DEFAULT_PORT   9090
    53 #define TR_NOERROR        0
     53
     54/***********************************************************************
     55 * Error codes
     56 **********************************************************************/
     57/* General errors */
     58#define TR_OK                   0x00000000
     59#define TR_ERROR                0x81000000
     60#define TR_ERROR_ASSERT         0x82000000
     61/* I/O errors */
     62#define TR_ERROR_IO_MASK        0x0000000F
     63#define TR_ERROR_IO_PARENT      0x80000001
     64#define TR_ERROR_IO_PERMISSIONS 0x80000002
     65#define TR_ERROR_IO_OTHER       0x80000008
     66/* Misc */
     67#define TR_ERROR_TC_MASK        0x000000F0
     68#define TR_ERROR_TC_ERROR       0x80000010
     69#define TR_ERROR_TC_WARNING     0x80000020
    5470
    5571/***********************************************************************
     
    371387    int                 status;
    372388
    373 #define TR_ETRACKER 1
    374 #define TR_EINOUT   2
    375389    int                 error;
    376     char                trackerError[128];
     390    char                errorString[128];
    377391    int                 cannotConnect;
    378392   
  • trunk/libtransmission/upnp.c

    r1337 r1356  
    454454        switch( recvSSDP( fd, buf, &len ) )
    455455        {
    456             case TR_WAIT:
     456            case TR_NET_WAIT:
    457457                return ret;
    458             case TR_ERROR:
     458            case TR_NET_ERROR:
    459459                return 1;
    460             case TR_OK:
     460            case TR_NET_OK:
    461461                ret = 1;
    462462                if( parseSSDP( buf, len, hdr ) &&
     
    476476    if( 0 > fd )
    477477    {
    478         return TR_ERROR;
     478        return TR_NET_ERROR;
    479479    }
    480480
     
    482482    if( TR_NET_BLOCK & *len )
    483483    {
    484         return TR_WAIT;
     484        return TR_NET_WAIT;
    485485    }
    486486    else if( TR_NET_CLOSE & *len )
    487487    {
    488488        tr_err( "Could not receive SSDP message (%s)", strerror( errno ) );
    489         return TR_ERROR;
     489        return TR_NET_ERROR;
    490490    }
    491491    else
    492492    {
    493         return TR_OK;
     493        return TR_NET_OK;
    494494    }
    495495}
     
    956956    switch( tr_httpPulse( dev->http, &headers, &hlen ) )
    957957    {
    958         case TR_OK:
     958        case TR_NET_OK:
    959959            code = tr_httpResponseCode( headers, hlen );
    960960            if( SOAP_METHOD_NOT_ALLOWED == code && !dev->soapretry )
     
    968968            *len = ( NULL == body ? 0 : hlen - ( *body - headers ) );
    969969            return code;
    970         case TR_ERROR:
     970        case TR_NET_ERROR:
    971971            killHttp( fdlimit, &dev->http );
    972972            if( dev->soapretry )
     
    982982            }
    983983            break;
    984         case TR_WAIT:
     984        case TR_NET_WAIT:
    985985            break;
    986986    }
  • trunk/libtransmission/utils.c

    r920 r1356  
    335335    return ret;
    336336}
     337
     338char *
     339tr_errorString( int code )
     340{
     341    switch( code )
     342    {
     343        case TR_OK:
     344            return "No error";
     345        case TR_ERROR:
     346            return "Generic error";
     347        case TR_ERROR_ASSERT:
     348            return "Assert error";
     349        case TR_ERROR_IO_PARENT:
     350            return "Download folder does not exist";
     351        case TR_ERROR_IO_PERMISSIONS:
     352            return "Unsufficient permissions";
     353        case TR_ERROR_IO_OTHER:
     354            return "Generic I/O error";
     355    }
     356    return "Unknown error";
     357}
     358
  • trunk/libtransmission/utils.h

    r920 r1356  
    7070 **********************************************************************/
    7171char * tr_dupstr( const char * base, int len );
     72
     73char * tr_errorString( int code );
    7274
    7375/***********************************************************************
  • trunk/macosx/Torrent.m

    r1335 r1356  
    378378    }
    379379   
    380     if (fStat->error & TR_ETRACKER)
     380    if (fStat->error)
    381381    {
    382382        [fStatusString setString: [NSLocalizedString(@"Error: ", "Torrent -> status string") stringByAppendingString:
     
    928928- (BOOL) isError
    929929{
    930     return fStat->error & TR_ETRACKER;
     930    return fStat->error;
    931931}
    932932
    933933- (NSString *) errorMessage
    934934{
    935     [NSString stringWithUTF8String: fStat->trackerError];
     935    [NSString stringWithUTF8String: fStat->errorString];
    936936}
    937937
Note: See TracChangeset for help on using the changeset viewer.