patch #8106
[mldonkey.git] / src / networks / donkey / donkeyProtoOvernet.ml
blobb288fd23695fe5d2b94d5d3d48253e7fad7b5372
1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
2 (*
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
20 open Printf2
21 open Md4
22 open AnyEndian
23 open BasicSocket
24 open CommonOptions
25 open Options
26 open DonkeyOptions
27 open CommonTypes
28 open LittleEndian
29 open CommonGlobals
30 open DonkeyMftp
31 open DonkeyOvernet
33 module Proto = struct
35 let log_prefix = "[OV]"
37 let lprintf_nl fmt =
38 lprintf_nl2 log_prefix fmt
40 let lprintf_n fmt =
41 lprintf2 log_prefix fmt
43 let lprintf fmt =
44 lprintf2 log_prefix fmt
46 let names_of_tag = [
47 "loc", Field_KNOWN "loc";
48 ] @ file_common_tags
50 let buf_peer buf p =
51 buf_md4 buf p.peer_md4;
52 buf_ip buf p.peer_ip;
53 buf_int16 buf p.peer_port;
54 buf_int8 buf p.peer_kind
56 let get_peer s pos =
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 *)
62 peer_md4 = md4;
63 peer_ip = ip;
64 peer_port = port;
65 peer_tcpport = 0;
66 peer_country_code = Geoip.get_country_code_option ip;
67 peer_kind = 3;
68 peer_last_send = 0;
69 peer_expire = 0;
70 peer_created = last_time ();
71 }, pos + 23
73 let write buf t =
74 match t with
75 | OvernetConnect p ->
76 buf_int8 buf 10;
77 buf_md4 buf p.peer_md4;
78 buf_ip buf p.peer_ip;
79 buf_int16 buf p.peer_port;
80 buf_int8 buf p.peer_kind
82 | OvernetConnectReply peers ->
83 buf_int8 buf 11;
84 buf_list16 buf_peer buf peers
86 | OvernetPublicize p ->
87 buf_int8 buf 12;
88 buf_md4 buf p.peer_md4;
89 buf_ip buf p.peer_ip;
90 buf_int16 buf p.peer_port;
91 buf_int8 buf p.peer_kind
93 | OvernetPublicized p ->
94 buf_int8 buf 13
96 | OvernetSearch (kind, md4, _) ->
97 buf_int8 buf 14;
98 buf_int8 buf kind;
99 buf_md4 buf md4
101 | OvernetSearchReply (md4, peers) ->
102 buf_int8 buf 15;
103 buf_md4 buf md4;
104 buf_list8 buf_peer buf peers
106 | OvernetGetSearchResults (md4, kind, min, max) ->
107 buf_int8 buf 16;
108 buf_md4 buf md4;
109 buf_int8 buf 0; (* the kind in overnet seems to always be 0 *)
110 (* buf_int8 buf kind; *)
111 buf_int16 buf min;
112 buf_int16 buf max
114 | OvernetSearchFilesResults (md4, [r_md4, r_tags]) ->
115 buf_int8 buf 17;
116 buf_md4 buf md4;
117 buf_md4 buf r_md4;
118 buf_tags buf r_tags names_of_tag
120 | OvernetSearchSourcesResults (md4, [p]) ->
121 (* buf_int8 buf 17;
122 buf_md4 buf md4;
123 buf_md4 buf r_md4;
124 buf_tags buf r_tags names_of_tag
125 *) ()
127 | OvernetNoResult md4 ->
128 buf_int8 buf 18;
129 buf_md4 buf md4
131 | OvernetPublishFiles (md4, [r_md4, r_tags]) ->
132 buf_int8 buf 19;
133 buf_md4 buf md4;
134 buf_md4 buf r_md4;
135 buf_tags buf r_tags names_of_tag
138 | OvernetPublishSources (md4, [p]) ->
139 buf_int8 buf 19;
140 buf_md4 buf md4;
141 buf_md4 buf p.peer_md4;
142 buf_tags buf r_tags names_of_tag
145 | OvernetPublished md4 ->
146 buf_int8 buf 20;
147 buf_md4 buf md4
149 | OvernetGetMyIP port ->
150 buf_int8 buf 27;
151 buf_int16 buf port
153 | OvernetGetMyIPResult (ip) ->
154 buf_int8 buf 28;
155 buf_ip buf ip
157 | OvernetGetMyIPDone ->
158 buf_int8 buf 29
160 | OvernetFirewallConnection(md4,port) ->
161 buf_int8 buf 24;
162 buf_md4 buf md4;
163 buf_int16 buf port
165 | OvernetFirewallConnectionACK(md4) ->
166 buf_int8 buf 25;
167 buf_md4 buf md4
169 | OvernetFirewallConnectionNACK(md4) ->
170 buf_int8 buf 26;
171 buf_md4 buf md4
173 | OvernetPeerNotFound peer ->
174 buf_int8 buf 33;
175 buf_peer buf peer
177 | OvernetUnknown21 peer ->
178 buf_int8 buf 21;
179 buf_peer buf peer
181 | OvernetUnknown (opcode, s) ->
182 buf_int8 buf opcode;
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
196 Field_KNOWN "loc" ->
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;
207 | [_;ip;port] -> ()
208 (* FIXME: A firewalled peer...
209 peer_ip := Ip.of_string ip;
210 peer_tcpport := int_of_string port;
213 | [ip;port] ->
214 peer_ip := Ip.of_string ip;
215 peer_tcpport := int_of_string port;
216 | _ ->
217 if !verbose_overnet then
218 lprintf_nl "Ill formed bcp: [%s]" bcp;
219 else
220 if !verbose_overnet then
221 lprintf_nl "Ill formed bcp: [%s]" bcp;
223 | _ ->
224 if !verbose_unknown_messages then
225 lprintf_nl "Unused source tag [%s]"
226 (escaped_string_of_field tag)
227 ) r_tags;
229 peer_ip = !peer_ip;
230 peer_port = !peer_udpport;
231 peer_tcpport = !peer_tcpport;
232 peer_country_code = Geoip.get_country_code_option !peer_ip;
233 peer_md4 = r_md4;
234 peer_last_send = 0;
235 peer_expire = 0;
236 peer_kind = 3;
237 peer_created = last_time ();
240 let parse ip port opcode s =
242 match opcode with
243 | 10 ->
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 *)
248 OvernetConnect {
249 peer_md4 = md4;
250 peer_ip = ip;
251 peer_port = port;
252 peer_country_code = Geoip.get_country_code_option ip;
253 peer_kind = 3;
254 peer_tcpport = 0;
255 peer_last_send = 0;
256 peer_expire = 0;
257 peer_created = last_time ();
259 | 11 ->
260 let peers, pos = get_list16 get_peer s 0 in
261 OvernetConnectReply peers
262 | 12 ->
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 *)
267 OvernetPublicize {
268 peer_md4 = md4;
269 peer_ip = ip;
270 peer_port = port;
271 peer_country_code = Geoip.get_country_code_option ip;
272 peer_kind = 3;
273 peer_tcpport = 0;
274 peer_last_send = 0;
275 peer_expire = 0;
276 peer_created = last_time ();
278 | 13 ->
279 OvernetPublicized None
280 | 14 ->
281 let kind = get_uint8 s 0 in
282 let md4 = get_md4 s 1 in
283 OvernetSearch (kind, md4, None)
284 | 15 ->
285 let md4 = get_md4 s 0 in
286 let peers, pos = get_list8 get_peer s 16 in
287 OvernetSearchReply (md4, peers)
288 | 16 ->
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)
294 | 17 ->
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;
301 ) r_tags;
302 if !sources then
303 let peer = get_peer_from_result ip port r_md4 r_tags in
304 OvernetSearchSourcesResults (md4, [peer])
305 else
306 OvernetSearchFilesResults (md4, [r_md4, r_tags])
307 | 18 ->
308 let md4 = get_md4 s 0 in
309 OvernetNoResult md4
310 | 19 ->
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;
317 ) r_tags;
318 if !sources then
319 let peer = get_peer_from_result ip port r_md4 r_tags in
320 OvernetPublishSources (md4, [peer])
321 else
322 OvernetPublishFiles (md4, [r_md4, r_tags])
323 | 20 ->
324 let md4 = get_md4 s 0 in
325 OvernetPublished md4
326 | 21 ->
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;
330 dump s;
331 lprint_newline ();
332 end;
333 let peer, _ = get_peer s 0 in
334 OvernetUnknown21 peer
335 | 24 ->
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)
341 | 25 ->
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)
346 | 26 ->
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)
351 | 27 ->
352 if !verbose_overnet then
353 lprintf_nl "RCVD: GETMYIP MESSAGE (27)";
354 OvernetGetMyIP (get_int16 s 0)
355 | 28 ->
356 if !verbose_overnet then
357 lprintf_nl "RCVD: GETMYIPRESULT MESSAGE (28)";
358 let ip = get_ip s 0 in
359 OvernetGetMyIPResult (ip)
360 | 29 ->
361 if !verbose_overnet then
362 lprintf_nl "RCVD: GETMYIPDONE MESSAGE (29)";
363 OvernetGetMyIPDone
364 | 33 ->
365 if !verbose_overnet then
366 lprintf_nl "RCVD: PEER NOT FOUND (33)";
367 let peer, _ = get_peer s 0 in
368 OvernetPeerNotFound peer
369 | _ ->
370 if !verbose_unknown_messages then
371 begin
372 lprintf_nl "unknown opcode %d" opcode;
373 dump s;
374 lprint_newline ();
375 end;
376 OvernetUnknown (opcode, s)
377 with e ->
378 if !verbose_unknown_messages then
379 begin
380 lprintf_nl "Error %s while parsing opcode %d" (Printexc2.to_string e) opcode;
381 dump s;
382 lprint_newline ();
383 end;
384 OvernetUnknown (opcode, s)
386 let udp_handler f sock event =
387 match event with
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
393 if len < 2 ||
394 int_of_char pbuf.[0] <> 227 then
395 begin
396 if !verbose_unknown_messages then begin
397 lprintf_nl "Received unknown UDP packet";
398 dump pbuf;
401 else
402 begin
403 let (ip, port) =
404 match p.UdpSocket.udp_addr with
405 Unix.ADDR_INET (inet, port) ->
406 Ip.of_inet_addr inet, port
407 | _ -> assert false
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
412 None -> true
413 | Some reason ->
414 if !verbose_overnet then
415 lprintf_nl "%s blocked: %s" (Ip.to_string ip) reason;
416 false
418 if is_not_banned ip then f t p
420 with e ->
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;
425 lprint_newline ()
428 | _ -> ()
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;
444 write udp_buf msg;
445 let s = Buffer.contents udp_buf in
446 if !verbose_overnet then
447 begin
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);
450 end;
451 UdpSocket.write sock ping s ip port
452 with e ->
453 lprintf_nl "Exception %s in udp_send" (Printexc2.to_string e)
455 let udp_send sock ip port ping msg =
456 match msg with
457 | OvernetSearchFilesResults (target, ((_ :: _ :: _) as results)) ->
458 List.iter (fun r ->
459 udp_send sock ip port ping
460 (OvernetSearchFilesResults (target, [r]))
461 ) results
462 | OvernetSearchSourcesResults (target, ((_ :: _ :: _) as results)) ->
463 List.iter (fun r ->
464 udp_send sock ip port ping
465 (OvernetSearchSourcesResults (target, [r]))
466 ) results
467 | OvernetPublishFiles (target, ((_ :: _ :: _) as results)) ->
468 List.iter (fun r ->
469 udp_send sock ip port ping
470 (OvernetPublishFiles (target, [r]))
471 ) results
472 | OvernetPublishSources (target, ((_ :: _ :: _) as results)) ->
473 List.iter (fun r ->
474 udp_send sock ip port ping
475 (OvernetPublishSources (target, [r]))
476 ) results
477 | _ -> udp_send sock ip port ping msg
479 let enable_overnet = enable_overnet
480 let command_prefix = "ov_"
481 let source_brand = true
482 let web_info = "ocl"
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"
493 int_option 1044
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"
498 int_option 44
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
510 let enable enabler =
511 enable enabler;
512 if !!enable_overnet then begin
514 let sock = TcpServerSocket.create
515 "overnet client server"
516 (Ip.to_inet_addr !!client_bind_addr)
517 (!!overnet_port)
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"
526 with e ->
527 lprintf_nl "[Overnet] Could not assign TCP port %d for Overnet" !!overnet_port;
528 tcp_sock := None
531 let disable () =
532 disable ();
533 (match !tcp_sock with
534 None -> ()
535 | Some sock ->
536 tcp_sock := None;
537 TcpServerSocket.close sock Closed_by_user);