patch #7310
[mldonkey.git] / src / networks / donkey / donkeyProtoServer.ml
blob0a8e907a272e0afee4b0db598a40bae07e4e0964
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 AnyEndian
21 open Printf2
22 open Md4
23 open Autoconf
24 open LittleEndian
25 open CommonTypes
26 open CommonGlobals
28 open DonkeyTypes
29 open DonkeyMftp
31 module Connect = struct
32 type t = {
33 md4 : Md4.t;
34 ip: Ip.t;
35 port: int;
36 tags : tag list;
39 let names_of_tag =
41 "\001", Field_KNOWN "name"; (* CT_NAME 0x01 *)
42 "\017", Field_KNOWN "version"; (* CT_VERSION 0x11 *)
43 "\032", Field_KNOWN "extended"; (* CT_SERVER_FLAGS 0x20 *)
44 "\251", Field_KNOWN "emule_version"; (* CT_EMULE_VERSION 0xfb *)
47 let parse len s =
48 let md4 = get_md4 s 1 in
49 let ip = get_ip s 17 in
50 let port = get_port s 21 in
51 (* lprintf "port: %d\n" port;*)
52 let tags, pos = DonkeyMftp.get_tags s 23 names_of_tag in
54 md4 = md4;
55 ip = ip;
56 port = port;
57 tags = tags;
60 let print t =
61 lprintf_nl "CONNECT:";
62 lprintf_nl "MD4: %s" (Md4.to_string t.md4);
63 lprintf_nl "ip: %s" (Ip.to_string t.ip);
64 lprintf_nl "port: %d" t.port;
65 lprintf "tags: ";
66 print_tags t.tags;
67 lprint_newline ()
69 let bprint oc t =
70 Printf.bprintf oc "CONNECT:\n";
71 Printf.bprintf oc "%s\n" (Md4.to_string t.md4);
72 Printf.bprintf oc "%s\n" (Ip.to_string t.ip);
73 Printf.bprintf oc "%d\n" t.port;
74 Printf.bprintf oc "TAGS:\n";
75 bprint_tags oc t.tags;
76 Printf.bprintf oc "\n"
78 let write buf t =
79 buf_md4 buf t.md4;
80 buf_ip buf t.ip;
81 buf_port buf t.port;
82 buf_tags buf t.tags names_of_tag
83 end
85 module ChatRooms = struct (* request: 57 *)
87 (* example:
88 ascii [ 9(3)(4)(0) M a i n(0)(0)(2)(0)(5)(0) M u s i c(0)(0)(3)(0)(3)(0) A r t(0)(0)(4)(0)]
91 type channel = {
92 name : string;
93 number : int;
96 type t = channel list
98 let parse len s =
99 let nchans = get_uint8 s 1 in
100 let rec iter s pos nchans =
101 if nchans = 0 then [] else
102 let name, pos = get_string s pos in
103 let number = get_int s pos in
104 { name = name; number = number; } :: (iter s (pos+4) (nchans-1))
106 iter s 2 nchans
108 let print t =
109 lprintf_nl "CHANNELS:";
110 List.iter (fun c ->
111 lprintf_nl " %s: %d" c.name c.number;
114 let bprint oc t =
115 Printf.bprintf oc "CHANNELS:\n";
116 List.iter (fun c ->
117 Printf.bprintf oc " %s: %d\n" c.name c.number;
120 let write buf t =
121 buf_int buf (List.length t);
122 List.iter (fun c ->
123 buf_string buf c.name;
124 buf_int buf c.number) t
128 module SetID = struct
129 type t = {
130 ip : Ip.t;
131 port : int option;
132 zlib : bool;
133 newtags : bool;
134 unicode : bool;
135 related_search : bool;
136 tag_integer : bool;
137 largefiles : bool;
138 udp_obfuscation : bool;
139 tcp_obfuscation : bool;
142 let parse len s =
143 let flags = get_int s 5 in
145 ip = get_ip s 1;
146 port = if len <= 9 then None else Some (get_int s 9);
147 zlib = 0x01 land flags = 0x01;
148 newtags = 0x08 land flags = 0x08;
149 unicode = 0x10 land flags = 0x10;
150 related_search = 0x40 land flags = 0x40;
151 tag_integer = 0x80 land flags = 0x80;
152 largefiles = 0x100 land flags = 0x100;
153 udp_obfuscation = 0x200 land flags = 0x200;
154 tcp_obfuscation = 0x400 land flags = 0x400;
157 let print t =
158 lprintf "SET_ID: %s id: %s %s\n"
159 (if t.zlib then "Zlib" else "")
160 (Ip.to_string t.ip)
161 (match t.port with
162 None -> Printf.sprintf ""
163 | Some port ->
164 Printf.sprintf "Real Port: %d" port);
165 lprintf "SET_ID: newtags %b unicode %b related_search %b tag_integer %b largefiles %b udp_obfuscation %b tcp_obfuscation %b"
166 t.newtags t.unicode t.related_search t.tag_integer t.largefiles t.udp_obfuscation t.tcp_obfuscation
168 let bprint oc t =
169 Printf.bprintf oc "SET_ID: %s\n" (if t.zlib then "Zlib" else "");
170 Printf.bprintf oc "SET_ID id: %s\n" (Ip.to_string t.ip);
171 Printf.bprintf oc "SET_ID: newtags %b unicode %b related_search %b tag_integer %b largefiles %b udp_obfuscation %b tcp_obfuscation %b\n"
172 t.newtags t.unicode t.related_search t.tag_integer t.largefiles t.udp_obfuscation t.tcp_obfuscation
174 let write buf t =
175 if t.zlib then buf_int buf 1;
176 buf_ip buf t.ip
180 let unit = ()
182 module QueryServerList = struct
183 type t = unit
185 let parse len s = ()
187 let print t =
188 lprintf_nl "QUERY_SERVER_LIST:"
190 let bprint oc t =
191 Printf.bprintf oc "QUERY_SERVER_LIST\n"
193 let write (buf: Buffer.t) (t: t) = unit
195 let t = (() : t)
198 module Message = struct
199 type t = string
201 let parse len s =
202 let v, pos = get_string s 1 in
205 let print t =
206 lprintf_nl "MESSAGE:";
207 lprintf_nl "message = \"%s\"" (String.escaped t)
209 let bprint oc t =
210 Printf.bprintf oc "MESSAGE:\n";
211 Printf.bprintf oc "%s\n" (String.escaped t)
213 let write buf t =
214 buf_string buf t
217 module Share = struct
219 type t = tagged_file list
221 let names_of_tag = file_common_tags
223 let rec get_files s pos n =
224 if n = 0 then [], pos else
225 let md4 = get_md4 s pos in
226 let ip = get_ip s (pos + 16) in
227 let port = get_port s (pos + 20) in
228 let tags, pos = get_tags s (pos+22) names_of_tag in
229 let file = {
230 f_md4 = md4;
231 f_ip = ip;
232 f_port = port;
233 f_tags = tags;
234 } in
235 let files, pos = get_files s pos (n-1) in
236 file :: files, pos
238 let parse len s =
239 let n = get_int s 1 in
240 let files, pos = get_files s 5 n in
241 files
243 let print t =
244 lprintf_nl "SHARED:";
245 List.iter (fun t ->
246 lprintf_nl "FILE:";
247 lprintf_nl " MD4: %s" (Md4.to_string t.f_md4);
248 lprintf_nl " ip: %s" (Ip.to_string t.f_ip);
249 lprintf_nl " port: %d" t.f_port;
250 lprintf " tags: ";
251 print_tags t.f_tags;
252 lprint_newline ();) t
254 let bprint oc t =
255 Printf.bprintf oc "SHARED:\n";
256 List.iter (fun t ->
257 Printf.bprintf oc "FILE:\n";
258 Printf.bprintf oc " %s\n" (Md4.to_string t.f_md4);
259 Printf.bprintf oc "%s\n" (Ip.to_string t.f_ip);
260 Printf.bprintf oc "%d\n" t.f_port;
261 Printf.bprintf oc "TAGS:\n";
262 bprint_tags oc t.f_tags;
263 Printf.bprintf oc "\n"
266 let rec write_files buf files =
267 match files with
268 [] -> ()
269 | file :: files ->
270 buf_md4 buf file.f_md4;
271 buf_ip buf file.f_ip;
272 buf_port buf file.f_port;
273 buf_tags buf file.f_tags names_of_tag;
274 write_files buf files
276 let write buf t =
277 buf_int buf (List.length t);
278 write_files buf t
280 let rec write_files_max buf files nfiles max_len =
281 let prev_len = Buffer.length buf in
282 match files with
283 [] -> nfiles, prev_len
284 | file :: files ->
285 buf_md4 buf file.f_md4;
286 buf_ip buf file.f_ip;
287 buf_port buf file.f_port;
288 buf_tags buf file.f_tags names_of_tag;
289 if Buffer.length buf < max_len then
290 write_files_max buf files (nfiles+1) max_len
291 else
292 nfiles, prev_len
296 module Info = struct
297 type t = int * int
299 let parse len s =
301 let users = get_int s 1 in
302 let files = get_int s 5 in
303 users, files
305 let print (users, files) =
306 lprintf_nl "INFO:";
307 lprintf_nl "users: %d files: %d" users files
309 let bprint oc (users, files) =
310 Printf.bprintf oc "INFO:\n";
311 Printf.bprintf oc "%d\n %d\n" users files
313 let write buf (users, files) =
314 buf_int buf users;
315 buf_int buf files
318 module ServerList = struct
319 type server = {
320 ip : Ip.t;
321 port : int;
324 type t = server list
326 let parse len s =
327 let n = get_uint8 s 1 in
328 let rec iter i =
329 if i = n then [] else
330 let ip = get_ip s (2 + i * 6) in
331 let port = get_port s (6+ i * 6) in
332 { ip = ip; port = port; } :: (iter (i+1))
334 iter 0
336 let print t =
337 lprintf_nl "SERVER LIST";
338 List.iter (fun l ->
339 lprintf_nl " %s : %d" (Ip.to_string l.ip) l.port;
342 let bprint oc t =
343 Printf.bprintf oc "SERVER LIST\n";
344 List.iter (fun l ->
345 Printf.bprintf oc "%s:%d\n" (Ip.to_string l.ip) l.port;
348 let write buf t =
349 buf_int8 buf (List.length t);
350 List.iter (fun l ->
351 buf_ip buf l.ip;
352 buf_int16 buf l.port
356 module ServerInfo = struct
357 type t = {
358 md4 : Md4.t;
359 ip: Ip.t;
360 port: int;
361 tags : tag list;
364 let names_of_tag =
366 "\001", Field_KNOWN "name";
367 "\011", Field_KNOWN "description";
370 let parse len s =
371 let md4 = get_md4 s 1 in
372 let ip = get_ip s 17 in
373 let port = get_port s 21 in
374 (* lprintf "port: %d\n" port; *)
375 let tags, pos = get_tags s 23 names_of_tag in
377 md4 = md4;
378 ip = ip;
379 port = port;
380 tags = tags;
383 let print t =
384 lprintf_nl "SERVER INFO:";
385 lprintf_nl "MD4: %s" (Md4.to_string t.md4);
386 lprintf_nl "ip: %s" (Ip.to_string t.ip);
387 lprintf_nl "port: %d" t.port;
388 lprintf "tags: ";
389 print_tags t.tags
391 let bprint oc t =
392 Printf.bprintf oc "SERVER INFO:\n";
393 Printf.bprintf oc "%s\n" (Md4.to_string t.md4);
394 Printf.bprintf oc "%s\n" (Ip.to_string t.ip);
395 Printf.bprintf oc "%d\n" t.port;
396 Printf.bprintf oc "TAGS:\n";
397 bprint_tags oc t.tags;
398 Printf.bprintf oc "\n"
400 let write buf t =
401 buf_md4 buf t.md4;
402 buf_ip buf t.ip;
403 buf_port buf t.port;
404 buf_tags buf t.tags names_of_tag
408 module QueryReply = struct
410 type t = tagged_file list
412 let names_of_tag = file_common_tags
414 let rec get_files s pos n =
415 if n = 0 then [], pos else
417 let md4 = get_md4 s pos in
418 let ip = get_ip s (pos + 16) in
419 let port = get_port s (pos + 20) in
420 let tags, pos = get_tags s (pos+22) names_of_tag in
421 let file = {
422 f_md4 = md4;
423 f_ip = ip;
424 f_port = port;
425 f_tags = tags;
426 } in
427 let files, pos = get_files s pos (n-1) in
428 file :: files, pos
429 with _ ->
430 raise Not_found
432 let get_replies s pos =
433 let n = get_int s pos in
434 let files, pos = get_files s (pos+4) n in
435 files
437 let parse len s = get_replies s 1
439 let print t =
440 lprintf_nl "FOUND:";
441 List.iter (fun t ->
442 lprintf_nl "FILE:";
443 lprintf_nl " MD4: %s" (Md4.to_string t.f_md4);
444 lprintf_nl " ip: %s" (Ip.to_string t.f_ip);
445 lprintf_nl " port: %d" t.f_port;
446 lprintf " tags: ";
447 print_tags t.f_tags;
448 lprint_newline ()) t
450 let bprint oc t =
451 Printf.bprintf oc "FOUND:\n";
452 List.iter (fun t ->
453 Printf.bprintf oc "FILE:\n";
454 Printf.bprintf oc "%s\n" (Md4.to_string t.f_md4);
455 Printf.bprintf oc "%s\n" (Ip.to_string t.f_ip);
456 Printf.bprintf oc "%d\n" t.f_port;
457 Printf.bprintf oc "TAGS:\n";
458 bprint_tags oc t.f_tags;
459 Printf.bprintf oc "\n"
462 let rec write_files buf files =
463 match files with
464 [] -> ()
465 | file :: files ->
466 buf_md4 buf file.f_md4;
467 buf_ip buf file.f_ip;
468 buf_port buf file.f_port;
469 buf_tags buf file.f_tags names_of_tag;
470 write_files buf files
472 let write_replies buf t =
473 buf_int buf (List.length t);
474 write_files buf t
476 let write buf t =
477 write_replies buf t;
478 buf_int8 buf 0
482 let unit = ()
483 module NoArg = functor(M: sig val m : string end) -> (struct
484 type t = unit
486 let parse len s = ()
488 let print t =
489 lprintf_nl "%s:" M.m
491 let write (buf: Buffer.t) (t: t) = unit
493 let t = (() : t)
494 end : sig
495 type t
496 val parse : int -> string -> t
497 val print : t -> unit
498 val write : Buffer.t -> t -> unit
499 val t :t
503 module QueryNext = NoArg(struct let m = "QUERY NEXT" end)
505 module Query = struct (* request 22 *)
507 (* TODO : build a complete list of tags used in these queries and their correct
508 translation, i.e. Field_Artist = "Artist" instead of "artist" *)
510 let names_of_tag =
512 "\002", Field_Size;
513 "\003", Field_Type;
514 "\004", Field_Format;
515 "\021", Field_Availability;
516 "\048", Field_Completesources;
519 let rec parse_query s pos =
520 let t = get_uint8 s pos in
521 match t with
522 0 ->
523 let t = get_uint8 s (pos+1) in
524 begin
525 match t with
526 0 ->
527 let q1, pos = parse_query s (pos + 2) in
528 let q2, pos = parse_query s pos in
529 QAnd (q1,q2), pos
530 | 1 ->
531 let q1, pos = parse_query s (pos + 2) in
532 let q2, pos = parse_query s pos in
533 QOr (q1,q2), pos
534 | 2 ->
535 let q1, pos = parse_query s (pos + 2) in
536 let q2, pos = parse_query s pos in
537 QAndNot (q1,q2), pos
538 |_ -> failwith "Unknown QUERY operator"
540 | 1 -> let s, pos = get_string s (pos + 1) in QHasWord s, pos
541 | 2 ->
542 let field, pos = get_string s (pos + 1) in
543 let name, pos = get_string s pos in
544 let name = try
545 List.assoc name names_of_tag
546 with _ -> field_of_string name
549 QHasField (name, field), pos
551 | 3 ->
552 let field = get_uint64_32 s (pos + 1) in
553 let minmax = get_uint8 s (pos + 5) in
554 let name, pos = get_string s (pos + 6) in
555 let name = try
556 List.assoc name names_of_tag
557 with _ -> field_of_string name
559 begin
560 match minmax with
561 1 -> QHasMinVal (name, field)
562 | 2 -> QHasMaxVal (name, field)
563 | _ -> failwith "Unknown QUERY minmax"
564 end, pos
565 | 4 -> QHasWord "", pos + 1
566 | _ -> failwith "Unknown QUERY format"
568 let parse len s =
569 let t, pos = parse_query s 1 in t
572 type = "Col" pour voir les collections
573 Fields:
574 "Album" | "Artist" | "Title"
577 let rec print_query t =
578 match t with
579 QOr (q1, q2) ->
580 print_query q1;
581 lprint_string " OR ";
582 print_query q2
583 | QAnd (q1, q2) ->
584 print_query q1;
585 lprint_string " AND ";
586 print_query q2
587 | QAndNot (q1, q2) ->
588 print_query q1;
589 lprint_string " NOT ";
590 print_query q2
591 | QHasWord s ->
592 lprintf "Contains[%s]" s
593 | QHasField (name, field) ->
594 lprintf "Field[%s] = [%s]" (string_of_field name) field
595 | QHasMinVal (name, field) ->
596 lprintf "Field[%s] > [%s]" (string_of_field name) (Int64.to_string field)
597 | QHasMaxVal (name, field) ->
598 lprintf "Field[%s] < [%s]" (string_of_field name) (Int64.to_string field)
599 | QNone ->
600 lprintf "print_query: QNone in query\n";
603 let print t =
604 lprintf "QUERY";
605 print_query t
607 let rec bprint_query oc t =
608 match t with
609 QOr (q1, q2) ->
610 print_query q1;
611 Printf.bprintf oc " OR ";
612 print_query q2
613 | QAnd (q1, q2) ->
614 print_query q1;
615 Printf.bprintf oc " AND ";
616 print_query q2
617 | QAndNot (q1, q2) ->
618 print_query q1;
619 Printf.bprintf oc " NOT ";
620 print_query q2
621 | QHasWord s ->
622 Printf.bprintf oc "Contains[%s]" s
623 | QHasField (name, field) ->
624 Printf.bprintf oc "Field[%s] = [%s]" (string_of_field name) field
625 | QHasMinVal (name, field) ->
626 Printf.bprintf oc "Field[%s] > [%s]" (string_of_field name) (Int64.to_string field)
627 | QHasMaxVal (name, field) ->
628 Printf.bprintf oc "Field[%s] < [%s]" (string_of_field name) (Int64.to_string field)
629 | QNone ->
630 lprintf_nl "print_query: QNone in query";
633 let bprint oc t =
634 Printf.bprintf oc "QUERY:\n";
635 bprint_query oc t;
636 Printf.bprintf oc "\n"
638 let rec write buf t =
639 match t with
640 QOr (q1, q2) ->
641 buf_int8 buf 0;
642 buf_int8 buf 1;
643 write buf q1;
644 write buf q2;
645 | QAnd (q1, q2) ->
646 buf_int8 buf 0;
647 buf_int8 buf 0;
648 write buf q1;
649 write buf q2;
650 | QAndNot (q1, q2) ->
651 buf_int8 buf 0;
652 buf_int8 buf 2;
653 write buf q1;
654 write buf q2;
655 | QHasWord s ->
656 buf_int8 buf 1;
657 buf_string buf s
658 | QHasField (name, field) ->
659 let name = try
660 rev_assoc name names_of_tag
661 with _ -> string_of_field name in
663 buf_int8 buf 2;
664 buf_string buf field;
665 buf_string buf name
667 | QHasMinVal (name, field) ->
669 let name = try
670 rev_assoc name names_of_tag
671 with _ -> string_of_field name
674 buf_int8 buf 3;
675 buf_int64_32 buf field;
676 buf_int8 buf 1;
677 buf_string buf name
679 | QHasMaxVal (name, field) ->
681 let name = try
682 rev_assoc name names_of_tag
683 with _ -> string_of_field name in
685 buf_int8 buf 3;
686 buf_int64_32 buf field;
687 buf_int8 buf 2;
688 buf_string buf name
690 | QNone ->
691 lprintf_nl "print_query: QNone in query";
696 module QueryUsers = struct (* request 26 *)
698 type t = string
700 let parse len s =
701 let targ = get_uint8 s 1 in
702 match targ with
703 4 -> ""
704 | 1 ->
705 let name, pos = get_string s 2 in
706 name
707 | _ ->
708 lprintf_nl "QueryUsers: unknown tag %d" targ;
709 raise Not_found
711 let print t =
712 lprintf_nl "QUERY USERS [%s]" t
714 let bprint oc t =
715 Printf.bprintf oc "QUERY USERS [%s]\n" t
717 let write buf t =
718 if t = "" then
719 buf_int8 buf 4
720 else begin
721 buf_int8 buf 1;
722 buf_string buf t
726 module QueryUsersReply = struct (* request 67 *)
727 type client = {
728 md4 : Md4.t;
729 ip: Ip.t;
730 port: int;
731 tags : tag list;
734 type t = client list
736 let names_of_tag =
738 "\001", Field_KNOWN "name";
739 "\017", Field_KNOWN "version";
740 "\015", Field_KNOWN "port";
743 let rec parse_clients s pos nclients left =
744 if nclients = 0 then List.rev left else
745 let md4 = get_md4 s pos in
746 let ip = get_ip s (pos+16) in
747 let port = get_port s (pos+20) in
748 let tags, pos = get_tags s (pos+22) names_of_tag in
749 parse_clients s pos (nclients-1) (
751 md4 = md4;
752 ip = ip;
753 port = port;
754 tags = tags;
755 } :: left)
757 let parse len s =
758 let nclients = get_int s 1 in
759 parse_clients s 5 nclients []
761 let print t =
762 lprintf_nl "QUERY USERS REPLY:";
763 List.iter (fun t ->
764 lprintf_nl "MD4: %s" (Md4.to_string t.md4);
765 lprintf_nl "ip: %s" (Ip.to_string t.ip);
766 lprintf_nl "port: %d" t.port;
767 lprintf "tags: ";
768 print_tags t.tags;
769 lprint_newline ();) t
771 let bprint oc t =
772 Printf.bprintf oc "QUERY USERS REPLY:\n";
773 List.iter (fun t ->
774 Printf.bprintf oc "%s\n" (Md4.to_string t.md4);
775 Printf.bprintf oc "%s\n" (Ip.to_string t.ip);
776 Printf.bprintf oc "%d\n" t.port;
777 Printf.bprintf oc "TAGS:\n";
778 bprint_tags oc t.tags;
779 Printf.bprintf oc "\n"
782 let write buf t =
783 buf_int buf (List.length t);
784 List.iter (fun t ->
785 buf_md4 buf t.md4;
786 buf_ip buf t.ip;
787 buf_port buf t.port;
788 buf_tags buf t.tags names_of_tag) t
791 module QueryLocation = struct
792 type t = {
793 md4: Md4.t;
794 size: Int64.t;
797 let parse len s =
798 let m = get_md4 s 1 in
800 md4 = m;
801 size = Int64.zero;
804 let print t =
805 lprintf_nl "QUERY LOCATION OF %s [%Ld]" (Md4.to_string t.md4) t.size
807 let bprint oc t =
808 Printf.bprintf oc "QUERY LOCATION OF %s [%Ld]\n" (Md4.to_string t.md4) t.size
810 let write buf t =
811 buf_md4 buf t.md4;
812 if t.size > old_max_emule_file_size then
813 begin
814 buf_int64_32 buf 0L; buf_int64 buf t.size
816 else
817 buf_int64_32 buf t.size
820 module QueryLocationReply = struct
821 type location = {
822 ip : Ip.t;
823 port : int;
826 type t = {
827 md4: Md4.t;
828 locs :location list;
831 let parse len s =
832 let md4 = get_md4 s 1 in
833 let n = get_uint8 s 17 in
834 let rec iter i =
835 if i = n then [] else
836 let ip = get_ip s (18 + i * 6) in
837 let port = get_port s (22+ i * 6) in
838 { ip = ip; port = port; } :: (iter (i+1))
840 let locs = iter 0 in
841 { locs =locs; md4 = md4 }
843 let print t =
844 lprintf_nl "LOCATION OF %s" (Md4.to_string t.md4);
845 List.iter (fun l ->
846 lprintf_nl " %s : %d %s" (Ip.to_string l.ip) l.port
847 (if not (Ip.valid l.ip) then
848 Printf.sprintf "(Firewalled %Ld)" (id_of_ip l.ip)
849 else "");
850 ) t.locs
852 let bprint oc t =
853 Printf.bprintf oc "LOCATION OF %s\n" (Md4.to_string t.md4);
854 List.iter (fun l ->
855 Printf.bprintf oc "%s:%d %s\n" (Ip.to_string l.ip) l.port
856 (if not (Ip.valid l.ip) then
857 Printf.sprintf "(Firewalled %Ld)" (id_of_ip l.ip)
858 else "");
860 ) t.locs
862 let write buf t =
863 buf_md4 buf t.md4;
864 buf_int8 buf (List.length t.locs);
865 List.iter (fun l ->
866 buf_ip buf l.ip;
867 buf_port buf l.port
868 ) t.locs
872 module QueryID = struct
873 type t = int64
875 let parse len s =
876 id_of_ip (get_ip s 1)
878 let print t =
879 lprintf "QUERY IP OF %Ld" t
881 let bprint oc t =
882 Printf.bprintf oc "QUERY IP OF %Ld\n" t
884 let write buf t =
885 buf_ip buf (ip_of_id t)
888 module QueryIDFailed = struct
889 type t = int64
891 let parse len s =
892 id_of_ip (get_ip s 1)
894 let print t =
895 lprintf "QUERY IP OF %Ld FAILED" t
897 let bprint oc t =
898 Printf.bprintf oc "QUERY IP OF %Ld FAILED\n" t
900 let write buf t =
901 buf_ip buf (ip_of_id t)
904 module QueryIDReply = struct
905 type t = {
906 ip : Ip.t;
907 port : int;
910 let parse len s =
911 let ip = get_ip s 1 in
912 let port = get_port s 5 in
913 { ip = ip; port = port; }
915 let print t =
916 lprintf_nl "IDENTIFICATION %s : %d" (Ip.to_string t.ip) t.port
918 let bprint oc t =
919 Printf.bprintf oc "IDENTIFICATION %s : %d\n" (Ip.to_string t.ip) t.port
921 let write buf t =
922 buf_ip buf t.ip;
923 buf_port buf t.port
927 module QueryServers = struct
928 type t = {
929 ip : Ip.t;
930 port : int;
933 let parse len s =
934 let ip = get_ip s 1 in
935 let port = get_port s 5 in
936 { ip = ip; port = port; }
938 let print t =
939 lprintf_nl "QUERY SERVERS %s : %d" (Ip.to_string t.ip) t.port
941 let bprint oc t =
942 Printf.bprintf oc "QUERY SERVERS %s : %d\n" (Ip.to_string t.ip) t.port
944 let write buf t =
945 buf_ip buf t.ip;
946 buf_port buf t.port
950 module QueryServersReply = struct
951 type server = {
952 ip : Ip.t;
953 port : int;
956 type t = {
957 server_ip : Ip.t;
958 server_port : int;
959 servers: server list;
962 let rec parse_servers nservers s pos =
963 if nservers = 0 then [] else
964 let ip = get_ip s pos in
965 let port = get_port s (pos+4) in
966 { ip = ip; port = port; } ::
967 (parse_servers (nservers-1) s (pos+6))
969 let parse len s =
971 let ip = get_ip s 1 in
972 let port = get_port s 5 in
973 let nservers = get_uint8 s 7 in
974 let servers = parse_servers nservers s 8 in
975 { server_ip = ip; server_port = port; servers = servers }
976 with _ ->
977 let nservers = get_uint8 s 1 in
978 let servers = parse_servers nservers s 2 in
979 { server_ip = Ip.null; server_port = 0; servers = servers }
981 let print t =
982 lprintf_nl "SERVERS QUERY REPLY %s : %d" (
983 Ip.to_string t.server_ip) t.server_port;
984 List.iter (fun s ->
985 lprintf_nl " %s:%d" (Ip.to_string s.ip) s.port;
986 ) t.servers
988 let bprint oc t =
989 Printf.bprintf oc "SERVERS QUERY REPLY:\n";
990 Printf.bprintf oc "%s:%d\n" (
991 Ip.to_string t.server_ip) t.server_port;
992 List.iter (fun s ->
993 Printf.bprintf oc "%s:%d\n" (Ip.to_string s.ip) s.port;
994 ) t.servers
996 let write buf t =
997 if (t.server_port = 0) then
998 begin
999 buf_int8 buf (List.length t.servers);
1000 List.iter (fun s ->
1001 buf_ip buf s.ip; buf_int16 buf s.port) t.servers
1003 else
1004 begin
1005 buf_ip buf t.server_ip;
1006 buf_port buf t.server_port;
1007 buf_int8 buf (List.length t.servers);
1008 List.iter (fun s ->
1009 buf_ip buf s.ip; buf_int16 buf s.port) t.servers
1015 module Req = struct
1016 type t
1018 let parse len s = raise Not_found
1019 let print t = raise Not_found
1020 let write buf s = raise Not_found
1023 type t =
1024 | ConnectReq of Connect.t
1025 | SetIDReq of SetID.t
1026 | QueryServerListReq of QueryServerList.t
1027 | BadProtocolVersionReq
1028 | MessageReq of Message.t
1029 | ShareReq of Share.t
1030 | InfoReq of Info.t
1031 | ServerListReq of ServerList.t
1032 | ServerInfoReq of ServerInfo.t
1033 | QueryReplyReq of QueryReply.t
1034 | QueryReq of CommonTypes.query
1035 | QueryLocationReq of QueryLocation.t
1036 | QueryLocationReplyReq of QueryLocationReply.t
1037 | QueryIDReq of QueryID.t
1038 | QueryIDFailedReq of QueryIDFailed.t
1039 | QueryIDReplyReq of QueryIDReply.t
1040 | ChatRoomsReq of ChatRooms.t
1041 | QueryUsersReq of QueryUsers.t
1042 | QueryUsersReplyReq of QueryUsersReply.t
1043 | QueryMoreResultsReq
1045 | UnknownReq of string
1047 (****************
1048 MLdonkey extensions messages
1049 ***************)
1051 (* server to client: client has been recognized as
1052 a mldonkey client by a mldonkey server *)
1053 | Mldonkey_MldonkeyUserReplyReq
1054 (* client to server: the client want to subscribe to this query *)
1055 | Mldonkey_SubscribeReq of int * int * CommonTypes.query
1056 (* server to client: the server send a notification to a subscription *)
1057 | Mldonkey_NotificationReq of int * QueryReply.t
1058 (* client to server: the client want to cancel a subscription *)
1059 | Mldonkey_CloseSubscribeReq of int
1061 let mldonkey_extensions len s =
1062 check_string s 1;
1063 let opcode = int_of_char s.[1] in
1064 match opcode with
1065 | 1 ->
1066 Mldonkey_MldonkeyUserReplyReq
1067 | 2 ->
1068 let num = get_int s 2 in
1069 let lifetime = get_int s 6 in
1070 let query, pos = Query.parse_query s 10 in
1071 Mldonkey_SubscribeReq (num, lifetime, query)
1072 | 3 ->
1073 let num = get_int s 2 in
1074 let files = QueryReply.get_replies s 6 in
1075 Mldonkey_NotificationReq (num, files)
1077 | 4 ->
1078 let num = get_int s 2 in
1079 Mldonkey_CloseSubscribeReq num
1080 | _ -> raise Not_found
1082 let rec parse magic s =
1084 let len = String.length s in
1085 if len = 0 then raise Not_found;
1086 let opcode = int_of_char (s.[0]) in
1087 match magic with
1088 227 -> begin
1089 (* lprintf "opcode: %d\n" opcode; *)
1090 match opcode with
1091 | 1 -> ConnectReq (Connect.parse len s)
1092 | 5 -> BadProtocolVersionReq
1093 | 20 -> QueryServerListReq (QueryServerList.parse len s) (* OP_GETSERVERLIST 0x14 *)
1094 | 21 -> ShareReq (Share.parse len s)
1095 | 22 -> QueryReq (Query.parse len s)
1096 | 25 -> QueryLocationReq (QueryLocation.parse len s)
1097 | 26 -> QueryUsersReq (QueryUsers.parse len s)
1098 | 28 -> QueryIDReq (QueryID.parse len s)
1099 (* | 29 -> QueryChats (C->S) *)
1100 (* | 30 -> ChatMessage (C->S) *)
1101 (* | 31 -> JoinRoom (C->S) *)
1102 | 33 -> QueryMoreResultsReq
1103 | 50 -> ServerListReq (ServerList.parse len s)
1104 | 51 -> QueryReplyReq (QueryReply.parse len s)
1105 | 52 -> InfoReq (Info.parse len s)
1106 | 53 -> QueryIDReplyReq (QueryIDReply.parse len s)
1107 | 54 -> QueryIDFailedReq (QueryIDFailed.parse len s)
1108 | 56 -> MessageReq (Message.parse len s)
1109 | 57 -> ChatRoomsReq (ChatRooms.parse len s)
1110 (* | 58 -> ChatBroadcastMessage (S->C) *)
1111 (* | 59 -> ChatUserJoin (S->C) *)
1112 (* | 60 -> ChatUserLeave (S->C) *)
1113 (* | 61 -> ChatUsers (S->C) *)
1114 | 64 -> SetIDReq (SetID.parse len s)
1115 | 65 -> ServerInfoReq (ServerInfo.parse len s)
1116 | 66 -> QueryLocationReplyReq (QueryLocationReply.parse len s)
1117 | 67 -> QueryUsersReplyReq (QueryUsersReply.parse len s)
1118 (* UDP *)
1121 (* MLDONKEY *)
1122 | 250 -> mldonkey_extensions len s
1123 | _ ->
1124 raise Not_found
1126 | 0xD4 -> (* 212 *)
1127 let s = Zlib.uncompress_string2 (String.sub s 1 (len-1)) in
1128 let s = Printf.sprintf "%c%s" (char_of_int opcode) s in
1129 parse 227 s
1131 | _ ->
1132 failwith (Printf.sprintf "Unknown opcode %d from server\n" opcode)
1133 with
1134 e ->
1135 if !CommonOptions.verbose_unknown_messages then begin
1136 lprintf_nl "Unknown message From server: %s (magic %d)"
1137 (Printexc2.to_string e) magic;
1138 let tmp_file = Filename2.temp_file "comp" "pak" in
1139 File.from_string tmp_file s;
1140 lprintf_nl "Saved unknown packet %s" tmp_file;
1141 dump s;
1142 lprint_newline ();
1143 end;
1144 UnknownReq s
1146 let print t =
1147 begin
1148 match t with
1149 ConnectReq t -> Connect.print t
1150 | SetIDReq t -> SetID.print t
1151 | QueryServerListReq t -> QueryServerList.print t
1152 | MessageReq t -> Message.print t
1153 | BadProtocolVersionReq -> lprintf_nl "BAD PROTOCOL VERSION"
1154 | ShareReq t -> Share.print t
1155 | InfoReq t -> Info.print t
1156 | ServerListReq t -> ServerList.print t
1157 | ServerInfoReq t -> ServerInfo.print t
1158 | QueryReq t -> Query.print t
1159 | QueryReplyReq t -> QueryReply.print t
1160 | QueryLocationReq t
1161 -> QueryLocation.print t
1162 | QueryLocationReplyReq t
1164 QueryLocationReply.print t
1165 | QueryIDReq t -> QueryID.print t
1166 | QueryIDFailedReq t -> QueryIDFailed.print t
1167 | QueryIDReplyReq t -> QueryIDReply.print t
1168 | QueryUsersReq t -> QueryUsers.print t
1169 | QueryUsersReplyReq t -> QueryUsersReply.print t
1170 | ChatRoomsReq t -> ChatRooms.print t
1172 | QueryMoreResultsReq ->
1173 lprintf_nl "QUERY MORE RESULTS";
1174 | Mldonkey_MldonkeyUserReplyReq ->
1175 lprintf_nl "MLDONKEY USER";
1176 | Mldonkey_SubscribeReq (num, lifetime, t) ->
1177 lprintf_nl "MLDONKEY SUBSCRIPTION %d FOR %d SECONDS" num lifetime;
1179 Query.print t
1180 | Mldonkey_NotificationReq (num,t) ->
1181 lprintf_nl "MLDONKEY NOTIFICATIONS TO %d" num;
1182 QueryReply.print t
1183 | Mldonkey_CloseSubscribeReq num ->
1184 lprintf_nl "MLDONKEY CLOSE SUBSCRIPTION %d" num;
1185 | UnknownReq s ->
1186 let len = String.length s in
1187 lprintf_nl "UnknownReq:";
1188 lprintf "ascii: [";
1189 for i = 0 to len - 1 do
1190 let c = s.[i] in
1191 let n = int_of_char c in
1192 if n > 31 && n < 127 then
1193 lprintf " %c" c
1194 else
1195 lprintf "(%d)" n
1196 done;
1197 lprintf_nl "]";
1198 lprintf "dec: [";
1199 for i = 0 to len - 1 do
1200 let c = s.[i] in
1201 let n = int_of_char c in
1202 lprintf "(%d)" n
1203 done;
1204 lprintf_nl "]";
1205 end;
1206 lprint_newline ()
1209 let bprint oc t =
1210 begin
1211 match t with
1212 ConnectReq t -> Connect.bprint oc t
1213 | SetIDReq t -> SetID.bprint oc t
1214 | QueryServerListReq t -> QueryServerList.bprint oc t
1215 | MessageReq t -> Message.bprint oc t
1216 | BadProtocolVersionReq -> Printf.bprintf oc "BAD PROTOCOL VERSION\n"
1217 | ShareReq t -> Share.bprint oc t
1218 | InfoReq t -> Info.bprint oc t
1219 | ServerListReq t -> ServerList.bprint oc t
1220 | ServerInfoReq t -> ServerInfo.bprint oc t
1221 | QueryReq t -> Query.bprint oc t
1222 | QueryReplyReq t -> QueryReply.bprint oc t
1223 | QueryLocationReq t -> QueryLocation.bprint oc t
1224 | QueryLocationReplyReq t -> QueryLocationReply.bprint oc t
1225 | QueryIDReq t -> QueryID.bprint oc t
1226 | QueryIDFailedReq t -> QueryIDFailed.bprint oc t
1227 | QueryIDReplyReq t -> QueryIDReply.bprint oc t
1228 | QueryUsersReq t -> QueryUsers.bprint oc t
1229 | QueryUsersReplyReq t -> QueryUsersReply.bprint oc t
1230 | ChatRoomsReq t -> ChatRooms.bprint oc t
1232 | QueryMoreResultsReq ->
1233 Printf.bprintf oc "QUERY MORE RESULTS\n"
1234 | Mldonkey_MldonkeyUserReplyReq ->
1235 Printf.bprintf oc "MLDONKEY USER\n"
1236 | Mldonkey_SubscribeReq (num, lifetime, t) ->
1237 Printf.bprintf oc "MLDONKEY SUBSCRIBE %d FOR %d SECONDS\n" num lifetime;
1238 Query.bprint oc t
1239 | Mldonkey_NotificationReq (num,t) ->
1240 Printf.bprintf oc "MLDONKEY NOTIFICATIONS TO %d\n" num;
1241 QueryReply.bprint oc t
1242 | Mldonkey_CloseSubscribeReq num ->
1243 lprintf_nl "MLDONKEY CLOSE SUBSCRIPTION %d" num;
1245 | UnknownReq s ->
1246 (* let len = String.length s in*)
1247 Printf.bprintf oc "UnknownReq\n"
1248 (* lprintf "ascii: [";
1249 for i = 0 to len - 1 do
1250 let c = s.[i] in
1251 let n = int_of_char c in
1252 if n > 31 && n < 127 then
1253 lprintf " %c" c
1254 else
1255 lprintf "(%d)" n
1256 done;
1257 lprintf "]\n";
1258 lprintf "dec: [";
1259 for i = 0 to len - 1 do
1260 let c = s.[i] in
1261 let n = int_of_char c in
1262 lprintf "(%d)" n
1263 done;
1264 lprintf "]\n";
1265 lprint_newline ()*)
1268 (* Why is this called udp_write ??? It is the normal function to encode messages
1269 both on UDP and TCP connections !!! *)
1271 let write buf t =
1272 match t with
1273 | ConnectReq t ->
1274 buf_int8 buf 1;
1275 Connect.write buf t
1276 | BadProtocolVersionReq ->
1277 buf_int8 buf 5
1278 | SetIDReq t ->
1279 buf_int8 buf 64;
1280 SetID.write buf t
1281 | QueryServerListReq t ->
1282 buf_int8 buf 20;
1283 QueryServerList.write buf t
1284 | MessageReq t ->
1285 buf_int8 buf 56;
1286 Message.write buf t
1287 | ShareReq t ->
1288 buf_int8 buf 21;
1289 Share.write buf t
1290 | InfoReq t ->
1291 buf_int8 buf 52;
1292 Info.write buf t
1293 | ServerListReq t ->
1294 buf_int8 buf 50;
1295 ServerList.write buf t
1296 | ServerInfoReq t ->
1297 buf_int8 buf 65;
1298 ServerInfo.write buf t
1299 | QueryReplyReq t ->
1300 buf_int8 buf 51;
1301 QueryReply.write buf t
1302 | QueryReq t ->
1303 buf_int8 buf 22;
1304 Query.write buf t
1305 | QueryLocationReq t ->
1306 buf_int8 buf 25;
1307 QueryLocation.write buf t
1308 | QueryLocationReplyReq t ->
1309 buf_int8 buf 66;
1310 QueryLocationReply.write buf t
1311 | QueryIDReq t ->
1312 buf_int8 buf 28;
1313 QueryID.write buf t
1314 | QueryIDReplyReq t ->
1315 buf_int8 buf 53;
1316 QueryIDReply.write buf t
1317 | QueryIDFailedReq t ->
1318 buf_int8 buf 54;
1319 QueryIDFailed.write buf t
1320 | ChatRoomsReq t ->
1321 buf_int8 buf 57;
1322 ChatRooms.write buf t
1323 | UnknownReq s ->
1324 Buffer.add_string buf s
1325 | QueryUsersReq t ->
1326 buf_int8 buf 26;
1327 QueryUsers.write buf t
1328 | QueryUsersReplyReq t ->
1329 buf_int8 buf 67;
1330 QueryUsersReply.write buf t
1331 | QueryMoreResultsReq ->
1332 buf_int8 buf 33
1334 (**************
1335 mldonkey extensions to the protocol
1336 **************)
1338 | Mldonkey_MldonkeyUserReplyReq ->
1339 buf_int8 buf 250; (* MLdonkey extensions opcode *)
1340 buf_int8 buf 1
1342 | Mldonkey_SubscribeReq (num, lifetime, t) ->
1343 buf_int8 buf 250; (* MLdonkey extensions opcode *)
1344 buf_int8 buf 2;
1345 buf_int buf num;
1346 buf_int buf lifetime;
1347 Query.write buf t
1349 | Mldonkey_CloseSubscribeReq num ->
1350 buf_int8 buf 250; (* MLdonkey extensions opcode *)
1351 buf_int8 buf 4;
1352 buf_int buf num;
1354 | Mldonkey_NotificationReq (num,t) ->
1355 buf_int8 buf 250; (* MLdonkey extensions opcode *)
1356 buf_int8 buf 3;
1357 buf_int buf num;
1358 QueryReply.write_replies buf t
1360 let to_string m =
1361 let b = Buffer.create 100 in
1362 bprint b m;
1363 Buffer.contents b
1366 let _ =
1367 let s = "abcdefghijklmnopqrstuvwxyz" in
1368 let compressed = Zlib.compress_string s in
1369 let ss = Zlib.uncompress_string2 compressed in
1370 lprintf "[%s] <> [%s]\n" s (String.escaped ss);
1371 assert (s = ss);
1372 exit 2