diff options
-rw-r--r-- | ot_udp.c | 102 | ||||
-rw-r--r-- | ot_udp.h | 9 |
2 files changed, 111 insertions, 0 deletions
diff --git a/ot_udp.c b/ot_udp.c new file mode 100644 index 0000000..94d7d3c --- /dev/null +++ b/ot_udp.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ | ||
3 | |||
4 | /* System */ | ||
5 | #include <string.h> | ||
6 | |||
7 | /* Libowfat */ | ||
8 | #include "socket.h" | ||
9 | #include "io.h" | ||
10 | |||
11 | /* Opentracker */ | ||
12 | #include "trackerlogic.h" | ||
13 | #include "ot_udp.h" | ||
14 | #include "ot_stats.h" | ||
15 | |||
16 | /* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */ | ||
17 | void handle_udp4( int64 serversocket ) { | ||
18 | ot_peer peer; | ||
19 | ot_torrent *torrent; | ||
20 | ot_hash *hash = NULL; | ||
21 | char remoteip[4]; | ||
22 | ot_dword *inpacket = (ot_dword*)static_inbuf; | ||
23 | ot_dword *outpacket = (ot_dword*)static_outbuf; | ||
24 | ot_dword numwant, left, event; | ||
25 | ot_word port, remoteport; | ||
26 | size_t r, r_out; | ||
27 | |||
28 | r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport); | ||
29 | |||
30 | stats_issue_event( EVENT_ACCEPT, 0, 0 ); | ||
31 | stats_issue_event( EVENT_READ, 0, r ); | ||
32 | |||
33 | /* Minimum udp tracker packet size, also catches error */ | ||
34 | if( r < 16 ) | ||
35 | return; | ||
36 | |||
37 | /* look for udp bittorrent magic id */ | ||
38 | if( (ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980) ) | ||
39 | return; | ||
40 | |||
41 | switch( ntohl( inpacket[2] ) ) { | ||
42 | case 0: /* This is a connect action */ | ||
43 | outpacket[0] = 0; outpacket[1] = inpacket[3]; | ||
44 | outpacket[2] = inpacket[0]; outpacket[3] = inpacket[1]; | ||
45 | socket_send4( serversocket, static_outbuf, 16, remoteip, remoteport ); | ||
46 | stats_issue_event( EVENT_CONNECT, 0, 16 ); | ||
47 | break; | ||
48 | case 1: /* This is an announce action */ | ||
49 | /* Minimum udp announce packet size */ | ||
50 | if( r < 98 ) | ||
51 | return; | ||
52 | |||
53 | numwant = 200; | ||
54 | /* We do only want to know, if it is zero */ | ||
55 | left = inpacket[64/4] | inpacket[68/4]; | ||
56 | |||
57 | event = ntohl( inpacket[80/4] ); | ||
58 | port = *(ot_word*)( static_inbuf + 96 ); | ||
59 | hash = (ot_hash*)( static_inbuf + 16 ); | ||
60 | |||
61 | OT_SETIP( &peer, remoteip ); | ||
62 | OT_SETPORT( &peer, &port ); | ||
63 | OT_FLAG( &peer ) = 0; | ||
64 | |||
65 | switch( event ) { | ||
66 | case 1: OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED; break; | ||
67 | case 3: OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; break; | ||
68 | default: break; | ||
69 | } | ||
70 | |||
71 | if( !left ) | ||
72 | OT_FLAG( &peer ) |= PEER_FLAG_SEEDING; | ||
73 | |||
74 | outpacket[0] = htonl( 1 ); /* announce action */ | ||
75 | outpacket[1] = inpacket[12/4]; | ||
76 | |||
77 | if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */ | ||
78 | r = remove_peer_from_torrent( hash, &peer, static_outbuf, 0 ); | ||
79 | else { | ||
80 | torrent = add_peer_to_torrent( hash, &peer WANT_TRACKER_SYNC_PARAM( 0 ) ); | ||
81 | if( !torrent ) | ||
82 | return; /* XXX maybe send error */ | ||
83 | |||
84 | r = 8 + return_peers_for_torrent( hash, numwant, static_outbuf + 8, 0 ); | ||
85 | } | ||
86 | |||
87 | socket_send4( serversocket, static_outbuf, r, remoteip, remoteport ); | ||
88 | stats_issue_event( EVENT_ANNOUNCE, 0, r ); | ||
89 | break; | ||
90 | |||
91 | case 2: /* This is a scrape action */ | ||
92 | outpacket[0] = htonl( 2 ); /* scrape action */ | ||
93 | outpacket[1] = inpacket[12/4]; | ||
94 | |||
95 | for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ ) | ||
96 | return_udp_scrape_for_torrent( (ot_hash*)( static_inbuf + 16 + 20 * r_out ), static_outbuf + 8 + 12 * r_out ); | ||
97 | |||
98 | socket_send4( serversocket, static_outbuf, 8 + 12 * r_out, remoteip, remoteport ); | ||
99 | stats_issue_event( EVENT_SCRAPE, 0, r ); | ||
100 | break; | ||
101 | } | ||
102 | } | ||
diff --git a/ot_udp.h b/ot_udp.h new file mode 100644 index 0000000..ba0d7e7 --- /dev/null +++ b/ot_udp.h | |||
@@ -0,0 +1,9 @@ | |||
1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ | ||
3 | |||
4 | #ifndef __OT_UDP_H__ | ||
5 | #define __OT_UDP_H__ | ||
6 | |||
7 | void handle_udp4( int64 serversocket ); | ||
8 | |||
9 | #endif \ No newline at end of file | ||