Changeset 9550
- Timestamp:
- Nov 24, 2009, 2:16:31 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gtk/add-dialog.c
r9547 r9550 493 493 else 494 494 { 495 GtkWidget * w = gtk_message_dialog_new( GTK_WINDOW( dialog ), 496 GTK_DIALOG_MODAL, 495 GtkWidget * w = gtk_message_dialog_new( GTK_WINDOW( dialog ), 0, 497 496 GTK_MESSAGE_ERROR, 498 497 GTK_BUTTONS_CLOSE, … … 500 499 gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), 501 500 _( "Transmission doesn't know how to use \"%s\"" ), url ); 502 gtk_dialog_run( GTK_DIALOG( w ) ); 503 gtk_widget_destroy( w ); 501 g_signal_connect_swapped( w, "response", 502 G_CALLBACK( gtk_widget_destroy ), w ); 503 gtk_widget_show( w ); 504 504 destroy = FALSE; 505 505 } -
trunk/gtk/icons.c
r9194 r9550 231 231 const char * stock_name; 232 232 233 if( !strcmp( mime_type, DIRECTORY_MIME_TYPE ) ) 233 if( !strcmp( mime_type, UNKNOWN_MIME_TYPE ) ) 234 stock_name = GTK_STOCK_MISSING_IMAGE; 235 else if( !strcmp( mime_type, DIRECTORY_MIME_TYPE ) ) 234 236 stock_name = GTK_STOCK_DIRECTORY; 235 237 else -
trunk/gtk/icons.h
r7999 r9550 8 8 9 9 #define DIRECTORY_MIME_TYPE "folder" 10 #define UNKNOWN_MIME_TYPE "unknown" 10 11 11 12 const char * get_mime_type_from_filename( const char *file ); -
trunk/gtk/torrent-cell-renderer.c
r9172 r9550 307 307 const tr_info * info = tr_torrentInfo( tor ); 308 308 309 if( info->fileCount > 1 ) 309 if( info->fileCount == 0 ) 310 mime_type = UNKNOWN_MIME_TYPE; 311 else if( info->fileCount > 1 ) 310 312 mime_type = DIRECTORY_MIME_TYPE; 311 313 else -
trunk/gtk/tr-core.c
r9547 r9550 1024 1024 tr_core_add_from_url( TrCore * core, const char * url ) 1025 1025 { 1026 tr_session * session = tr_core_session( core ); 1027 1026 1028 if( gtr_is_magnet_link( url ) ) 1027 1029 { 1028 g_message( "FIXME: magnet link \"%s\" not handled", url ); 1030 tr_ctor * ctor = tr_ctorNew( session ); 1031 int err = tr_ctorSetMagnet( ctor, url ); 1032 if( !err ) 1033 { 1034 tr_session * session = tr_core_session( core ); 1035 TrTorrent * gtor = tr_torrent_new_ctor( session, ctor, &err ); 1036 if( !err ) 1037 tr_core_add_torrent( core, gtor, FALSE ); 1038 else 1039 g_message( "tr_torrent_new_ctor err %d", err ); 1040 } 1041 else 1042 { 1043 GtkWidget * w = gtk_message_dialog_new( NULL, 0, 1044 GTK_MESSAGE_ERROR, 1045 GTK_BUTTONS_CLOSE, 1046 "%s", _( "Unrecognized URL" ) ); 1047 gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), 1048 _( "Transmission doesn't know how to use \"%s\"" ), url ); 1049 g_signal_connect_swapped( w, "response", 1050 G_CALLBACK( gtk_widget_destroy ), w ); 1051 gtk_widget_show( w ); 1052 tr_ctorFree( ctor ); 1053 } 1029 1054 } 1030 1055 else … … 1032 1057 struct url_dialog_data * data = g_new( struct url_dialog_data, 1 ); 1033 1058 data->core = core; 1034 tr_webRun( tr_core_session( core ), url, NULL, onURLDone, data );1059 tr_webRun( session, url, NULL, onURLDone, data ); 1035 1060 } 1036 1061 } … … 1052 1077 return; 1053 1078 1079 g_message( "filename [%s]", filename ); 1054 1080 if( gtr_is_supported_url( filename ) || gtr_is_magnet_link( filename ) ) 1055 1081 { -
trunk/gtk/util.c
r9547 r9550 347 347 for( i=0; i<argc; ++i ) 348 348 { 349 if( gtr_is_supported_url( argv[i] ) )349 if( gtr_is_supported_url( argv[i] ) || gtr_is_magnet_link( argv[i] ) ) 350 350 { 351 351 ret = g_slist_prepend( ret, g_strdup( argv[i] ) ); -
trunk/libtransmission/Makefile.am
r9531 r9550 48 48 torrent.c \ 49 49 torrent-ctor.c \ 50 torrent-magnet.c \ 50 51 tr-dht.c \ 51 52 tr-getopt.c \ … … 95 96 stats.h \ 96 97 torrent.h \ 98 torrent-magnet.h \ 97 99 tr-getopt.h \ 98 100 transmission.h \ -
trunk/libtransmission/completion.c
r8212 r9550 17 17 #include "completion.h" 18 18 #include "torrent.h" 19 #include "torrent-magnet.h" 19 20 #include "utils.h" 20 21 … … 241 242 tr_cpGetStatus( const tr_completion * cp ) 242 243 { 244 if( !tr_torrentHasMetadata( cp->tor ) ) return TR_LEECH; 243 245 if( cp->sizeNow == cp->tor->info.totalSize ) return TR_SEED; 244 246 if( cp->sizeNow == tr_cpSizeWhenDone( cp ) ) return TR_PARTIAL_SEED; … … 255 257 const uint64_t lastPieceSize = tor->lastPieceSize; 256 258 const tr_piece_index_t lastPiece = tor->info.pieceCount - 1; 259 260 if( !tr_torrentHasMetadata( tor ) ) 261 return 0; 257 262 258 263 for( i=0; i!=lastPiece; ++i ) -
trunk/libtransmission/metainfo.c
r9170 r9550 38 38 #include "bencode.h" 39 39 #include "crypto.h" /* tr_sha1 */ 40 #include "magnet.h" 40 41 #include "metainfo.h" 41 42 #include "platform.h" … … 228 229 229 230 static char * 230 announceToScrape( const char * announce )231 tr_convertAnnounceToScrape( const char * announce ) 231 232 { 232 233 char * scrape = NULL; … … 295 296 t->tier = validTiers; 296 297 t->announce = tr_strdup( url ); 297 t->scrape = announceToScrape( url );298 t->scrape = tr_convertAnnounceToScrape( url ); 298 299 299 300 anyAdded = TRUE; … … 325 326 trackers[trackerCount].tier = 0; 326 327 trackers[trackerCount].announce = tr_strdup( url ); 327 trackers[trackerCount++].scrape = announceToScrape( url );328 trackers[trackerCount++].scrape = tr_convertAnnounceToScrape( url ); 328 329 /*fprintf( stderr, "single announce: [%s]\n", url );*/ 329 330 } … … 382 383 static const char* 383 384 tr_metainfoParseImpl( const tr_session * session, 384 tr_info * inf, 385 const tr_benc * meta_in ) 385 tr_info * inf, 386 int * infoDictOffset, 387 int * infoDictLength, 388 const tr_benc * meta_in ) 386 389 { 387 390 int64_t i; … … 405 408 tr_sha1_to_hex( inf->hashString, inf->hash ); 406 409 escape( inf->hashEscaped, inf->hash, SHA_DIGEST_LENGTH ); 410 411 if( infoDictLength != NULL ) 412 *infoDictLength = len; 413 414 if( infoDictOffset != NULL ) 415 { 416 int mlen = 0; 417 char * mstr = tr_bencToStr( meta_in, TR_FMT_BENC, &mlen ); 418 const char * offset = tr_memmem( mstr, mlen, bstr, len ); 419 if( offset != NULL ) 420 *infoDictOffset = offset - mstr; 421 tr_free( mstr ); 422 if( offset == NULL ) 423 return "info"; 424 } 425 407 426 tr_free( bstr ); 408 427 } … … 484 503 tr_metainfoParse( const tr_session * session, 485 504 tr_info * inf, 505 int * infoDictOffset, 506 int * infoDictLength, 486 507 const tr_benc * meta_in ) 487 508 { 488 const char * badTag = tr_metainfoParseImpl( session, inf, meta_in ); 509 const char * badTag = tr_metainfoParseImpl( session, 510 inf, 511 infoDictOffset, 512 infoDictLength, 513 meta_in ); 489 514 const tr_bool success = badTag == NULL; 490 515 … … 501 526 tr_metainfoFree( tr_info * inf ) 502 527 { 528 int i; 503 529 tr_file_index_t ff; 504 int i;505 530 506 531 for( i = 0; i < inf->webseedCount; ++i ) … … 543 568 } 544 569 570 /*** 571 **** 572 ***/ 573 574 void 575 tr_metainfoSetFromMagnet( tr_info * inf, const tr_magnet_info * m ) 576 { 577 /* hash */ 578 memcpy( inf->hash, m->hash, 20 ); 579 tr_sha1_to_hex( inf->hashString, inf->hash ); 580 escape( inf->hashEscaped, inf->hash, SHA_DIGEST_LENGTH ); 581 582 /* name */ 583 if( *m->displayName ) 584 inf->name = tr_strdup( m->displayName ); 585 else 586 inf->name = tr_strdup( inf->hashString ); 587 588 /* trackers */ 589 if( m->announceCount > 0 ) 590 { 591 int i; 592 const int n = m->announceCount; 593 594 inf->trackerCount = n; 595 inf->trackers = tr_new0( tr_tracker_info, n ); 596 for( i=0; i<n; ++i ) { 597 const char * url = m->announceURLs[i]; 598 inf->trackers[i].tier = i; 599 inf->trackers[i].announce = tr_strdup( url ); 600 inf->trackers[i].scrape = tr_convertAnnounceToScrape( url ); 601 } 602 } 603 } -
trunk/libtransmission/metainfo.h
r8871 r9550 24 24 25 25 #ifndef __TRANSMISSION__ 26 #error only libtransmission should #include this header.26 #error only libtransmission should #include this header. 27 27 #endif 28 28 … … 33 33 34 34 struct tr_benc; 35 struct tr_magnet_info; 35 36 36 37 tr_bool tr_metainfoParse( const tr_session * session, 37 tr_info * info, 38 tr_info * setmeInfo, 39 int * setmeInfoDictLength, 40 int * setmeInfoDictOffset, 38 41 const struct tr_benc * benc ); 39 42 … … 44 47 tr_info * inf ); 45 48 49 void tr_metainfoSetFromMagnet( tr_info * inf, const struct tr_magnet_info * m ); 50 51 46 52 #endif -
trunk/libtransmission/peer-mgr.c
r9548 r9550 344 344 { 345 345 tr_peer * peer = tr_new0( tr_peer, 1 ); 346 tr_bitsetConstructor( &peer->have, 0 ); 346 347 peer->atom = atom; 347 348 return peer; … … 384 385 tr_peerIoUnref( peer->io ); /* balanced by the ref in handshakeDoneCB() */ 385 386 386 tr_bit fieldFree(peer->have );387 tr_bitsetDestructor( &peer->have ); 387 388 tr_bitfieldFree( peer->blame ); 388 389 tr_free( peer->client ); … … 907 908 Torrent * t; 908 909 struct weighted_piece * pieces; 909 const tr_bit field * have =peer->have;910 const tr_bitset * have = &peer->have; 910 911 const time_t now = time( NULL ); 911 912 … … 929 930 930 931 /* if the peer has this piece that we want... */ 931 if( tr_bit fieldHasFast( have, p->index ) )932 if( tr_bitsetHasFast( have, p->index ) ) 932 933 { 933 934 tr_block_index_t b = tr_torPieceFirstBlock( tor, p->index ); … … 1942 1943 int j; 1943 1944 for( j = 0; j < peerCount; ++j ) 1944 if( tr_bit fieldHas(peers[j]->have, i ) )1945 if( tr_bitsetHas( &peers[j]->have, i ) ) 1945 1946 ++tab[i]; 1946 1947 } … … 1965 1966 peers = (const tr_peer**) tr_ptrArrayBase( &t->peers ); 1966 1967 for( i=0; i<peerCount; ++i ) 1967 tr_bit fieldOr( pieces,peers[i]->have );1968 tr_bitsetOr( pieces, &peers[i]->have ); 1968 1969 1969 1970 managerUnlock( t->manager ); … … 2352 2353 else { 2353 2354 tr_bitfield * tmp = tr_bitfieldDup( tr_cpPieceBitfield( &tor->completion ) ); 2354 tr_bit fieldDifference( tmp,peer->have );2355 tr_bitsetDifference( tmp, &peer->have ); 2355 2356 peerHasEverything = tr_bitfieldCountTrueBits( tmp ) == 0; 2356 2357 tr_bitfieldFree( tmp ); -
trunk/libtransmission/peer-mgr.h
r9532 r9550 25 25 26 26 #include "bitfield.h" 27 #include "bitset.h" 27 28 #include "net.h" 28 29 #include "peer-common.h" /* struct peer_request */ … … 94 95 95 96 struct tr_bitfield * blame; 96 struct tr_bit field *have;97 struct tr_bitset have; 97 98 98 99 /** how complete the peer's copy of the torrent is. [0.0...1.0] */ -
trunk/libtransmission/peer-msgs.c
r9549 r9550 36 36 #include "stats.h" 37 37 #include "torrent.h" 38 #include "torrent-magnet.h" 38 39 #include "tr-dht.h" 39 40 #include "utils.h" … … 67 68 LTEP_HANDSHAKE = 0, 68 69 69 TR_LTEP_PEX = 1, 70 UT_PEX_ID = 1, 71 UT_METADATA_ID = 3, 70 72 71 73 MAX_PEX_PEER_COUNT = 50, 72 74 73 MIN_CHOKE_PERIOD_SEC = ( 10 ),75 MIN_CHOKE_PERIOD_SEC = 10, 74 76 75 77 /* idle seconds before we send a keepalive */ … … 79 81 80 82 REQQ = 512, 83 84 METADATA_REQQ = 64, 81 85 82 86 MAX_BLOCK_SIZE = ( 1024 * 16 ), … … 92 96 93 97 /* number of pieces we'll allow in our fast set */ 94 MAX_FAST_SET_SIZE = 3 98 MAX_FAST_SET_SIZE = 3, 99 100 /* defined in BEP #9 */ 101 METADATA_MSG_TYPE_REQUEST = 0, 102 METADATA_MSG_TYPE_DATA = 1, 103 METADATA_MSG_TYPE_REJECT = 2 95 104 }; 96 105 … … 166 175 { 167 176 tr_bool peerSupportsPex; 177 tr_bool peerSupportsMetadataXfer; 168 178 tr_bool clientSentLtepHandshake; 169 179 tr_bool peerSentLtepHandshake; 180 tr_bool requestingMetadataFromPeer; 181 170 182 /*tr_bool haveFastSet;*/ 171 183 … … 182 194 uint8_t state; 183 195 uint8_t ut_pex_id; 196 uint8_t ut_metadata_id; 184 197 uint16_t pexCount; 185 198 uint16_t pexCount6; … … 200 213 struct peer_request peerAskedFor[REQQ]; 201 214 int peerAskedForCount; 202 215 216 int peerAskedForMetadata[METADATA_REQQ]; 217 int peerAskedForMetadataCount; 218 203 219 tr_pex * pex; 204 220 tr_pex * pex6; … … 219 235 struct event pexTimer; 220 236 }; 237 238 /** 239 *** 240 **/ 241 242 #if 0 243 static tr_bitfield* 244 getHave( const struct tr_peermsgs * msgs ) 245 { 246 if( msgs->peer->have == NULL ) 247 msgs->peer->have = tr_bitfieldNew( msgs->torrent->info.pieceCount ); 248 return msgs->peer->have; 249 } 250 #endif 221 251 222 252 static TR_INLINE tr_session* … … 655 685 const tr_torrent * torrent = msgs->torrent; 656 686 657 return ( !torrent->info.pieces[piece].dnd ) /* we want it */687 return ( !torrent->info.pieces[piece].dnd ) /* we want it */ 658 688 && ( !tr_cpPieceIsComplete( &torrent->completion, piece ) ) /* !have */ 659 && ( tr_bit fieldHas( msgs->peer->have, piece ) );/* peer has it */689 && ( tr_bitsetHas( &msgs->peer->have, piece ) ); /* peer has it */ 660 690 } 661 691 … … 678 708 bitfield = tr_cpPieceBitfield( &torrent->completion ); 679 709 680 if( !msgs->peer->have )681 return TRUE;682 683 assert( bitfield->byteCount == msgs->peer->have->byteCount );684 685 710 for( i = 0; i < torrent->info.pieceCount; ++i ) 686 711 if( isPieceInteresting( msgs, i ) ) … … 715 740 if( i != msgs->peer->clientIsInterested ) 716 741 sendInterest( msgs, i ); 742 } 743 744 static tr_bool 745 popNextMetadataRequest( tr_peermsgs * msgs, int * piece ) 746 { 747 if( msgs->peerAskedForMetadataCount == 0 ) 748 return FALSE; 749 750 *piece = msgs->peerAskedForMetadata[0]; 751 752 memmove( msgs->peerAskedForMetadata, 753 msgs->peerAskedForMetadata + 1, 754 sizeof( int ) * --msgs->peerAskedForMetadataCount ); 755 756 return TRUE; 717 757 } 718 758 … … 820 860 char * buf; 821 861 int len; 822 int pex; 862 tr_bool allow_pex; 863 tr_bool allow_metadata_xfer; 823 864 struct evbuffer * out = msgs->outMessages; 824 865 const unsigned char * ipv6 = tr_globalIPv6(); … … 830 871 msgs->clientSentLtepHandshake = 1; 831 872 873 /* decide if we want to advertise metadata xfer support (BEP 9) */ 874 if( tr_torrentIsPrivate( msgs->torrent ) ) 875 allow_metadata_xfer = 0; 876 else 877 allow_metadata_xfer = 1; 878 832 879 /* decide if we want to advertise pex support */ 833 880 if( !tr_torrentAllowsPex( msgs->torrent ) ) 834 pex = 0;881 allow_pex = 0; 835 882 else if( msgs->peerSentLtepHandshake ) 836 pex = msgs->peerSupportsPex ? 1 : 0;883 allow_pex = msgs->peerSupportsPex ? 1 : 0; 837 884 else 838 pex = 1;839 840 tr_bencInitDict( &val, 7);885 allow_pex = 1; 886 887 tr_bencInitDict( &val, 8 ); 841 888 tr_bencDictAddInt( &val, "e", getSession(msgs)->encryptionMode != TR_CLEAR_PREFERRED ); 842 if( ipv6 )889 if( ipv6 != NULL ) 843 890 tr_bencDictAddRaw( &val, "ipv6", ipv6, 16 ); 891 if( allow_metadata_xfer && tr_torrentHasMetadata( msgs->torrent ) 892 && ( msgs->torrent->infoDictLength > 0 ) ) 893 tr_bencDictAddInt( &val, "metadata_size", msgs->torrent->infoDictLength ); 844 894 tr_bencDictAddInt( &val, "p", tr_sessionGetPeerPort( getSession(msgs) ) ); 845 895 tr_bencDictAddInt( &val, "reqq", REQQ ); 846 896 tr_bencDictAddInt( &val, "upload_only", tr_torrentIsSeed( msgs->torrent ) ); 847 897 tr_bencDictAddStr( &val, "v", TR_NAME " " USERAGENT_PREFIX ); 848 m = tr_bencDictAddDict( &val, "m", 1 ); 849 if( pex ) 850 tr_bencDictAddInt( m, "ut_pex", TR_LTEP_PEX ); 898 m = tr_bencDictAddDict( &val, "m", 2 ); 899 if( allow_metadata_xfer ) 900 tr_bencDictAddInt( m, "ut_metadata", UT_METADATA_ID ); 901 if( allow_pex ) 902 tr_bencDictAddInt( m, "ut_pex", UT_PEX_ID ); 903 851 904 buf = tr_bencToStr( &val, TR_FMT_BENC, &len ); 852 905 … … 899 952 /* check supported messages for utorrent pex */ 900 953 msgs->peerSupportsPex = 0; 954 msgs->peerSupportsMetadataXfer = 0; 955 901 956 if( tr_bencDictFindDict( &val, "m", &sub ) ) { 902 957 if( tr_bencDictFindInt( sub, "ut_pex", &i ) ) { 958 msgs->peerSupportsPex = i != 0; 903 959 msgs->ut_pex_id = (uint8_t) i; 904 msgs->peerSupportsPex = msgs->ut_pex_id == 0 ? 0 : 1;905 960 dbgmsg( msgs, "msgs->ut_pex is %d", (int)msgs->ut_pex_id ); 906 961 } 907 } 962 if( tr_bencDictFindInt( sub, "ut_metadata", &i ) ) { 963 msgs->peerSupportsMetadataXfer = i != 0; 964 msgs->ut_metadata_id = (uint8_t) i; 965 dbgmsg( msgs, "msgs->ut_metadata_id is %d", (int)msgs->ut_metadata_id ); 966 } 967 } 968 969 /* look for metainfo size (BEP 9) */ 970 if( tr_bencDictFindInt( &val, "metadata_size", &i ) ) 971 tr_torrentSetMetadataSizeHint( msgs->torrent, i ); 908 972 909 973 /* look for upload_only (BEP 21) */ … … 926 990 tr_peerMgrAddPex( msgs->torrent, TR_PEER_FROM_ALT, &pex ); 927 991 } 928 992 929 993 if( tr_bencDictFindRaw( &val, "ipv6", &addr, &addr_len) && addr_len == 16 ) { 930 994 pex.addr.type = TR_AF_INET6; … … 938 1002 939 1003 tr_bencFree( &val ); 1004 tr_free( tmp ); 1005 } 1006 1007 static void 1008 parseUtMetadata( tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf ) 1009 { 1010 tr_benc dict; 1011 char * msg_end; 1012 char * benc_end; 1013 int64_t msg_type = -1; 1014 int64_t piece = -1; 1015 int64_t total_size = 0; 1016 uint8_t * tmp = tr_new( uint8_t, msglen ); 1017 1018 tr_peerIoReadBytes( msgs->peer->io, inbuf, tmp, msglen ); 1019 msg_end = (char*)tmp + msglen; 1020 1021 if( !tr_bencLoad( tmp, msglen, &dict, &benc_end ) ) 1022 { 1023 tr_bencDictFindInt( &dict, "msg_type", &msg_type ); 1024 tr_bencDictFindInt( &dict, "piece", &piece ); 1025 tr_bencDictFindInt( &dict, "total_size", &total_size ); 1026 tr_bencFree( &dict ); 1027 } 1028 1029 dbgmsg( msgs, "got ut_metadata msg: type %d, piece %d, total_size %d", 1030 (int)msg_type, (int)piece, (int)total_size ); 1031 1032 if( msg_type == METADATA_MSG_TYPE_REJECT ) 1033 { 1034 /* NOOP */ 1035 } 1036 1037 if( ( msg_type == METADATA_MSG_TYPE_DATA ) 1038 && ( !tr_torrentHasMetadata( msgs->torrent ) ) 1039 && ( msg_end - benc_end <= METADATA_PIECE_SIZE ) 1040 && ( piece * METADATA_PIECE_SIZE + (msg_end - benc_end) <= total_size ) ) 1041 { 1042 const int pieceLen = msg_end - benc_end; 1043 dbgmsg( msgs, "got a metadata piece... calling tr_torrentSetMetadataPiece" ); 1044 msgs->requestingMetadataFromPeer = FALSE; 1045 tr_torrentSetMetadataPiece( msgs->torrent, piece, benc_end, pieceLen ); 1046 } 1047 1048 if( msg_type == METADATA_MSG_TYPE_REQUEST ) 1049 { 1050 if( ( piece >= 0 ) 1051 && tr_torrentHasMetadata( msgs->torrent ) 1052 && !tr_torrentIsPrivate( msgs->torrent ) 1053 && ( msgs->peerAskedForMetadataCount < METADATA_REQQ ) ) 1054 { 1055 msgs->peerAskedForMetadata[msgs->peerAskedForMetadataCount++] = piece; 1056 } 1057 else 1058 { 1059 tr_benc tmp; 1060 int payloadLen; 1061 char * payload; 1062 tr_peerIo * io = msgs->peer->io; 1063 struct evbuffer * out = msgs->outMessages; 1064 1065 /* build the rejection message */ 1066 tr_bencInitDict( &tmp, 2 ); 1067 tr_bencDictAddInt( &tmp, "msg_type", METADATA_MSG_TYPE_REJECT ); 1068 tr_bencDictAddInt( &tmp, "piece", piece ); 1069 payload = tr_bencToStr( &tmp, TR_FMT_BENC, &payloadLen ); 1070 tr_bencFree( &tmp ); 1071 1072 /* write it out as a LTEP message to our outMessages buffer */ 1073 tr_peerIoWriteUint32( io, out, 2 * sizeof( uint8_t ) + payloadLen ); 1074 tr_peerIoWriteUint8 ( io, out, BT_LTEP ); 1075 tr_peerIoWriteUint8 ( io, out, msgs->ut_metadata_id ); 1076 tr_peerIoWriteBytes ( io, out, payload, payloadLen ); 1077 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 1078 dbgOutMessageLen( msgs ); 1079 1080 tr_free( payload ); 1081 } 1082 } 1083 940 1084 tr_free( tmp ); 941 1085 } … … 1018 1162 } 1019 1163 } 1020 else if( ltep_msgid == TR_LTEP_PEX)1164 else if( ltep_msgid == UT_PEX_ID ) 1021 1165 { 1022 1166 dbgmsg( msgs, "got ut pex" ); 1023 1167 msgs->peerSupportsPex = 1; 1024 1168 parseUtPex( msgs, msglen, inbuf ); 1169 } 1170 else if( ltep_msgid == UT_METADATA_ID ) 1171 { 1172 dbgmsg( msgs, "got ut metadata" ); 1173 msgs->peerSupportsMetadataXfer = 1; 1174 parseUtMetadata( msgs, msglen, inbuf ); 1025 1175 } 1026 1176 else … … 1088 1238 updatePeerProgress( tr_peermsgs * msgs ) 1089 1239 { 1090 msgs->peer->progress = tr_bit fieldCountTrueBits( msgs->peer->have ) / (float)msgs->torrent->info.pieceCount;1240 msgs->peer->progress = tr_bitsetPercent( &msgs->peer->have ); 1091 1241 dbgmsg( msgs, "peer progress is %f", msgs->peer->progress ); 1092 1242 updateFastSet( msgs ); … … 1287 1437 tr_peerIoReadUint32( msgs->peer->io, inbuf, &ui32 ); 1288 1438 dbgmsg( msgs, "got Have: %u", ui32 ); 1289 if( tr_bit fieldAdd(msgs->peer->have, ui32 ) ) {1439 if( tr_bitsetAdd( &msgs->peer->have, ui32 ) ) { 1290 1440 fireError( msgs, ERANGE ); 1291 1441 return READ_ERR; … … 1296 1446 case BT_BITFIELD: 1297 1447 dbgmsg( msgs, "got a bitfield" ); 1298 tr_peerIoReadBytes( msgs->peer->io, inbuf, msgs->peer->have->bits, msglen ); 1448 tr_bitsetReserve( &msgs->peer->have, msglen*8 ); 1449 tr_peerIoReadBytes( msgs->peer->io, inbuf, msgs->peer->have.bitfield.bits, msglen ); 1299 1450 updatePeerProgress( msgs ); 1300 1451 break; … … 1319 1470 tr_peerIoReadUint32( msgs->peer->io, inbuf, &r.length ); 1320 1471 dbgmsg( msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length ); 1472 1321 1473 for( i=0; i<msgs->peerAskedForCount; ++i ) { 1322 1474 const struct peer_request * req = msgs->peerAskedFor + i; … … 1324 1476 break; 1325 1477 } 1478 1326 1479 if( i < msgs->peerAskedForCount ) 1327 memmove( msgs->peerAskedFor+i, msgs->peerAskedFor+i+1, --msgs->peerAskedForCount-i ); 1480 memmove( msgs->peerAskedFor+i, 1481 msgs->peerAskedFor+i+1, 1482 sizeof(struct peer_request) *( --msgs->peerAskedForCount-i) ); 1328 1483 break; 1329 1484 } … … 1367 1522 dbgmsg( msgs, "Got a BT_FEXT_HAVE_ALL" ); 1368 1523 if( fext ) { 1369 tr_bit fieldAddRange( msgs->peer->have, 0, msgs->torrent->info.pieceCount);1524 tr_bitsetSetHaveAll( &msgs->peer->have ); 1370 1525 updatePeerProgress( msgs ); 1371 1526 } else { … … 1378 1533 dbgmsg( msgs, "Got a BT_FEXT_HAVE_NONE" ); 1379 1534 if( fext ) { 1380 tr_bit fieldClear(msgs->peer->have );1535 tr_bitsetSetHaveNone( &msgs->peer->have ); 1381 1536 updatePeerProgress( msgs ); 1382 1537 } else { … … 1587 1742 1588 1743 static void 1589 updateRequests( tr_peermsgs * msgs ) 1744 updateMetadataRequests( tr_peermsgs * msgs, time_t now ) 1745 { 1746 int piece; 1747 1748 if( msgs->peerSupportsMetadataXfer 1749 && !msgs->requestingMetadataFromPeer 1750 && tr_torrentGetNextMetadataRequest( msgs->torrent, now, &piece ) ) 1751 { 1752 tr_benc tmp; 1753 int payloadLen; 1754 char * payload; 1755 tr_peerIo * io = msgs->peer->io; 1756 struct evbuffer * out = msgs->outMessages; 1757 1758 /* build the data message */ 1759 tr_bencInitDict( &tmp, 3 ); 1760 tr_bencDictAddInt( &tmp, "msg_type", METADATA_MSG_TYPE_REQUEST ); 1761 tr_bencDictAddInt( &tmp, "piece", piece ); 1762 payload = tr_bencToStr( &tmp, TR_FMT_BENC, &payloadLen ); 1763 tr_bencFree( &tmp ); 1764 1765 dbgmsg( msgs, "requesting metadata piece #%d", piece ); 1766 1767 /* write it out as a LTEP message to our outMessages buffer */ 1768 tr_peerIoWriteUint32( io, out, 2 * sizeof( uint8_t ) + payloadLen ); 1769 tr_peerIoWriteUint8 ( io, out, BT_LTEP ); 1770 tr_peerIoWriteUint8 ( io, out, msgs->ut_metadata_id ); 1771 tr_peerIoWriteBytes ( io, out, payload, payloadLen ); 1772 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 1773 dbgOutMessageLen( msgs ); 1774 1775 msgs->requestingMetadataFromPeer = TRUE; 1776 1777 tr_free( payload ); 1778 } 1779 } 1780 1781 static void 1782 updateBlockRequests( tr_peermsgs * msgs ) 1590 1783 { 1591 1784 const int MIN_BATCH_SIZE = 4; … … 1642 1835 fillOutputBuffer( tr_peermsgs * msgs, time_t now ) 1643 1836 { 1837 int piece; 1644 1838 size_t bytesWritten = 0; 1645 1839 struct peer_request req; … … 1669 1863 1670 1864 /** 1671 *** Blocks 1865 *** Metadata Pieces 1866 **/ 1867 1868 if( ( tr_peerIoGetWriteBufferSpace( msgs->peer->io, now ) >= METADATA_PIECE_SIZE ) 1869 && popNextMetadataRequest( msgs, &piece ) ) 1870 { 1871 char * data; 1872 int dataLen; 1873 tr_bool ok = FALSE; 1874 1875 data = tr_torrentGetMetadataPiece( msgs->torrent, piece, &dataLen ); 1876 if( ( dataLen > 0 ) && ( data != NULL ) ) 1877 { 1878 tr_benc tmp; 1879 int payloadLen; 1880 char * payload; 1881 tr_peerIo * io = msgs->peer->io; 1882 struct evbuffer * out = msgs->outMessages; 1883 1884 /* build the data message */ 1885 tr_bencInitDict( &tmp, 3 ); 1886 tr_bencDictAddInt( &tmp, "msg_type", METADATA_MSG_TYPE_DATA ); 1887 tr_bencDictAddInt( &tmp, "piece", piece ); 1888 tr_bencDictAddInt( &tmp, "total_size", dataLen ); 1889 payload = tr_bencToStr( &tmp, TR_FMT_BENC, &payloadLen ); 1890 tr_bencFree( &tmp ); 1891 1892 /* write it out as a LTEP message to our outMessages buffer */ 1893 tr_peerIoWriteUint32( io, out, 2 * sizeof( uint8_t ) + payloadLen + dataLen ); 1894 tr_peerIoWriteUint8 ( io, out, BT_LTEP ); 1895 tr_peerIoWriteUint8 ( io, out, msgs->ut_metadata_id ); 1896 tr_peerIoWriteBytes ( io, out, payload, payloadLen ); 1897 tr_peerIoWriteBytes ( io, out, data, dataLen ); 1898 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 1899 dbgOutMessageLen( msgs ); 1900 1901 tr_free( payload ); 1902 tr_free( data ); 1903 1904 ok = TRUE; 1905 } 1906 1907 if( !ok ) /* send a rejection message */ 1908 { 1909 tr_benc tmp; 1910 int payloadLen; 1911 char * payload; 1912 tr_peerIo * io = msgs->peer->io; 1913 struct evbuffer * out = msgs->outMessages; 1914 1915 /* build the rejection message */ 1916 tr_bencInitDict( &tmp, 2 ); 1917 tr_bencDictAddInt( &tmp, "msg_type", METADATA_MSG_TYPE_REJECT ); 1918 tr_bencDictAddInt( &tmp, "piece", piece ); 1919 payload = tr_bencToStr( &tmp, TR_FMT_BENC, &payloadLen ); 1920 tr_bencFree( &tmp ); 1921 1922 /* write it out as a LTEP message to our outMessages buffer */ 1923 tr_peerIoWriteUint32( io, out, 2 * sizeof( uint8_t ) + payloadLen ); 1924 tr_peerIoWriteUint8 ( io, out, BT_LTEP ); 1925 tr_peerIoWriteUint8 ( io, out, msgs->ut_metadata_id ); 1926 tr_peerIoWriteBytes ( io, out, payload, payloadLen ); 1927 pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS ); 1928 dbgOutMessageLen( msgs ); 1929 1930 tr_free( payload ); 1931 } 1932 } 1933 1934 /** 1935 *** Data Blocks 1672 1936 **/ 1673 1937 … … 1750 2014 if ( tr_isPeerIo( msgs->peer->io ) ) { 1751 2015 updateDesiredRequestCount( msgs, now ); 1752 updateRequests( msgs ); 2016 updateBlockRequests( msgs ); 2017 updateMetadataRequests( msgs, now ); 1753 2018 } 1754 2019 … … 2112 2377 m->peer->clientIsInterested = 0; 2113 2378 m->peer->peerIsInterested = 0; 2114 m->peer->have = tr_bitfieldNew( torrent->info.pieceCount );2115 2379 m->state = AWAITING_BT_LENGTH; 2116 2380 m->outMessages = evbuffer_new( ); … … 2168 2432 tr_publisherUnsubscribe( &peer->publisher, tag ); 2169 2433 } 2170 -
trunk/libtransmission/rpcimpl.c
r9538 r9550 1094 1094 else 1095 1095 { 1096 if( filename != NULL ) 1097 tr_ctorSetMetainfoFromFile( ctor, filename ); 1098 else { 1096 if( filename == NULL ) 1097 { 1099 1098 int len; 1100 char * metainfo = tr_base64_decode( metainfo_base64, -1, 1099 char * metainfo = tr_base64_decode( metainfo_base64, -1, &len ); 1101 1100 tr_ctorSetMetainfo( ctor, (uint8_t*)metainfo, len ); 1102 1101 tr_free( metainfo ); 1103 1102 } 1103 else if( !strncmp( filename, "magnet:?", 8 ) ) 1104 { 1105 tr_ctorSetMagnet( ctor, filename ); 1106 } 1107 else 1108 { 1109 tr_ctorSetMetainfoFromFile( ctor, filename ); 1110 } 1111 1104 1112 addTorrentImpl( idle_data, ctor ); 1105 1113 } -
trunk/libtransmission/torrent-ctor.c
r9341 r9550 14 14 #include "transmission.h" 15 15 #include "bencode.h" 16 #include "magnet.h" 16 17 #include "platform.h" 17 18 #include "session.h" /* tr_sessionFindTorrentFile() */ … … 42 43 tr_benc metainfo; 43 44 char * sourceFile; 45 46 tr_magnet_info * magnetInfo; 44 47 45 48 struct optional_args optionalArgs[2]; … … 100 103 { 101 104 return ctor->sourceFile; 105 } 106 107 int 108 tr_ctorSetMagnet( tr_ctor * ctor, const char * uri ) 109 { 110 int err; 111 112 if( ctor->magnetInfo != NULL ) 113 tr_magnetFree( ctor->magnetInfo ); 114 115 ctor->magnetInfo = tr_magnetParse( uri ); 116 117 err = ctor->magnetInfo == NULL; 118 return err; 102 119 } 103 120 … … 373 390 374 391 int 392 tr_ctorGetMagnet( const tr_ctor * ctor, const tr_magnet_info ** setme ) 393 { 394 int err = 0; 395 396 if( ctor->magnetInfo == NULL ) 397 err = 1; 398 else 399 *setme = ctor->magnetInfo; 400 401 return err; 402 } 403 404 int 375 405 tr_ctorGetMetainfo( const tr_ctor * ctor, 376 406 const tr_benc ** setme ) -
trunk/libtransmission/torrent.c
r9549 r9550 33 33 #include "resume.h" 34 34 #include "fdlimit.h" /* tr_fdTorrentClose */ 35 #include "magnet.h" 35 36 #include "metainfo.h" 36 37 #include "peer-mgr.h" … … 44 45 #include "verify.h" 45 46 46 #define MAX_BLOCK_SIZE ( 1024 * 16 ) 47 enum 48 { 49 MAX_BLOCK_SIZE = 1024 * 16 50 }; 47 51 48 52 /*** … … 551 555 } 552 556 553 static void refreshCurrentDir( tr_torrent * tor ); ;557 static void refreshCurrentDir( tr_torrent * tor ); 554 558 555 559 static void 556 torrentRealInit( tr_torrent * tor, const tr_ctor * ctor ) 557 { 558 int doStart; 559 uint64_t loaded; 560 uint64_t t; 561 const char * dir; 562 static int nextUniqueId = 1; 563 tr_info * info = &tor->info; 564 tr_session * session = tr_ctorGetSession( ctor ); 565 566 assert( session != NULL ); 567 568 tr_globalLock( session ); 569 570 tor->session = session; 571 tor->uniqueId = nextUniqueId++; 572 tor->magicNumber = TORRENT_MAGIC_NUMBER; 573 574 randomizeTiers( info ); 575 576 tor->bandwidth = tr_bandwidthNew( session, session->bandwidth ); 560 torrentInitFromInfo( tr_torrent * tor ) 561 { 562 uint64_t t; 563 tr_info * info = &tor->info; 577 564 578 565 tor->blockSize = getBlockSize( info->pieceSize ); 579 566 580 if( !tr_ctorGetDownloadDir( ctor, TR_FORCE, &dir ) || 581 !tr_ctorGetDownloadDir( ctor, TR_FALLBACK, &dir ) ) 582 tor->downloadDir = tr_strdup( dir ); 583 584 if( tr_ctorGetIncompleteDir( ctor, &dir ) ) 585 dir = tr_sessionGetIncompleteDir( session ); 586 if( tr_sessionIsIncompleteDirEnabled( session ) ) 587 tor->incompleteDir = tr_strdup( dir ); 588 589 tor->lastPieceSize = info->totalSize % info->pieceSize; 567 if( info->pieceSize ) 568 tor->lastPieceSize = info->totalSize % info->pieceSize; 590 569 591 570 if( !tor->lastPieceSize ) 592 571 tor->lastPieceSize = info->pieceSize; 593 572 594 tor->lastBlockSize = info->totalSize % tor->blockSize; 573 if( tor->blockSize ) 574 tor->lastBlockSize = info->totalSize % tor->blockSize; 595 575 596 576 if( !tor->lastBlockSize ) 597 577 tor->lastBlockSize = tor->blockSize; 598 578 599 tor->blockCount = 600 ( info->totalSize + tor->blockSize - 1 ) / tor->blockSize; 601 602 tor->blockCountInPiece = 603 info->pieceSize / tor->blockSize; 604 605 tor->blockCountInLastPiece = 606 ( tor->lastPieceSize + tor->blockSize - 1 ) / tor->blockSize; 579 tor->blockCount = tor->blockSize 580 ? ( info->totalSize + tor->blockSize - 1 ) / tor->blockSize 581 : 0; 582 583 tor->blockCountInPiece = tor->blockSize 584 ? info->pieceSize / tor->blockSize 585 : 0; 586 587 tor->blockCountInLastPiece = tor->blockSize 588 ? ( tor->lastPieceSize + tor->blockSize - 1 ) / tor->blockSize 589 : 0; 607 590 608 591 /* check our work */ 609 assert( ( info->pieceSize % tor->blockSize ) == 0 ); 592 if( tor->blockSize != 0 ) 593 assert( ( info->pieceSize % tor->blockSize ) == 0 ); 610 594 t = info->pieceCount - 1; 611 595 t *= info->pieceSize; … … 625 609 tr_torrentInitFilePieces( tor ); 626 610 611 tr_bitfieldConstruct( &tor->checkedPieces, tor->info.pieceCount ); 612 613 tor->completeness = tr_cpGetStatus( &tor->completion ); 614 } 615 616 void 617 tr_torrentGotNewInfoDict( tr_torrent * tor ) 618 { 619 torrentInitFromInfo( tor ); 620 } 621 622 static void 623 torrentInit( tr_torrent * tor, const tr_ctor * ctor ) 624 { 625 int doStart; 626 uint64_t loaded; 627 const char * dir; 628 static int nextUniqueId = 1; 629 tr_session * session = tr_ctorGetSession( ctor ); 630 631 assert( session != NULL ); 632 633 tr_globalLock( session ); 634 635 tor->session = session; 636 tor->uniqueId = nextUniqueId++; 637 tor->magicNumber = TORRENT_MAGIC_NUMBER; 638 639 randomizeTiers( &tor->info ); 640 627 641 tr_sha1( tor->obfuscatedHash, "req2", 4, 628 info->hash, SHA_DIGEST_LENGTH,642 tor->info.hash, SHA_DIGEST_LENGTH, 629 643 NULL ); 644 645 if( !tr_ctorGetDownloadDir( ctor, TR_FORCE, &dir ) || 646 !tr_ctorGetDownloadDir( ctor, TR_FALLBACK, &dir ) ) 647 tor->downloadDir = tr_strdup( dir ); 648 649 if( tr_ctorGetIncompleteDir( ctor, &dir ) ) 650 dir = tr_sessionGetIncompleteDir( session ); 651 if( tr_sessionIsIncompleteDirEnabled( session ) ) 652 tor->incompleteDir = tr_strdup( dir ); 653 654 tor->bandwidth = tr_bandwidthNew( session, session->bandwidth ); 655 656 tor->error = TR_STAT_OK; 630 657 631 658 tr_peerMgrAddTorrent( session->peerMgr, tor ); … … 638 665 tr_ctorInitTorrentWanted( ctor, tor ); 639 666 640 tor->error = TR_STAT_OK;641 642 tr_bitfieldConstruct( &tor->checkedPieces, tor->info.pieceCount );643 667 tr_torrentUncheck( tor ); 644 668 … … 668 692 } 669 693 670 tor->completeness = tr_cpGetStatus( &tor->completion );671 672 694 { 673 695 tr_torrent * it = NULL; … … 683 705 } 684 706 685 t r_globalUnlock( session);707 torrentInitFromInfo( tor ); 686 708 687 709 /* maybe save our own copy of the metainfo */ … … 691 713 if( !tr_ctorGetMetainfo( ctor, &val ) ) 692 714 { 693 const char * filename= tor->info.torrent;694 tr_bencToFile( val, TR_FMT_BENC, filename);695 tr_sessionSetTorrentFile( tor->session, tor->info.hashString, filename);715 const char * path = tor->info.torrent; 716 tr_bencToFile( val, TR_FMT_BENC, path ); 717 tr_sessionSetTorrentFile( tor->session, tor->info.hashString, path ); 696 718 } 697 719 } 698 720 699 tor->tiers = tr_announcerAddTorrent( session->announcer, tor );721 tor->tiers = tr_announcerAddTorrent( tor->session->announcer, tor ); 700 722 tor->tiersSubscription = tr_announcerSubscribe( tor->tiers, onTrackerResponse, tor ); 701 702 tr_metainfoMigrate( session, &tor->info );703 723 704 724 if( doStart ) 705 725 torrentStart( tor ); 726 727 tr_globalUnlock( session ); 706 728 } 707 729 … … 723 745 return TR_PARSE_ERR; 724 746 725 didParse = tr_metainfoParse( session, setmeInfo, metainfo );747 didParse = tr_metainfoParse( session, setmeInfo, NULL, NULL, metainfo ); 726 748 doFree = didParse && ( setmeInfo == &tmp ); 727 749 … … 745 767 int * setmeError ) 746 768 { 747 int 748 tr_info 769 int err; 770 tr_info tmpInfo; 749 771 tr_torrent * tor = NULL; 772 const tr_magnet_info * magnetInfo; 750 773 751 774 assert( ctor != NULL ); 752 775 assert( tr_isSession( tr_ctorGetSession( ctor ) ) ); 753 776 754 err = tr_torrentParse( ctor, &tmpInfo ); 755 if( !err ) 777 if( !tr_ctorGetMagnet( ctor, &magnetInfo ) ) 756 778 { 757 779 tor = tr_new0( tr_torrent, 1 ); 758 tor->info = tmpInfo; 759 torrentRealInit( tor, ctor ); 760 } 761 else if( setmeError ) 762 { 763 *setmeError = err; 780 tr_metainfoSetFromMagnet( &tor->info, magnetInfo ); 781 torrentInit( tor, ctor ); 782 } 783 else 784 { 785 err = tr_torrentParse( ctor, &tmpInfo ); 786 if( !err ) 787 { 788 tor = tr_new0( tr_torrent, 1 ); 789 tor->info = tmpInfo; 790 torrentInit( tor, ctor ); 791 } 792 else if( setmeError ) 793 { 794 *setmeError = err; 795 } 764 796 } 765 797 … … 989 1021 tor->etaDLSpeedCalculatedAt = now; 990 1022 } 991 1023 992 1024 if( s->leftUntilDone > s->desiredAvailable ) 993 1025 s->eta = TR_ETA_NOT_AVAIL; … … 1007 1039 tor->etaULSpeedCalculatedAt = now; 1008 1040 } 1009 1041 1010 1042 if( s->pieceUploadSpeed < 0.1 ) 1011 1043 s->eta = TR_ETA_UNKNOWN; … … 1021 1053 break; 1022 1054 } 1023 1024 if( !checkSeedRatio || s->ratio >= seedRatio || s->ratio == TR_RATIO_INF ) 1025 s->percentRatio = 1.0; 1026 else if( s->ratio == TR_RATIO_NA ) 1027 s->percentRatio = 0.0; 1028 else 1029 s->percentRatio = s->ratio / seedRatio; 1055 1056 if( !checkSeedRatio || s->ratio >= seedRatio || s->ratio == TR_RATIO_INF ) 1057 s->percentRatio = 1.0; 1058 else if( s->ratio == TR_RATIO_NA ) 1059 s->percentRatio = 0.0; 1060 else 1061 s->percentRatio = s->ratio / seedRatio; 1030 1062 1031 1063 tr_torrentUnlock( tor ); … … 2097 2129 /* try to parse it back again, to make sure it's good */ 2098 2130 memset( &tmpInfo, 0, sizeof( tr_info ) ); 2099 if( tr_metainfoParse( tor->session, &tmpInfo, &metainfo ) ) 2131 if( tr_metainfoParse( tor->session, &tmpInfo, 2132 &tor->infoDictOffset, 2133 &tor->infoDictLength, 2134 &metainfo ) ) 2100 2135 { 2101 2136 /* it's good, so keep these new trackers and free the old ones */ … … 2368 2403 tr_free( path ); 2369 2404 2370 2371 2405 tmp = tr_torrentBuildPartial( tor, 0 ); 2372 2406 path = tr_buildPath( tor->currentDir, tmp, NULL ); … … 2657 2691 } 2658 2692 2659 2660 2693 char* 2661 2694 tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNum ) -
trunk/libtransmission/torrent.h
r9549 r9550 26 26 struct tr_ratecontrol; 27 27 struct tr_torrent_tiers; 28 struct tr_magnet_info; 28 29 29 30 /** … … 35 36 36 37 int tr_ctorGetSave( const tr_ctor * ctor ); 38 39 int tr_ctorGetMagnet( const tr_ctor * ctor, const struct tr_magnet_info ** setme ); 37 40 38 41 void tr_ctorInitTorrentPriorities( const tr_ctor * ctor, tr_torrent * tor ); … … 132 135 tr_verify_state state ); 133 136 137 struct tr_incomplete_metadata; 138 134 139 struct tr_torrent 135 140 { … … 143 148 144 149 uint8_t obfuscatedHash[SHA_DIGEST_LENGTH]; 150 151 /* Used when the torrent has been created with a magnet link 152 * and we're in the process of downloading the metainfo from 153 * other peers */ 154 struct tr_incomplete_metadata * incompleteMetadata; 145 155 146 156 /* If the initiator of the connection receives a handshake in which the … … 159 169 char * incompleteDir; 160 170 171 /* Length, in bytes, of the "info" dict in the .torrent file */ 172 int infoDictLength; 173 174 /* Offset, in bytes, of the beginning of the "info" dict in the .torrent file */ 175 int infoDictOffset; 176 161 177 /* Where the files are now. 162 178 * This pointer will be equal to downloadDir or incompleteDir */ … … 340 356 /* set a flag indicating that the torrent's .resume file 341 357 * needs to be saved when the torrent is closed */ 342 static TR_INLINE void tr_torrentSetDirty( tr_torrent * tor ) 358 static TR_INLINE 359 void tr_torrentSetDirty( tr_torrent * tor ) 343 360 { 344 361 assert( tr_isTorrent( tor ) ); … … 347 364 } 348 365 349 static TR_INLINE const char * tr_torrentName( const tr_torrent * tor ) 366 static TR_INLINE 367 const char * tr_torrentName( const tr_torrent * tor ) 350 368 { 351 369 assert( tr_isTorrent( tor ) ); … … 383 401 char* tr_torrentBuildPartial( const tr_torrent *, tr_file_index_t fileNo ); 384 402 403 /* for when the info dict has been fundamentally changed wrt files, 404 * piece size, etc. such as in BEP 9 where peers exchange metadata */ 405 void tr_torrentGotNewInfoDict( tr_torrent * tor ); 385 406 386 407 #endif -
trunk/libtransmission/transmission.h
r9538 r9550 859 859 tr_bool doDelete ); 860 860 861 int tr_ctorSetMagnet( tr_ctor * ctor, 862 const char * url ); 863 861 864 int tr_ctorSetMetainfo( tr_ctor * ctor, 862 865 const uint8_t * metainfo, -
trunk/libtransmission/utils-test.c
r9544 r9550 298 298 } 299 299 300 static int 301 test_array( void ) 302 { 303 int i; 304 int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 305 int n = sizeof( array ) / sizeof( array[0] ); 306 307 tr_removeElementFromArray( array, 5, sizeof( int ), n-- ); 308 for( i=0; i<n; ++i ) 309 check( array[i] == ( i<5 ? i : i+1 ) ); 310 311 tr_removeElementFromArray( array, 0, sizeof( int ), n-- ); 312 for( i=0; i<n; ++i ) 313 check( array[i] == ( i<4 ? i+1 : i+2 ) ); 314 315 tr_removeElementFromArray( array, n-1, sizeof( int ), n ); n--; 316 for( i=0; i<n; ++i ) 317 check( array[i] == ( i<4 ? i+1 : i+2 ) ); 318 319 return 0; 320 } 321 300 322 int 301 323 main( void ) … … 339 361 if( ( i = test_memmem( ) ) ) 340 362 return i; 363 if( ( i = test_array( ) ) ) 364 return i; 341 365 342 366 /* test that tr_cryptoRandInt() stays in-bounds */ -
trunk/libtransmission/utils.c
r9531 r9550 1416 1416 return 0; 1417 1417 } 1418 1419 /*** 1420 **** 1421 ***/ 1422 1423 void 1424 tr_removeElementFromArray( void * array, int index_to_remove, 1425 size_t sizeof_element, size_t nmemb ) 1426 { 1427 char * a = array; 1428 1429 memmove( a + sizeof_element * index_to_remove, 1430 a + sizeof_element * ( index_to_remove + 1 ), 1431 sizeof_element * ( --nmemb - index_to_remove ) ); 1432 } -
trunk/libtransmission/utils.h
r9531 r9550 425 425 426 426 /** on success, return 0. on failure, return -1 and set errno */ 427 int tr_moveFile( const char * oldpath, const char * newpath, tr_bool * renamed ) TR_GNUC_NONNULL(1,2); 428 427 int tr_moveFile( const char * oldpath, const char * newpath, 428 tr_bool * renamed ) TR_GNUC_NONNULL(1,2); 429 430 void tr_removeElementFromArray( void * array, int index_to_remove, 431 size_t sizeof_element, size_t nmemb ); 429 432 430 433 #ifdef __cplusplus
Note: See TracChangeset
for help on using the changeset viewer.