Changeset 864
- Timestamp:
- Sep 17, 2006, 11:00:51 PM (16 years ago)
- Location:
- branches/nat-traversal
- Files:
-
- 8 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/nat-traversal/cli/transmissioncli.1
r261 r864 27 27 .Op Fl s Ar torrent-file 28 28 .Op Fl v Ar level 29 .Op Fl n 29 30 .Op Fl p Ar port 30 31 .Op Fl u Ar upload-rate … … 51 52 Sets debugging options. The current range is 0-2, with the highest 52 53 level producing the most output. The default is 0. 54 .It Fl n, Fl -nat-traversal 55 Attempt to use the NAT-PMP and UPnP IGD protocols to establish a port 56 mapping for allowing incoming peer connections. 53 57 .It Fl p, -port Ar port 54 58 Specifies an alternate port for the client to listen on. The default is -
branches/nat-traversal/cli/transmissioncli.c
r310 r864 38 38 "Usage: %s [options] file.torrent [options]\n\n" \ 39 39 "Options:\n" \ 40 " -d, --download <int> Maximum download rate (-1 = no limit, default = -1)\n"\ 41 " -f, --finish <shell script> Command you wish to run on completion\n" \ 40 42 " -h, --help Print this help and exit\n" \ 41 43 " -i, --info Print metainfo and exit\n" \ 44 " -n --nat-traversal Attempt NAT traversal using NAT-PMP or UPnP IGD\n" \ 45 " -p, --port <int> Port we should listen on (default = %d)\n" \ 42 46 " -s, --scrape Print counts of seeders/leechers and exit\n" \ 43 " -v, --verbose <int> Verbose level (0 to 2, default = 0)\n" \44 " -p, --port <int> Port we should listen on (default = %d)\n" \45 47 " -u, --upload <int> Maximum upload rate (-1 = no limit, default = 20)\n" \ 46 " -d, --download <int> Maximum download rate (-1 = no limit, default = -1)\n" \ 47 " -f, --finish <shell script> Command you wish to run on completion\n" 48 " -v, --verbose <int> Verbose level (0 to 2, default = 0)\n" 48 49 49 50 static int showHelp = 0; … … 56 57 static char * torrentPath = NULL; 57 58 static volatile char mustDie = 0; 59 static int natTraversal = 0; 58 60 59 61 static char * finishCall = NULL; … … 64 66 int main( int argc, char ** argv ) 65 67 { 66 int i, error ;68 int i, error, nat; 67 69 tr_handle_t * h; 68 70 tr_torrent_t * tor; … … 164 166 tr_setUploadLimit( h, uploadLimit ); 165 167 tr_setDownloadLimit( h, downloadLimit ); 168 169 if( natTraversal ) 170 { 171 tr_natTraversalEnable( h ); 172 } 173 else 174 { 175 tr_natTraversalDisable( h ); 176 } 166 177 167 178 tr_torrentSetFolder( tor, "." ); … … 201 212 memset( &string[chars], ' ', 79 - chars ); 202 213 string[79] = '\0'; 203 fprintf( stderr, "\r%s", string );214 //fprintf( stderr, "\r%s", string ); 204 215 205 216 if( s->error & TR_ETRACKER ) … … 219 230 fprintf( stderr, "\n" ); 220 231 221 /* Try for 5 seconds to notice the tracker that we are leaving */ 232 /* Try for 5 seconds to notify the tracker that we are leaving 233 and to delete any port mappings for nat traversal */ 222 234 tr_torrentStop( tor ); 235 tr_natTraversalDisable( h ); 223 236 for( i = 0; i < 10; i++ ) 224 237 { 225 238 s = tr_torrentStat( tor ); 226 if( s->status & TR_STATUS_PAUSE ) 227 { 228 /* The 'stopped' message was sent */ 239 nat = tr_natTraversalStatus( h ); 240 if( s->status & TR_STATUS_PAUSE && TR_NAT_TRAVERSAL_DISABLED == nat ) 241 { 242 /* The 'stopped' tracker message was sent 243 and port mappings were deleted */ 229 244 break; 230 245 } … … 254 269 { "download", required_argument, NULL, 'd' }, 255 270 { "finish", required_argument, NULL, 'f' }, 271 { "nat-traversal", no_argument, NULL, 'n' }, 256 272 { 0, 0, 0, 0} }; 257 273 258 274 int c, optind = 0; 259 c = getopt_long( argc, argv, "hisv:p:u:d:f: ", long_options, &optind );275 c = getopt_long( argc, argv, "hisv:p:u:d:f:n", long_options, &optind ); 260 276 if( c < 0 ) 261 277 { … … 287 303 case 'f': 288 304 finishCall = optarg; 305 break; 306 case 'n': 307 natTraversal = 1; 289 308 break; 290 309 default: -
branches/nat-traversal/gtk/conf.c
r760 r864 359 359 GError *err; 360 360 char *datastr; 361 size_t len;361 int len; 362 362 gsize written; 363 363 -
branches/nat-traversal/gtk/conf.h
r804 r864 60 60 #define PREF_ADDIPC "add-behavior-ipc" 61 61 #define PREF_MSGLEVEL "message-level" 62 #define PREF_NAT "use-nat-traversal" 62 63 63 64 #endif /* TG_CONF_H */ -
branches/nat-traversal/gtk/dialogs.c
r804 r864 42 42 #define DEF_UPLIMIT 20 43 43 #define DEF_USEUPLIMIT TRUE 44 #define DEF_NAT TRUE 44 45 45 46 struct prefdata { … … 171 172 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 172 173 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); 173 const unsigned int rowcount = 8;174 const unsigned int rowcount = 9; 174 175 GtkWidget *table = gtk_table_new(rowcount, 2, FALSE); 175 176 GtkWidget *portnum = gtk_spin_button_new_with_range(1, 0xffff, 1); 177 GtkWidget *natcheck = gtk_check_button_new_with_mnemonic( 178 _("Use NAT _Traversal (NAT-PMP and UPnP)")); 176 179 GtkWidget *dirstr = gtk_file_chooser_button_new( 177 180 _("Choose a download directory"), … … 197 200 GtkTreeIter iter; 198 201 GtkCellRenderer *rend; 202 gboolean boolval; 203 int intval; 199 204 200 205 g_free(title); … … 207 212 208 213 data->prefwidgets = makeglist(portnum, lim[0].on, lim[0].num, lim[1].on, 209 lim[1].num, dirstr, addstd, addipc, NULL);214 lim[1].num, dirstr, addstd, addipc, natcheck, NULL); 210 215 data->parent = parent; 211 216 data->back = back; … … 252 257 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, RN(ii)); 253 258 gtk_table_attach_defaults(GTK_TABLE(table), portnum, 1, 2, RN(ii)); 259 ii++; 260 261 /* NAT traversal checkbox */ 262 intval = tr_natTraversalStatus(tr_backend_handle(back)); 263 boolval = !TR_NAT_TRAVERSAL_IS_DISABLED( intval ); 264 setupprefwidget(natcheck, PREF_NAT, boolval); 265 gtk_table_attach_defaults(GTK_TABLE(table), natcheck, 0, 2, RN(ii)); 254 266 ii++; 255 267 … … 341 353 } 342 354 355 applyprefs(data->back); 343 356 /* XXX would be nice to have errno strings, are they printed to stdout? */ 344 345 tr_setBindPort(tr_backend_handle(data->back),346 strtol(cf_getpref(PREF_PORT), NULL, 10));347 setlimit(data->back);348 357 } 349 358 … … 353 362 354 363 void 355 setlimit(TrBackend *back) {364 applyprefs(TrBackend *back) { 356 365 struct { void (*func)(tr_handle_t*, int); 357 366 const char *use; const char *num; gboolean defuse; long def; } lim[] = { … … 362 371 }; 363 372 const char *pref; 364 unsignedint ii;373 int ii; 365 374 tr_handle_t *tr = tr_backend_handle(back); 366 367 for(ii = 0; ii < ALEN(lim); ii++) { 375 gboolean boolval; 376 377 /* set upload and download limits */ 378 for(ii = 0; ii < (int)ALEN(lim); ii++) { 368 379 pref = cf_getpref(lim[ii].use); 369 380 if(!(NULL == pref ? lim[ii].defuse : strbool(pref))) … … 374 385 } 375 386 } 387 388 /* set the listening port */ 389 if(NULL != (pref = cf_getpref(PREF_PORT)) && 390 0 < (ii = strtol(pref, NULL, 10)) && 0xffff >= ii) 391 tr_setBindPort(tr, ii); 392 393 /* enable/disable NAT traversal */ 394 boolval = (NULL == (pref = cf_getpref(PREF_NAT)) ? DEF_NAT : strbool(pref)); 395 if( boolval ) 396 tr_natTraversalEnable(tr); 397 else 398 tr_natTraversalDisable(tr); 376 399 } 377 400 -
branches/nat-traversal/gtk/dialogs.h
r804 r864 33 33 makeprefwindow(GtkWindow *parent, TrBackend *back); 34 34 35 /* set the upload limitbased on saved prefs */35 /* set various things based on saved prefs */ 36 36 void 37 setlimit(TrBackend *back);37 applyprefs(TrBackend *back); 38 38 39 39 /* show the "add a torrent" dialog */ -
branches/nat-traversal/gtk/ipc.c
r760 r864 264 264 send_msg(struct constate *con, const char *name, benc_val_t *val) { 265 265 char *buf; 266 size_t used, total;266 int used, total; 267 267 benc_val_t dict; 268 268 char stupid; -
branches/nat-traversal/gtk/main.c
r815 r864 178 178 TrBackend *back; 179 179 benc_val_t *state; 180 const char *pref;181 long intval;182 180 GList *argfiles; 183 181 gboolean didinit, didlock; … … 234 232 back = tr_backend_new(); 235 233 236 /* set the upload limit */ 237 setlimit(back); 238 239 /* set the listening port */ 240 if(NULL != (pref = cf_getpref(PREF_PORT)) && 241 0 < (intval = strtol(pref, NULL, 10)) && 0xffff >= intval) 242 tr_setBindPort(tr_backend_handle(back), intval); 234 /* apply a few prefs */ 235 applyprefs(back); 243 236 244 237 makewind(mainwind, back, state, argfiles); … … 524 517 tr_backend_stop_torrents(data->back); 525 518 519 /* shut down nat traversal */ 520 tr_natTraversalDisable(tr_backend_handle(data->back)); 521 526 522 /* set things up to wait for torrents to stop */ 527 523 edata = g_new0(struct exitdata, 1); … … 545 541 exitcheck(gpointer gdata) { 546 542 struct exitdata *data = gdata; 547 548 /* keep going if we still have torrents and haven't hit the exit timeout */ 543 int natstat = tr_natTraversalStatus(tr_backend_handle(data->cbdata->back)); 544 545 /* keep going if we haven't hit the exit timeout and 546 we either have torrents left or nat traversal is stopping */ 549 547 if(time(NULL) - data->started < TRACKER_EXIT_TIMEOUT && 550 !tr_backend_torrents_stopped(data->cbdata->back)) { 548 !tr_backend_torrents_stopped(data->cbdata->back) && 549 TR_NAT_TRAVERSAL_DISABLED != natstat) { 551 550 updatemodel(data->cbdata); 552 551 return TRUE; -
branches/nat-traversal/libtransmission/bencode.c
r543 r864 26 26 27 27 #define LIST_SIZE 20 28 #define OUTBUF_SIZE 100 29 30 static int tr_bencSprintf( char ** buf, size_t * used, size_t * max, 31 char * format, ... ) 32 #ifdef __GNUC__ 33 __attribute__ ((format (printf, 4, 5))) 34 #endif 35 ; 36 37 int _tr_bencLoad( char * buf, size_t len, benc_val_t * val, char ** end ) 28 29 int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end ) 38 30 { 39 31 char * p, * e, * foo; … … 90 82 cur = &buf[1]; 91 83 str_expected = 1; 92 while( (size_t)(cur - buf)< len && cur[0] != 'e' )84 while( cur - buf < len && cur[0] != 'e' ) 93 85 { 94 86 if( val->val.l.count == val->val.l.alloc ) … … 140 132 141 133 if( p != e || 0 > val->val.s.i || 142 (size_t)(val->val.s.i)> len - ((p + 1) - buf) )134 val->val.s.i > len - ((p + 1) - buf) ) 143 135 { 144 136 return 1; … … 241 233 } 242 234 243 char * tr_bencSaveMalloc( benc_val_t * val, size_t * len )235 char * tr_bencSaveMalloc( benc_val_t * val, int * len ) 244 236 { 245 237 char * buf = NULL; 246 size_t alloc = 0;238 int alloc = 0; 247 239 248 240 *len = 0; … … 260 252 } 261 253 262 int tr_bencSave( benc_val_t * val, char ** buf, size_t * used, size_t * max )254 int tr_bencSave( benc_val_t * val, char ** buf, int * used, int * max ) 263 255 { 264 256 int ii; … … 267 259 { 268 260 case TYPE_INT: 269 if( tr_ bencSprintf( buf, used, max, "i%"PRIu64"e", val->val.i ) )261 if( tr_sprintf( buf, used, max, "i%"PRIu64"e", val->val.i ) ) 270 262 { 271 263 return 1; … … 278 270 return 1; 279 271 } 280 if( tr_ bencSprintf( buf, used, max, "%i:%s",281 272 if( tr_sprintf( buf, used, max, "%i:%s", 273 val->val.s.i, val->val.s.s ) ) 282 274 { 283 275 return 1; … … 287 279 case TYPE_LIST: 288 280 case TYPE_DICT: 289 if( tr_ bencSprintf( buf, used, max,290 281 if( tr_sprintf( buf, used, max, 282 (TYPE_LIST == val->type ? "l" : "d") ) ) 291 283 { 292 284 return 1; … … 299 291 } 300 292 } 301 if( tr_ bencSprintf( buf, used, max, "e" ) )293 if( tr_sprintf( buf, used, max, "e" ) ) 302 294 { 303 295 return 1; … … 308 300 return 0; 309 301 } 310 311 static int tr_bencSprintf( char ** buf, size_t * used, size_t * max,312 char * format, ... )313 {314 va_list ap;315 int want;316 char * newbuf;317 318 va_start( ap, format );319 want = vsnprintf( NULL, 0, format, ap );320 va_end(ap);321 322 while( *used + want + 1 > *max )323 {324 *max += OUTBUF_SIZE;325 newbuf = realloc( *buf, *max );326 if( NULL == newbuf )327 {328 return 1;329 }330 *buf = newbuf;331 }332 333 va_start( ap, format );334 *used += vsnprintf( *buf + *used, *max - *used, format, ap );335 va_end( ap );336 337 return 0;338 } -
branches/nat-traversal/libtransmission/bencode.h
r261 r864 53 53 54 54 #define tr_bencLoad(b,l,v,e) _tr_bencLoad((char*)(b),(l),(v),(char**)(e)) 55 int _tr_bencLoad( char * buf, size_t len, benc_val_t * val,55 int _tr_bencLoad( char * buf, int len, benc_val_t * val, 56 56 char ** end ); 57 57 void tr_bencPrint( benc_val_t * val ); 58 58 void tr_bencFree( benc_val_t * val ); 59 59 benc_val_t * tr_bencDictFind( benc_val_t * val, char * key ); 60 char * tr_bencSaveMalloc( benc_val_t * val, size_t * len );60 char * tr_bencSaveMalloc( benc_val_t * val, int * len ); 61 61 int tr_bencSave( benc_val_t * val, char ** buf, 62 size_t * used, size_t * max );62 int * used, int * max ); 63 63 64 64 #endif -
branches/nat-traversal/libtransmission/fastresume.h
r326 r864 249 249 { 250 250 tr_inf( "Wrong size for resume file (%d bytes, %d expected)", 251 ftell( file ), size );251 (int)ftell( file ), size ); 252 252 fclose( file ); 253 253 return 1; -
branches/nat-traversal/libtransmission/inout.c
r723 r864 417 417 { 418 418 /* Should not happen */ 419 tr_err( "readOrWriteBytes: offset out of range (% lld, %d, %d)",419 tr_err( "readOrWriteBytes: offset out of range (%"PRIu64", %d, %d)", 420 420 offset, size, isWrite ); 421 421 goto fail; -
branches/nat-traversal/libtransmission/internal.h
r788 r864 29 29 That is probably ugly to put them all here, but it is sooo 30 30 convenient */ 31 #if ( defined( __unix__ ) || defined( unix ) ) && !defined( USG ) 32 #include <sys/param.h> 33 #endif 31 34 #include <stdio.h> 32 35 #include <stdarg.h> … … 51 54 #ifdef BEOS_NETSERVER 52 55 # define in_port_t uint16_t 56 # define socklen_t uint32_t 53 57 #else 54 58 # include <arpa/inet.h> 55 59 #endif 56 60 61 #ifndef INADDR_NONE 62 #define INADDR_NONE 0xffffffff 63 #endif 64 57 65 #ifdef __GNUC__ 58 66 # define UNUSED __attribute__((unused)) 67 # define PRINTF( fmt, args ) __attribute__((format (printf, fmt, args))) 59 68 #else 60 69 # define UNUSED 70 # define PRINTF( fmt, args ) 61 71 #endif 62 72 … … 108 118 typedef struct tr_completion_s tr_completion_t; 109 119 120 typedef enum { TR_OK, TR_ERROR, TR_WAIT } tr_tristate_t; 121 110 122 #include "platform.h" 111 123 #include "bencode.h" … … 119 131 #include "clients.h" 120 132 #include "choking.h" 133 #include "natpmp.h" 134 #include "upnp.h" 135 #include "http.h" 136 #include "xml.h" 121 137 122 138 struct tr_torrent_s … … 188 204 tr_fd_t * fdlimit; 189 205 tr_choking_t * choking; 206 tr_natpmp_t * natpmp; 207 tr_upnp_t * upnp; 190 208 191 209 int bindPort; -
branches/nat-traversal/libtransmission/metainfo.c
r786 r864 70 70 if( sb.st_size > TORRENT_MAX_SIZE ) 71 71 { 72 tr_err( "Torrent file is too big (%d bytes)", sb.st_size );72 tr_err( "Torrent file is too big (%d bytes)", (int)sb.st_size ); 73 73 return 1; 74 74 } -
branches/nat-traversal/libtransmission/net.c
r791 r864 36 36 * Returns a non-zero value if an error occurs. 37 37 **********************************************************************/ 38 int tr_netResolve( c har * address, struct in_addr * addr )38 int tr_netResolve( const char * address, struct in_addr * addr ) 39 39 { 40 40 addr->s_addr = inet_addr( address ); … … 53 53 struct tr_resolve_s 54 54 { 55 intstatus;55 tr_tristate_t status; 56 56 char * address; 57 57 struct in_addr addr; … … 95 95 * Adds an address to the resolution queue. 96 96 **********************************************************************/ 97 tr_resolve_t * tr_netResolveInit( c har * address )97 tr_resolve_t * tr_netResolveInit( const char * address ) 98 98 { 99 99 tr_resolve_t * r; 100 100 101 101 r = malloc( sizeof( tr_resolve_t ) ); 102 r->status = TR_ RESOLVE_WAIT;102 r->status = TR_WAIT; 103 103 r->address = strdup( address ); 104 104 r->refcount = 2; … … 126 126 * Checks the current status of a resolution. 127 127 **********************************************************************/ 128 int tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )129 { 130 int ret;128 tr_tristate_t tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr ) 129 { 130 tr_tristate_t ret; 131 131 132 132 tr_lockLock( &resolveLock ); 133 133 ret = r->status; 134 if( ret == TR_ RESOLVE_OK )134 if( ret == TR_OK ) 135 135 { 136 136 *addr = r->addr; … … 202 202 { 203 203 memcpy( &r->addr, host->h_addr, host->h_length ); 204 r->status = TR_ RESOLVE_OK;204 r->status = TR_OK; 205 205 } 206 206 else 207 207 { 208 r->status = TR_ RESOLVE_ERROR;208 r->status = TR_ERROR; 209 209 } 210 210 … … 252 252 } 253 253 254 static int createSocket( )254 static int createSocket( int type ) 255 255 { 256 256 int s; 257 257 258 s = socket( AF_INET, SOCK_STREAM, 0 );258 s = socket( AF_INET, type, 0 ); 259 259 if( s < 0 ) 260 260 { … … 266 266 } 267 267 268 int tr_netOpen( struct in_addr addr, in_port_t port )268 int tr_netOpen( struct in_addr addr, in_port_t port, int type ) 269 269 { 270 270 int s; 271 271 struct sockaddr_in sock; 272 272 273 s = createSocket( );273 s = createSocket( type ); 274 274 if( s < 0 ) 275 275 { … … 294 294 } 295 295 296 int tr_netBind( int port ) 296 #ifdef IP_ADD_MEMBERSHIP 297 int tr_netMcastOpen( int port, struct in_addr addr ) 298 { 299 int fd; 300 struct ip_mreq req; 301 302 fd = tr_netBindUDP( port ); 303 if( 0 > fd ) 304 { 305 return -1; 306 } 307 308 memset( &req, 0, sizeof( req ) ); 309 req.imr_multiaddr.s_addr = addr.s_addr; 310 req.imr_interface.s_addr = htonl( INADDR_ANY ); 311 if( setsockopt( fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof ( req ) ) ) 312 { 313 tr_err( "Could not join multicast group (%s)", strerror( errno ) ); 314 tr_netClose( fd ); 315 return -1; 316 } 317 318 return fd; 319 } 320 #else /* IP_ADD_MEMBERSHIP */ 321 int tr_netMcastOpen( int port UNUSED, struct in_addr addr UNUSED ) 322 { 323 return -1; 324 } 325 #endif /* IP_ADD_MEMBERSHIP */ 326 327 int tr_netBind( int port, int type ) 297 328 { 298 329 int s; 299 330 struct sockaddr_in sock; 300 #if def SO_REUSEADDR331 #if defined( SO_REUSEADDR ) || defined( SO_REUSEPORT ) 301 332 int optval; 302 333 #endif 303 334 304 s = createSocket( );335 s = createSocket( type ); 305 336 if( s < 0 ) 306 337 { … … 313 344 #endif 314 345 346 #ifdef SO_REUSEPORT 347 if( SOCK_DGRAM == type ) 348 { 349 optval = 1; 350 setsockopt( s, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof( optval ) ); 351 } 352 #endif 353 315 354 memset( &sock, 0, sizeof( sock ) ); 316 355 sock.sin_family = AF_INET; … … 325 364 return -1; 326 365 } 327 328 tr_inf( "Binded port %d", port );329 listen( s, 5 );330 366 331 367 return s; … … 372 408 } 373 409 374 int tr_netRecv( int s, uint8_t * buf, int size ) 375 { 376 int ret; 377 378 ret = recv( s, buf, size, 0 ); 410 int tr_netRecvFrom( int s, uint8_t * buf, int size, struct sockaddr_in * addr ) 411 { 412 socklen_t len; 413 int ret; 414 415 len = ( NULL == addr ? 0 : sizeof( *addr ) ); 416 ret = recvfrom( s, buf, size, 0, ( struct sockaddr * ) addr, &len ); 379 417 if( ret < 0 ) 380 418 { -
branches/nat-traversal/libtransmission/net.h
r791 r864 27 27 * DNS resolution 28 28 **********************************************************************/ 29 int tr_netResolve( c har *, struct in_addr * );29 int tr_netResolve( const char *, struct in_addr * ); 30 30 31 #define TR_RESOLVE_WAIT 032 #define TR_RESOLVE_ERROR 133 #define TR_RESOLVE_OK 234 31 typedef struct tr_resolve_s tr_resolve_t; 35 32 void tr_netResolveThreadInit(); 36 33 void tr_netResolveThreadClose(); 37 tr_resolve_t * tr_netResolveInit( c har * );38 inttr_netResolvePulse( tr_resolve_t *, struct in_addr * );34 tr_resolve_t * tr_netResolveInit( const char * ); 35 tr_tristate_t tr_netResolvePulse( tr_resolve_t *, struct in_addr * ); 39 36 void tr_netResolveClose( tr_resolve_t * ); 40 37 … … 43 40 * TCP sockets 44 41 **********************************************************************/ 45 int tr_netOpen ( struct in_addr addr, in_port_t port ); 46 int tr_netBind ( int ); 42 #define tr_netOpenTCP( addr, port ) tr_netOpen( (addr), (port), SOCK_STREAM ) 43 #define tr_netOpenUDP( addr, port ) tr_netOpen( (addr), (port), SOCK_DGRAM ) 44 int tr_netOpen ( struct in_addr addr, in_port_t port, int type ); 45 int tr_netMcastOpen( int port, struct in_addr addr ); 46 #define tr_netBindTCP( port ) tr_netBind( (port), SOCK_STREAM ) 47 #define tr_netBindUDP( port ) tr_netBind( (port), SOCK_DGRAM ) 48 int tr_netBind ( int port, int type ); 47 49 int tr_netAccept ( int s, struct in_addr *, in_port_t * ); 48 50 void tr_netClose ( int s ); … … 51 53 #define TR_NET_CLOSE 0x40000000 52 54 int tr_netSend ( int s, uint8_t * buf, int size ); 53 int tr_netRecv ( int s, uint8_t * buf, int size ); 55 #define tr_netRecv( s, buf, size ) tr_netRecvFrom( (s), (buf), (size), NULL ) 56 int tr_netRecvFrom( int s, uint8_t * buf, int size, struct sockaddr_in * ); 54 57 55 58 void tr_netNtop( const struct in_addr * addr, char * buf, int len ); -
branches/nat-traversal/libtransmission/peer.c
r774 r864 101 101 102 102 #define peer_dbg( a... ) __peer_dbg( peer, ## a ) 103 static void __peer_dbg( tr_peer_t * peer, char * msg, ... ) PRINTF( 2, 3 ); 104 103 105 static void __peer_dbg( tr_peer_t * peer, char * msg, ... ) 104 106 { -
branches/nat-traversal/libtransmission/peerutils.h
r261 r864 152 152 !tr_fdSocketWillCreate( tor->fdlimit, 0 ) ) 153 153 { 154 peer->socket = tr_netOpen ( peer->addr, peer->port );154 peer->socket = tr_netOpenTCP( peer->addr, peer->port ); 155 155 if( peer->socket < 0 ) 156 156 { -
branches/nat-traversal/libtransmission/platform.c
r679 r864 197 197 } 198 198 199 #if defined( BSD ) 200 201 #include <sys/sysctl.h> 202 #include <net/route.h> 203 204 static uint8_t * 205 getroute( int * buflen ); 206 static int 207 parseroutes( uint8_t * buf, int len, struct in_addr * addr ); 208 209 int 210 tr_getDefaultRoute( struct in_addr * addr ) 211 { 212 uint8_t * buf; 213 int len; 214 215 buf = getroute( &len ); 216 if( NULL == buf ) 217 { 218 tr_err( "failed to get default route (BSD)" ); 219 return 1; 220 } 221 222 len = parseroutes( buf, len, addr ); 223 free( buf ); 224 225 return len; 226 } 227 228 #ifndef SA_SIZE 229 #define ROUNDUP( a, size ) \ 230 ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) ) 231 #define SA_SIZE( sap ) \ 232 ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \ 233 sizeof( u_long ) ) 234 #endif /* !SA_SIZE */ 235 #define NEXT_SA( sap ) \ 236 (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) ) 237 238 static uint8_t * 239 getroute( int * buflen ) 240 { 241 int mib[6]; 242 size_t len; 243 uint8_t * buf; 244 245 mib[0] = CTL_NET; 246 mib[1] = PF_ROUTE; 247 mib[2] = 0; 248 mib[3] = AF_INET; 249 mib[4] = NET_RT_FLAGS; 250 mib[5] = RTF_GATEWAY; 251 252 if( sysctl( mib, 6, NULL, &len, NULL, 0 ) ) 253 { 254 if( ENOENT != errno ) 255 { 256 tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)", 257 strerror( errno ) ); 258 } 259 *buflen = 0; 260 return NULL; 261 } 262 263 buf = malloc( len ); 264 if( NULL == buf ) 265 { 266 *buflen = 0; 267 return NULL; 268 } 269 270 if( sysctl( mib, 6, buf, &len, NULL, 0 ) ) 271 { 272 tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)", 273 strerror( errno ) ); 274 free( buf ); 275 *buflen = 0; 276 return NULL; 277 } 278 279 *buflen = len; 280 281 return buf; 282 } 283 284 static int 285 parseroutes( uint8_t * buf, int len, struct in_addr * addr ) 286 { 287 uint8_t * end; 288 struct rt_msghdr * rtm; 289 struct sockaddr * sa; 290 struct sockaddr_in * sin; 291 int ii; 292 struct in_addr dest, gw; 293 294 end = buf + len; 295 while( end > buf + sizeof( *rtm ) ) 296 { 297 rtm = (struct rt_msghdr *) buf; 298 buf += rtm->rtm_msglen; 299 if( end >= buf ) 300 { 301 dest.s_addr = INADDR_NONE; 302 gw.s_addr = INADDR_NONE; 303 sa = (struct sockaddr *) ( rtm + 1 ); 304 305 for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ ) 306 { 307 if( buf < (uint8_t *) NEXT_SA( sa ) ) 308 { 309 break; 310 } 311 312 if( rtm->rtm_addrs & ( 1 << ii ) ) 313 { 314 if( AF_INET == sa->sa_family ) 315 { 316 sin = (struct sockaddr_in *) sa; 317 switch( ii ) 318 { 319 case RTAX_DST: 320 dest = sin->sin_addr; 321 break; 322 case RTAX_GATEWAY: 323 gw = sin->sin_addr; 324 break; 325 } 326 } 327 sa = NEXT_SA( sa ); 328 } 329 } 330 331 if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr ) 332 { 333 *addr = gw; 334 return 0; 335 } 336 } 337 } 338 339 return 1; 340 } 341 342 #elif defined( linux ) || defined( __linux ) || defined( __linux__ ) 343 344 #include <linux/types.h> 345 #include <linux/netlink.h> 346 #include <linux/rtnetlink.h> 347 348 #define SEQNUM 195909 349 350 static int 351 getsock( void ); 352 static uint8_t * 353 getroute( int fd, unsigned int * buflen ); 354 static int 355 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr ); 356 357 int 358 tr_getDefaultRoute( struct in_addr * addr ) 359 { 360 int fd, ret; 361 unsigned int len; 362 uint8_t * buf; 363 364 ret = 1; 365 fd = getsock(); 366 if( 0 <= fd ) 367 { 368 while( ret ) 369 { 370 buf = getroute( fd, &len ); 371 if( NULL == buf ) 372 { 373 break; 374 } 375 ret = parseroutes( buf, len, addr ); 376 free( buf ); 377 } 378 close( fd ); 379 } 380 381 if( ret ) 382 { 383 tr_err( "failed to get default route (Linux)" ); 384 } 385 386 return ret; 387 } 388 389 static int 390 getsock( void ) 391 { 392 int fd, flags; 393 struct 394 { 395 struct nlmsghdr nlh; 396 struct rtgenmsg rtg; 397 } req; 398 struct sockaddr_nl snl; 399 400 fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ); 401 if( 0 > fd ) 402 { 403 tr_err( "failed to create routing socket (%s)", strerror( errno ) ); 404 return -1; 405 } 406 407 flags = fcntl( fd, F_GETFL ); 408 if( 0 > flags || 0 > fcntl( fd, F_SETFL, O_NONBLOCK | flags ) ) 409 { 410 tr_err( "failed to set socket nonblocking (%s)", strerror( errno ) ); 411 close( fd ); 412 return -1; 413 } 414 415 bzero( &snl, sizeof( snl ) ); 416 snl.nl_family = AF_NETLINK; 417 418 bzero( &req, sizeof( req ) ); 419 req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) ); 420 req.nlh.nlmsg_type = RTM_GETROUTE; 421 req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 422 req.nlh.nlmsg_seq = SEQNUM; 423 req.nlh.nlmsg_pid = 0; 424 req.rtg.rtgen_family = AF_INET; 425 426 if( 0 > sendto( fd, &req, sizeof( req ), 0, 427 (struct sockaddr *) &snl, sizeof( snl ) ) ) 428 { 429 tr_err( "failed to write to routing socket (%s)", strerror( errno ) ); 430 close( fd ); 431 return -1; 432 } 433 434 return fd; 435 } 436 437 static uint8_t * 438 getroute( int fd, unsigned int * buflen ) 439 { 440 void * buf; 441 unsigned int len; 442 ssize_t res; 443 struct sockaddr_nl snl; 444 socklen_t slen; 445 446 len = 8192; 447 buf = calloc( 1, len ); 448 if( NULL == buf ) 449 { 450 *buflen = 0; 451 return NULL; 452 } 453 454 for( ;; ) 455 { 456 bzero( &snl, sizeof( snl ) ); 457 slen = sizeof( snl ); 458 res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen ); 459 if( 0 > res ) 460 { 461 if( EAGAIN != errno ) 462 { 463 tr_err( "failed to read from routing socket (%s)", 464 strerror( errno ) ); 465 } 466 free( buf ); 467 *buflen = 0; 468 return NULL; 469 } 470 if( slen < sizeof( snl ) || AF_NETLINK != snl.nl_family ) 471 { 472 tr_err( "bad address" ); 473 free( buf ); 474 *buflen = 0; 475 return NULL; 476 } 477 478 if( 0 == snl.nl_pid ) 479 { 480 break; 481 } 482 } 483 484 *buflen = res; 485 486 return buf; 487 } 488 489 static int 490 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr ) 491 { 492 struct nlmsghdr * nlm; 493 struct nlmsgerr * nle; 494 struct rtmsg * rtm; 495 struct rtattr * rta; 496 int rtalen; 497 struct in_addr gw, dst; 498 499 nlm = ( struct nlmsghdr * ) buf; 500 while( NLMSG_OK( nlm, len ) ) 501 { 502 gw.s_addr = INADDR_ANY; 503 dst.s_addr = INADDR_ANY; 504 if( NLMSG_ERROR == nlm->nlmsg_type ) 505 { 506 nle = (struct nlmsgerr *) NLMSG_DATA( nlm ); 507 if( NLMSG_LENGTH( NLMSG_ALIGN( sizeof( struct nlmsgerr ) ) ) > 508 nlm->nlmsg_len ) 509 { 510 tr_err( "truncated netlink error" ); 511 } 512 else 513 { 514 tr_err( "netlink error (%s)", strerror( nle->error ) ); 515 } 516 return 1; 517 } 518 else if( RTM_NEWROUTE == nlm->nlmsg_type && SEQNUM == nlm->nlmsg_seq && 519 getpid() == (pid_t) nlm->nlmsg_pid && 520 NLMSG_LENGTH( sizeof( struct rtmsg ) ) <= nlm->nlmsg_len ) 521 { 522 rtm = NLMSG_DATA( nlm ); 523 rta = RTM_RTA( rtm ); 524 rtalen = RTM_PAYLOAD( nlm ); 525 526 while( RTA_OK( rta, rtalen ) ) 527 { 528 if( sizeof( struct in_addr ) <= RTA_PAYLOAD( rta ) ) 529 { 530 switch( rta->rta_type ) 531 { 532 case RTA_GATEWAY: 533 memcpy( &gw, RTA_DATA( rta ), sizeof( gw ) ); 534 break; 535 case RTA_DST: 536 memcpy( &dst, RTA_DATA( rta ), sizeof( dst ) ); 537 break; 538 } 539 } 540 rta = RTA_NEXT( rta, rtalen ); 541 } 542 } 543 544 if( INADDR_NONE != gw.s_addr && INADDR_ANY != gw.s_addr && 545 INADDR_ANY == dst.s_addr ) 546 { 547 *addr = gw; 548 return 0; 549 } 550 551 nlm = NLMSG_NEXT( nlm, len ); 552 } 553 554 return 1; 555 } 556 557 #else /* not BSD or Linux */ 558 559 int 560 tr_getDefaultRoute( struct in_addr * addr UNUSED ) 561 { 562 tr_inf( "don't know how to get default route on this platform" ); 563 return 1; 564 } 565 566 #endif -
branches/nat-traversal/libtransmission/platform.h
r310 r864 61 61 } 62 62 63 int 64 tr_getDefaultRoute( struct in_addr * addr ); 65 63 66 #endif -
branches/nat-traversal/libtransmission/tracker.c
r854 r864 43 43 uint64_t dateOk; 44 44 45 #define TC_STATUS_IDLE 146 #define TC_STATUS_RESOLVE 247 #define TC_STATUS_CONNECT 448 #define TC_STATUS_RECV 849 char status;50 51 45 #define TC_ATTEMPT_NOREACH 1 52 46 #define TC_ATTEMPT_ERROR 2 … … 54 48 char lastAttempt; 55 49 56 tr_resolve_t * resolve; 57 int socket; 58 uint8_t * buf; 59 int size; 60 int pos; 50 tr_http_t * http; 61 51 62 52 int bindPort; … … 67 57 }; 68 58 69 static void sendQuery( tr_tracker_t * tc );70 static void recvAnswer ( tr_tracker_t * tc);59 static tr_http_t * getQuery ( tr_tracker_t * tc ); 60 static void readAnswer ( tr_tracker_t * tc, const char *, int ); 71 61 72 62 tr_tracker_t * tr_trackerInit( tr_torrent_t * tor ) … … 84 74 tc->leechers = -1; 85 75 86 tc->status = TC_STATUS_IDLE;87 76 tc->lastAttempt = TC_ATTEMPT_NOREACH; 88 tc->size = 1024;89 tc->buf = malloc( tc->size );90 77 91 78 tc->bindPort = *(tor->bindPort); … … 160 147 tr_torrent_t * tor = tc->tor; 161 148 tr_info_t * inf = &tor->info; 162 uint64_t now = tr_date(); 163 164 if( ( tc->status & TC_STATUS_IDLE ) && shouldConnect( tc ) ) 165 { 166 tc->resolve = tr_netResolveInit( inf->trackerAddress ); 149 const char * data; 150 int len; 151 152 if( ( NULL == tc->http ) && shouldConnect( tc ) ) 153 { 154 if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) ) 155 { 156 return 0; 157 } 158 tc->http = getQuery( tc ); 167 159 168 160 tr_inf( "Tracker: connecting to %s:%d (%s)", … … 173 165 ( 0 < tc->newPort ? "sending 'stopped' to change port" : 174 166 "getting peers" ) ) ) ); 175 176 tc->status = TC_STATUS_RESOLVE; 177 tc->dateTry = tr_date(); 178 } 179 180 if( tc->status & TC_STATUS_RESOLVE ) 181 { 182 int ret; 183 struct in_addr addr; 184 185 ret = tr_netResolvePulse( tc->resolve, &addr ); 186 if( ret == TR_RESOLVE_WAIT ) 187 { 188 return 0; 189 } 190 else 191 { 192 tr_netResolveClose( tc->resolve ); 193 } 194 195 if( ret == TR_RESOLVE_ERROR ) 196 { 197 tc->status = TC_STATUS_IDLE; 198 return 0; 199 } 200 201 if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) ) 202 { 203 tc->status = TC_STATUS_IDLE; 204 return 0; 205 } 206 207 tc->socket = tr_netOpen( addr, htons( inf->trackerPort ) ); 208 if( tc->socket < 0 ) 209 { 210 tr_fdSocketClosed( tor->fdlimit, 1 ); 211 tc->status = TC_STATUS_IDLE; 212 return 0; 213 } 214 215 tc->status = TC_STATUS_CONNECT; 216 } 217 218 if( tc->status & TC_STATUS_CONNECT ) 219 { 220 /* We are connecting to the tracker. Try to send the query */ 221 sendQuery( tc ); 222 } 223 224 if( tc->status & TC_STATUS_RECV ) 225 { 226 /* Try to get something */ 227 recvAnswer( tc ); 228 } 229 230 if( tc->status > TC_STATUS_IDLE && now > tc->dateTry + 60000 ) 231 { 232 /* Give up if the request wasn't successful within 60 seconds */ 233 tr_inf( "Tracker: timeout reached (60 s)" ); 234 235 tr_netClose( tc->socket ); 236 tr_fdSocketClosed( tor->fdlimit, 1 ); 237 238 tc->status = TC_STATUS_IDLE; 239 tc->dateTry = tr_date(); 167 } 168 169 if( NULL != tc->http ) 170 { 171 switch( tr_httpPulse( tc->http, &data, &len ) ) 172 { 173 case TR_WAIT: 174 return 0; 175 176 case TR_ERROR: 177 tr_httpClose( tc->http ); 178 tr_fdSocketClosed( tor->fdlimit, 1 ); 179 tc->http = NULL; 180 return 0; 181 182 case TR_OK: 183 readAnswer( tc, data, len ); 184 tr_httpClose( tc->http ); 185 tc->http = NULL; 186 tr_fdSocketClosed( tor->fdlimit, 1 ); 187 break; 188 } 240 189 } 241 190 … … 254 203 tr_torrent_t * tor = tc->tor; 255 204 256 if( tc->status > TC_STATUS_CONNECT)205 if( NULL != tc->http ) 257 206 { 258 207 /* If we are already sendy a query at the moment, we need to 259 208 reconnect */ 260 tr_netClose( tc->socket ); 209 tr_httpClose( tc->http ); 210 tc->http = NULL; 261 211 tr_fdSocketClosed( tor->fdlimit, 1 ); 262 tc->status = TC_STATUS_IDLE;263 212 } 264 213 … … 268 217 269 218 /* Even if we have connected recently, reconnect right now */ 270 if( tc->status & TC_STATUS_IDLE ) 271 { 272 tc->dateTry = 0; 273 } 219 tc->dateTry = 0; 274 220 } 275 221 … … 278 224 tr_torrent_t * tor = tc->tor; 279 225 280 if( tc->status == TC_STATUS_RESOLVE ) 281 { 282 tr_netResolveClose( tc->resolve ); 283 } 284 else if( tc->status > TC_STATUS_RESOLVE ) 285 { 286 tr_netClose( tc->socket ); 226 if( NULL != tc->http ) 227 { 228 tr_httpClose( tc->http ); 287 229 tr_fdSocketClosed( tor->fdlimit, 1 ); 288 230 } 289 free( tc->buf );290 231 free( tc ); 291 232 } 292 233 293 static void sendQuery( tr_tracker_t * tc )234 static tr_http_t * getQuery( tr_tracker_t * tc ) 294 235 { 295 236 tr_torrent_t * tor = tc->tor; 296 237 tr_info_t * inf = &tor->info; 297 238 298 char * event; 299 uint64_t left; 300 int ret; 301 uint64_t down; 302 uint64_t up; 239 char * event; 240 uint64_t left; 241 uint64_t down; 242 uint64_t up; 303 243 304 244 assert( tor->downloaded >= tc->download && tor->uploaded >= tc->upload ); … … 331 271 left = tr_cpLeftBytes( tor->completion ); 332 272 333 ret = snprintf( (char *) tc->buf, tc->size, 334 "GET %s?" 335 "info_hash=%s&" 336 "peer_id=%s&" 337 "port=%d&" 338 "uploaded=%"PRIu64"&" 339 "downloaded=%"PRIu64"&" 340 "left=%"PRIu64"&" 341 "compact=1&" 342 "numwant=50&" 343 "key=%s" 344 "%s " 345 "HTTP/1.1\r\n" 346 "Host: %s\r\n" 347 "User-Agent: Transmission/%d.%d\r\n" 348 "Connection: close\r\n\r\n", 349 inf->trackerAnnounce, tor->hashString, tc->id, 350 tc->bindPort, up, down, 351 left, tor->key, event, inf->trackerAddress, 352 VERSION_MAJOR, VERSION_MINOR ); 353 354 ret = tr_netSend( tc->socket, tc->buf, ret ); 355 if( ret & TR_NET_CLOSE ) 356 { 357 tr_inf( "Tracker: connection failed" ); 358 tr_netClose( tc->socket ); 359 tr_fdSocketClosed( tor->fdlimit, 1 ); 360 tc->status = TC_STATUS_IDLE; 361 tc->dateTry = tr_date(); 362 } 363 else if( !( ret & TR_NET_BLOCK ) ) 364 { 365 // printf( "Tracker: sent %s", tc->buf ); 366 tc->status = TC_STATUS_RECV; 367 tc->pos = 0; 368 } 369 } 370 371 static void recvAnswer( tr_tracker_t * tc ) 273 return tr_httpClient( TR_HTTP_GET, inf->trackerAddress, 274 inf->trackerPort, 275 "%s?" 276 "info_hash=%s&" 277 "peer_id=%s&" 278 "port=%d&" 279 "uploaded=%"PRIu64"&" 280 "downloaded=%"PRIu64"&" 281 "left=%"PRIu64"&" 282 "compact=1&" 283 "numwant=50&" 284 "key=%s" 285 "%s ", 286 inf->trackerAnnounce, tor->hashString, tc->id, 287 tc->bindPort, up, down, left, tor->key, event ); 288 } 289 290 static void readAnswer( tr_tracker_t * tc, const char * data, int len ) 372 291 { 373 292 tr_torrent_t * tor = tc->tor; 374 int ret;375 293 int i; 294 int code; 376 295 benc_val_t beAll; 377 296 benc_val_t * bePeers, * beFoo; 378 uint8_t * body;297 const uint8_t * body; 379 298 int bodylen; 380 299 int shouldfree; 381 300 382 if( tc->pos == tc->size )383 {384 tc->size *= 2;385 tc->buf = realloc( tc->buf, tc->size );386 }387 388 ret = tr_netRecv( tc->socket, &tc->buf[tc->pos],389 tc->size - tc->pos );390 391 if( ret & TR_NET_BLOCK )392 {393 return;394 }395 if( !( ret & TR_NET_CLOSE ) )396 {397 // printf( "got %d bytes\n", ret );398 tc->pos += ret;399 return;400 }401 402 tr_netClose( tc->socket );403 tr_fdSocketClosed( tor->fdlimit, 1 );404 // printf( "connection closed, got total %d bytes\n", tc->pos );405 406 tc->status = TC_STATUS_IDLE;407 301 tc->dateTry = tr_date(); 408 409 if( tc->pos < 12 || ( 0 != memcmp( tc->buf, "HTTP/1.0 ", 9 ) && 410 0 != memcmp( tc->buf, "HTTP/1.1 ", 9 ) ) ) 411 { 412 /* We don't have a complete HTTP status line */ 413 tr_inf( "Tracker: incomplete HTTP status line" ); 302 code = tr_httpResponseCode( data, len ); 303 if( 0 > code ) 304 { 305 /* We don't have a valid HTTP status line */ 306 tr_inf( "Tracker: invalid HTTP status line" ); 414 307 tc->lastAttempt = TC_ATTEMPT_NOREACH; 415 308 return; 416 309 } 417 310 418 if( '2' != tc->buf[9])311 if( !TR_HTTP_STATUS_OK( code ) ) 419 312 { 420 313 /* we didn't get a 2xx status code */ 421 tr_err( "Tracker: invalid HTTP status code: %c%c%c", 422 tc->buf[9], tc->buf[10], tc->buf[11] ); 314 tr_err( "Tracker: invalid HTTP status code: %i", code ); 423 315 tc->lastAttempt = TC_ATTEMPT_ERROR; 424 316 return; … … 426 318 427 319 /* find the end of the http headers */ 428 body = tr_memmem( tc->buf, tc->pos, "\015\012\015\012", 4 ); 429 if( NULL != body ) 430 { 431 body += 4; 432 } 433 /* hooray for trackers that violate the HTTP spec */ 434 else if( NULL != ( body = tr_memmem( tc->buf, tc->pos, "\015\015", 2 ) ) || 435 NULL != ( body = tr_memmem( tc->buf, tc->pos, "\012\012", 2 ) ) ) 436 { 437 body += 2; 438 } 439 else 320 body = (uint8_t *) tr_httpParse( data, len, NULL ); 321 if( NULL == body ) 440 322 { 441 323 tr_err( "Tracker: could not find end of HTTP headers" ); … … 443 325 return; 444 326 } 445 bodylen = tc->pos - (body - tc->buf);327 bodylen = len - (body - (const uint8_t*)data); 446 328 447 329 /* Find and load the dictionary */ … … 611 493 tr_info_t * inf = &tor->info; 612 494 613 int s, i, ret; 614 uint8_t buf[1024]; 615 benc_val_t scrape, * val1, * val2; 616 struct in_addr addr; 617 uint64_t date; 618 int pos, len; 619 tr_resolve_t * resolve; 495 tr_http_t * http; 496 const char * data, * body; 497 int datalen, bodylen; 498 int code, ii; 499 benc_val_t scrape, * val1, * val2; 620 500 621 501 if( !tor->scrape[0] ) … … 625 505 } 626 506 627 resolve = tr_netResolveInit( inf->trackerAddress ); 628 for( date = tr_date();; ) 629 { 630 ret = tr_netResolvePulse( resolve, &addr ); 631 if( ret == TR_RESOLVE_OK ) 632 { 633 tr_netResolveClose( resolve ); 507 http = tr_httpClient( TR_HTTP_GET, inf->trackerAddress, inf->trackerPort, 508 "%s?info_hash=%s", tor->scrape, tor->hashString ); 509 510 data = NULL; 511 while( NULL == data ) 512 { 513 switch( tr_httpPulse( http, &data, &datalen ) ) 514 { 515 case TR_WAIT: 516 break; 517 518 case TR_ERROR: 519 tr_httpClose( http ); 520 return 1; 521 522 case TR_OK: 523 if( NULL == data || 0 >= datalen ) 524 { 525 tr_httpClose( http ); 526 return 1; 527 } 528 break; 529 } 530 tr_wait( 10 ); 531 } 532 533 code = tr_httpResponseCode( data, datalen ); 534 if( !TR_HTTP_STATUS_OK( code ) ) 535 { 536 tr_httpClose( http ); 537 return 1; 538 } 539 540 body = tr_httpParse( data, datalen , NULL ); 541 if( NULL == body ) 542 { 543 tr_httpClose( http ); 544 return 1; 545 } 546 bodylen = datalen - ( body - data ); 547 548 for( ii = 0; ii < bodylen - 8; ii++ ) 549 { 550 if( !memcmp( body + ii, "d5:files", 8 ) ) 551 { 634 552 break; 635 553 } 636 if( ret == TR_RESOLVE_ERROR || 637 ( ret == TR_RESOLVE_WAIT && tr_date() > date + 10000 ) ) 638 { 639 tr_err( "Could not resolve %s", inf->trackerAddress ); 640 tr_netResolveClose( resolve ); 641 return 1; 642 } 643 tr_wait( 10 ); 644 } 645 646 s = tr_netOpen( addr, htons( inf->trackerPort ) ); 647 if( s < 0 ) 648 { 649 return 1; 650 } 651 652 len = snprintf( (char *) buf, sizeof( buf ), 653 "GET %s?info_hash=%s HTTP/1.1\r\n" 654 "Host: %s\r\n" 655 "Connection: close\r\n\r\n", 656 tor->scrape, tor->hashString, 657 inf->trackerAddress ); 658 659 for( date = tr_date();; ) 660 { 661 ret = tr_netSend( s, buf, len ); 662 if( ret & TR_NET_CLOSE ) 663 { 664 tr_err( "Could not connect to tracker" ); 665 tr_netClose( s ); 666 return 1; 667 } 668 else if( ret & TR_NET_BLOCK ) 669 { 670 if( tr_date() > date + 10000 ) 671 { 672 tr_err( "Could not connect to tracker" ); 673 tr_netClose( s ); 674 return 1; 675 } 676 } 677 else 678 { 679 break; 680 } 681 tr_wait( 10 ); 682 } 683 684 pos = 0; 685 for( date = tr_date();; ) 686 { 687 ret = tr_netRecv( s, &buf[pos], sizeof( buf ) - pos ); 688 if( ret & TR_NET_CLOSE ) 689 { 690 break; 691 } 692 else if( ret & TR_NET_BLOCK ) 693 { 694 if( tr_date() > date + 10000 ) 695 { 696 tr_err( "Could not read from tracker" ); 697 tr_netClose( s ); 698 return 1; 699 } 700 } 701 else 702 { 703 pos += ret; 704 } 705 tr_wait( 10 ); 706 } 707 708 if( pos < 1 ) 709 { 710 tr_err( "Could not read from tracker" ); 711 tr_netClose( s ); 712 return 1; 713 } 714 715 for( i = 0; i < pos - 8; i++ ) 716 { 717 if( !memcmp( &buf[i], "d5:files", 8 ) ) 718 { 719 break; 720 } 721 } 722 if( i >= pos - 8 ) 723 { 724 return 1; 725 } 726 if( tr_bencLoad( &buf[i], pos - i, &scrape, NULL ) ) 727 { 554 } 555 if( ii >= bodylen - 8 ) 556 { 557 tr_httpClose( http ); 558 return 1; 559 } 560 if( tr_bencLoad( body + ii, bodylen - ii, &scrape, NULL ) ) 561 { 562 tr_httpClose( http ); 728 563 return 1; 729 564 } … … 732 567 if( !val1 ) 733 568 { 569 tr_bencFree( &scrape ); 570 tr_httpClose( http ); 734 571 return 1; 735 572 } … … 737 574 if( !val1 ) 738 575 { 576 tr_bencFree( &scrape ); 577 tr_httpClose( http ); 739 578 return 1; 740 579 } … … 742 581 if( !val2 ) 743 582 { 583 tr_bencFree( &scrape ); 584 tr_httpClose( http ); 744 585 return 1; 745 586 } … … 748 589 if( !val2 ) 749 590 { 591 tr_bencFree( &scrape ); 592 tr_httpClose( http ); 750 593 return 1; 751 594 } 752 595 *leechers = val2->val.i; 753 596 tr_bencFree( &scrape ); 597 tr_httpClose( http ); 754 598 755 599 return 0; -
branches/nat-traversal/libtransmission/transmission.c
r815 r864 75 75 h->fdlimit = tr_fdInit(); 76 76 h->choking = tr_chokingInit( h ); 77 h->natpmp = tr_natpmpInit( h->fdlimit ); 78 h->upnp = tr_upnpInit( h->fdlimit ); 77 79 78 80 h->bindPort = -1; … … 105 107 { 106 108 /* XXX should handle failure here in a better way */ 107 sock = tr_netBind( port ); 109 sock = tr_netBindTCP( port ); 110 if( 0 > sock) 111 { 112 tr_fdSocketClosed( h->fdlimit, 0 ); 113 } 114 else 115 { 116 tr_inf( "Bound listening port %d", port ); 117 listen( sock, 5 ); 118 } 108 119 } 109 120 #else … … 133 144 h->bindSocket = sock; 134 145 146 tr_natpmpForwardPort( h->natpmp, port ); 147 tr_upnpForwardPort( h->upnp, port ); 148 135 149 tr_lockUnlock( &h->acceptLock ); 150 } 151 152 void tr_natTraversalEnable( tr_handle_t * h ) 153 { 154 tr_natpmpStart( h->natpmp ); 155 tr_upnpStart( h->upnp ); 156 } 157 158 void tr_natTraversalDisable( tr_handle_t * h ) 159 { 160 tr_natpmpStop( h->natpmp ); 161 tr_upnpStop( h->upnp ); 162 } 163 164 int tr_natTraversalStatus( tr_handle_t * h ) 165 { 166 int statuses[] = { 167 TR_NAT_TRAVERSAL_MAPPED, 168 TR_NAT_TRAVERSAL_MAPPING, 169 TR_NAT_TRAVERSAL_UNMAPPING, 170 TR_NAT_TRAVERSAL_ERROR, 171 TR_NAT_TRAVERSAL_NOTFOUND, 172 TR_NAT_TRAVERSAL_DISABLED, 173 -1, 174 }; 175 int natpmp, upnp, ii; 176 177 natpmp = tr_natpmpStatus( h->natpmp ); 178 upnp = tr_upnpStatus( h->upnp ); 179 180 for( ii = 0; 0 <= statuses[ii]; ii++ ) 181 { 182 if( statuses[ii] == natpmp || statuses[ii] == upnp ) 183 { 184 return statuses[ii]; 185 } 186 } 187 188 assert( 0 ); 189 190 return TR_NAT_TRAVERSAL_ERROR; 136 191 } 137 192 … … 630 685 { 631 686 acceptStop( h ); 687 tr_natpmpClose( h->natpmp ); 688 tr_upnpClose( h->upnp ); 632 689 tr_chokingClose( h->choking ); 633 690 tr_fdClose( h->fdlimit ); … … 735 792 { 736 793 date1 = tr_date(); 794 795 /* do NAT-PMP and UPnP pulses here since there's nowhere better */ 796 tr_natpmpPulse( h->natpmp ); 797 tr_upnpPulse( h->upnp ); 737 798 738 799 /* Check for incoming connections */ -
branches/nat-traversal/libtransmission/transmission.h
r817 r864 100 100 * tr_setBindPort 101 101 *********************************************************************** 102 * Sets the port to listen for incoming peer connections 102 * Sets the port to listen for incoming peer connections. 103 * This can be safely called even with active torrents. 103 104 **********************************************************************/ 104 105 void tr_setBindPort( tr_handle_t *, int ); 106 107 /*********************************************************************** 108 * tr_natTraversalEnable 109 * tr_natTraversalDisable 110 *********************************************************************** 111 * Enable or disable NAT traversal using NAT-PMP or UPnP IGD. 112 **********************************************************************/ 113 void tr_natTraversalEnable( tr_handle_t * ); 114 void tr_natTraversalDisable( tr_handle_t * ); 115 116 /*********************************************************************** 117 * tr_natTraversalStatus 118 *********************************************************************** 119 * Return the status of NAT traversal 120 **********************************************************************/ 121 #define TR_NAT_TRAVERSAL_MAPPING 1 122 #define TR_NAT_TRAVERSAL_MAPPED 2 123 #define TR_NAT_TRAVERSAL_NOTFOUND 3 124 #define TR_NAT_TRAVERSAL_ERROR 4 125 #define TR_NAT_TRAVERSAL_UNMAPPING 5 126 #define TR_NAT_TRAVERSAL_DISABLED 6 127 #define TR_NAT_TRAVERSAL_IS_DISABLED( st ) \ 128 ( TR_NAT_TRAVERSAL_DISABLED == (st) || TR_NAT_TRAVERSAL_UNMAPPING == (st) ) 129 int tr_natTraversalStatus( tr_handle_t * ); 105 130 106 131 /*********************************************************************** -
branches/nat-traversal/libtransmission/utils.c
r837 r864 25 25 #include "transmission.h" 26 26 27 #define SPRINTF_BUFSIZE 100 28 27 29 static tr_lock_t * messageLock = NULL; 28 30 static int messageLevel = 0; … … 97 99 void tr_msg( int level, char * msg, ... ) 98 100 { 99 va_list args;101 va_list args1, args2; 100 102 tr_msg_list_t * newmsg; 103 int len1, len2; 101 104 102 105 assert( NULL != messageLock ); … … 113 116 if( messageLevel >= level ) 114 117 { 115 va_start( args , msg );118 va_start( args1, msg ); 116 119 if( messageQueuing ) 117 120 { … … 121 124 newmsg->level = level; 122 125 newmsg->when = time( NULL ); 123 vasprintf( &newmsg->message, msg, args ); 126 len1 = len2 = 0; 127 va_start( args2, msg ); 128 tr_vsprintf( &newmsg->message, &len1, &len2, msg, 129 args1, args2 ); 130 va_end( args2 ); 124 131 if( NULL == newmsg->message ) 125 132 { … … 135 142 else 136 143 { 137 vfprintf( stderr, msg, args );144 vfprintf( stderr, msg, args1 ); 138 145 fputc( '\n', stderr ); 139 146 } 140 va_end( args );147 va_end( args1 ); 141 148 } 142 149 … … 235 242 return 0; 236 243 } 244 245 #define UPPER( cc ) \ 246 ( 'a' <= (cc) && 'z' >= (cc) ? (cc) - ( 'a' - 'A' ) : (cc) ) 247 248 int tr_strncasecmp( const char * first, const char * second, int len ) 249 { 250 int ii; 251 char firstchar, secondchar; 252 253 if( 0 > len ) 254 { 255 len = strlen( first ); 256 ii = strlen( second ); 257 len = MIN( len, ii ); 258 } 259 260 for( ii = 0; ii < len; ii++ ) 261 { 262 if( first[ii] != second[ii] ) 263 { 264 firstchar = UPPER( first[ii] ); 265 secondchar = UPPER( second[ii] ); 266 if( firstchar > secondchar ) 267 { 268 return 1; 269 } 270 else if( firstchar < secondchar ) 271 { 272 return -1; 273 } 274 } 275 if( '\0' == first[ii] ) 276 { 277 /* if first[ii] is '\0' then second[ii] is too */ 278 return 0; 279 } 280 } 281 282 return 0; 283 } 284 285 int tr_sprintf( char ** buf, int * used, int * max, const char * format, ... ) 286 { 287 va_list ap1, ap2; 288 int ret; 289 290 va_start( ap1, format ); 291 va_start( ap2, format ); 292 ret = tr_vsprintf( buf, used, max, format, ap1, ap2 ); 293 va_end( ap2 ); 294 va_end( ap1 ); 295 296 return ret; 297 } 298 299 int tr_vsprintf( char ** buf, int * used, int * max, const char * fmt, 300 va_list ap1, va_list ap2 ) 301 { 302 int want; 303 char * newbuf; 304 305 want = vsnprintf( NULL, 0, fmt, ap1 ); 306 307 while( *used + want + 1 > *max ) 308 { 309 *max += SPRINTF_BUFSIZE; 310 newbuf = realloc( *buf, *max ); 311 if( NULL == newbuf ) 312 { 313 return 1; 314 } 315 *buf = newbuf; 316 } 317 318 *used += vsnprintf( *buf + *used, *max - *used, fmt, ap2 ); 319 320 return 0; 321 } 322 323 char * 324 tr_dupstr( const char * base, int len ) 325 { 326 char * ret; 327 328 ret = malloc( len + 1 ); 329 if( NULL != ret ) 330 { 331 memcpy( ret, base, len ); 332 ret[len] = '\0'; 333 } 334 335 return ret; 336 } -
branches/nat-traversal/libtransmission/utils.h
r815 r864 31 31 #define tr_inf( a... ) tr_msg( TR_MSG_INF, ## a ) 32 32 #define tr_dbg( a... ) tr_msg( TR_MSG_DBG, ## a ) 33 void tr_msg ( int level, char * msg, ... ) ;33 void tr_msg ( int level, char * msg, ... ) PRINTF( 2, 3 ); 34 34 35 35 int tr_rand ( int ); … … 44 44 **********************************************************************/ 45 45 int tr_mkdir( char * path ); 46 47 /*********************************************************************** 48 * tr_strcasecmp 49 *********************************************************************** 50 * A case-insensitive strncmp() 51 **********************************************************************/ 52 #define tr_strcasecmp( ff, ss ) ( tr_strncasecmp( (ff), (ss), -1 ) ) 53 int tr_strncasecmp( const char * first, const char * second, int len ); 54 55 /*********************************************************************** 56 * tr_sprintf 57 *********************************************************************** 58 * Appends to the end of a buffer using printf formatting, 59 * growing the buffer if needed 60 **********************************************************************/ 61 int tr_sprintf( char ** buf, int * used, int * max, 62 const char * format, ... ) PRINTF( 4, 5 ); 63 /* gee, it sure would be nice if BeOS had va_copy() */ 64 int tr_vsprintf( char **, int *, int *, const char *, va_list, va_list ); 65 66 /*********************************************************************** 67 * tr_dupstr 68 *********************************************************************** 69 * Creates a nul-terminated string 70 **********************************************************************/ 71 char * tr_dupstr( const char * base, int len ); 46 72 47 73 /*********************************************************************** -
branches/nat-traversal/mk/common.mk
r517 r864 1 1 # $Id$ 2 2 3 TMPCFLAGS = -g -Wall -W - O3 -funroll-loops -D_FILE_OFFSET_BITS=64 \3 TMPCFLAGS = -g -Wall -W -D_FILE_OFFSET_BITS=64 \ 4 4 -D_LARGEFILE_SOURCE -D_GNU_SOURCE \ 5 5 -DSYS_$(shell echo $(SYSTEM) | tr a-z A-Z) -
branches/nat-traversal/mk/lib.mk
r265 r864 6 6 SRCS = transmission.c bencode.c net.c tracker.c peer.c inout.c \ 7 7 metainfo.c sha1.c utils.c fdlimit.c clients.c completion.c \ 8 platform.c ratecontrol.c choking.c 8 platform.c ratecontrol.c choking.c natpmp.c upnp.c http.c xml.c 9 9 OBJS = $(SRCS:%.c=%.o) 10 10
Note: See TracChangeset
for help on using the changeset viewer.