From 0a9021668658a2db0f52a3bcb062c74bd318ac8b Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Tue, 6 Mar 2007 19:43:47 +0000 Subject: udp is working in theory, return_peers_for_torrent accepts a switch to request an udp answer. Fixed prototypes. --- opentracker.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 13 deletions(-) (limited to 'opentracker.c') diff --git a/opentracker.c b/opentracker.c index 51a5b33..657f4f3 100644 --- a/opentracker.c +++ b/opentracker.c @@ -74,6 +74,12 @@ static void handle_timeouted( void ); static void handle_accept( const int64 serversocket ); static void handle_read( const int64 clientsocket ); static void handle_write( const int64 clientsocket ); +static void handle_udp4( const int64 serversocket ); + +static void ot_try_bind_udp4( char ip[4], uint16 port ); +static void ot_try_bind_tcp4( char ip[4], uint16 port ); +static int ot_in_udp4_sockets( int64 fd ); +static int ot_in_tcp4_sockets( int64 fd ); static void usage( char *name ); static void help( char *name ); @@ -381,7 +387,7 @@ ANNOUNCE_WORKAROUND: reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM ); } else { torrent = add_peer_to_torrent( hash, &peer ); - if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; + if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; } ot_overall_successfulannounces++; break; @@ -555,17 +561,76 @@ static void handle_timeouted( void ) { } } -void handle_udp4( int64 serversocket ) { - size_t r; - char remoteip[4]; - uint16 port; - - r = socket_recv4(serversocket, static_inbuf, 8192, remoteip, &port); +static void handle_udp4( int64 serversocket ) { + ot_peer peer; + ot_torrent *torrent; + ot_hash *hash = NULL; + char remoteip[4]; + unsigned long *inpacket = (unsigned long*)static_inbuf; + unsigned long *outpacket = (unsigned long*)static_outbuf; + unsigned long numwant, left, event; + uint16 port; + size_t r; + + r = socket_recv4( serversocket, static_inbuf, 8192, remoteip, &port); + + /* Minimum udp tracker packet size, also catches error */ + if( r < 16 ) + return; - // too lazy :) + switch( ntohl( inpacket[2] ) ) { + case 0: /* This is a connect action */ + outpacket[0] = 0; outpacket[1] = inpacket[3]; + outpacket[2] = inpacket[0]; outpacket[3] = inpacket[1]; + socket_send4( serversocket, static_outbuf, 16, remoteip, port ); + break; + case 1: /* This is an announce action */ + /* Minimum udp announce packet size */ + if( r < 98 ) + return; + + numwant = 200; + left = ntohl( inpacket[64/4] ); + event = ntohl( inpacket[80/4] ); + port = ntohl( inpacket[96/4] ); + hash = (ot_hash*)inpacket+(16/4); + + OT_SETIP( &peer, remoteip ); + OT_SETPORT( &peer, &port ); + OT_FLAG( &peer ) = 0; + + switch( event ) { + case 1: OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED; break; + case 3: OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; break; + default: break; + } + if( !left ) + OT_FLAG( &peer ) |= PEER_FLAG_SEEDING; + + if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) { + /* Peer is gone. */ + remove_peer_from_torrent( hash, &peer ); + + /* Create fake packet to satisfy parser on the other end */ + outpacket[0] = htonl( 1 ); + outpacket[1] = inpacket[12/4]; + outpacket[2] = outpacket[3] = outpacket[4] = 0; + socket_send4( serversocket, static_outbuf, 20, remoteip, port ); + } else { + torrent = add_peer_to_torrent( hash, &peer ); + if( !torrent ) + return; /* XXX maybe send error */ + + outpacket[0] = htonl( 1 ); + outpacket[1] = inpacket[12/4]; + r = 8 + return_peers_for_torrent( torrent, numwant, static_outbuf + 8, 0 ); + socket_send4( serversocket, static_outbuf, r, remoteip, port ); + } + break; + } } -int ot_in_tcp4_sockets( int64 fd ) { +static int ot_in_tcp4_sockets( int64 fd ) { int i; for( i=0; i