mirror of
https://github.com/transmission/transmission
synced 2025-01-31 03:12:44 +00:00
(trunk libT) #2112: provide "ipv6=" parameter to trackers
This commit is contained in:
parent
03e9189333
commit
44df1d5548
7 changed files with 88 additions and 60 deletions
|
@ -649,6 +649,7 @@ createAnnounceURL( const tr_announcer * announcer,
|
|||
const char * ann = tracker->announce;
|
||||
struct evbuffer * buf = evbuffer_new( );
|
||||
char * ret;
|
||||
const unsigned char * ipv6;
|
||||
|
||||
evbuffer_add_printf( buf, "%s"
|
||||
"%c"
|
||||
|
@ -688,6 +689,23 @@ createAnnounceURL( const tr_announcer * announcer,
|
|||
if( tracker->tracker_id && *tracker->tracker_id )
|
||||
evbuffer_add_printf( buf, "&trackerid=%s", tracker->tracker_id );
|
||||
|
||||
/* There are two incompatible techniques for announcing an IPv6 address.
|
||||
BEP-7 suggests adding an "ipv6=" parameter to the announce URL,
|
||||
while OpenTracker requires that peers announce twice, once over IPv4
|
||||
and once over IPv6.
|
||||
|
||||
To be safe, we should do both: add the "ipv6=" parameter and
|
||||
announce twice. At any rate, we're already computing our IPv6
|
||||
address (for the LTEP handshake), so this comes for free. */
|
||||
|
||||
ipv6 = tr_globalIPv6( );
|
||||
if( ipv6 ) {
|
||||
char ipv6_readable[INET6_ADDRSTRLEN];
|
||||
inet_ntop( AF_INET6, ipv6, ipv6_readable, INET6_ADDRSTRLEN );
|
||||
evbuffer_add_printf( buf, "&ipv6=");
|
||||
tr_http_escape( buf, ipv6_readable, strlen(ipv6_readable), 0 );
|
||||
}
|
||||
|
||||
ret = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
|
||||
evbuffer_free( buf );
|
||||
|
||||
|
@ -1444,7 +1462,7 @@ onScrapeDone( tr_session * session,
|
|||
{
|
||||
tier->isScraping = FALSE;
|
||||
tier->lastScrapeTime = now;
|
||||
|
||||
|
||||
if( tier->currentTracker->host )
|
||||
{
|
||||
tr_host * host = tier->currentTracker->host;
|
||||
|
@ -1557,7 +1575,7 @@ flushCloseMessages( tr_announcer * announcer )
|
|||
static tr_bool
|
||||
tierNeedsToAnnounce( const tr_tier * tier, const time_t now )
|
||||
{
|
||||
return !tier->isAnnouncing
|
||||
return !tier->isAnnouncing
|
||||
&& !tier->isScraping
|
||||
&& ( tier->announceEvent != NULL )
|
||||
&& ( tier->announceAt <= now );
|
||||
|
@ -1726,7 +1744,7 @@ tr_announcerStats( const tr_torrent * torrent,
|
|||
else if( tier->scrapeAt > now )
|
||||
{
|
||||
st->scrapeState = TR_TRACKER_WAITING;
|
||||
st->nextScrapeTime = tier->scrapeAt;
|
||||
st->nextScrapeTime = tier->scrapeAt;
|
||||
}
|
||||
else
|
||||
st->scrapeState = TR_TRACKER_QUEUED;
|
||||
|
@ -1748,7 +1766,7 @@ tr_announcerStats( const tr_torrent * torrent,
|
|||
else if( tier->announceAt > now )
|
||||
{
|
||||
st->announceState = TR_TRACKER_WAITING;
|
||||
st->nextAnnounceTime = tier->announceAt;
|
||||
st->nextAnnounceTime = tier->announceAt;
|
||||
}
|
||||
else
|
||||
st->announceState = TR_TRACKER_QUEUED;
|
||||
|
|
|
@ -603,3 +603,25 @@ tr_globalAddress( int af, void *addr, int *addr_len )
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return our global IPv6 address, with caching. */
|
||||
|
||||
const unsigned char *
|
||||
tr_globalIPv6( void )
|
||||
{
|
||||
static unsigned char ipv6[16];
|
||||
static time_t last_time = 0;
|
||||
static int have_ipv6 = 0;
|
||||
const time_t now = time( NULL );
|
||||
|
||||
/* Re-check every half hour */
|
||||
if( last_time < now - 1800 )
|
||||
{
|
||||
int addrlen = 16;
|
||||
const int rc = tr_globalAddress( AF_INET6, ipv6, &addrlen );
|
||||
have_ipv6 = ( rc >= 0 ) && ( addrlen == 16 );
|
||||
last_time = now;
|
||||
}
|
||||
|
||||
return have_ipv6 ? ipv6 : NULL;
|
||||
}
|
||||
|
|
|
@ -122,4 +122,6 @@ void tr_netInit( void );
|
|||
|
||||
int tr_globalAddress(int af, void *addr, int *addr_len);
|
||||
|
||||
const unsigned char *tr_globalIPv6( void );
|
||||
|
||||
#endif /* _TR_NET_H_ */
|
||||
|
|
|
@ -807,28 +807,6 @@ tr_peerMsgsCancel( tr_peermsgs * msgs, tr_block_index_t block )
|
|||
***
|
||||
**/
|
||||
|
||||
/* Return our global IPv6 address, with caching. */
|
||||
|
||||
static const unsigned char *
|
||||
globalIPv6( void )
|
||||
{
|
||||
static unsigned char ipv6[16];
|
||||
static time_t last_time = 0;
|
||||
static int have_ipv6 = 0;
|
||||
const time_t now = time( NULL );
|
||||
|
||||
/* Re-check every half hour */
|
||||
if( last_time < now - 1800 )
|
||||
{
|
||||
int addrlen = 16;
|
||||
const int rc = tr_globalAddress( AF_INET6, ipv6, &addrlen );
|
||||
have_ipv6 = ( rc >= 0 ) && ( addrlen == 16 );
|
||||
last_time = now;
|
||||
}
|
||||
|
||||
return have_ipv6 ? ipv6 : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sendLtepHandshake( tr_peermsgs * msgs )
|
||||
{
|
||||
|
@ -837,7 +815,7 @@ sendLtepHandshake( tr_peermsgs * msgs )
|
|||
int len;
|
||||
int pex;
|
||||
struct evbuffer * out = msgs->outMessages;
|
||||
const unsigned char * ipv6 = globalIPv6();
|
||||
const unsigned char * ipv6 = tr_globalIPv6();
|
||||
|
||||
if( msgs->clientSentLtepHandshake )
|
||||
return;
|
||||
|
|
|
@ -647,3 +647,40 @@ tr_webGetResponseStr( long code )
|
|||
compareResponseCodes );
|
||||
return msg ? msg->text : "Unknown Error";
|
||||
}
|
||||
|
||||
/* escapes a string to be URI-legal as per RFC 2396.
|
||||
like curl_escape() but can optionally avoid munging slashes. */
|
||||
void
|
||||
tr_http_escape( struct evbuffer *out, const char *str, int len, int keep_slashes )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < len; i++ ) {
|
||||
switch( str[i] ) {
|
||||
case ',': case '-': case '.':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
evbuffer_add( out, &str[i], 1 );
|
||||
break;
|
||||
case '/':
|
||||
if(keep_slashes) {
|
||||
evbuffer_add( out, &str[i], 1 );
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
default:
|
||||
evbuffer_add_printf( out, "%%%02X", (unsigned)(str[i]&0xFF) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,5 +36,6 @@ void tr_webRun( tr_session * session,
|
|||
tr_web_done_func done_func,
|
||||
void * done_func_user_data );
|
||||
|
||||
void tr_http_escape( struct evbuffer *out, const char *str, int len, int noslashes );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -108,39 +108,9 @@ makeURL( tr_webseed * w,
|
|||
evbuffer_add( out, url, url_len );
|
||||
|
||||
/* if url ends with a '/', add the torrent name */
|
||||
if( url[url_len - 1] == '/' )
|
||||
{
|
||||
const char * str = file->name;
|
||||
|
||||
/* this is like curl_escape() but doesn't munge the
|
||||
* '/' directory separators in the path */
|
||||
while( str && *str )
|
||||
{
|
||||
switch( *str )
|
||||
{
|
||||
case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
evbuffer_add( out, str, 1 );
|
||||
break;
|
||||
default:
|
||||
evbuffer_add_printf( out, "%%%02X", *str );
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
if( url[url_len - 1] == '/' && file->name )
|
||||
tr_http_escape( out, file->name, strlen(file->name), 1 );
|
||||
|
||||
ret = tr_strndup( EVBUFFER_DATA( out ), EVBUFFER_LENGTH( out ) );
|
||||
evbuffer_free( out );
|
||||
return ret;
|
||||
|
|
Loading…
Reference in a new issue