An open and free bittorrent tracker https://erdgeist.org/gitweb/opentracker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.9 KiB

13 years ago
13 years ago
13 years ago
13 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
13 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
** struct ot_workstruct gets ritcher (and will become even ritcher soon). This is where we encapsulate all per-request data from peer to hash to peer_id, so that it is available everywhere without passing hundreds of pointers down the stack. Most functions that do work down the stack now accept an ot_workstruct and some flags. So it can end up in the stats/event-handler where it will be the default parameter in the future. ** peer_id is now being copied by default and moved to ot_workstruct So it is available in stats and subsequent functions. ** sync scrape madness is gone SYNC_SCRAPE was intended to sync tracker state that would normally be lost on restarts i.e. downloaded counts per torrent. The way was to push it in the tracker cloud after finding all neighbouring trackers. This is madness. It never was tested and can be done per tracker by fetching stats/mode=statedump from time to time and starting opentracker with the -l option later. ** livesync thread has its own ot_workstruct now So it can behave like ot_udp and ot_http against trackerlogic.c and get rid of the first half of the embarrassing global variables. The sending half will be fixed soon [tm]. ** stats can log completed events The author recognizes the needs of original content distributors to keep track of the amount of times a work has been downloaded. While not feasible and used on openbittorrent and other open and anonymous tracker installations, a tracker user can now choose to send those events to syslog.
11 years ago
  1. /* This software was written by Dirk Engling <erdgeist@erdgeist.org>
  2. It is considered beerware. Prost. Skol. Cheers or whatever.
  3. $id$ */
  4. /* System */
  5. #include <stdlib.h>
  6. #include <pthread.h>
  7. #include <string.h>
  8. #include <arpa/inet.h>
  9. #include <stdio.h>
  10. /* Libowfat */
  11. #include "socket.h"
  12. #include "io.h"
  13. /* Opentracker */
  14. #include "trackerlogic.h"
  15. #include "ot_udp.h"
  16. #include "ot_stats.h"
  17. #include "ot_rijndael.h"
  18. #if 0
  19. static const uint8_t g_static_connid[8] = { 0x23, 0x42, 0x05, 0x17, 0xde, 0x41, 0x50, 0xff };
  20. #endif
  21. static uint32_t g_rijndael_round_key[44] = {0};
  22. static uint32_t g_key_of_the_hour[2] = {0};
  23. static ot_time g_hour_of_the_key;
  24. static void udp_generate_rijndael_round_key() {
  25. uint32_t key[16];
  26. key[0] = random();
  27. key[1] = random();
  28. key[2] = random();
  29. key[3] = random();
  30. rijndaelKeySetupEnc128( g_rijndael_round_key, (uint8_t*)key );
  31. g_key_of_the_hour[0] = random();
  32. g_hour_of_the_key = g_now_minutes;
  33. }
  34. /* Generate current and previous connection id for ip */
  35. static void udp_make_connectionid( uint32_t connid[2], const ot_ip6 remoteip, int age ) {
  36. uint32_t plain[4], crypt[4];
  37. int i;
  38. if( g_now_minutes + 60 > g_hour_of_the_key ) {
  39. g_hour_of_the_key = g_now_minutes;
  40. g_key_of_the_hour[1] = g_key_of_the_hour[0];
  41. g_key_of_the_hour[0] = random();
  42. }
  43. memcpy( plain, remoteip, sizeof( plain ) );
  44. for( i=0; i<4; ++i ) plain[i] ^= g_key_of_the_hour[age];
  45. rijndaelEncrypt128( g_rijndael_round_key, (uint8_t*)remoteip, (uint8_t*)crypt );
  46. connid[0] = crypt[0] ^ crypt[1];
  47. connid[1] = crypt[2] ^ crypt[3];
  48. }
  49. /* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
  50. int handle_udp6( int64 serversocket, struct ot_workstruct *ws ) {
  51. ot_ip6 remoteip;
  52. uint32_t *inpacket = (uint32_t*)ws->inbuf;
  53. uint32_t *outpacket = (uint32_t*)ws->outbuf;
  54. uint32_t numwant, left, event, scopeid;
  55. uint32_t connid[2];
  56. uint32_t action;
  57. uint16_t port, remoteport;
  58. size_t byte_count, scrape_count;
  59. byte_count = socket_recv6( serversocket, ws->inbuf, G_INBUF_SIZE, remoteip, &remoteport, &scopeid );
  60. if( !byte_count ) return 0;
  61. stats_issue_event( EVENT_ACCEPT, FLAG_UDP, (uintptr_t)remoteip );
  62. stats_issue_event( EVENT_READ, FLAG_UDP, byte_count );
  63. /* Minimum udp tracker packet size, also catches error */
  64. if( byte_count < 16 )
  65. return 1;
  66. /* Get action to take. Ignore error messages and broken packets */
  67. action = ntohl( inpacket[2] );
  68. if( action > 2 )
  69. return 1;
  70. /* Generate the connection id we give out and expect to and from
  71. the requesting ip address, this prevents udp spoofing */
  72. udp_make_connectionid( connid, remoteip, 0 );
  73. /* Initialise hash pointer */
  74. ws->hash = NULL;
  75. ws->peer_id = NULL;
  76. /* If action is not 0 (connect), then we expect the derived
  77. connection id in first 64 bit */
  78. if( ( action > 0 ) && ( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) ) {
  79. /* If connection id does not match, try the one that was
  80. valid in the previous hour. Only if this also does not
  81. match, return an error packet */
  82. udp_make_connectionid( connid, remoteip, 1 );
  83. if( inpacket[0] != connid[0] || inpacket[1] != connid[1] ) {
  84. const size_t s = sizeof( "Connection ID missmatch." );
  85. outpacket[0] = htonl( 3 ); outpacket[1] = inpacket[3];
  86. memcpy( &outpacket[2], "Connection ID missmatch.", s );
  87. socket_send6( serversocket, ws->outbuf, 8 + s, remoteip, remoteport, 0 );
  88. stats_issue_event( EVENT_CONNID_MISSMATCH, FLAG_UDP, 8 + s );
  89. return 1;
  90. }
  91. }
  92. switch( action ) {
  93. case 0: /* This is a connect action */
  94. /* look for udp bittorrent magic id */
  95. if( (ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980) )
  96. return 1;
  97. outpacket[0] = 0;
  98. outpacket[1] = inpacket[3];
  99. outpacket[2] = connid[0];
  100. outpacket[3] = connid[1];
  101. socket_send6( serversocket, ws->outbuf, 16, remoteip, remoteport, 0 );
  102. stats_issue_event( EVENT_CONNECT, FLAG_UDP, 16 );
  103. break;
  104. case 1: /* This is an announce action */
  105. /* Minimum udp announce packet size */
  106. if( byte_count < 98 )
  107. return 1;
  108. /* We do only want to know, if it is zero */
  109. left = inpacket[64/4] | inpacket[68/4];
  110. /* Limit amount of peers to 200 */
  111. numwant = ntohl( inpacket[92/4] );
  112. if (numwant > 200) numwant = 200;
  113. event = ntohl( inpacket[80/4] );
  114. port = *(uint16_t*)( ((char*)inpacket) + 96 );
  115. ws->hash = (ot_hash*)( ((char*)inpacket) + 16 );
  116. OT_SETIP( &ws->peer, remoteip );
  117. OT_SETPORT( &ws->peer, &port );
  118. OT_PEERFLAG( &ws->peer ) = 0;
  119. switch( event ) {
  120. case 1: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_COMPLETED; break;
  121. case 3: OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_STOPPED; break;
  122. default: break;
  123. }
  124. if( !left )
  125. OT_PEERFLAG( &ws->peer ) |= PEER_FLAG_SEEDING;
  126. outpacket[0] = htonl( 1 ); /* announce action */
  127. outpacket[1] = inpacket[12/4];
  128. if( OT_PEERFLAG( &ws->peer ) & PEER_FLAG_STOPPED ) { /* Peer is gone. */
  129. ws->reply = ws->outbuf;
  130. ws->reply_size = remove_peer_from_torrent( FLAG_UDP, ws );
  131. } else {
  132. ws->reply = ws->outbuf + 8;
  133. ws->reply_size = 8 + add_peer_to_torrent_and_return_peers( FLAG_UDP, ws, numwant );
  134. }
  135. socket_send6( serversocket, ws->outbuf, ws->reply_size, remoteip, remoteport, 0 );
  136. stats_issue_event( EVENT_ANNOUNCE, FLAG_UDP, ws->reply_size );
  137. break;
  138. case 2: /* This is a scrape action */
  139. outpacket[0] = htonl( 2 ); /* scrape action */
  140. outpacket[1] = inpacket[12/4];
  141. for( scrape_count = 0; ( scrape_count * 20 < byte_count - 16) && ( scrape_count <= 74 ); scrape_count++ )
  142. return_udp_scrape_for_torrent( *(ot_hash*)( ((char*)inpacket) + 16 + 20 * scrape_count ), ((char*)outpacket) + 8 + 12 * scrape_count );
  143. socket_send6( serversocket, ws->outbuf, 8 + 12 * scrape_count, remoteip, remoteport, 0 );
  144. stats_issue_event( EVENT_SCRAPE, FLAG_UDP, scrape_count );
  145. break;
  146. }
  147. return 1;
  148. }
  149. static void* udp_worker( void * args ) {
  150. int64 sock = (int64)args;
  151. struct ot_workstruct ws;
  152. memset( &ws, 0, sizeof(ws) );
  153. ws.inbuf=malloc(G_INBUF_SIZE);
  154. ws.outbuf=malloc(G_OUTBUF_SIZE);
  155. #ifdef _DEBUG_HTTPERROR
  156. ws.debugbuf=malloc(G_DEBUGBUF_SIZE);
  157. #endif
  158. while( g_opentracker_running )
  159. handle_udp6( sock, &ws );
  160. free( ws.inbuf );
  161. free( ws.outbuf );
  162. #ifdef _DEBUG_HTTPERROR
  163. free( ws.debugbuf );
  164. #endif
  165. return NULL;
  166. }
  167. void udp_init( int64 sock, unsigned int worker_count ) {
  168. pthread_t thread_id;
  169. if( !g_rijndael_round_key[0] )
  170. udp_generate_rijndael_round_key();
  171. #ifdef _DEBUG
  172. fprintf( stderr, " installing %d workers on udp socket %ld", worker_count, (unsigned long)sock );
  173. #endif
  174. while( worker_count-- )
  175. pthread_create( &thread_id, NULL, udp_worker, (void *)sock );
  176. }
  177. const char *g_version_udp_c = "$Source: /home/cvsroot/opentracker/ot_udp.c,v $: $Revision: 1.32 $\n";