static void connection_succeeded (void * vdata) { tr_torrent * tor; struct connection_succeeded_data * data = vdata; struct tr_webseed * w = data->webseed; if (++w->active_transfers >= w->retry_challenge && w->retry_challenge) /* the server seems to be accepting more connections now */ w->consecutive_failures = w->retry_tickcount = w->retry_challenge = 0; if (data->real_url && (tor = tr_torrentFindFromId (w->session, w->torrent_id))) { uint64_t file_offset; tr_file_index_t file_index; tr_ioFindFileLocation (tor, data->piece_index, data->piece_offset, &file_index, &file_offset); tr_free (w->file_urls[file_index]); w->file_urls[file_index] = data->real_url; data->real_url = NULL; } tr_free (data->real_url); tr_free (data); }
static void requestNextChunk( tr_webseed * w ) { tr_torrent * tor = tr_torrentFindFromHash( w->session, w->hash ); if( tor != NULL ) { const tr_info * inf = tr_torrentInfo( tor ); const uint32_t have = EVBUFFER_LENGTH( w->content ); const uint32_t left = w->byteCount - have; const uint32_t pieceOffset = w->pieceOffset + have; tr_file_index_t fileIndex; uint64_t fileOffset; uint32_t thisPass; char * url; char * range; tr_ioFindFileLocation( tor, w->pieceIndex, pieceOffset, &fileIndex, &fileOffset ); thisPass = MIN( left, inf->files[fileIndex].length - fileOffset ); url = makeURL( w, &inf->files[fileIndex] ); /*fprintf( stderr, "url is [%s]\n", url );*/ range = tr_strdup_printf( "%"PRIu64"-%"PRIu64, fileOffset, fileOffset + thisPass - 1 ); /*fprintf( stderr, "range is [%s] ... we want %lu total, we have %lu, so %lu are left, and we're asking for %lu this time\n", range, (unsigned long)w->byteCount, (unsigned long)have, (unsigned long)left, (unsigned long)thisPass );*/ tr_webRun( w->session, url, range, webResponseFunc, w ); tr_free( range ); tr_free( url ); } }
/* returns 0 on success, or an errno on failure */ static int readOrWritePiece( const tr_torrent * tor, int ioMode, tr_piece_index_t pieceIndex, uint32_t pieceOffset, uint8_t * buf, size_t buflen ) { int err = 0; tr_file_index_t fileIndex; uint64_t fileOffset; const tr_info * info = &tor->info; if( pieceIndex >= tor->info.pieceCount ) return EINVAL; if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) ) return EINVAL; tr_ioFindFileLocation( tor, pieceIndex, pieceOffset, &fileIndex, &fileOffset ); while( buflen && !err ) { const tr_file * file = &info->files[fileIndex]; const uint64_t bytesThisPass = MIN( buflen, file->length - fileOffset ); err = readOrWriteBytes( tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass ); buf += bytesThisPass; buflen -= bytesThisPass; ++fileIndex; fileOffset = 0; } return err; }
/* returns 0 on success, or an errno on failure */ static int readOrWritePiece( tr_torrent * tor, int ioMode, tr_piece_index_t pieceIndex, uint32_t pieceOffset, uint8_t * buf, size_t buflen ) { int err = 0; tr_file_index_t fileIndex; uint64_t fileOffset; const tr_info * info = &tor->info; if( pieceIndex >= tor->info.pieceCount ) return EINVAL; //if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) ) // return EINVAL; tr_ioFindFileLocation( tor, pieceIndex, pieceOffset, &fileIndex, &fileOffset ); while( buflen && !err ) { const tr_file * file = &info->files[fileIndex]; const uint64_t bytesThisPass = MIN( buflen, file->length - fileOffset ); err = readOrWriteBytes( tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass ); buf += bytesThisPass; buflen -= bytesThisPass; //fprintf( stderr, "++fileIndex to %d\n", (int)fileIndex ); ++fileIndex; fileOffset = 0; if( ( err != 0 ) && (ioMode == TR_IO_WRITE ) && ( tor->error != TR_STAT_LOCAL_ERROR ) ) { char * path = tr_buildPath( tor->downloadDir, file->name, NULL ); tr_torrentSetLocalError( tor, "%s (%s)", tr_strerror( err ), path ); tr_free( path ); } } return err; }