--- transmission-1.92/daemon/daemon.c 2010-03-12 03:04:28.000000000 +0100 +++ transmission-1.93/daemon/daemon.c 2010-05-01 23:35:45.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: daemon.c 10281 2010-02-24 18:14:40Z charles $ + * $Id: daemon.c 10594 2010-05-01 13:45:03Z charles $ */ #include @@ -119,6 +119,7 @@ const char * configDir = tr_sessionGetConfigDir( mySession ); tr_inf( "Reloading settings from \"%s\"", configDir ); tr_bencInitDict( &settings, 0 ); + tr_bencDictAddBool( &settings, TR_PREFS_KEY_RPC_ENABLED, TRUE ); tr_sessionLoadSettings( &settings, configDir, MY_NAME ); tr_sessionSet( mySession, &settings ); tr_bencFree( &settings ); @@ -297,6 +298,7 @@ /* load settings from defaults + config file */ tr_bencInitDict( &settings, 0 ); + tr_bencDictAddBool( &settings, TR_PREFS_KEY_RPC_ENABLED, TRUE ); configDir = getConfigDir( argc, (const char**)argv ); loaded = tr_sessionLoadSettings( &settings, configDir, MY_NAME ); --- transmission-1.92/daemon/remote.c 2010-03-12 03:04:28.000000000 +0100 +++ transmission-1.93/daemon/remote.c 2010-05-01 23:35:45.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: remote.c 10288 2010-02-25 23:06:05Z livings124 $ + * $Id: remote.c 10582 2010-05-01 04:36:01Z charles $ */ #include /* isspace */ @@ -1840,7 +1840,6 @@ curl_easy_setopt( curl, CURLOPT_POST, 1 ); curl_easy_setopt( curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL ); curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY ); - curl_easy_setopt( curl, CURLOPT_TIMEOUT, 60L ); curl_easy_setopt( curl, CURLOPT_VERBOSE, debug ); curl_easy_setopt( curl, CURLOPT_ENCODING, "" ); /* "" tells curl to fill in the blanks with what it was compiled to support */ if( netrc ) @@ -1856,6 +1855,14 @@ return curl; } +static long +getTimeoutSecs( const char * req ) +{ + if( strstr( req, "\"method\":\"blocklist-update\"" ) != NULL ) + return 300L; + + return 60L; /* default value */ +} static int processRequests( const char * host, @@ -1881,6 +1888,7 @@ } curl_easy_setopt( curl, CURLOPT_POSTFIELDS, reqs[i] ); + curl_easy_setopt( curl, CURLOPT_TIMEOUT, getTimeoutSecs( reqs[i] ) ); if( debug ) fprintf( stderr, "posting:\n--------\n%s\n--------\n", reqs[i] ); --- transmission-1.92/daemon/watch.c 2010-03-12 03:04:28.000000000 +0100 +++ transmission-1.93/daemon/watch.c 2010-05-01 23:35:45.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: watch.c 10295 2010-02-27 22:13:29Z charles $ + * $Id: watch.c 10569 2010-05-01 03:50:48Z charles $ */ #ifdef WITH_INOTIFY #include @@ -74,12 +74,20 @@ int i; DIR * odir; w->inotify_fd = inotify_init( ); - tr_inf( "Using inotify to watch directory \"%s\"", w->dir ); - i = inotify_add_watch( w->inotify_fd, w->dir, DTR_INOTIFY_MASK ); + + if( w->inotify_fd < 0 ) + { + i = -1; + } + else + { + tr_inf( "Using inotify to watch directory \"%s\"", w->dir ); + i = inotify_add_watch( w->inotify_fd, w->dir, DTR_INOTIFY_MASK ); + } if( i < 0 ) { - tr_err( "Unable to watch \"%s\": %s", w->dir, strerror (errno) ); + tr_err( "Unable to watch \"%s\": %s", w->dir, strerror( errno ) ); } else if(( odir = opendir( w->dir ))) { @@ -105,8 +113,12 @@ static void watchdir_free_impl( dtr_watchdir * w ) { - inotify_rm_watch( w->inotify_fd, DTR_INOTIFY_MASK ); - close( w->inotify_fd ); + if( w->inotify_fd >= 0 ) + { + inotify_rm_watch( w->inotify_fd, DTR_INOTIFY_MASK ); + + close( w->inotify_fd ); + } } static void watchdir_update_impl( dtr_watchdir * w ) --- transmission-1.92/gtk/actions.c 2010-03-12 03:04:14.000000000 +0100 +++ transmission-1.93/gtk/actions.c 2010-05-01 23:35:12.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: actions.c 9989 2010-01-21 20:51:48Z charles $ + * $Id: actions.c 10563 2010-05-01 03:32:54Z charles $ */ #include @@ -23,7 +23,8 @@ #include "tr-prefs.h" #include "lock.h" -#include "logo.h" +#include "logo-24.h" +#include "logo-48.h" #include "ratio-icon.h" #include "options-icon.h" #include "turtles.h" @@ -144,14 +145,14 @@ static const BuiltinIconInfo my_fallback_icons[] = { - { tr_icon_logo, WINDOW_ICON }, - { tr_icon_logo, TRAY_ICON }, - { tr_icon_logo, NOTIFICATION_ICON }, - { tr_icon_lock, "transmission-lock" }, - { options_icon, "options" }, - { blue_turtle, "alt-speed-on" }, - { grey_turtle, "alt-speed-off" }, - { ratio_icon, "ratio" } + { tr_icon_logo_48, WINDOW_ICON }, + { tr_icon_logo_24, TRAY_ICON }, + { tr_icon_logo_48, NOTIFICATION_ICON }, + { tr_icon_lock, "transmission-lock" }, + { options_icon, "options" }, + { blue_turtle, "alt-speed-on" }, + { grey_turtle, "alt-speed-off" }, + { ratio_icon, "ratio" } }; static void --- transmission-1.92/gtk/main.c 2010-03-12 03:04:14.000000000 +0100 +++ transmission-1.93/gtk/main.c 2010-05-01 23:35:12.000000000 +0200 @@ -1,5 +1,5 @@ /****************************************************************************** - * $Id: main.c 10292 2010-02-27 18:00:24Z charles $ + * $Id: main.c 10598 2010-05-01 14:06:53Z charles $ * * Copyright (c) 2005-2008 Transmission authors and contributors * @@ -227,7 +227,7 @@ **** ***/ -#ifdef HAVE_LIBGCONF +#ifdef HAVE_GCONF2 #include #include #endif @@ -235,7 +235,7 @@ static void registerMagnetLinkHandler( void ) { -#ifdef HAVE_LIBGCONF +#ifdef HAVE_GCONF2 GError * err; GConfValue * value; GConfClient * client = gconf_client_get_default( ); --- transmission-1.92/gtk/tr-torrent.c 2010-03-12 03:04:14.000000000 +0100 +++ transmission-1.93/gtk/tr-torrent.c 2010-05-01 23:35:12.000000000 +0200 @@ -1,5 +1,5 @@ /****************************************************************************** - * $Id: tr-torrent.c 9691 2009-12-09 03:51:21Z charles $ + * $Id: tr-torrent.c 10453 2010-04-06 02:53:14Z charles $ * * Copyright (c) 2006-2008 Transmission authors and contributors * @@ -215,64 +215,6 @@ return tor ? maketorrent( tor ) : NULL; } -char * -tr_torrent_status_str( TrTorrent * gtor ) -{ - char * top = NULL; - - const tr_stat * st = tr_torrent_stat( gtor ); - - const int tpeers = MAX ( st->peersConnected, 0 ); - const int upeers = MAX ( st->peersGettingFromUs, 0 ); - const int eta = st->eta; - - switch( st->activity ) - { - case TR_STATUS_CHECK_WAIT: - top = - g_strdup_printf( _( "Waiting to verify local data (%.1f%% tested)" ), - tr_truncd( 100 * st->recheckProgress, 1 ) ); - break; - - case TR_STATUS_CHECK: - top = - g_strdup_printf( _( "Verifying local data (%.1f%% tested)" ), - tr_truncd( 100 * st->recheckProgress, 1 ) ); - break; - - case TR_STATUS_DOWNLOAD: - - if( eta < 0 ) - top = g_strdup_printf( _( "Remaining time unknown" ) ); - else - { - char timestr[128]; - tr_strltime( timestr, eta, sizeof( timestr ) ); - /* %s is # of minutes */ - top = g_strdup_printf( _( "%1$s remaining" ), timestr ); - } - break; - - case TR_STATUS_SEED: - top = g_strdup_printf( - ngettext( "Seeding to %1$'d of %2$'d connected peer", - "Seeding to %1$'d of %2$'d connected peers", - tpeers ), - upeers, tpeers ); - break; - - case TR_STATUS_STOPPED: - top = g_strdup( _( "Stopped" ) ); - break; - - default: - top = g_strdup( "???" ); - break; - } - - return top; -} - void tr_torrent_set_remove_flag( TrTorrent * gtor, gboolean do_remove ) --- transmission-1.92/libtransmission/announcer.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/announcer.c 2010-05-01 23:35:04.000000000 +0200 @@ -1201,7 +1201,6 @@ if( bencLoaded && tr_bencIsDict( &benc ) ) { int peerCount = 0; - int incomplete = -1; size_t rawlen; int64_t i; tr_benc * tmp; @@ -1245,16 +1244,18 @@ tier->currentTracker->tracker_id = tr_strdup( str ); } - if( tr_bencDictFindInt( &benc, "complete", &i ) ) - { + if( !tr_bencDictFindInt( &benc, "complete", &i ) ) + tier->currentTracker->seederCount = 0; + else { ++scrapeFields; tier->currentTracker->seederCount = i; } - if( tr_bencDictFindInt( &benc, "incomplete", &i ) ) - { + if( !tr_bencDictFindInt( &benc, "incomplete", &i ) ) + tier->currentTracker->leecherCount = 0; + else { ++scrapeFields; - tier->currentTracker->leecherCount = incomplete = i; + tier->currentTracker->leecherCount = i; } if( tr_bencDictFindInt( &benc, "downloaded", &i ) ) @@ -1266,14 +1267,14 @@ if( tr_bencDictFindRaw( &benc, "peers", &raw, &rawlen ) ) { /* "compact" extension */ - const int allAreSeeds = incomplete == 0; + const tr_bool allAreSeeds = !tier->currentTracker->leecherCount; peerCount += publishNewPeersCompact( tier, allAreSeeds, raw, rawlen ); gotPeers = TRUE; } else if( tr_bencDictFindList( &benc, "peers", &tmp ) ) { /* original version of peers */ - const tr_bool allAreSeeds = incomplete == 0; + const tr_bool allAreSeeds = !tier->currentTracker->leecherCount; size_t byteCount = 0; uint8_t * array = parseOldPeers( tmp, &byteCount ); peerCount += publishNewPeers( tier, allAreSeeds, array, byteCount ); @@ -1284,7 +1285,7 @@ if( tr_bencDictFindRaw( &benc, "peers6", &raw, &rawlen ) ) { /* "compact" extension */ - const tr_bool allAreSeeds = incomplete == 0; + const tr_bool allAreSeeds = !tier->currentTracker->leecherCount; peerCount += publishNewPeersCompact6( tier, allAreSeeds, raw, rawlen ); gotPeers = TRUE; } --- transmission-1.92/libtransmission/bencode.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/bencode.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,15 +7,16 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: bencode.c 10342 2010-03-09 22:59:13Z charles $ + * $Id: bencode.c 10584 2010-05-01 04:40:53Z charles $ */ #include -#include /* isdigit */ +#include /* isdigit() */ #include -#include /* fabs */ +#include /* PATH_MAX */ +#include /* fabs() */ #include -#include +#include /* realpath() */ #include #include /* stat() */ @@ -23,7 +24,7 @@ #include #include /* stat(), close() */ -#include /* evbuffer */ +#include /* struct evbuffer */ #include "ConvertUTF.h" @@ -1358,7 +1359,6 @@ { switch( *it ) { - case '/': evbuffer_add( data->out, "\\/", 2 ); break; case '\b': evbuffer_add( data->out, "\\b", 2 ); break; case '\f': evbuffer_add( data->out, "\\f", 2 ); break; case '\n': evbuffer_add( data->out, "\\n", 2 ); break; @@ -1621,6 +1621,12 @@ char * tmp; int fd; int err = 0; + char buf[PATH_MAX]; + + /* follow symlinks to find the "real" file, to make sure the temporary + * we build with mkstemp() is created on the right partition */ + if( realpath( filename, buf ) != NULL ) + filename = buf; /* if the file already exists, try to move it out of the way & keep it as a backup */ tmp = tr_strdup_printf( "%s.tmp.XXXXXX", filename ); --- transmission-1.92/libtransmission/blocklist.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/blocklist.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,11 +7,11 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: blocklist.c 9868 2010-01-04 21:00:47Z charles $ + * $Id: blocklist.c 10604 2010-05-01 15:00:17Z livings124 $ */ #include -#include /* free */ +#include /* free() */ #include #ifdef WIN32 @@ -234,7 +234,8 @@ FILE * in; FILE * out; char * line; - int lineCount = 0; + int inCount = 0; + int outCount = 0; const char * err_fmt = _( "Couldn't read \"%1$s\": %2$s" ); if( !filename ) @@ -268,6 +269,8 @@ tr_address addr; struct tr_ip_range range; + ++inCount; + rangeBegin = strrchr( line, ':' ); if( !rangeBegin ){ free( line ); continue; } ++rangeBegin; @@ -279,11 +282,19 @@ *crpos = '\0'; if( !tr_pton( rangeBegin, &addr ) ) - tr_err( "blocklist skipped invalid address [%s]\n", rangeBegin ); + { + tr_err( _( "blocklist skipped invalid address at line %d" ), inCount ); + free( line ); + continue; + } range.begin = ntohl( addr.addr.addr4.s_addr ); if( !tr_pton( rangeEnd, &addr ) ) - tr_err( "blocklist skipped invalid address [%s]\n", rangeEnd ); + { + tr_err( _( "blocklist skipped invalid address at line %d" ), inCount ); + free( line ); + continue; + } range.end = ntohl( addr.addr.addr4.s_addr ); free( line ); @@ -296,21 +307,20 @@ break; } - ++lineCount; + ++outCount; } { char * base = tr_basename( b->filename ); - tr_inf( _( "Blocklist \"%1$s\" updated with %2$'d entries" ), base, lineCount ); + tr_inf( _( "Blocklist \"%1$s\" updated with %2$'d entries" ), base, outCount ); tr_free( base ); } - fclose( out ); fclose( in ); blocklistLoad( b ); - return lineCount; + return outCount; } --- transmission-1.92/libtransmission/list.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/list.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: list.c 9891 2010-01-06 00:18:33Z charles $ + * $Id: list.c 10583 2010-05-01 04:37:52Z charles $ */ #include "transmission.h" @@ -157,50 +157,3 @@ return size; } - - - -/* - * Double-linked list with easy memory management and fast - * insert/remove operations - */ - - -void -__tr_list_insert( struct __tr_list * list, - struct __tr_list * prev, - struct __tr_list * next) -{ - next->prev = list; - list->next = next; - list->prev = prev; - prev->next = list; -} - -static void -__tr_list_splice( struct __tr_list * prev, - struct __tr_list * next) -{ - next->prev = prev; - prev->next = next; -} - -void -__tr_list_remove( struct __tr_list * head ) -{ - __tr_list_splice( head->prev, head->next ); - head->next = head->prev = NULL; -} - -void -__tr_list_destroy( struct __tr_list * head, - __tr_list_free_t func) -{ - while ( head->next != head ) - { - struct __tr_list * list = head->next; - __tr_list_splice( list->prev, list->next ); - - func( list ); - } -} --- transmission-1.92/libtransmission/metainfo.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/metainfo.c 2010-05-01 23:35:04.000000000 +0200 @@ -8,7 +8,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: metainfo.c 10239 2010-02-20 15:57:05Z charles $ + * $Id: metainfo.c 10575 2010-05-01 04:12:15Z charles $ */ #include @@ -34,15 +34,31 @@ **** ***/ +char* +tr_metainfoGetBasename( const tr_info * inf ) +{ + char *ret, *pch, *name; + + name = tr_strdup( inf->name ); + for( pch=name; pch && *pch; ++pch ) + if( *pch == '/' ) + *pch = '_'; + + ret = tr_strdup_printf( "%s.%16.16s", name, inf->hashString ); + + tr_free( name ); + return ret; +} + static char* getTorrentFilename( const tr_session * session, const tr_info * inf ) { - return tr_strdup_printf( "%s%c%s.%16.16s.torrent", - tr_getTorrentDir( session ), - TR_PATH_DELIMITER, - inf->name, - inf->hashString ); + char * base = tr_metainfoGetBasename( inf ); + char * filename = tr_strdup_printf( "%s" TR_PATH_DELIMITER_STR "%s.torrent", + tr_getTorrentDir( session ), base ); + tr_free( base ); + return filename; } static char* --- transmission-1.92/libtransmission/net.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/net.c 2010-05-01 23:35:04.000000000 +0200 @@ -1,6 +1,6 @@ /****************************************************************************** * - * $Id: net.c 10111 2010-02-06 14:43:28Z charles $ + * $Id: net.c 10570 2010-05-01 03:53:16Z charles $ * * Copyright (c) 2005-2008 Transmission authors and contributors * @@ -441,11 +441,10 @@ } /* - get_source_address(), get_name_source_address(), and - global_unicast_address() were written by Juliusz Chroboczek, - and are covered under the same license as dht.c. - Please feel free to copy them into your software - if it can help unbreaking the double-stack Internet. */ + get_source_address() and global_unicast_address() were written by + Juliusz Chroboczek, and are covered under the same license as dht.c. + Please feel free to copy them into your software if it can help + unbreaking the double-stack Internet. */ /* Get the source address used for a given destination address. Since there is no official interface to get this information, we create @@ -483,41 +482,6 @@ return -1; } -/* Like above, but for a given DNS name. */ -static int -get_name_source_address(int af, const char *name, - struct sockaddr *src, socklen_t *src_len) -{ - struct addrinfo hints, *info, *infop; - int rc; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_DGRAM; - - rc = getaddrinfo(name, "80", &hints, &info); - if(rc != 0) { - errno = ENOENT; - return -1; - } - - rc = -1; - errno = ENOENT; - infop = info; - while(infop) { - if(infop->ai_addr->sa_family == af) { - rc = get_source_address(infop->ai_addr, infop->ai_addrlen, - src, src_len); - if(rc >= 0) - break; - } - infop = infop->ai_next; - } - - freeaddrinfo(info); - return rc; -} - /* We all hate NATs. */ static int global_unicast_address(struct sockaddr *sa) @@ -545,16 +509,37 @@ tr_globalAddress( int af, void *addr, int *addr_len ) { struct sockaddr_storage ss; - socklen_t ss_len = sizeof(ss); + socklen_t sslen = sizeof(ss); + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; + socklen_t salen; int rc; - /* This should be a name with both IPv4 and IPv6 addresses. */ - rc = get_name_source_address( af, "www.transmissionbt.com", - (struct sockaddr*)&ss, &ss_len ); - /* In case Charles removes IPv6 from his website. */ - if( rc < 0 ) - rc = get_name_source_address( af, "www.ietf.org", - (struct sockaddr*)&ss, &ss_len ); + switch(af) { + case AF_INET: + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + inet_pton(AF_INET, "91.121.74.28", &sin.sin_addr); + sin.sin_port = htons(6969); + sa = (struct sockaddr*)&sin; + salen = sizeof(sin); + break; + case AF_INET6: + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + /* In order for address selection to work right, this should be + a native IPv6 address, not Teredo or 6to4. */ + inet_pton(AF_INET6, "2001:1890:1112:1::20", &sin6.sin6_addr); + sin6.sin6_port = htons(6969); + sa = (struct sockaddr*)&sin6; + salen = sizeof(sin6); + break; + default: + return -1; + } + + rc = get_source_address( sa, salen, (struct sockaddr*)&ss, &sslen ); if( rc < 0 ) return -1; --- transmission-1.92/libtransmission/peer-io.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/peer-io.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: peer-io.c 10300 2010-03-02 04:51:40Z charles $ + * $Id: peer-io.c 10603 2010-05-01 14:53:37Z charles $ */ #include @@ -75,7 +75,6 @@ { tr_bool isPieceData; size_t length; - struct __tr_list head; }; /*** @@ -87,7 +86,8 @@ { while( bytes_transferred && tr_isPeerIo( io ) ) { - struct tr_datatype * next = __tr_list_entry( io->outbuf_datatypes.next, struct tr_datatype, head ); + struct tr_datatype * next = io->outbuf_datatypes->data; + const size_t payload = MIN( next->length, bytes_transferred ); const size_t overhead = guessPacketOverhead( payload ); @@ -104,7 +104,7 @@ bytes_transferred -= payload; next->length -= payload; if( !next->length ) { - __tr_list_remove( io->outbuf_datatypes.next ); + tr_list_pop_front( &io->outbuf_datatypes ); tr_free( next ); } } @@ -398,8 +398,6 @@ event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io ); event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io ); - __tr_list_init( &io->outbuf_datatypes ); - return io; } @@ -451,6 +449,9 @@ assert( event_initialized( &io->event_read ) ); assert( event_initialized( &io->event_write ) ); + if( io->socket < 0 ) + return; + if( ( event & EV_READ ) && ! ( io->pendingEvents & EV_READ ) ) { dbgmsg( io, "enabling libevent ready-to-read polling" ); @@ -513,13 +514,6 @@ ***/ static void -trDatatypeFree( void * data ) -{ - struct tr_datatype * dt = __tr_list_entry( data, struct tr_datatype, head ); - tr_free(dt); -} - -static void io_dtor( void * vio ) { tr_peerIo * io = vio; @@ -535,7 +529,7 @@ evbuffer_free( io->inbuf ); tr_netClose( io->session, io->socket ); tr_cryptoFree( io->crypto ); - __tr_list_destroy( &io->outbuf_datatypes, trDatatypeFree ); + tr_list_free( &io->outbuf_datatypes, tr_free ); memset( io, ~0, sizeof( tr_peerIo ) ); tr_free( io ); @@ -641,10 +635,10 @@ io->socket = tr_netOpenPeerSocket( session, &io->addr, io->port, io->isSeed ); event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io ); event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io ); - event_enable( io, pendingEvents ); if( io->socket >= 0 ) { + event_enable( io, pendingEvents ); tr_netSetTOS( io->socket, session->peerSocketTOS ); return 0; } @@ -800,9 +794,7 @@ datatype = tr_new( struct tr_datatype, 1 ); datatype->isPieceData = isPieceData != 0; datatype->length = byteCount; - - __tr_list_init( &datatype->head ); - __tr_list_append( &io->outbuf_datatypes, &datatype->head ); + tr_list_append( &io->outbuf_datatypes, datatype ); switch( io->encryptionMode ) { @@ -981,15 +973,17 @@ tr_peerIoFlushOutgoingProtocolMsgs( tr_peerIo * io ) { size_t byteCount = 0; - struct __tr_list * walk; - struct __tr_list * fencepost = &io->outbuf_datatypes; + tr_list * it; /* count up how many bytes are used by non-piece-data messages at the front of our outbound queue */ - for( walk=fencepost->next; walk!=fencepost; walk=walk->next ) { - struct tr_datatype * d = __tr_list_entry( walk, struct tr_datatype, head ); + for( it=io->outbuf_datatypes; it!=NULL; it=it->next ) + { + struct tr_datatype * d = it->data; + if( d->isPieceData ) break; + byteCount += d->length; } --- transmission-1.92/libtransmission/peer-mgr.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/peer-mgr.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: peer-mgr.c 10328 2010-03-07 22:36:20Z charles $ + * $Id: peer-mgr.c 10562 2010-05-01 03:29:48Z charles $ */ #include @@ -2780,6 +2780,7 @@ tordbg( t, "peerIo not created; marking peer %s as unreachable", tr_atomAddrStr( atom ) ); atom->myflags |= MYFLAG_UNREACHABLE; + atom->numFails++; } else { --- transmission-1.92/libtransmission/resume.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/resume.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: resume.c 10084 2010-02-02 22:45:22Z charles $ + * $Id: resume.c 10575 2010-05-01 04:12:15Z charles $ */ #include /* unlink */ @@ -17,8 +17,9 @@ #include "transmission.h" #include "bencode.h" #include "completion.h" +#include "metainfo.h" /* tr_metainfoGetBasename() */ #include "peer-mgr.h" /* pex */ -#include "platform.h" /* tr_getResumeDir */ +#include "platform.h" /* tr_getResumeDir() */ #include "resume.h" #include "session.h" #include "torrent.h" @@ -66,11 +67,11 @@ static char* getResumeFilename( const tr_torrent * tor ) { - return tr_strdup_printf( "%s%c%s.%16.16s.resume", - tr_getResumeDir( tor->session ), - TR_PATH_DELIMITER, - tr_torrentName( tor ), - tor->info.hashString ); + char * base = tr_metainfoGetBasename( tr_torrentInfo( tor ) ); + char * filename = tr_strdup_printf( "%s" TR_PATH_DELIMITER_STR "%s.resume", + tr_getResumeDir( tor->session ), base ); + tr_free( base ); + return filename; } /*** --- transmission-1.92/libtransmission/rpcimpl.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/rpcimpl.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,11 +7,12 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: rpcimpl.c 10288 2010-02-25 23:06:05Z livings124 $ + * $Id: rpcimpl.c 10573 2010-05-01 04:06:58Z charles $ */ #include #include /* isdigit */ +#include #include /* strtol */ #include /* strcmp */ #include /* unlink */ @@ -898,26 +899,44 @@ tr_snprintf( result, sizeof( result ), "http error %ld: %s", response_code, tr_webGetResponseStr( response_code ) ); } - else /* success */ + else /* successfully fetched the blocklist... */ { - int ruleCount; - char * filename = tr_buildPath( tr_sessionGetConfigDir( session ), "blocklist.tmp", NULL ); - FILE * fp; - - /* download a new blocklist */ - fp = fopen( filename, "w+" ); - fwrite( response, 1, response_byte_count, fp ); - fclose( fp ); + const char * configDir = tr_sessionGetConfigDir( session ); + char * filename = tr_buildPath( configDir, "blocklist.tmp", NULL ); + FILE * fp = fopen( filename, "w+" ); - /* feed it to the session */ - ruleCount = tr_blocklistSetContent( session, filename ); + if( fp == NULL ) + { + tr_snprintf( result, sizeof( result ), + _( "Couldn't save file \"%1$s\": %2$s" ), + filename, tr_strerror( errno ) ); + } + else + { + const size_t n = fwrite( response, 1, response_byte_count, fp ); + fclose( fp ); - /* give the client a response */ - tr_bencDictAddInt( data->args_out, "blocklist-size", ruleCount ); - tr_snprintf( result, sizeof( result ), "success" ); + if( n != response_byte_count ) + { + tr_snprintf( result, sizeof( result ), + _( "Couldn't save file \"%1$s\": %2$s" ), + filename, tr_strerror( errno ) ); + } + else + { + /* feed it to the session */ + const int ruleCount = tr_blocklistSetContent( session, filename ); + + /* give the client a response */ + tr_bencDictAddInt( data->args_out, "blocklist-size", ruleCount ); + tr_snprintf( result, sizeof( result ), "success" ); + } + + /* cleanup */ + unlink( filename ); + } /* cleanup */ - unlink( filename ); tr_free( filename ); } --- transmission-1.92/libtransmission/session.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/session.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: session.c 10303 2010-03-06 15:05:05Z charles $ + * $Id: session.c 10602 2010-05-01 14:19:45Z charles $ */ #include @@ -214,12 +214,16 @@ const tr_address* tr_sessionGetPublicAddress( const tr_session * session, int tr_af_type ) { + const struct tr_bindinfo * bindinfo; + switch( tr_af_type ) { - case TR_AF_INET: return &session->public_ipv4->addr; - case TR_AF_INET6: return &session->public_ipv6->addr; break; - default: return NULL; + case TR_AF_INET: bindinfo = session->public_ipv4; break; + case TR_AF_INET6: bindinfo = session->public_ipv6; break; + default: bindinfo = NULL; break; } + + return bindinfo ? &bindinfo->addr : NULL; } /*** @@ -233,10 +237,8 @@ #endif void -tr_sessionGetDefaultSettings( const char * configDir, tr_benc * d ) +tr_sessionGetDefaultSettings( const char * configDir UNUSED, tr_benc * d ) { - char * incompleteDir = tr_buildPath( configDir, "Incomplete", NULL ); - assert( tr_bencIsDict( d ) ); tr_bencDictReserve( d, 35 ); @@ -246,7 +248,7 @@ tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED, 100 ); tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, FALSE ); tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION ); - tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, incompleteDir ); + tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_getDefaultDownloadDir( ) ); tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, FALSE ); tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD, TRUE ); tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF ); @@ -260,11 +262,7 @@ tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, atoi( TR_DEFAULT_PEER_SOCKET_TOS_STR ) ); tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, TRUE ); tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, TRUE ); -#ifdef HAVE_FALLOCATE64 - tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_FULL ); -#else tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_SPARSE ); -#endif tr_bencDictAddStr ( d, TR_PREFS_KEY_PROXY, "" ); tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_AUTH_ENABLED, FALSE ); tr_bencDictAddBool( d, TR_PREFS_KEY_PROXY_ENABLED, FALSE ); @@ -277,7 +275,7 @@ tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, TRUE ); tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, FALSE ); tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, "0.0.0.0" ); - tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, TRUE ); + tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, FALSE ); tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, "" ); tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, "" ); tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST ); @@ -296,8 +294,6 @@ tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 ); tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, TR_DEFAULT_BIND_ADDRESS_IPV4 ); tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, TR_DEFAULT_BIND_ADDRESS_IPV6 ); - - tr_free( incompleteDir ); } void @@ -524,7 +520,7 @@ return session; } -static void turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser ); +static void turtleCheckClock( tr_session * s, struct tr_turtle_info * t ); static void onNowTimer( int foo UNUSED, short bar UNUSED, void * vsession ) @@ -548,7 +544,8 @@ /* tr_session things to do once per second */ tr_timeUpdate( tv.tv_sec ); - turtleCheckClock( session, &session->turtle, FALSE ); + if( session->turtle.isClockEnabled ) + turtleCheckClock( session, &session->turtle ); } static void loadBlocklists( tr_session * session ); @@ -628,6 +625,7 @@ } static void turtleBootstrap( tr_session *, struct tr_turtle_info * ); +static void setPeerPort( tr_session * session, tr_port port ); static void sessionSetImpl( void * vdata ) @@ -713,7 +711,6 @@ b.addr = tr_inaddr_any; b.socket = -1; session->public_ipv4 = tr_memdup( &b, sizeof( struct tr_bindinfo ) ); - tr_webSetInterface( session, &session->public_ipv4->addr ); str = TR_PREFS_KEY_BIND_ADDRESS_IPV6; tr_bencDictFindStr( settings, TR_PREFS_KEY_BIND_ADDRESS_IPV6, &str ); @@ -731,7 +728,7 @@ tr_sessionSetPeerPortRandomOnStart( session, boolVal ); if( !tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_PORT, &i ) ) i = session->peerPort; - tr_sessionSetPeerPort( session, boolVal ? getRandomPort( session ) : i ); + setPeerPort( session, boolVal ? getRandomPort( session ) : i ); if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PORT_FORWARDING, &boolVal ) ) tr_sessionSetPortForwardingEnabled( session, boolVal ); @@ -942,7 +939,7 @@ **********************************************************************/ static void -setPeerPort( void * session ) +peerPortChanged( void * session ) { tr_torrent * tor = NULL; @@ -956,6 +953,14 @@ tr_torrentChangeMyPort( tor ); } +static void +setPeerPort( tr_session * session, tr_port port ) +{ + session->peerPort = port; + + tr_runInEventThread( session, peerPortChanged, session ); +} + void tr_sessionSetPeerPort( tr_session * session, tr_port port ) { @@ -963,9 +968,7 @@ if( session->peerPort != port ) { - session->peerPort = port; - - tr_runInEventThread( session, setPeerPort, session ); + setPeerPort( session, port ); } } @@ -1094,51 +1097,35 @@ tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, limit ); } +enum +{ + MINUTES_PER_HOUR = 60, + MINUTES_PER_DAY = MINUTES_PER_HOUR * 24, + MINUTES_PER_WEEK = MINUTES_PER_DAY * 7 +}; + static void -turtleFindNextChange( struct tr_turtle_info * t ) +turtleUpdateTable( struct tr_turtle_info * t ) { int day; - struct tm tm; - time_t today_began_at; - time_t next_begin; - time_t next_end; - const time_t now = tr_time( ); - const int SECONDS_PER_DAY = 86400; + tr_bitfield * b = &t->minutes; - tr_localtime_r( &now, &tm ); - tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - today_began_at = mktime( &tm ); + tr_bitfieldClear( b ); - next_begin = today_began_at + ( t->beginMinute * 60 ); - if( next_begin <= now ) - next_begin += SECONDS_PER_DAY; - - next_end = today_began_at + ( t->endMinute * 60 ); - if( next_end <= now ) - next_end += SECONDS_PER_DAY; - - if( next_begin < next_end ) { - t->_nextChangeAt = next_begin; - t->_nextChangeValue = TRUE; - } else { - t->_nextChangeAt = next_end; - t->_nextChangeValue = FALSE; - } - - /* if the next change is today, look for today in t->days. - if the next change is tomorrow to turn limits OFF, look for today in t->days. - if the next change is tomorrow to turn limits ON, look for tomorrow in t->days. */ - if( t->_nextChangeValue && (( t->_nextChangeAt >= today_began_at + SECONDS_PER_DAY ))) - day = ( tm.tm_wday + 1 ) % 7; - else - day = tm.tm_wday; - t->_nextChangeAllowed = ( t->days & (1<days & (1<beginMinute; + time_t end = t->endMinute; + + if( end <= begin ) + end += MINUTES_PER_DAY; - if( t->isClockEnabled && t->_nextChangeAllowed ) { - char buf[128]; - tr_localtime_r( &t->_nextChangeAt, &tm ); - strftime( buf, sizeof( buf ), "%a %b %d %T %Y", &tm ); - tr_inf( "Turtle clock updated: at %s we'll turn limits %s", buf, (t->_nextChangeValue?"on":"off") ); + for( i=begin; icallback != NULL ) (*t->callback)( session, t->isEnabled, t->changedByUser, t->callbackUserData ); } static void -useAltSpeed( tr_session * s, struct tr_turtle_info * t, tr_bool enabled, tr_bool byUser ) +useAltSpeed( tr_session * s, struct tr_turtle_info * t, + tr_bool enabled, tr_bool byUser ) { assert( tr_isSession( s ) ); assert( t != NULL ); @@ -1174,25 +1161,54 @@ } } +/** + * @param enabled whether turtle should be on/off according to the scheduler + * @param changed whether that's different from the previous minute + */ static void -turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser ) +testTurtleTime( const struct tr_turtle_info * t, + tr_bool * enabled, + tr_bool * changed ) { + tr_bool e; + struct tm tm; + size_t minute_of_the_week; const time_t now = tr_time( ); - const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( )); - t->testedAt = now; + tr_localtime_r( &now, &tm ); + + minute_of_the_week = tm.tm_wday * MINUTES_PER_DAY + + tm.tm_hour * MINUTES_PER_HOUR + + tm.tm_min; + if( minute_of_the_week >= MINUTES_PER_WEEK ) /* leap minutes? */ + minute_of_the_week = MINUTES_PER_WEEK - 1; - if( hit ) + e = tr_bitfieldHasFast( &t->minutes, minute_of_the_week ); + if( enabled != NULL ) + *enabled = e; + + if( changed != NULL ) { - const tr_bool enabled = t->_nextChangeValue; + const size_t prev = minute_of_the_week > 0 ? minute_of_the_week - 1 + : MINUTES_PER_WEEK - 1; + *changed = e != tr_bitfieldHasFast( &t->minutes, prev ); + } +} - if( t->isClockEnabled && t->_nextChangeAllowed ) - { - tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") ); - useAltSpeed( session, t, enabled, byUser ); - } +static void +turtleCheckClock( tr_session * s, struct tr_turtle_info * t ) +{ + tr_bool enabled; + tr_bool changed; - turtleFindNextChange( t ); + assert( t->isClockEnabled ); + + testTurtleTime( t, &enabled, &changed ); + + if( changed ) + { + tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") ); + useAltSpeed( s, t, enabled, FALSE ); } } @@ -1202,12 +1218,14 @@ static void turtleBootstrap( tr_session * session, struct tr_turtle_info * turtle ) { - turtleFindNextChange( turtle ); - turtle->changedByUser = FALSE; + tr_bitfieldConstruct( &turtle->minutes, MINUTES_PER_WEEK ); + + turtleUpdateTable( turtle ); + if( turtle->isClockEnabled ) - turtle->isEnabled = !turtle->_nextChangeValue; + testTurtleTime( turtle, &turtle->isEnabled, NULL ); altSpeedToggled( session ); } @@ -1288,11 +1306,14 @@ { tr_dbg( "Refreshing the turtle mode clock due to user changes" ); - t->testedAt = 0; - turtleFindNextChange( t ); + turtleUpdateTable( t ); - if( t->isClockEnabled && t->_nextChangeAllowed ) - useAltSpeed( s, t, !t->_nextChangeValue, TRUE ); + if( t->isClockEnabled ) + { + tr_bool enabled, changed; + testTurtleTime( t, &enabled, &changed ); + useAltSpeed( s, t, enabled, TRUE ); + } } void @@ -1592,6 +1613,7 @@ /* free the session memory */ tr_bencFree( &session->removedTorrents ); tr_bandwidthFree( session->bandwidth ); + tr_bitfieldDestruct( &session->turtle.minutes ); tr_lockFree( session->lock ); if( session->metainfoLookup ) { tr_bencFree( session->metainfoLookup ); --- transmission-1.92/libtransmission/torrent.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/torrent.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent.c 10308 2010-03-06 22:33:45Z charles $ + * $Id: torrent.c 10595 2010-05-01 13:46:42Z charles $ */ #include /* stat */ @@ -643,10 +643,6 @@ assert( !tor->downloadedCur ); assert( !tor->uploadedCur ); - tr_ctorInitTorrentPriorities( ctor, tor ); - - tr_ctorInitTorrentWanted( ctor, tor ); - tr_torrentUncheck( tor ); tr_torrentSetAddedDate( tor, tr_time( ) ); /* this is a default value to be @@ -656,6 +652,9 @@ loaded = tr_torrentLoadResume( tor, ~0, ctor ); tor->completeness = tr_cpGetStatus( &tor->completion ); + tr_ctorInitTorrentPriorities( ctor, tor ); + tr_ctorInitTorrentWanted( ctor, tor ); + refreshCurrentDir( tor ); doStart = tor->isRunning; @@ -1518,6 +1517,8 @@ tr_bencDictAddInt( d, "id", tor->uniqueId ); tr_bencDictAddInt( d, "date", tr_time( ) ); + tr_torinf( tor, _( "Removing torrent" ) ); + stopTorrent( tor ); if( tor->isDeleting ) --- transmission-1.92/libtransmission/torrent-ctor.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/torrent-ctor.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent-ctor.c 10084 2010-02-02 22:45:22Z charles $ + * $Id: torrent-ctor.c 10565 2010-05-01 03:38:02Z charles $ */ #include /* EINVAL */ @@ -321,7 +321,7 @@ args->downloadDir = NULL; args->isSet_downloadDir = 0; - if( directory ) + if( directory && *directory ) { args->isSet_downloadDir = 1; args->downloadDir = tr_strdup( directory ); --- transmission-1.92/libtransmission/torrent-magnet.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/torrent-magnet.c 2010-05-01 23:35:04.000000000 +0200 @@ -75,8 +75,8 @@ { int i; struct tr_incomplete_metadata * m; - int n = ( size + ( METADATA_PIECE_SIZE - 1 ) ) / METADATA_PIECE_SIZE; - dbgmsg( tor, "there are %d pieces", n ); + const int n = ( size + ( METADATA_PIECE_SIZE - 1 ) ) / METADATA_PIECE_SIZE; + dbgmsg( tor, "metadata is %d bytes in %d pieces", size, n ); m = tr_new( struct tr_incomplete_metadata, 1 ); m->pieceCount = n; --- transmission-1.92/libtransmission/tr-dht.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/tr-dht.c 2010-05-01 23:35:04.000000000 +0200 @@ -101,7 +101,7 @@ } static void -bootstrap_from_name( const char *name, short int port, int af ) +bootstrap_from_name( const char *name, tr_port port, int af ) { struct addrinfo hints, *info, *infop; char pp[10]; @@ -111,7 +111,7 @@ hints.ai_socktype = SOCK_DGRAM; hints.ai_family = af; /* No, just passing p + 1 to gai won't work. */ - tr_snprintf(pp, sizeof(pp), "%d", port); + tr_snprintf(pp, sizeof(pp), "%d", (int)port); rc = getaddrinfo(name, pp, &hints, &info); if(rc != 0) { --- transmission-1.92/libtransmission/upnp.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/upnp.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: upnp.c 9868 2010-01-04 21:00:47Z charles $ + * $Id: upnp.c 10581 2010-05-01 04:32:15Z charles $ */ #include @@ -137,7 +137,7 @@ tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port ); i = UPNP_GetSpecificPortMappingEntry( handle->urls.controlURL, - handle->data.servicetype, portStr, + handle->data.first.servicetype, portStr, "TCP", intClient, intPort ); if( i != UPNPCOMMAND_SUCCESS ) { @@ -151,12 +151,12 @@ char portStr[16]; tr_snprintf( portStr, sizeof( portStr ), "%d", handle->port ); UPNP_DeletePortMapping( handle->urls.controlURL, - handle->data.servicetype, + handle->data.first.servicetype, portStr, "TCP", NULL ); tr_ninf( getKey( ), _( "Stopping port forwarding through \"%s\", service \"%s\"" ), - handle->urls.controlURL, handle->data.servicetype ); + handle->urls.controlURL, handle->data.first.servicetype ); handle->isMapped = 0; handle->state = TR_UPNP_IDLE; handle->port = -1; @@ -173,7 +173,7 @@ int err = -1; errno = 0; - if( !handle->urls.controlURL || !handle->data.servicetype ) + if( !handle->urls.controlURL || !handle->data.first.servicetype ) handle->isMapped = 0; else { @@ -182,7 +182,7 @@ tr_snprintf( portStr, sizeof( portStr ), "%d", port ); tr_snprintf( desc, sizeof( desc ), "%s at %d", TR_NAME, port ); err = UPNP_AddPortMapping( handle->urls.controlURL, - handle->data.servicetype, + handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, "TCP", NULL ); handle->isMapped = !err; @@ -190,7 +190,7 @@ tr_ninf( getKey( ), _( "Port forwarding through \"%s\", service \"%s\". (local address: %s:%d)" ), - handle->urls.controlURL, handle->data.servicetype, + handle->urls.controlURL, handle->data.first.servicetype, handle->lanaddr, port ); if( handle->isMapped ) { --- transmission-1.92/libtransmission/web.c 2010-03-12 03:04:12.000000000 +0100 +++ transmission-1.93/libtransmission/web.c 2010-05-01 23:35:04.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: web.c 10306 2010-03-06 20:15:23Z charles $ + * $Id: web.c 10602 2010-05-01 14:19:45Z charles $ */ #include @@ -25,6 +25,10 @@ #include "version.h" /* User-Agent */ #include "web.h" +#if LIBCURL_VERSION_NUM >= 0x070F06 /* CURLOPT_SOCKOPT* was added in 7.15.6 */ + #define USE_LIBCURL_SOCKOPT +#endif + enum { THREADFUNC_MAX_SLEEP_MSEC = 1000, @@ -51,10 +55,8 @@ struct tr_web { int close_mode; - tr_bool haveAddr; tr_list * tasks; tr_lock * taskLock; - tr_address addr; }; @@ -96,6 +98,7 @@ return byteCount; } +#ifdef USE_LIBCURL_SOCKOPT static int sockoptfunction( void * vtask, curl_socket_t fd, curlsocktype purpose UNUSED ) { @@ -115,6 +118,7 @@ /* return nonzero if this function encountered an error */ return 0; } +#endif static int getCurlProxyType( tr_proxy_type t ) @@ -133,8 +137,9 @@ } static CURL * -createEasy( tr_session * s, struct tr_web * w, struct tr_web_task * task ) +createEasy( tr_session * s, struct tr_web_task * task ) { + const tr_address * addr; CURL * e = curl_easy_init( ); const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL; @@ -159,8 +164,10 @@ curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L ); curl_easy_setopt( e, CURLOPT_NOSIGNAL, 1L ); curl_easy_setopt( e, CURLOPT_PRIVATE, task ); +#ifdef USE_LIBCURL_SOCKOPT curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction ); curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task ); +#endif curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L ); curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L ); curl_easy_setopt( e, CURLOPT_TIMEOUT, getTimeoutFromURL( task->url ) ); @@ -169,8 +176,10 @@ curl_easy_setopt( e, CURLOPT_VERBOSE, verbose ); curl_easy_setopt( e, CURLOPT_WRITEDATA, task ); curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc ); - if( w->haveAddr ) - curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( &w->addr ) ); + + if(( addr = tr_sessionGetPublicAddress( s, TR_AF_INET ))) + curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) ); + if( task->range ) curl_easy_setopt( e, CURLOPT_RANGE, task->range ); @@ -227,16 +236,6 @@ } } -void -tr_webSetInterface( tr_session * session, const tr_address * addr ) -{ - struct tr_web * web = session->web; - - if( web != NULL ) - if(( web->haveAddr = ( addr != NULL ))) - web->addr = *addr; -} - static void tr_webThreadFunc( void * vsession ) { @@ -274,7 +273,7 @@ tr_lockLock( web->taskLock ); while(( task = tr_list_pop_front( &web->tasks ))) { - curl_multi_add_handle( multi, createEasy( session, web, task )); + curl_multi_add_handle( multi, createEasy( session, task )); /*fprintf( stderr, "adding a task.. taskCount is now %d\n", taskCount );*/ ++taskCount; } --- transmission-1.92/qt/app.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/app.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: app.cc 9868 2010-01-04 21:00:47Z charles $ + * $Id: app.cc 10576 2010-05-01 04:15:33Z charles $ */ #include @@ -138,7 +138,7 @@ if( username != 0 ) myPrefs->set( Prefs::SESSION_REMOTE_USERNAME, username ); if( password != 0 ) - myPrefs->set( Prefs::SESSION_REMOTE_USERNAME, password ); + myPrefs->set( Prefs::SESSION_REMOTE_PASSWORD, password ); if( ( host != 0 ) || ( port != 0 ) || ( username != 0 ) || ( password != 0 ) ) myPrefs->set( Prefs::SESSION_IS_REMOTE, true ); --- transmission-1.92/qt/prefs-dialog.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/prefs-dialog.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: prefs-dialog.cc 10065 2010-02-01 04:43:10Z charles $ + * $Id: prefs-dialog.cc 10571 2010-05-01 03:56:41Z charles $ */ #include @@ -568,11 +568,12 @@ hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) ); hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) ); + myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED ); b = myIncompleteButton = new QPushButton; b->setIcon( folderPixmap ); b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" ); - connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) ); - hig->addRow( tr( "Keep &incomplete files in:" ), b ); + connect( b, SIGNAL(clicked(bool)), this, SLOT(onIncompleteClicked(void)) ); + hig->addRow( myIncompleteCheckbox, b ); b = myDestinationButton = new QPushButton; b->setIcon( folderPixmap ); --- transmission-1.92/qt/squeezelabel.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/squeezelabel.cc 2010-05-01 23:35:05.000000000 +0200 @@ -41,12 +41,20 @@ #include "squeezelabel.h" +void +SqueezeLabel::init() +{ + setTextInteractionFlags( Qt::TextSelectableByMouse ); +} + SqueezeLabel::SqueezeLabel(const QString& text, QWidget *parent) : QLabel(text, parent) { + init(); } SqueezeLabel::SqueezeLabel(QWidget *parent) : QLabel(parent) { + init(); } void SqueezeLabel::paintEvent(QPaintEvent *event) --- transmission-1.92/qt/torrent.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/torrent.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent.cc 10077 2010-02-02 05:34:26Z charles $ + * $Id: torrent.cc 10586 2010-05-01 04:46:08Z charles $ */ #include @@ -388,8 +388,8 @@ const bool haveA( hasETA( ) ); const bool haveB( that.hasETA( ) ); if( haveA && haveB ) return getETA() - that.getETA(); - if( haveA ) return -1; - if( haveB ) return 1; + if( haveA ) return 1; + if( haveB ) return -1; return 0; } --- transmission-1.92/qt/torrent-delegate.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/torrent-delegate.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent-delegate.cc 9890 2010-01-05 23:47:50Z charles $ + * $Id: torrent-delegate.cc 10580 2010-05-01 04:26:46Z charles $ */ #include @@ -87,7 +87,7 @@ %5 is our upload-to-download ratio */ str = tr( "%1 of %2 (%3%), uploaded %4 (Ratio: %5)" ) .arg( Utils::sizeToString( haveTotal ) ) - .arg( Utils::sizeToString( tor.sizeWhenDone( ) ) ) + .arg( Utils::sizeToString( tor.totalSize( ) ) ) .arg( tor.percentDone( ) * 100.0, 0, 'f', 2 ) .arg( Utils::sizeToString( tor.uploadedEver( ) ) ) .arg( Utils::ratioToString( tor.ratio( ) ) ); @@ -116,7 +116,7 @@ } /* add time when downloading */ - if( hasSeedRatio || tor.isDownloading( ) ) + if( ( hasSeedRatio && tor.isSeeding( ) ) || tor.isDownloading( ) ) { str += tr( " - " ); if( tor.hasETA( ) ) --- transmission-1.92/qt/torrent-filter.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/torrent-filter.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent-filter.cc 9868 2010-01-04 21:00:47Z charles $ + * $Id: torrent-filter.cc 10586 2010-05-01 04:46:08Z charles $ */ #include @@ -85,51 +85,67 @@ **** ***/ +namespace +{ + template int compare( const T a, const T b ) + { + if( a < b ) return -1; + if( b < a ) return 1; + return 0; + } +} + bool TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) const { const Torrent * a = sourceModel()->data( left, TorrentModel::TorrentRole ).value(); const Torrent * b = sourceModel()->data( right, TorrentModel::TorrentRole ).value(); - bool less; + int less = 0; switch( myPrefs.get(Prefs::SORT_MODE).mode() ) { case SortMode :: SORT_BY_SIZE: - less = a->sizeWhenDone() < b->sizeWhenDone(); + less = compare( a->sizeWhenDone(), b->sizeWhenDone() ); break; case SortMode :: SORT_BY_ACTIVITY: - less = a->downloadSpeed() + a->uploadSpeed() < b->downloadSpeed() + b->uploadSpeed(); + less = compare( a->downloadSpeed() + a->uploadSpeed(), b->downloadSpeed() + b->uploadSpeed() ); + if( !less ) + less = compare( a->uploadedEver(), b->uploadedEver() ); break; case SortMode :: SORT_BY_AGE: - less = a->dateAdded() < b->dateAdded(); + less = compare( a->dateAdded().toTime_t(), b->dateAdded().toTime_t() ); break; case SortMode :: SORT_BY_ID: - less = a->id() < b->id(); - break; - case SortMode :: SORT_BY_RATIO: - less = a->compareRatio( *b ) < 0; - break; - case SortMode :: SORT_BY_PROGRESS: - less = a->percentDone() < b->percentDone(); - break; - case SortMode :: SORT_BY_ETA: - less = a->compareETA( *b ) < 0; + less = compare( a->id(), b->id() ); break; case SortMode :: SORT_BY_STATE: if( a->hasError() != b->hasError() ) less = a->hasError(); else - less = a->getActivity() < b->getActivity(); + less = compare( a->getActivity(), b->getActivity() ); + if( less ) + break; + case SortMode :: SORT_BY_PROGRESS: + less = compare( a->percentDone(), b->percentDone() ); + if( less ) + break; + case SortMode :: SORT_BY_RATIO: + less = a->compareRatio( *b ); + break; + case SortMode :: SORT_BY_ETA: + less = a->compareETA( *b ); break; case SortMode :: SORT_BY_TRACKER: - less = a->compareTracker( *b ) < 0; + less = a->compareTracker( *b ); break; default: - less = a->name().compare( b->name(), Qt::CaseInsensitive ) > 0; break; } - - return less; + if( less == 0 ) + less = -a->name().compare( b->name(), Qt::CaseInsensitive ); + if( less == 0 ) + less = compare( a->hashString(), b->hashString() ); + return less < 0; } --- transmission-1.92/qt/torrent-model.cc 2010-03-12 03:04:13.000000000 +0100 +++ transmission-1.93/qt/torrent-model.cc 2010-05-01 23:35:05.000000000 +0200 @@ -7,7 +7,7 @@ * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: torrent-model.cc 9868 2010-01-04 21:00:47Z charles $ + * $Id: torrent-model.cc 10579 2010-05-01 04:23:18Z charles $ */ #include @@ -206,6 +206,10 @@ Torrent * tor = myIdToTorrent.value( id, 0 ); beginRemoveRows( QModelIndex(), row, row ); + // make the myIdToRow map consistent with list view/model + for( QMap::iterator i = myIdToRow.begin(); i != myIdToRow.end(); ++i ) + if( i.value() > row ) + --i.value(); myIdToRow.remove( id ); myIdToTorrent.remove( id ); myTorrents.remove( myTorrents.indexOf( tor ) ); --- transmission-1.92/third-party/dht/dht.c 2010-03-12 03:04:28.000000000 +0100 +++ transmission-1.93/third-party/dht/dht.c 2010-05-01 23:35:45.000000000 +0200 @@ -1,5 +1,5 @@ /* -Copyright (c) 2009 by Juliusz Chroboczek +Copyright (c) 2010 by Juliusz Chroboczek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -262,9 +262,9 @@ static time_t mybucket_grow_time, mybucket6_grow_time; static time_t expire_stuff_time; -#define MAX_LEAKY_BUCKET_TOKENS 40 -static time_t leaky_bucket_time; -static int leaky_bucket_tokens; +#define MAX_TOKEN_BUCKET_TOKENS 40 +static time_t token_bucket_time; +static int token_bucket_tokens; FILE *dht_debug = NULL; @@ -988,7 +988,7 @@ /* A proposed extension to the protocol consists in omitting the token when storage tables are full. While I don't think this makes a lot of sense -- just sending - a positive reply is just as good, let's deal with it. */ + a positive reply is just as good --, let's deal with it. */ if(n->token_len == 0) n->acked = 1; if(!n->acked) { @@ -1592,8 +1592,8 @@ next_blacklisted = 0; - leaky_bucket_time = now.tv_sec; - leaky_bucket_tokens = MAX_LEAKY_BUCKET_TOKENS; + token_bucket_time = now.tv_sec; + token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS; memset(secret, 0, sizeof(secret)); rc = rotate_secrets(); @@ -1655,18 +1655,18 @@ /* Rate control for requests we receive. */ static int -leaky_bucket(void) +token_bucket(void) { - if(leaky_bucket_tokens == 0) { - leaky_bucket_tokens = MIN(MAX_LEAKY_BUCKET_TOKENS, - 4 * (now.tv_sec - leaky_bucket_time)); - leaky_bucket_time = now.tv_sec; + if(token_bucket_tokens == 0) { + token_bucket_tokens = MIN(MAX_TOKEN_BUCKET_TOKENS, + 4 * (now.tv_sec - token_bucket_time)); + token_bucket_time = now.tv_sec; } - if(leaky_bucket_tokens == 0) + if(token_bucket_tokens == 0) return 0; - leaky_bucket_tokens--; + token_bucket_tokens--; return 1; } @@ -1869,7 +1869,7 @@ if(message > REPLY) { /* Rate limit requests. */ - if(!leaky_bucket()) { + if(!token_bucket()) { debugf("Dropping request due to rate limiting.\n"); goto dontread; } @@ -2373,11 +2373,6 @@ rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048); COPY(buf, i, myid, 20, 2048); - if(token_len > 0) { - rc = snprintf(buf + i, 2048 - i, "5:token%d:", token_len); - INC(i, rc, 2048); - COPY(buf, i, token, token_len, 2048); - } if(nodes_len > 0) { rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len); INC(i, rc, 2048); @@ -2388,6 +2383,11 @@ INC(i, rc, 2048); COPY(buf, i, nodes6, nodes6_len, 2048); } + if(token_len > 0) { + rc = snprintf(buf + i, 2048 - i, "5:token%d:", token_len); + INC(i, rc, 2048); + COPY(buf, i, token, token_len, 2048); + } if(st && st->numpeers > 0) { /* We treat the storage as a circular list, and serve a randomly --- transmission-1.92/third-party/miniupnp/connecthostport.c 1970-01-01 01:00:00.000000000 +0100 +++ transmission-1.93/third-party/miniupnp/connecthostport.c 2010-05-01 23:35:46.000000000 +0200 @@ -0,0 +1,221 @@ +/* $Id: connecthostport.c,v 1.2 2010/04/05 00:08:15 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2010 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ + +/* use getaddrinfo() or gethostbyname() + * uncomment the following line in order to use gethostbyname() */ +/* #define USE_GETHOSTBYNAME */ + +#include +#include +#ifdef WIN32 +#include +#include +#include +#define snprintf _snprintf +#define herror +#define socklen_t int +#else /* #ifdef WIN32 */ +#include +#include +#define closesocket close +#include +/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions + * during the connect() call */ +#define MINIUPNPC_IGNORE_EINTR +#ifndef USE_GETHOSTBYNAME +#include +#include +#endif /* #ifndef USE_GETHOSTBYNAME */ +#endif /* #else WIN32 */ + +/* definition of PRINT_SOCKET_ERROR */ +#ifdef WIN32 +#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); +#else +#define PRINT_SOCKET_ERROR(x) perror(x) +#endif + +#if defined(__amigaos__) || defined(__amigaos4__) +#define herror(A) printf("%s\n", A) +#endif + +#include "connecthostport.h" + +/* connecthostport() + * return a socket connected (TCP) to the host and port + * or -1 in case of error */ +int connecthostport(const char * host, unsigned short port) +{ + int s, n; +#ifdef USE_GETHOSTBYNAME + struct sockaddr_in dest; + struct hostent *hp; +#else /* #ifdef USE_GETHOSTBYNAME */ + char port_str[8]; + struct addrinfo *ai, *p; + struct addrinfo hints; +#endif /* #ifdef USE_GETHOSTBYNAME */ +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + struct timeval timeout; +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + +#ifdef USE_GETHOSTBYNAME + hp = gethostbyname(host); + if(hp == NULL) + { + herror(host); + return -1; + } + memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); + memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); + s = socket(PF_INET, SOCK_STREAM, 0); + if(s < 0) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); +#ifdef MINIUPNPC_IGNORE_EINTR + while(n < 0 && errno == EINTR) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*len = 0;*/ + /*n = getpeername(s, NULL, &len);*/ + len = sizeof(err); + if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + PRINT_SOCKET_ERROR("getsockopt"); + closesocket(s); + return -1; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n<0) + { + PRINT_SOCKET_ERROR("connect"); + closesocket(s); + return -1; + } +#else /* #ifdef USE_GETHOSTBYNAME */ + /* use getaddrinfo() instead of gethostbyname() */ + memset(&hints, 0, sizeof(hints)); + /* hints.ai_flags = AI_ADDRCONFIG; */ +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ + /* hints.ai_protocol = IPPROTO_TCP; */ + snprintf(port_str, sizeof(port_str), "%hu", port); + n = getaddrinfo(host, port_str, &hints, &ai); + if(n != 0) + { +#ifdef WIN32 + fprintf(stderr, "getaddrinfo() error : %d\n", n); +#else + fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); +#endif + return -1; + } + s = -1; + for(p = ai; p; p = p->ai_next) + { + s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if(s < 0) + continue; +#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT + /* setting a 3 seconds timeout for the connect() call */ + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } + timeout.tv_sec = 3; + timeout.tv_usec = 0; + if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt"); + } +#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ + n = connect(s, p->ai_addr, p->ai_addrlen); +#ifdef MINIUPNPC_IGNORE_EINTR + while(n < 0 && errno == EINTR) + { + socklen_t len; + fd_set wset; + int err; + FD_ZERO(&wset); + FD_SET(s, &wset); + if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) + continue; + /*len = 0;*/ + /*n = getpeername(s, NULL, &len);*/ + len = sizeof(err); + if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + PRINT_SOCKET_ERROR("getsockopt"); + closesocket(s); + freeaddrinfo(ai); + return -1; + } + if(err != 0) { + errno = err; + n = -1; + } + } +#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ + if(n < 0) + { + closesocket(s); + continue; + } + else + { + break; + } + } + freeaddrinfo(ai); + if(s < 0) + { + PRINT_SOCKET_ERROR("socket"); + return -1; + } + if(n < 0) + { + PRINT_SOCKET_ERROR("connect"); + return -1; + } +#endif /* #ifdef USE_GETHOSTBYNAME */ + return s; +} + --- transmission-1.92/third-party/miniupnp/igd_desc_parse.c 2010-03-12 03:04:29.000000000 +0100 +++ transmission-1.93/third-party/miniupnp/igd_desc_parse.c 2010-05-01 23:35:46.000000000 +0200 @@ -1,18 +1,15 @@ -/* $Id: igd_desc_parse.c,v 1.9 2009/12/03 13:50:06 nanard Exp $ */ +/* $Id: igd_desc_parse.c,v 1.10 2010/04/05 20:36:59 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2008 Thomas Bernard + * Copyright (c) 2005-2010 Thomas Bernard * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ + * LICENCE file provided in this distribution. */ + #include "igd_desc_parse.h" #include #include -/* TODO : rewrite this code so it correctly handle descriptions with - * both WANIPConnection and/or WANPPPConnection */ - /* Start element handler : * update nesting level counter and copy element name */ void IGDstartelt(void * d, const char * name, int l) @@ -22,10 +19,10 @@ datas->cureltname[l] = '\0'; datas->level++; if( (l==7) && !memcmp(name, "service", l) ) { - datas->controlurl_tmp[0] = '\0'; - datas->eventsuburl_tmp[0] = '\0'; - datas->scpdurl_tmp[0] = '\0'; - datas->servicetype_tmp[0] = '\0'; + datas->tmp.controlurl[0] = '\0'; + datas->tmp.eventsuburl[0] = '\0'; + datas->tmp.scpdurl[0] = '\0'; + datas->tmp.servicetype[0] = '\0'; } } @@ -46,20 +43,18 @@ "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) datas->state ++; */ - if(0==strcmp(datas->servicetype_tmp, + if(0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) { - memcpy(datas->controlurl_CIF, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->eventsuburl_CIF, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->scpdurl_CIF, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->servicetype_CIF, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE); - } else if(0==strcmp(datas->servicetype_tmp, + memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); + } else if(0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANIPConnection:1") - || 0==strcmp(datas->servicetype_tmp, + || 0==strcmp(datas->tmp.servicetype, "urn:schemas-upnp-org:service:WANPPPConnection:1") ) { - memcpy(datas->controlurl, datas->controlurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->eventsuburl, datas->eventsuburl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->scpdurl, datas->scpdurl_tmp, MINIUPNPC_URL_MAXSIZE); - memcpy(datas->servicetype, datas->servicetype_tmp, MINIUPNPC_URL_MAXSIZE); + if(datas->first.servicetype[0] == '\0') { + memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); + } else { + memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); + } } } } @@ -75,13 +70,13 @@ if( !strcmp(datas->cureltname, "URLBase") ) dstmember = datas->urlbase; else if( !strcmp(datas->cureltname, "serviceType") ) - dstmember = datas->servicetype_tmp; + dstmember = datas->tmp.servicetype; else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->controlurl_tmp; + dstmember = datas->tmp.controlurl; else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->eventsuburl_tmp; + dstmember = datas->tmp.eventsuburl; else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->scpdurl_tmp; + dstmember = datas->tmp.scpdurl; /* else if( !strcmp(datas->cureltname, "deviceType") ) dstmember = datas->devicetype_tmp;*/ if(dstmember) @@ -97,17 +92,23 @@ { printf("urlbase = '%s'\n", d->urlbase); printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = '%s'\n", d->devicetype_CIF);*/ - printf(" serviceType = '%s'\n", d->servicetype_CIF); - printf(" controlURL = '%s'\n", d->controlurl_CIF); - printf(" eventSubURL = '%s'\n", d->eventsuburl_CIF); - printf(" SCPDURL = '%s'\n", d->scpdurl_CIF); + /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ + printf(" serviceType = '%s'\n", d->CIF.servicetype); + printf(" controlURL = '%s'\n", d->CIF.controlurl); + printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); + printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); printf("WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->devicetype);*/ - printf(" servicetype = '%s'\n", d->servicetype); - printf(" controlURL = '%s'\n", d->controlurl); - printf(" eventSubURL = '%s'\n", d->eventsuburl); - printf(" SCPDURL = '%s'\n", d->scpdurl); + /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ + printf(" servicetype = '%s'\n", d->first.servicetype); + printf(" controlURL = '%s'\n", d->first.controlurl); + printf(" eventSubURL = '%s'\n", d->first.eventsuburl); + printf(" SCPDURL = '%s'\n", d->first.scpdurl); + printf("secondary WAN Connection Device (IP or PPP Connection):\n"); + /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ + printf(" servicetype = '%s'\n", d->second.servicetype); + printf(" controlURL = '%s'\n", d->second.controlurl); + printf(" eventSubURL = '%s'\n", d->second.eventsuburl); + printf(" SCPDURL = '%s'\n", d->second.scpdurl); } --- transmission-1.92/third-party/miniupnp/minisoap.c 2010-03-12 03:04:29.000000000 +0100 +++ transmission-1.93/third-party/miniupnp/minisoap.c 2010-05-01 23:35:46.000000000 +0200 @@ -1,4 +1,4 @@ -/* $Id: minisoap.c,v 1.18 2009/12/04 11:29:18 nanard Exp $ */ +/* $Id: minisoap.c,v 1.19 2010/04/12 20:39:41 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2009 Thomas Bernard @@ -75,7 +75,8 @@ const char * host, unsigned short port, const char * action, - const char * body) + const char * body, + const char * httpversion) { int bodysize; char headerbuf[512]; @@ -93,8 +94,7 @@ if(port != 80) snprintf(portstr, sizeof(portstr), ":%hu", port); headerssize = snprintf(headerbuf, sizeof(headerbuf), -/* "POST %s HTTP/1.1\r\n" */ - "POST %s HTTP/1.0\r\n" + "POST %s HTTP/%s\r\n" "Host: %s%s\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "Content-Length: %d\r\n" @@ -104,7 +104,7 @@ "Cache-Control: no-cache\r\n" /* ??? */ "Pragma: no-cache\r\n" "\r\n", - url, host, portstr, bodysize, action); + url, httpversion, host, portstr, bodysize, action); #ifdef DEBUG printf("SOAP request : headersize=%d bodysize=%d\n", headerssize, bodysize); --- transmission-1.92/third-party/miniupnp/miniupnpc.c 2010-03-12 03:04:29.000000000 +0100 +++ transmission-1.93/third-party/miniupnp/miniupnpc.c 2010-05-01 23:35:46.000000000 +0200 @@ -1,4 +1,4 @@ -/* $Id: miniupnpc.c,v 1.74 2010/01/09 23:54:40 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.80 2010/04/12 20:39:41 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2005-2010 Thomas Bernard @@ -16,10 +16,6 @@ #endif #endif -#ifdef __APPLE__ -#define _DARWIN_C_SOURCE -#endif - #include #include #include @@ -50,10 +46,10 @@ #include #include #include +#include #if !defined(__amigaos__) && !defined(__amigaos4__) #include #endif -#include #include #include #define closesocket close @@ -73,6 +69,7 @@ #include "minisoap.h" #include "minixml.h" #include "upnpcommands.h" +#include "connecthostport.h" #ifdef WIN32 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); @@ -171,16 +168,15 @@ } } -/* simpleUPnPcommand : +/* simpleUPnPcommand2 : * not so simple ! * return values : * 0 - OK * -1 - error */ -int simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - char * buffer, int * bufsize) +static int simpleUPnPcommand2(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + char * buffer, int * bufsize, const char * httpversion) { - struct sockaddr_in dest; char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; char * path; @@ -190,9 +186,7 @@ int buffree; int n; int contentlen, headerlen; /* for the response */ -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif + snprintf(soapact, sizeof(soapact), "%s#%s", service, action); if(args==NULL) { @@ -261,68 +255,15 @@ if(!parseURL(url, hostname, &port, &path)) return -1; if(s<0) { - s = socket(PF_INET, SOCK_STREAM, 0); - if(s<0) - { - PRINT_SOCKET_ERROR("socket"); - *bufsize = 0; - return -1; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#endif - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - dest.sin_addr.s_addr = inet_addr(hostname); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr)); -#ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) + s = connecthostport(hostname, port); + if(s < 0) { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - return -1; - } - if(err != 0) { - errno = err; - n = -1; - } else { - n = 0; - } - } -#endif - if(n < 0) - { - PRINT_SOCKET_ERROR("connect"); - closesocket(s); *bufsize = 0; return -1; } } - n = soapPostSubmit(s, path, hostname, port, soapact, soapbody); + n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); if(n<=0) { #ifdef DEBUG printf("Error sending SOAP request\n"); @@ -355,6 +296,30 @@ return 0; } +/* simpleUPnPcommand : + * not so simple ! + * return values : + * 0 - OK + * -1 - error */ +int simpleUPnPcommand(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + char * buffer, int * bufsize) +{ + int result; + int origbufsize = *bufsize; + + result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.0"); + if (result < 0 || *bufsize == 0) + { +#ifdef DEBUG + printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); +#endif + *bufsize = origbufsize; + result = simpleUPnPcommand2(s, url, service, action, args, buffer, bufsize, "1.1"); + } + return result; +} + /* parseMSEARCHReply() * the last 4 arguments are filled during the parsing : * - location/locationsize : "location:" field of the SSDP reply packet @@ -450,8 +415,10 @@ char bufr[1536]; /* reception and emission buffer */ int sudp; int n; - struct sockaddr_in sockudp_r, sockudp_w; + struct sockaddr sockudp_r; unsigned int mx; + int rv; + struct addrinfo hints, *servinfo, *p; #ifdef WIN32 /*MIB_IPFORWARDROW ip_forward;*/ #endif @@ -481,17 +448,28 @@ PRINT_SOCKET_ERROR("socket"); return NULL; } - /* reception */ - memset(&sockudp_r, 0, sizeof(struct sockaddr_in)); - sockudp_r.sin_family = AF_INET; - if(sameport) - sockudp_r.sin_port = htons(PORT); - sockudp_r.sin_addr.s_addr = INADDR_ANY; - /* emission */ - memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); - sockudp_w.sin_family = AF_INET; - sockudp_w.sin_port = htons(PORT); - sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); + /* reception */ + memset(&sockudp_r, 0, sizeof(struct sockaddr)); + if(0/*ipv6*/) { + struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r; + p->sin6_family = AF_INET6; + if(sameport) + p->sin6_port = htons(PORT); + p->sin6_addr = in6addr_any;//IN6ADDR_ANY_INIT;/*INADDR_ANY;*/ + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; + p->sin_family = AF_INET; + if(sameport) + p->sin_port = htons(PORT); + p->sin_addr.s_addr = INADDR_ANY; + } +#if 0 + /* emission */ + memset(&sockudp_w, 0, sizeof(struct sockaddr_in)); + sockudp_w.sin_family = AF_INET; + sockudp_w.sin_port = htons(PORT); + sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); +#endif #ifdef WIN32 /* This code could help us to use the right Network interface for * SSDP multicast traffic */ @@ -546,7 +524,10 @@ { struct in_addr mc_if; mc_if.s_addr = inet_addr(multicastif); - sockudp_r.sin_addr.s_addr = mc_if.s_addr; + if(0/*ipv6*/) { + } else { + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; + } if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); @@ -554,7 +535,7 @@ } /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ - if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0) + if (bind(sudp, &sockudp_r, 0/*ipv6*/?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)) != 0) { PRINT_SOCKET_ERROR("bind"); closesocket(sudp); @@ -572,6 +553,7 @@ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, deviceList[deviceIndex++], mx); /*printf("Sending %s", bufr);*/ +#if 0 n = sendto(sudp, bufr, n, 0, (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in)); if (n < 0) { @@ -579,6 +561,31 @@ closesocket(sudp); return devlist; } +#endif + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET + hints.ai_socktype = SOCK_DGRAM; + /*hints.ai_flags = */ + if ((rv = getaddrinfo(UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) { +#ifdef WIN32 + fprintf(stderr, "getaddrinfo() failed: %d\n", rv); +#else + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); +#endif + return devlist; + } + for(p = servinfo; p; p = p->ai_next) { + n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); + if (n < 0) { + PRINT_SOCKET_ERROR("sendto"); + continue; + } + } + freeaddrinfo(servinfo); + if(n < 0) { + closesocket(sudp); + return devlist; + } } /* Waiting for SSDP REPLY packet to M-SEARCH */ n = ReceiveData(sudp, bufr, sizeof(bufr), delay); @@ -602,8 +609,21 @@ parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize); if(st&&descURL) { - /*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", - stsize, st, urlsize, descURL); */ +#ifdef DEBUG + printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", + stsize, st, urlsize, descURL); +#endif + for(tmp=devlist; tmp; tmp = tmp->pNext) { + if(memcmp(tmp->descURL, descURL, urlsize) == 0 && + tmp->descURL[urlsize] == '\0' && + memcmp(tmp->st, st, stsize) == 0 && + tmp->st[stsize] == '\0') + break; + } + /* at the exit of the loop above, tmp is null if + * no duplicate device was found */ + if(tmp) + continue; tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); tmp->pNext = devlist; tmp->descURL = tmp->buffer; @@ -666,9 +686,9 @@ n1 = strlen(descURL); n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ n2 = n1; n3 = n1; - n1 += strlen(data->scpdurl); - n2 += strlen(data->controlurl); - n3 += strlen(data->controlurl_CIF); + n1 += strlen(data->first.scpdurl); + n2 += strlen(data->first.controlurl); + n3 += strlen(data->CIF.controlurl); urls->ipcondescURL = (char *)malloc(n1); urls->controlURL = (char *)malloc(n2); @@ -683,19 +703,19 @@ strncpy(urls->controlURL, urls->ipcondescURL, n2); strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); - url_cpy_or_cat(urls->ipcondescURL, data->scpdurl, n1); + url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); - url_cpy_or_cat(urls->controlURL, data->controlurl, n2); + url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); - url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3); + url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); #ifdef DEBUG - printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL, - strlen(urls->ipcondescURL), n1); - printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL, - strlen(urls->controlURL), n2); - printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF, - strlen(urls->controlURL_CIF), n3); + printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, + (unsigned)strlen(urls->ipcondescURL), n1); + printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, + (unsigned)strlen(urls->controlURL), n2); + printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF, + (unsigned)strlen(urls->controlURL_CIF), n3); #endif } @@ -768,7 +788,7 @@ char status[64]; unsigned int uptime; status[0] = '\0'; - UPNP_GetStatusInfo(urls->controlURL, data->servicetype, + UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, status, &uptime, NULL); if(0 == strcmp("Connected", status)) { @@ -825,7 +845,7 @@ parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; - if(0==strcmp(data->servicetype_CIF, + if(0==strcmp(data->CIF.servicetype, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") || state >= 3 ) { @@ -839,6 +859,25 @@ if((state >= 2) || UPNPIGD_IsConnected(urls, data)) return state; FreeUPNPUrls(urls); + if(data->second.servicetype[0] != '\0') { +#ifdef DEBUG + printf("We tried %s, now we try %s !\n", + data->first.servicetype, data->second.servicetype); +#endif + /* swaping WANPPPConnection and WANIPConnection ! */ + memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); + memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); + memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); + GetUPNPUrls(urls, data, dev->descURL); +#ifdef DEBUG + printf("UPNPIGD_IsConnected(%s) = %d\n", + urls->controlURL, + UPNPIGD_IsConnected(urls, data)); +#endif + if((state >= 2) || UPNPIGD_IsConnected(urls, data)) + return state; + FreeUPNPUrls(urls); + } } memset(data, 0, sizeof(struct IGDdatas)); } --- transmission-1.92/third-party/miniupnp/miniwget.c 2010-03-12 03:04:29.000000000 +0100 +++ transmission-1.93/third-party/miniupnp/miniwget.c 2010-05-01 23:35:46.000000000 +0200 @@ -1,145 +1,79 @@ -/* $Id: miniwget.c,v 1.31 2009/12/04 11:29:19 nanard Exp $ */ +/* $Id: miniwget.c,v 1.37 2010/04/12 20:39:42 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard + * Copyright (c) 2005-2010 Thomas Bernard * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ + * LICENCE file provided in this distribution. */ + #include #include #include #include "miniupnpc.h" #ifdef WIN32 #include +#include #include #define MAXHOSTNAMELEN 64 #define MIN(x,y) (((x)<(y))?(x):(y)) #define snprintf _snprintf -#define herror #define socklen_t int -#else +#else /* #ifdef WIN32 */ #include #include #if defined(__amigaos__) && !defined(__amigaos4__) #define socklen_t int -#else +#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ #include -#endif +#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ #include -#include -#include #include -#include -#include +#include #define closesocket close +/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions + * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR -#endif +#endif /* #else WIN32 */ #if defined(__sun) || defined(sun) #define MIN(x,y) (((x)<(y))?(x):(y)) #endif -#if defined(__amigaos__) || defined(__amigaos4__) -#define herror(A) printf("%s\n", A) -#endif #include "miniupnpcstrings.h" #include "miniwget.h" +#include "connecthostport.h" -/* miniwget2() : - * */ +/* miniwget3() : + * do all the work. + * Return NULL if something failed. */ static void * -miniwget2(const char * url, const char * host, +miniwget3(const char * url, const char * host, unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len) + int * size, char * addr_str, int addr_str_len, const char * httpversion) { char buf[2048]; int s; - struct sockaddr_in dest; - struct hostent *hp; int n; int len; int sent; -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif + *size = 0; - hp = gethostbyname(host); - if(hp==NULL) - { - herror(host); - return NULL; - } - /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */ - memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); - memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); - s = socket(PF_INET, SOCK_STREAM, 0); + s = connecthostport(host, port); if(s < 0) - { - perror("socket"); - return NULL; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt"); - } -#endif - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); -#ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - perror("getsockopt"); - closesocket(s); - return NULL; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif - if(n<0) - { - perror("connect"); - closesocket(s); return NULL; - } /* get address for caller ! */ if(addr_str) { - struct sockaddr_in saddr; + struct sockaddr saddr; socklen_t saddrlen; saddrlen = sizeof(saddr); - if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) + if(getsockname(s, &saddr, &saddrlen) < 0) { perror("getsockname"); } else { -#if defined(WIN32) || (defined(__amigaos__) && !defined(__amigaos4__)) +#if defined(__amigaos__) && !defined(__amigaos4__) /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); * But his function make a string with the port : nn.nn.nn.nn:port */ /* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), @@ -147,9 +81,20 @@ { printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); }*/ - strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len); + strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); #else - inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len); + /*inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);*/ + n = getnameinfo(&saddr, saddrlen, + addr_str, addr_str_len, + NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + if(n != 0) { +#ifdef WIN32 + fprintf(stderr, "getnameinfo() failed : %d\n", n); +#else + fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); +#endif + } #endif } #ifdef DEBUG @@ -158,13 +103,13 @@ } len = snprintf(buf, sizeof(buf), - "GET %s HTTP/1.0\r\n" + "GET %s HTTP/%s\r\n" "Host: %s:%d\r\n" "Connection: Close\r\n" "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" "\r\n", - path, host, port); + path, httpversion, host, port); sent = 0; /* sending the HTTP request */ while(sent < len) @@ -231,6 +176,30 @@ } } +/* miniwget2() : + * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ +static void * +miniwget2(const char * url, const char * host, + unsigned short port, const char * path, + int * size, char * addr_str, int addr_str_len) +{ + char * respbuffer; + + respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.0"); + if (*size == 0) + { +#ifdef DEBUG + printf("Retrying with HTTP/1.1\n"); +#endif + free(respbuffer); + respbuffer = miniwget3(url, host, port, path, size, addr_str, addr_str_len, "1.1"); + } + return respbuffer; +} + + + + /* parseURL() * arguments : * url : source string not modified --- transmission-1.92/web/javascript/transmission.js 2010-03-12 03:04:34.000000000 +0100 +++ transmission-1.93/web/javascript/transmission.js 2010-05-01 23:35:50.000000000 +0200 @@ -1083,6 +1083,7 @@ // The 'reverse sort' option state can be toggled independently of the other options if ($element.is('#reverse_sort_order')) { + if(!$element.is('#reverse_sort_order.active')) break; var dir; if ($element.menuItemIsSelected()) { $element.deselectMenuItem();