CryptoPP: drop unnecessary caml/config.h include, fix #86
[mldonkey.git] / src / networks / donkey / donkeyProtoUdp.ml
blob75ac62ed6513ee396294ea81a420dbc0e369f936
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 LittleEndian
23 open AnyEndian
25 open CommonTypes
26 open CommonGlobals
27 open CommonOptions
29 open DonkeyTypes
30 open DonkeyMftp
31 open Int64ops
33 module QueryReplyUdp = struct
35 type t = tagged_file list
37 let names_of_tag = file_common_tags
39 let get_file s pos =
40 let md4 = get_md4 s pos in
41 let ip = get_ip s (pos + 16) in
42 let port = get_port s (pos + 20) in
43 let tags, pos = get_tags s (pos+22) names_of_tag in
44 let file = {
45 f_md4 = md4;
46 f_ip = ip;
47 f_port = port;
48 f_tags = tags;
49 } in
50 file, pos
52 let parse len s =
53 let rec iter pos list =
54 if pos < len then
55 let file, pos = get_file s pos in
56 let pos = pos + 2 in
57 iter pos (file :: list)
58 else List.rev list
60 iter 1 []
62 let bprint oc t =
63 Printf.bprintf oc "FOUND:\n";
64 List.iter (fun t ->
65 Printf.bprintf oc "%s\n" (Md4.to_string t.f_md4);
66 Printf.bprintf oc "%s\n" (Ip.to_string t.f_ip);
67 Printf.bprintf oc "%d\n" t.f_port;
68 Printf.bprintf oc "TAGS:\n";
69 bprint_tags oc t.f_tags;
70 Printf.bprintf oc "\n"
71 ) t
73 let write buf t =
74 List.iter (fun file ->
75 buf_md4 buf file.f_md4;
76 buf_ip buf file.f_ip;
77 buf_port buf file.f_port;
78 buf_tags buf file.f_tags names_of_tag
79 ) t
81 end
83 module QueryCallUdp = struct
84 type t = {
85 ip : Ip.t;
86 port : int;
87 id : int64;
90 let parse len s =
91 let ip = get_ip s 1 in
92 let port = get_port s 5 in
93 let id = id_of_ip (get_ip s 7) in
94 { ip = ip; port = port; id = id; }
96 let bprint oc t =
97 Printf.bprintf oc "QueryCall %s : %d --> %Ld\n" (Ip.to_string t.ip)
98 t.port t.id
100 let write buf t =
101 buf_ip buf t.ip;
102 buf_port buf t.port;
103 buf_ip buf (ip_of_id t.id)
107 module PingServerUdp = struct (* client -> serveur pour identification ? *)
108 type t = int64
110 let parse len s =
112 get_uint64_32 s 1 (*, get_int8 s 2, get_int8 s 3*)
113 with _ -> 0L
115 let bprint oc t =
116 Printf.bprintf oc "PING %s\n" (Int64.to_string t)
118 let write buf t =
119 buf_int64_32 buf t
121 (* let bprint oc (t1,t2,t3) =
122 Printf.bprintf oc "MESSAGE 150 UDP %d %d %d\n" t1 t2 t3*)
124 (*let write buf (t1,t2,t3) =
125 buf_int8 buf t1;
126 buf_int8 buf t2;
127 buf_int8 buf t3;*)
131 module PingServerReplyUdp = struct (* reponse du serveur a 150 *)
133 type t = {
134 challenge : int64;
135 users : int64;
136 files : int64;
137 soft_limit : int64 option;
138 hard_limit : int64 option;
139 max_users : int64 option;
140 lowid_users : int64 option;
141 get_sources : bool;
142 get_files : bool;
143 newtags : bool;
144 unicode : bool;
145 get_sources2 : bool;
146 largefiles : bool;
147 udp_obfuscation : bool;
148 tcp_obfuscation : bool;
151 let parse len s =
152 let challenge = get_uint64_32 s 1 in
153 let users = get_uint64_32 s 5 in
154 let files = get_uint64_32 s 9 in
155 let max_users = if len >= 17 then Some (get_uint64_32 s 13) else None in
156 let soft_limit = if len >= 21 then Some (get_uint64_32 s 17) else None in
157 let hard_limit = if len >= 25 then Some (get_uint64_32 s 21) else None in
158 let flags = if len >= 29 then get_int s 25 else 0 in
159 let lowid_users = if len >= 33 then Some (get_uint64_32 s 29) else None in
162 challenge = challenge;
163 users = users;
164 files = files;
165 soft_limit = soft_limit;
166 hard_limit = hard_limit;
167 max_users = max_users;
168 lowid_users = lowid_users;
169 get_sources = 0x01 land flags = 0x01;
170 get_files = 0x02 land flags = 0x02;
171 newtags = 0x08 land flags = 0x08;
172 unicode = 0x10 land flags = 0x10;
173 get_sources2 = 0x20 land flags = 0x20;
174 largefiles = 0x100 land flags = 0x100;
175 udp_obfuscation = 0x200 land flags = 0x200;
176 tcp_obfuscation = 0x200 land flags = 0x200;
179 let bprint oc t =
180 Printf.bprintf oc "PING REPLY\n";
181 Printf.bprintf oc " %Ld users %Ld files\n" t.users t.files;
182 (match t.soft_limit with Some x -> Printf.bprintf oc " Soft limit: %Ld\n" x | None -> ());
183 (match t.hard_limit with Some x -> Printf.bprintf oc " Hard limit: %Ld\n" x | None -> ());
184 (match t.max_users with Some x -> Printf.bprintf oc " Max nusers: %Ld\n" x | None -> ());
185 (match t.lowid_users with Some x -> Printf.bprintf oc " LowId nusers: %Ld\n" x | None -> ());
186 Printf.bprintf oc " get_sources %b, get_files %b, newtags %b, unicode %b, get_sources2 %b, largefiles %b, udp_obfuscation %b, tcp_obfuscation %b"
187 t.get_sources t.get_files t.newtags t.unicode t.get_sources2 t.largefiles t.udp_obfuscation t.tcp_obfuscation
189 let write buf t =
190 buf_int64_32 buf t.challenge;
191 buf_int64_32 buf t.users;
192 buf_int64_32 buf t.files;
193 (match t.soft_limit, t.hard_limit, t.max_users with
194 None, None, None -> ()
195 | _ ->
196 buf_int64_32 buf (
197 match t.soft_limit with Some x -> x | None -> 0L);
198 buf_int64_32 buf (
199 match t.hard_limit with Some x -> x | None -> 0L);
200 buf_int64_32 buf (
201 match t.max_users with Some x -> x | None -> 0L)
205 module ServerDescUdp = struct
206 type t = int64
208 let invalid_len = Int64.of_int 0xF0FF
210 let parse len s = Int64.of_string s
212 let bprint b t =
213 Printf.bprintf b "ServerDescUdpReq\n"
216 // eserver 16.45+ supports a new OP_SERVER_DESC_RES answer, if the OP_SERVER_DESC_REQ contains a uint32
217 // challenge, the server returns additional info with OP_SERVER_DESC_RES. To properly distinguish the
218 // old and new OP_SERVER_DESC_RES answer, the challenge has to be selected carefully. The first 2 bytes
219 // of the challenge (in network byte order) MUST NOT be a valid string-len-int16!
222 let write buf t =
223 buf_int64_32 buf t
227 module ServerDescReplyUdp = struct
228 type t = {
229 name : string;
230 desc : string;
231 tags : tag list;
232 challenge : int64;
235 let names_of_tag = [
236 "\001", Field_KNOWN "servername";
237 "\011", Field_KNOWN "description";
238 "\012", Field_KNOWN "ping";
239 "\013", Field_KNOWN "fail";
240 "\014", Field_KNOWN "preference";
241 "\015", Field_KNOWN "port";
242 "\016", Field_KNOWN "ip";
243 "\133", Field_KNOWN "dynip";
244 "\135", Field_KNOWN "maxusers";
245 "\136", Field_KNOWN "softfiles";
246 "\137", Field_KNOWN "hardfiles";
247 "\144", Field_KNOWN "lastping";
248 "\145", Field_KNOWN "version";
249 "\146", Field_KNOWN "udpflags";
250 "\147", Field_KNOWN "auxportslist";
251 "\148", Field_KNOWN "lowidusers";
254 let parse1 len s challenge =
255 let name, pos = get_string s 1 in
256 let desc, pos = get_string s pos in
258 tags = [];
259 name = name;
260 desc = desc;
261 challenge = challenge;
264 let parse2 len s challenge =
265 let stags,pos = get_tags s 5 names_of_tag in
266 let name = ref "" in
267 let desc = ref "" in
268 List.iter (fun tag ->
269 match tag with
270 | { tag_name = Field_KNOWN "servername"; tag_value = String v } ->
271 name := v
272 | { tag_name = Field_KNOWN "description"; tag_value = String v } ->
273 desc := v
274 | _ -> ()
275 ) stags;
277 tags = stags;
278 name = !name;
279 desc = !desc;
280 challenge = challenge;
283 let parse len s =
284 let challenge = get_uint64_32 s 1 in
285 let test = right64 (left64 challenge 48) 48 in
286 let f = if test = ServerDescUdp.invalid_len then parse2 else parse1 in
287 f len s challenge
289 let bprint b t =
290 Printf.bprintf b "ServerDescReplyUdpReq\n";
291 Printf.bprintf b "name : %s\n" t.name;
292 Printf.bprintf b "desc : %s\n" t.desc
294 let write buf t =
295 buf_string buf t.name;
296 buf_string buf t.desc
300 module ServerListUdp = struct
301 type t = {
302 ip : Ip.t;
305 let parse len s =
307 let ip = get_ip s 1 in
309 ip = ip;
311 with _ ->
313 ip = Ip.null
316 let bprint b t =
317 Printf.bprintf b "ServerListUdp %s\n" (Ip.to_string t.ip)
319 let write buf t =
320 buf_ip buf t.ip
324 module QueryServersUdp = DonkeyProtoServer.QueryServers
325 module QueryServersReplyUdp = DonkeyProtoServer.QueryServersReply
326 module QueryLocationUdp = struct
328 type t = Md4.t list
330 let parse len s =
331 let rec iter pos list =
332 if pos < len then
333 iter (pos+16) (get_md4 s pos :: list)
334 else
335 List.rev list
337 iter 1 []
339 let bprint b t =
340 Printf.bprintf b "UDP QUERY LOCATIONS: ";
341 List.iter (fun md4 -> Printf.bprintf b "%s " (Md4.to_string md4)) t
343 let write buf t =
344 List.iter (fun md4 -> buf_md4 buf md4) t
347 module QueryLocationUdpReq2 = struct
349 type t = (Md4.t * Int64.t) list
351 (* We never parse this anyway, it is outgoing only *)
352 let parse len s =
353 let rec iter pos list =
354 if pos < len then
355 iter (pos+20) ( (get_md4 s pos, get_uint64_32 s (pos+16)) :: list)
356 else
357 List.rev list
359 iter 1 []
361 let bprint b t =
362 Printf.bprintf b "UDP QUERY LOCATIONS2: ";
363 List.iter (fun (md4,size) -> Printf.bprintf b "%s|%Ld " (Md4.to_string md4) size) t;
364 Printf.bprintf b "\n"
366 let write buf t =
367 List.iter (fun (md4,size) -> buf_md4 buf md4; buf_int64_32 buf size) t
371 module QueryLocationReplyUdp = struct
372 open DonkeyProtoServer.QueryLocationReply
374 type t = DonkeyProtoServer.QueryLocationReply.t list
376 let parse len s =
377 let rec iter_len pos list =
378 if pos < len then
379 let md4 = get_md4 s pos in
380 let n = get_uint8 s (pos+16) in
381 let rec iter i =
382 if i = n then [] else
383 let ip = get_ip s (pos+17 + i * 6) in
384 let port = get_port s (pos+21+ i * 6) in
385 { ip = ip; port = port; } :: (iter (i+1))
387 let locs = iter 0 in
388 let pos = pos+17+6*n + 2 in
389 iter_len pos ({ locs =locs; md4 = md4 } :: list)
390 else
391 List.rev list
393 iter_len 1 []
395 let bprint b t =
396 Printf.bprintf b "UDP LOCATION: %d\n" (List.length t);
397 List.iter (fun t ->
398 Printf.bprintf b " of %s:\n" (Md4.to_string t.md4);
399 List.iter (fun l ->
400 Printf.bprintf b "%s:%d " (Ip.to_string l.ip) l.port;
401 ) t.locs;
402 Printf.bprintf b "\n") t
404 let write buf t =
405 List.iter (fun t ->
406 buf_md4 buf t.md4;
407 buf_int8 buf (List.length t.locs);
408 List.iter (fun l ->
409 buf_ip buf l.ip;
410 buf_port buf l.port;
411 ) t.locs
417 module QueryUdp = DonkeyProtoServer.Query
420 let parse len s =
421 let rec iter list pos =
422 if len > pos then
423 let t, pos = parse_query s pos in
424 iter (t :: list) pos
425 else List.rev list
427 iter [] 1
429 let bprint b t =
430 Printf.bprintf b "UDP QUERY: %d\n" (List.length t);
431 List.iter (bprint_query b) t
433 let write buf t =
434 List.iter write t
439 module QueryIDReplyUdp = DonkeyProtoServer.QueryIDReply
441 type t =
442 | QueryServersUdpReq of QueryServersUdp.t
443 | QueryServersReplyUdpReq of QueryServersReplyUdp.t
445 | PingServerUdpReq of PingServerUdp.t
446 | PingServerReplyUdpReq of PingServerReplyUdp.t
448 | QueryLocationUdpReq2 of QueryLocationUdpReq2.t
449 | QueryLocationUdpReq of QueryLocationUdp.t
450 | QueryLocationReplyUdpReq of QueryLocationReplyUdp.t
452 | QueryReplyUdpReq of QueryReplyUdp.t
453 | QueryUdpReq of CommonTypes.query
454 | QueryMultipleUdpReq of CommonTypes.query
455 | QueryCallUdpReq of QueryCallUdp.t
456 | QueryIDReplyUdpReq of QueryIDReplyUdp.t
457 | FileGroupInfoUdpReq of QueryLocationReplyUdp.t
458 | ServerDescUdpReq of ServerDescUdp.t
459 | ServerDescReplyUdpReq of ServerDescReplyUdp.t
460 | ServerListUdpReq of ServerListUdp.t
462 | EmuleReaskFilePingUdpReq of Md4.t
463 | EmuleReaskAckUdpReq of Md4.t
464 | EmuleFileNotFoundUdpReq
465 | EmuleQueueFullUdpReq
466 | EmulePortTestReq
468 | UnknownUdpReq of int * string
470 let parse magic s =
472 let len = String.length s in
473 if len = 0 then raise Not_found;
474 let opcode = int_of_char (s.[0]) in
475 (* lprintf "opcode: %d" opcode; lprint_newline (); *)
476 match opcode with
477 | 150 -> PingServerUdpReq (PingServerUdp.parse len s)
478 | 151 -> PingServerReplyUdpReq (PingServerReplyUdp.parse len s)
480 | 146 -> QueryMultipleUdpReq (QueryUdp.parse len s)
481 | 152 -> QueryUdpReq (QueryUdp.parse len s)
482 | 153 -> QueryReplyUdpReq (QueryReplyUdp.parse len s)
483 | 154 -> QueryLocationUdpReq (QueryLocationUdp.parse len s)
484 | 155 -> QueryLocationReplyUdpReq (QueryLocationReplyUdp.parse len s)
485 | 156 -> QueryCallUdpReq (QueryCallUdp.parse len s)
486 | 160 -> QueryServersUdpReq (QueryServersUdp.parse len s)
487 | 161 -> QueryServersReplyUdpReq (QueryServersReplyUdp.parse len s)
488 | 162 -> ServerDescUdpReq (ServerDescUdp.parse len s)
489 | 163 -> ServerDescReplyUdpReq (ServerDescReplyUdp.parse len s)
490 | 164 -> ServerListUdpReq (ServerListUdp.parse len s)
492 | 144 -> EmuleReaskFilePingUdpReq (get_md4 s 1)
493 | 145 -> EmuleReaskAckUdpReq (get_md4 s 1)
494 (* | 146 -> EmuleFileNotFoundUdpReq *)
495 | 147 -> EmuleQueueFullUdpReq
496 | 254 -> EmulePortTestReq
498 | _ -> raise Exit
499 with
500 e ->
501 if !verbose_unknown_messages then begin lprintf "Unknown UDP request:\n"; dump s end;
502 UnknownUdpReq (magic, s)
504 let print t =
505 let b = Buffer.create 100 in
506 begin
507 match t with
509 | QueryUdpReq t -> QueryUdp.bprint b t
510 | QueryMultipleUdpReq t -> QueryUdp.bprint b t
511 | QueryReplyUdpReq t -> QueryReplyUdp.bprint b t
512 | QueryLocationUdpReq2 t -> QueryLocationUdpReq2.bprint b t
513 | QueryLocationUdpReq t -> QueryLocationUdp.bprint b t
514 | QueryLocationReplyUdpReq t
515 | FileGroupInfoUdpReq t -> QueryLocationReplyUdp.bprint b t
516 | QueryCallUdpReq t -> QueryCallUdp.bprint b t
518 | QueryServersUdpReq t -> QueryServersUdp.bprint b t
519 | QueryServersReplyUdpReq t -> QueryServersReplyUdp.bprint b t
520 | QueryIDReplyUdpReq t -> QueryIDReplyUdp.bprint b t
522 | PingServerUdpReq t -> PingServerUdp.bprint b t
523 | PingServerReplyUdpReq t -> PingServerReplyUdp.bprint b t
524 | ServerDescUdpReq t -> ServerDescUdp.bprint b t
525 | ServerDescReplyUdpReq t -> ServerDescReplyUdp.bprint b t
526 | ServerListUdpReq t -> ServerListUdp.bprint b t
528 | EmuleReaskFilePingUdpReq md4 ->
529 Printf.bprintf b "EmuleReaskFilePingUdpReq %s" (Md4.to_string md4)
530 | EmuleReaskAckUdpReq md4 ->
531 Printf.bprintf b "EmuleReaskAckUdpReq %s" (Md4.to_string md4)
532 | EmuleFileNotFoundUdpReq ->
533 Printf.bprintf b "EmuleFileNotFoundUdpReq"
534 | EmuleQueueFullUdpReq ->
535 Printf.bprintf b "EmuleQueueFullUdpReq"
536 | EmulePortTestReq ->
537 Printf.bprintf b "EmulePortTestReq"
539 | UnknownUdpReq (magic, s) ->
540 Printf.bprintf b "UnknownReq magic %d\n" magic;
541 bdump b s;
542 end;
543 Printf.bprintf b "\n";
544 Buffer.contents b
546 let write buf t =
547 match t with
549 | UnknownUdpReq (magic, s) ->
550 buf_int8 buf magic;
551 Buffer.add_string buf s
553 | EmuleReaskFilePingUdpReq md4 ->
554 buf_int8 buf 197;
555 buf_int8 buf 145;
556 buf_md4 buf md4
558 | EmuleReaskAckUdpReq md4 ->
559 buf_int8 buf 197;
560 buf_int8 buf 145;
561 buf_md4 buf md4
563 | EmuleFileNotFoundUdpReq ->
564 buf_int8 buf 197;
565 buf_int8 buf 146
567 | EmuleQueueFullUdpReq ->
568 buf_int8 buf 197;
569 buf_int8 buf 147
571 | _ ->
572 buf_int8 buf 227;
573 match t with
574 | QueryServersUdpReq t ->
575 buf_int8 buf 160;
576 QueryServersUdp.write buf t
577 | QueryServersReplyUdpReq t ->
578 buf_int8 buf 161;
579 QueryServersReplyUdp.write buf t
581 | ServerDescUdpReq t ->
582 buf_int8 buf 162;
583 ServerDescUdp.write buf t
584 | ServerDescReplyUdpReq t ->
585 buf_int8 buf 163;
586 ServerDescReplyUdp.write buf t
587 | ServerListUdpReq t ->
588 buf_int8 buf 164;
589 ServerListUdp.write buf t
591 | PingServerUdpReq t ->
592 buf_int8 buf 150;
593 PingServerUdp.write buf t
594 | PingServerReplyUdpReq t ->
595 buf_int8 buf 151;
596 PingServerReplyUdp.write buf t
598 | QueryLocationUdpReq t ->
599 buf_int8 buf 154;
600 QueryLocationUdp.write buf t
601 | QueryLocationUdpReq2 t ->
602 buf_int8 buf 148;
603 QueryLocationUdpReq2.write buf t
604 | QueryLocationReplyUdpReq t ->
605 buf_int8 buf 155;
606 QueryLocationReplyUdp.write buf t
607 | QueryUdpReq t ->
608 buf_int8 buf 152;
609 QueryUdp.write buf t
610 | QueryMultipleUdpReq t ->
611 buf_int8 buf 146;
612 QueryUdp.write buf t
613 | QueryReplyUdpReq t ->
614 buf_int8 buf 153;
615 QueryReplyUdp.write buf t
616 | QueryCallUdpReq t ->
617 buf_int8 buf 156;
618 QueryCallUdp.write buf t
619 | FileGroupInfoUdpReq t ->
620 buf_int8 buf 251;
621 QueryLocationReplyUdp.write buf t
623 | QueryIDReplyUdpReq t ->
624 buf_int8 buf 53;
625 QueryIDReplyUdp.write buf t
627 | EmulePortTestReq ->
628 buf_int8 buf 2;
629 buf_int8 buf 0;
630 buf_int8 buf 0;
631 buf_int8 buf 0;
632 buf_int8 buf 0xfe;
633 buf_int8 buf 0x31
635 | EmuleQueueFullUdpReq
636 | EmuleFileNotFoundUdpReq
637 | EmuleReaskAckUdpReq _
638 | EmuleReaskFilePingUdpReq _
639 | UnknownUdpReq _ -> assert false