1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 let log_prefix = "[OV]"
38 lprintf_nl2
log_prefix fmt
41 lprintf2
log_prefix fmt
44 lprintf2
log_prefix fmt
47 "loc", Field_KNOWN
"loc";
51 buf_md4 buf p
.peer_md4
;
53 buf_int16 buf p
.peer_port
;
54 buf_int8 buf p
.peer_kind
57 let md4 = get_md4 s pos
in
58 let ip = get_ip s
(pos
+16) in
59 let port = get_int16 s
(pos
+20) in
60 (* let kind = get_uint8 s (pos+22) in *)
66 peer_country_code
= Geoip.get_country_code_option
ip;
70 peer_created
= last_time
();
77 buf_md4 buf p
.peer_md4
;
79 buf_int16 buf p
.peer_port
;
80 buf_int8 buf p
.peer_kind
82 | OvernetConnectReply peers
->
84 buf_list16
buf_peer buf peers
86 | OvernetPublicize p
->
88 buf_md4 buf p
.peer_md4
;
90 buf_int16 buf p
.peer_port
;
91 buf_int8 buf p
.peer_kind
93 | OvernetPublicized p
->
96 | OvernetSearch
(kind, md4, _
) ->
101 | OvernetSearchReply
(md4, peers
) ->
104 buf_list8
buf_peer buf peers
106 | OvernetGetSearchResults
(md4, kind, min
, max
) ->
109 buf_int8 buf
0; (* the kind in overnet seems to always be 0 *)
110 (* buf_int8 buf kind; *)
114 | OvernetSearchFilesResults
(md4, [r_md4
, r_tags
]) ->
118 buf_tags buf r_tags
names_of_tag
120 | OvernetSearchSourcesResults
(md4, [p
]) ->
124 buf_tags buf r_tags names_of_tag
127 | OvernetNoResult
md4 ->
131 | OvernetPublishFiles
(md4, [r_md4
, r_tags
]) ->
135 buf_tags buf r_tags
names_of_tag
138 | OvernetPublishSources (md4, [p]) ->
141 buf_md4 buf p.peer_md4;
142 buf_tags buf r_tags names_of_tag
145 | OvernetPublished
md4 ->
149 | OvernetGetMyIP
port ->
153 | OvernetGetMyIPResult
(ip) ->
157 | OvernetGetMyIPDone
->
160 | OvernetFirewallConnection
(md4,port) ->
165 | OvernetFirewallConnectionACK
(md4) ->
169 | OvernetFirewallConnectionNACK
(md4) ->
173 | OvernetPeerNotFound peer
->
177 | OvernetUnknown21 peer
->
181 | OvernetUnknown
(opcode
, s
) ->
183 Buffer.add_string buf s
184 | OvernetSearchFilesResults _
185 | OvernetPublishFiles _
186 | OvernetPublishSources _
187 | OvernetSearchSourcesResults _
->
188 raise MessageNotImplemented
190 let get_peer_from_result ip port r_md4 r_tags
=
191 let peer_ip = ref ip in
192 let peer_udpport = ref port in
193 let peer_tcpport = ref 0 in
194 List.iter
(fun tag
->
195 match tag
.tag_name
with
197 for_string_tag tag
(fun bcp
->
198 if String2.starts_with bcp
"bcp://" then
199 let bcp2 = String.sub bcp
6 (String.length bcp
- 6)
201 match String2.split_simplify
bcp2 '
:'
with
202 | [_
;ip;udpport
;tcpport
] ->
203 peer_ip := Ip.of_string
ip;
204 peer_udpport := int_of_string udpport
;
205 peer_tcpport := int_of_string tcpport
;
208 (* FIXME: A firewalled peer...
209 peer_ip := Ip.of_string ip;
210 peer_tcpport := int_of_string port;
214 peer_ip := Ip.of_string
ip;
215 peer_tcpport := int_of_string
port;
217 if !verbose_overnet
then
218 lprintf_nl "Ill formed bcp: [%s]" bcp
;
220 if !verbose_overnet
then
221 lprintf_nl "Ill formed bcp: [%s]" bcp
;
224 if !verbose_unknown_messages
then
225 lprintf_nl "Unused source tag [%s]"
226 (escaped_string_of_field tag
)
230 peer_port
= !peer_udpport;
231 peer_tcpport = !peer_tcpport;
232 peer_country_code
= Geoip.get_country_code_option
!peer_ip;
237 peer_created
= last_time
();
240 let parse ip port opcode s
=
244 let md4 = get_md4 s
0 in
245 let ip = get_ip s
16 in
246 let port = get_int16 s
20 in
247 (* let kind = get_uint8 s 22 in *)
252 peer_country_code
= Geoip.get_country_code_option
ip;
257 peer_created
= last_time
();
260 let peers, pos
= get_list16
get_peer s
0 in
261 OvernetConnectReply
peers
263 let md4 = get_md4 s
0 in
264 let ip = get_ip s
16 in
265 let port = get_int16 s
20 in
266 (* let kind = get_uint8 s 22 in *)
271 peer_country_code
= Geoip.get_country_code_option
ip;
276 peer_created
= last_time
();
279 OvernetPublicized None
281 let kind = get_uint8 s
0 in
282 let md4 = get_md4 s
1 in
283 OvernetSearch
(kind, md4, None
)
285 let md4 = get_md4 s
0 in
286 let peers, pos
= get_list8
get_peer s
16 in
287 OvernetSearchReply
(md4, peers)
289 let md4 = get_md4 s
0 in
290 let kind = get_uint8 s
16 in
291 let min = get_int16 s
17 in
292 let max = get_int16 s
19 in
293 OvernetGetSearchResults
(md4, Search_for_kind
kind, min, max)
295 let md4 = get_md4 s
0 in
296 let r_md4 = get_md4 s
16 in
297 let r_tags, pos
= get_tags s
32 names_of_tag in
298 let sources = ref false in
299 List.iter
(fun tag
->
300 if tag
.tag_name
= Field_KNOWN
"loc" then sources := true;
303 let peer = get_peer_from_result ip port r_md4 r_tags in
304 OvernetSearchSourcesResults
(md4, [peer])
306 OvernetSearchFilesResults
(md4, [r_md4, r_tags])
308 let md4 = get_md4 s
0 in
311 let md4 = get_md4 s
0 in
312 let r_md4 = get_md4 s
16 in
313 let r_tags, pos
= get_tags s
32 names_of_tag in
314 let sources = ref false in
315 List.iter
(fun tag
->
316 if tag
.tag_name
= Field_KNOWN
"loc" then sources := true;
319 let peer = get_peer_from_result ip port r_md4 r_tags in
320 OvernetPublishSources
(md4, [peer])
322 OvernetPublishFiles
(md4, [r_md4, r_tags])
324 let md4 = get_md4 s
0 in
327 (* idem as 33, but IP seem to be a low ID *)
328 if !verbose_overnet
then begin
329 lprintf_nl "Received code %d message. Dump:" opcode
;
333 let peer, _
= get_peer s
0 in
334 OvernetUnknown21
peer
336 if !verbose_overnet
then
337 lprintf_nl "RCVD: OVERNET FIREWALL CONNECTION (24)";
338 let md4 = get_md4 s
0 in
339 let port = get_int16 s
16 in
340 OvernetFirewallConnection
(md4,port)
342 if !verbose_overnet
then
343 lprintf_nl "RCVD: OVERNET FIREWALL CONNECTION ACK (25)";
344 let md4 = get_md4 s
0 in
345 OvernetFirewallConnectionACK
(md4)
347 if !verbose_overnet
then
348 lprintf_nl "RCVD: OVERNET FIREWALL CONNECTION NACK (26)";
349 let md4 = get_md4 s
0 in
350 OvernetFirewallConnectionNACK
(md4)
352 if !verbose_overnet
then
353 lprintf_nl "RCVD: GETMYIP MESSAGE (27)";
354 OvernetGetMyIP
(get_int16 s
0)
356 if !verbose_overnet
then
357 lprintf_nl "RCVD: GETMYIPRESULT MESSAGE (28)";
358 let ip = get_ip s
0 in
359 OvernetGetMyIPResult
(ip)
361 if !verbose_overnet
then
362 lprintf_nl "RCVD: GETMYIPDONE MESSAGE (29)";
365 if !verbose_overnet
then
366 lprintf_nl "RCVD: PEER NOT FOUND (33)";
367 let peer, _
= get_peer s
0 in
368 OvernetPeerNotFound
peer
370 if !verbose_unknown_messages
then
372 lprintf_nl "unknown opcode %d" opcode
;
376 OvernetUnknown
(opcode
, s
)
378 if !verbose_unknown_messages
then
380 lprintf_nl "Error %s while parsing opcode %d" (Printexc2.to_string e
) opcode
;
384 OvernetUnknown
(opcode
, s
)
386 let udp_handler f sock event
=
388 UdpSocket.READ_DONE
->
389 UdpSocket.read_packets sock
(fun p
->
391 let pbuf = p
.UdpSocket.udp_content
in
392 let len = String.length
pbuf in
394 int_of_char
pbuf.[0] <> 227 then
396 if !verbose_unknown_messages
then begin
397 lprintf_nl "Received unknown UDP packet";
404 match p
.UdpSocket.udp_addr
with
405 Unix.ADDR_INET
(inet
, port) ->
406 Ip.of_inet_addr inet
, port
409 let t = parse ip port (int_of_char
pbuf.[1]) (String.sub
pbuf 2 (len-2)) in
410 let is_not_banned ip =
411 match !Ip.banned
(ip, None
) with
414 if !verbose_overnet
then
415 lprintf_nl "%s blocked: %s" (Ip.to_string
ip) reason
;
418 if is_not_banned ip then f
t p
421 if !verbose_unknown_messages
then begin
422 lprintf_nl "Error %s in udp_handler, dump of packet:"
423 (Printexc2.to_string e
);
424 dump p
.UdpSocket.udp_content
;
430 let checking_kind_timeout = 180
432 let redirector_section = "DKKO"
433 let options_section_name = overnet_options_section_name
434 let overnet_section = overnet_section
435 let overnet_port = overnet_port
436 let overnet_tcpport = overnet_port
438 let udp_buf = Buffer.create
2000
440 let udp_send sock
ip port ping msg
=
442 Buffer.reset
udp_buf;
443 buf_int8
udp_buf 227;
445 let s = Buffer.contents
udp_buf in
446 if !verbose_overnet
then
448 lprintf_nl "UDP to %s:%d op 0x%02X len %d type %s"
449 (Ip.to_string
ip) port (get_uint8
s 1) (String.length
s) (message_to_string msg
);
451 UdpSocket.write sock ping
s ip port
453 lprintf_nl "Exception %s in udp_send" (Printexc2.to_string e
)
455 let udp_send sock
ip port ping msg
=
457 | OvernetSearchFilesResults
(target
, ((_
:: _
:: _
) as results
)) ->
459 udp_send sock
ip port ping
460 (OvernetSearchFilesResults
(target
, [r
]))
462 | OvernetSearchSourcesResults
(target
, ((_
:: _
:: _
) as results
)) ->
464 udp_send sock
ip port ping
465 (OvernetSearchSourcesResults
(target
, [r
]))
467 | OvernetPublishFiles
(target
, ((_
:: _
:: _
) as results
)) ->
469 udp_send sock
ip port ping
470 (OvernetPublishFiles
(target
, [r
]))
472 | OvernetPublishSources
(target
, ((_
:: _
:: _
) as results
)) ->
474 udp_send sock
ip port ping
475 (OvernetPublishSources
(target
, [r
]))
477 | _
-> udp_send sock
ip port ping msg
479 let enable_overnet = enable_overnet
480 let command_prefix = "ov_"
481 let source_brand = true
483 let web_info_descr = "Overnet network boot peers"
486 module Overnet_initial
= Make
(Proto
)
488 let overnet_protocol_connect_version =
489 define_option
overnet_section [
490 Proto.options_section_name;
491 "protocol_connect_version"]
492 "The protocol version sent on Overnet connections"
495 let overnet_protocol_connectreply_version =
496 define_option
overnet_section [Proto.options_section_name; "protocol_connectreply_version"]
497 "The protocol version sent on Overnet connections replies"
501 (* In Overnet case, the TCP protocol is changed, so we need to create a special
502 TCP port for Overnet clients, that will not be used by normal Edonkey
503 and Kademlia clients. *)
505 let tcp_sock = ref None
507 module Overnet
= struct
508 include Overnet_initial
512 if !!enable_overnet then begin
514 let sock = TcpServerSocket.create
515 "overnet client server"
516 (Ip.to_inet_addr
!!client_bind_addr
)
518 (DonkeyClient.client_connection_handler
true) in
520 tcp_sock := Some
sock;
522 match Unix.getsockname
(BasicSocket.fd
(TcpServerSocket.sock sock)) with
523 Unix.ADDR_INET
(ip, port) ->
524 assert (port = !!overnet_port)
525 | _
-> failwith
"Bad socket address"
527 lprintf_nl "[Overnet] Could not assign TCP port %d for Overnet" !!overnet_port;
533 (match !tcp_sock with
537 TcpServerSocket.close
sock Closed_by_user
);