patch #7310
[mldonkey.git] / src / networks / donkey / donkeyProtoClient.ml
blobc63c6a32391fa3f3107c3c343fc7a34b37c8c825
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 Options
21 open Int64ops
22 open AnyEndian
23 open Printf2
24 open Md4
25 open CommonTypes
26 open LittleEndian
27 open CommonGlobals
28 open CommonOptions
30 open DonkeyOptions
31 open DonkeyTypes
32 open DonkeyMftp
34 let compatibleclient = ref 10
36 let get_emule_version () =
37 (!compatibleclient lsl 24) lor
38 (int_of_string(Autoconf.major_version) lsl 17) lor
39 (int_of_string(Autoconf.minor_version) lsl 10) lor
40 (int_of_string(Autoconf.sub_version) lsl 7)
42 let mldonkey_emule_proto =
44 emule_version = get_emule_version ();
45 emule_release = "";
46 emule_osinfosupport = 1;
47 emule_features = 3;
49 (* emule_miscoptions1 *)
50 received_miscoptions1 = false;
51 emule_aich = 0;
52 emule_unicode = 0;
53 emule_udpver = 0;
54 emule_compression = 1;
55 emule_secident = 3; (* Emule uses v1 if advertising both, v2 if only advertising 2 *)
56 emule_sourceexchange = 2; (* 2 : +client_md4 3 : +IdHybrid (emule Kademlia?)*)
57 emule_extendedrequest = 1; (* 1: +file_status 2: +ncomplete_sources*)
58 emule_comments = 1;
59 emule_peercache = 0;
60 emule_noviewshared = 0;
61 emule_multipacket = 0;
62 emule_supportpreview = 0;
64 (* emule_miscoptions2 *)
65 received_miscoptions2 = false;
66 emule_require_crypt = 0;
67 emule_request_crypt = 0;
68 emule_support_crypt = 0;
69 emule_extmultipacket = 0;
70 emule_largefiles = 1;
71 emule_kad_version = 0;
74 let emule_miscoptions1 m =
75 let o =
76 (m.emule_aich lsl 29) lor
77 (m.emule_unicode lsl 28) lor
78 (m.emule_udpver lsl 24) lor
79 (m.emule_compression lsl 20) lor
80 (m.emule_secident lsl 16) lor
81 (m.emule_sourceexchange lsl 12) lor
82 (m.emule_extendedrequest lsl 8) lor
83 (m.emule_comments lsl 4) lor
84 (m.emule_peercache lsl 3) lor
85 (m.emule_noviewshared lsl 2) lor
86 (m.emule_multipacket lsl 1) lor
87 (m.emule_supportpreview lsl 0)
89 Int64.of_int o
91 let update_emule_proto_from_miscoptions1 m o =
92 let o = Int64.to_int o in
93 m.emule_aich <- (o lsr 29) land 0x7;
94 m.emule_unicode <- (o lsr 28) land 0xf;
95 m.emule_udpver <- (o lsr 24) land 0xf;
96 m.emule_compression <- (o lsr 20) land 0xf;
97 m.emule_secident <- (o lsr 16) land 0xf;
98 m.emule_sourceexchange <- (o lsr 12) land 0xf;
99 m.emule_extendedrequest <- (o lsr 8) land 0xf;
100 m.emule_comments <- (o lsr 4) land 0xf;
101 m.emule_peercache <- (o lsr 3) land 0x1;
102 m.emule_noviewshared <- (o lsr 2) land 0x1;
103 m.emule_multipacket <- (o lsr 1) land 0x1;
104 m.emule_supportpreview <- (o lsr 0) land 0x1
106 let print_emule_proto_miscoptions1 m =
107 let buf = Buffer.create 50 in
108 if m.emule_aich <> 0 then Printf.bprintf buf " aich %d\n" m.emule_aich;
109 if m.emule_unicode <> 0 then Printf.bprintf buf " unicode %d\n" m.emule_unicode;
110 if m.emule_udpver <> 0 then Printf.bprintf buf " udpver %d\n" m.emule_udpver;
111 if m.emule_compression <> 0 then Printf.bprintf buf " compression %d\n" m.emule_compression;
112 if m.emule_secident <> 0 then Printf.bprintf buf " secident %d\n" m.emule_secident;
113 if m.emule_sourceexchange <> 0 then Printf.bprintf buf " sourceexchange %d\n" m.emule_sourceexchange;
114 if m.emule_extendedrequest <> 0 then Printf.bprintf buf " extendedrequest %d\n" m.emule_extendedrequest;
115 if m.emule_comments <> 0 then Printf.bprintf buf " comments %d\n" m.emule_comments;
116 if m.emule_peercache <> 0 then Printf.bprintf buf " peercache %d\n" m.emule_peercache;
117 if m.emule_noviewshared <> 0 then Printf.bprintf buf " noviewshared %d\n" m.emule_noviewshared;
118 if m.emule_multipacket <> 0 then Printf.bprintf buf " multipacket %d\n" m.emule_multipacket;
119 if m.emule_supportpreview <> 0 then Printf.bprintf buf " supportpreview %d\n" m.emule_supportpreview;
120 Buffer.contents buf
122 let emule_miscoptions2 m =
123 let o =
124 (m.emule_largefiles lsl 4)
126 Int64.of_int o
128 let update_emule_proto_from_miscoptions2 m o =
129 let o = Int64.to_int o in
130 m.emule_require_crypt <- (o lsr 9) land 0x1;
131 m.emule_request_crypt <- (o lsr 8) land 0x1;
132 m.emule_support_crypt <- (o lsr 7) land 0x1;
133 m.emule_extmultipacket <- (o lsr 5) land 0x1;
134 m.emule_largefiles <- (o lsr 4) land 0x1;
135 m.emule_kad_version <- (o lsr 0) land 0xf
137 let print_emule_proto_miscoptions2 m =
138 let buf = Buffer.create 50 in
139 if m.emule_require_crypt <> 0 then Printf.bprintf buf " require_crypt %d\n" m.emule_require_crypt;
140 if m.emule_request_crypt <> 0 then Printf.bprintf buf " request_crypt %d\n" m.emule_request_crypt;
141 if m.emule_support_crypt <> 0 then Printf.bprintf buf " support_crypt %d\n" m.emule_support_crypt;
142 if m.emule_extmultipacket <> 0 then Printf.bprintf buf " extmultipacket %d\n" m.emule_extmultipacket;
143 if m.emule_largefiles <> 0 then Printf.bprintf buf " largefiles %d\n" m.emule_largefiles;
144 if m.emule_kad_version <> 0 then Printf.bprintf buf " kad_version %d\n" m.emule_kad_version;
145 Buffer.contents buf
147 let emule_compatoptions m =
148 (m.emule_osinfosupport lsl 0)
150 let update_emule_proto_from_compatoptions m o =
151 m.emule_osinfosupport <- (o lsr 0) land 0x1
153 let extendedrequest e =
154 min e.emule_extendedrequest mldonkey_emule_proto.emule_extendedrequest
156 let sourceexchange e =
157 min e.emule_sourceexchange mldonkey_emule_proto.emule_sourceexchange
160 BAD MESSAGE FROM CONNECTING CLIENT
161 UnknownReq:
162 ascii: [(1)(16)(231)(129)(131)(26) O(247)(154)(145)(251)(253)(167) G }(207) j(146)(140) { l(139) F(18)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)]
163 dec: [
165 (16)
166 (231)(129)(131)(26)(79)(247)(154)(145)(251)(253)(167)(71)(125)(207)(106)(146)
167 (140)(123)(108)(139)
168 (70)(18)
169 (0)(0)(0)(0)
170 (0)(0)(0)(0)(0)(0)
173 let rec lbprint_tags buf tags =
174 match tags with
175 [] -> Printf.bprintf buf ""
176 | tag :: tags ->
177 Printf.bprintf buf " (%s)=(%s)" (escaped_string_of_field tag)
178 (string_of_tag_value tag.tag_value);
179 lbprint_tags buf tags
181 module Connect = struct
182 type t = {
183 hash_len : int;
184 md4 : Md4.t;
185 ip: Ip.t;
186 port: int;
187 tags : tag list;
188 server_info : (Ip.t * int) option;
189 left_bytes : string;
192 let names_of_tag = client_common_tags
194 let names_of_tag =
195 List.map (fun (v, name) -> (v, Field_KNOWN name)) names_of_tag
197 let parse reply len s =
198 let hash_len, pos = if not reply then get_uint8 s 1, 2 else -1, 1 in
199 let md4 = get_md4 s pos in
200 let ip = get_ip s (pos+16) in
201 let port = get_port s (pos+20) in
202 let tags, pos = get_tags s (pos+22) names_of_tag in
203 let server_info = Some (get_ip s pos, get_port s (pos+4)) in
204 let left_bytes = String.sub s (pos+6) (String.length s - pos - 6) in
206 hash_len = hash_len;
207 md4 = md4;
208 ip = ip;
209 port = port;
210 tags = tags;
211 server_info = server_info;
212 left_bytes = left_bytes;
216 let print t =
217 let b1 = Buffer.create 50 in
218 let b2 = Buffer.create 5 in
219 lbprint_tags b1 t.tags;
220 String.iter (fun c -> Printf.bprintf b2 "(%d)" (int_of_char c)) t.left_bytes;
221 lprintf_nl "Connect [hl: %d] [md4: %s] [ip: %s:%d] [server: %s] [left: %s] [tags:%s]"
222 t.hash_len
223 (Md4.to_string t.md4)
224 (Ip.to_string t.ip) t.port
225 (match t.server_info with
226 None -> "None"
227 | Some (ip, port) -> Printf.sprintf "%s:%d" (Ip.to_string ip) port)
228 (if String.length t.left_bytes <> 0 then (Buffer.contents b2) else "None")
229 (Buffer.contents b1)
232 let write reply buf t =
233 if not reply then
234 buf_int8 buf 16;
236 buf_md4 buf t.md4;
237 buf_ip buf t.ip;
238 buf_port buf t.port;
239 buf_tags buf t.tags names_of_tag;
240 begin
241 match t.server_info with
242 None ->
243 buf_ip buf Ip.null;
244 buf_port buf 0
245 | Some (ip, port) ->
246 buf_ip buf ip;
247 buf_port buf port;
252 module Say = struct
253 type t = string
255 let parse len s =
256 let (s, p) = get_string s 1 in
259 let print t =
260 lprintf_nl "SAY %s" t
262 let write buf t =
263 buf_string buf t
266 module OneMd4 = functor(M: sig val m : string end) -> (struct
267 type t = Md4.t
269 let parse len s =
270 get_md4 s 1
272 let print t =
273 lprintf_nl "OneMd4: %s OF %s" M.m (Md4.to_string t)
275 let write buf t =
276 buf_md4 buf t
278 end)
280 module JoinQueue = struct
281 type t = Md4.t option
283 let parse len s =
284 if len >= 17 then
285 Some (get_md4 s 1)
286 else None
288 let print t =
289 lprintf_nl "JOIN QUEUE %s"
290 (match t with None -> "" | Some md4 ->
291 Printf.sprintf "OF %s" (Md4.to_string md4))
293 let write emule buf t =
294 if extendedrequest emule > 0 then
295 match t with
296 None -> ()
297 | Some md4 ->
298 buf_md4 buf md4
301 : sig
302 type t
303 val parse : int -> string -> t
304 val print : t -> unit
305 val write : Buffer.t -> t -> unit
306 val t :t
311 (* In Emule, this message contains much more information, and will probably
312 remove the need for QueryChunks. *)
314 let get_bitmap s pos =
315 let nchunks = get_int16 s pos in
316 let chunks, pos =
317 if nchunks = 0 then (Bitv.create 0 false), pos+2 else
318 let pos = pos + 2 in
319 let chunks = (Bitv.create nchunks false) in
320 for i = 0 to (nchunks-1) / 8 do
321 let m = get_uint8 s (pos + i) in
322 for j = 0 to 7 do
323 let n = i * 8 + j in
324 if n < nchunks then
325 Bitv.set chunks n ((m land (1 lsl j)) <> 0);
326 done;
327 done;
328 let pos = pos + (nchunks-1)/8 + 1 in
329 chunks, pos
331 chunks, pos
333 let print_bitmap chunks =
334 lprintf "\n%s\n" (Bitv.to_string chunks)
336 let write_bitmap buf chunks =
337 let nchunks = Bitv.length chunks in
338 buf_int16 buf nchunks;
339 if nchunks > 0 then
340 for i = 0 to (nchunks-1) / 8 do
341 let m = ref 0 in
342 for j = 0 to 7 do
343 let n = i * 8 + j in
344 if n < nchunks then
345 if (Bitv.get chunks n) then
346 m := !m lor (1 lsl j);
347 done;
348 buf_int8 buf !m
349 done
351 module QueryFile = struct
352 type t = {
353 md4 : Md4.t;
354 emule_extension : (Bitv.t * int) option;
357 let parse emule len s =
358 (* lprintf "Query File: emule version %d len %d"
359 (extendedrequest emule) len;
360 print_newline (); *)
361 let md4 = get_md4 s 1 in
362 let emule_extension =
364 if len < 18 || extendedrequest emule = 0 then None else
365 let chunks, pos = get_bitmap s 17 in
366 let ncompletesources =
367 if extendedrequest emule > 1 && len > pos+1 then get_int16 s pos
368 else -1 in
369 Some (chunks, ncompletesources)
370 with _ -> None
372 { md4 = md4;
373 emule_extension = emule_extension }
375 let print t =
376 lprintf_nl "QUERY FILE OF %s" (Md4.to_string t.md4);
377 match t.emule_extension with
378 None -> ()
379 | Some (bitmap, ncompletesources) ->
380 print_bitmap bitmap;
381 lprint_newline ();
382 if ncompletesources >= 0 then
383 lprintf_nl "Complete sources: %d" ncompletesources
385 let write emule buf t =
386 buf_md4 buf t.md4;
387 match t.emule_extension with
388 None -> ()
389 | Some (chunks, ncompletesources) ->
390 if extendedrequest emule > 0 then begin
391 write_bitmap buf chunks;
392 if extendedrequest emule > 1 && ncompletesources >= 0 then
393 buf_int16 buf ncompletesources
397 module QueryChunks = OneMd4(struct let m = "QUERY CHUNKS" end)
398 (* Request 79 *)
400 module QueryChunkMd4 = OneMd4(struct let m = "QUERY CHUNKS MD4" end)
401 module EndOfDownload = OneMd4(struct let m = "END OF DOWNLOAD MD4" end)
402 module NoSuchFile = OneMd4(struct let m = "NO SUCH FILE" end)
404 module QueryChunksReply = struct (* Request 80 *)
406 type t = {
407 md4 : Md4.t;
408 chunks: Bitv.t;
411 let parse len s =
412 let md4 = get_md4 s 1 in
413 let chunks, pos = get_bitmap s 17 in
415 md4 = md4;
416 chunks = chunks;
419 let print t =
420 lprintf_nl "CHUNKS for %s" (Md4.to_string t.md4);
421 lprintf_nl "%s\n" (Bitv.to_string t.chunks)
423 let write buf t =
424 buf_md4 buf t.md4;
425 write_bitmap buf t.chunks;
426 if Bitv.length t.chunks = 0 then buf_int8 buf 0
429 dec: [(96)(215)(1)(0)(0)(0)(0)(0)(0)(0)(0)(0)(0)]
431 OP_QUEUERANKING: int16
434 module QueryChunkMd4Reply = struct (* Request 80 *)
436 type t = {
437 md4 : Md4.t;
438 chunks: Md4.t array;
441 let parse len s =
442 let md4 = get_md4 s 1 in
443 let nchunks = get_int16 s 17 in
444 (* lprintf "nchunks : %d" nchunks; lprint_newline (); *)
445 let chunks = Array.create nchunks md4 in
446 for i = 0 to nchunks - 1 do
447 chunks.(i) <- get_md4 s (19 + i * 16)
448 done;
450 md4 = md4;
451 chunks = chunks;
454 let print t =
455 lprintf_nl "CHUNKSMd4 for %s" (Md4.to_string t.md4);
456 lprint_string " ";
457 Array.iter (fun b ->
458 lprintf " %s" (Md4.to_string b))
459 t.chunks;
460 lprint_newline ()
462 let write buf t =
463 buf_md4 buf t.md4;
464 let nchunks = Array.length t.chunks in
465 buf_int16 buf nchunks;
466 for i = 0 to nchunks - 1 do
467 buf_md4 buf t.chunks.(i)
468 done
471 module QueryFileReply = struct
472 type t = {
473 md4 : Md4.t;
474 name : string;
477 let parse len s =
478 let name, _ = get_string s 17 in
479 { md4 = get_md4 s 1;
480 name = name;
483 let print t =
484 lprintf_nl "QUERY FILE REPLY OF %s : \"%s\"" (Md4.to_string t.md4) t.name
486 let write buf t =
487 buf_md4 buf t.md4;
488 buf_string buf t.name
491 module Bloc = struct
492 type t = {
493 md4 : Md4.t;
494 usesixtyfour : bool;
495 start_pos : int64;
496 end_pos: int64;
497 bloc_str: string;
498 bloc_begin : int;
499 bloc_len : int;
502 let parse usesixtyfour len s =
504 md4 = get_md4 s 1;
505 usesixtyfour = usesixtyfour;
506 start_pos = if usesixtyfour then get_int64 s 17 else get_uint64_32 s 17;
507 end_pos = if usesixtyfour then get_int64 s 25 else get_uint64_32 s 21;
508 bloc_str = s;
509 bloc_begin = if usesixtyfour then 33 else 25;
510 bloc_len = if usesixtyfour then len - 33 else len - 25;
513 let print t =
514 lprintf_nl "BLOC OF %s len %Ld [%Ld - %Ld] " (Md4.to_string t.md4)
515 (t.end_pos -- t.start_pos)
516 t.start_pos
517 t.end_pos
519 let write buf t =
520 buf_md4 buf t.md4;
521 if t.usesixtyfour then buf_int64 buf t.start_pos else buf_int64_32 buf t.start_pos;
522 if t.usesixtyfour then buf_int64 buf t.end_pos else buf_int64_32 buf t.end_pos;
523 Buffer.add_substring buf t.bloc_str t.bloc_begin t.bloc_len
526 module QueryBloc = struct
527 type t = {
528 md4 : Md4.t;
529 usesixtyfour : bool;
530 start_pos1 : int64; (* 180 ko *)
531 end_pos1: int64;
532 start_pos2 : int64;
533 end_pos2: int64;
534 start_pos3 : int64;
535 end_pos3: int64;
538 let parse usesixtyfour len s =
540 md4 = get_md4 s 1;
541 usesixtyfour = usesixtyfour;
542 start_pos1 = if usesixtyfour then get_int64 s 17 else get_uint64_32 s 17;
543 end_pos1 = if usesixtyfour then get_int64 s 41 else get_uint64_32 s 29;
544 start_pos2 = if usesixtyfour then get_int64 s 25 else get_uint64_32 s 21;
545 end_pos2 = if usesixtyfour then get_int64 s 49 else get_uint64_32 s 33;
546 start_pos3 = if usesixtyfour then get_int64 s 33 else get_uint64_32 s 25;
547 end_pos3 = if usesixtyfour then get_int64 s 57 else get_uint64_32 s 37;
550 let print t =
551 lprintf_nl "QUERY BLOCS OF %s [%s - %s] [%s - %s] [%s - %s]"
552 (Md4.to_string t.md4)
553 (Int64.to_string t.start_pos1) (Int64.to_string t.end_pos1)
554 (Int64.to_string t.start_pos2) (Int64.to_string t.end_pos2)
555 (Int64.to_string t.start_pos3) (Int64.to_string t.end_pos3)
557 let write buf t =
558 buf_md4 buf t.md4;
559 if t.usesixtyfour then buf_int64 buf t.start_pos1 else buf_int64_32 buf t.start_pos1;
560 if t.usesixtyfour then buf_int64 buf t.start_pos2 else buf_int64_32 buf t.start_pos2;
561 if t.usesixtyfour then buf_int64 buf t.start_pos3 else buf_int64_32 buf t.start_pos3;
562 if t.usesixtyfour then buf_int64 buf t.end_pos1 else buf_int64_32 buf t.end_pos1;
563 if t.usesixtyfour then buf_int64 buf t.end_pos2 else buf_int64_32 buf t.end_pos2;
564 if t.usesixtyfour then buf_int64 buf t.end_pos3 else buf_int64_32 buf t.end_pos3
567 let unit = ()
568 module NoArg = functor(M: sig val m : string end) -> (struct
569 type t = unit
571 let parse len s = ()
573 let print t =
574 lprintf_nl "%s:" M.m
576 let write (buf: Buffer.t) (t: t) = unit
578 let t = (() : t)
579 end : sig
580 type t
581 val parse : int -> string -> t
582 val print : t -> unit
583 val write : Buffer.t -> t -> unit
584 val t :t
588 module AvailableSlot = NoArg(struct let m = "AvailableSlot" end)
589 module ReleaseSlot = NoArg(struct let m = "ReleaseSlot" end)
590 module OutOfParts = NoArg(struct let m = "OutOfParts" end)
591 module ViewFiles = NoArg(struct let m = "VIEW FILES" end)
592 module ViewDirs = NoArg(struct let m = "VIEW DIRS" end)
594 module ViewFilesReply = struct
596 type file = {
597 md4: Md4.t;
598 ip: Ip.t;
599 port: int;
600 tags: tag list;
603 type t = tagged_file list
605 let names_of_tag = file_common_tags
607 let rec get_files s pos n =
608 if n = 0 then [], pos else
609 let md4 = get_md4 s pos in
610 let ip = get_ip s (pos + 16) in
611 let port = get_port s (pos + 20) in
612 let tags, pos = get_tags s (pos+22) names_of_tag in
613 let file = {
614 f_md4 = md4;
615 f_ip = ip;
616 f_port = port;
617 f_tags = tags;
618 } in
619 let files, pos = get_files s pos (n-1) in
620 file :: files, pos
622 let parse len s =
623 let n = get_int s 1 in
624 let files, pos = get_files s 5 n in
625 files
627 let print t =
628 lprintf_nl "VIEW FILES REPLY:";
629 List.iter (fun t ->
630 lprintf_nl "FILE:";
631 lprintf_nl " MD4: %s" (Md4.to_string t.f_md4);
632 lprintf_nl " ip: %s" (Ip.to_string t.f_ip);
633 lprintf_nl " port: %d" t.f_port;
634 lprintf " tags: ";
635 print_tags t.f_tags;
636 lprint_newline ();) t
638 let rec write_files buf files =
639 match files with
640 [] -> ()
641 | file :: files ->
642 buf_md4 buf file.f_md4;
643 buf_ip buf file.f_ip;
644 buf_port buf file.f_port;
645 buf_tags buf file.f_tags names_of_tag;
646 write_files buf files
648 let write buf t =
649 buf_int buf (List.length t);
650 write_files buf t
652 let rec write_files_max buf files nfiles max_len =
653 let prev_len = Buffer.length buf in
654 match files with
655 [] -> nfiles, prev_len
656 | file :: files ->
657 buf_md4 buf file.f_md4;
658 buf_ip buf file.f_ip;
659 buf_port buf file.f_port;
660 buf_tags buf file.f_tags names_of_tag;
661 if Buffer.length buf < max_len then
662 write_files_max buf files (nfiles+1) max_len
663 else
664 nfiles, prev_len
667 module ViewDirsReply = struct
669 type t = string list
671 let rec get_dirs s pos n =
672 if n = 0 then [], pos else
673 let dir, pos = get_string16 s pos in
674 let dirs, pos = get_dirs s pos (n-1) in
675 dir :: dirs, pos
677 let parse len s =
678 let dirs, pos = get_dirs s 2 (get_int16 s 0) in
679 dirs
681 let print t =
682 lprintf_nl "VIEW DIRS REPLY:";
683 List.iter (fun dir ->
684 lprintf_nl "DIR: %s" dir;) t
686 let write buf t =
687 buf_int buf (List.length t);
688 List.iter (fun dir ->
689 buf_string buf dir;) t
693 module ViewFilesDir = struct
695 type t = string
697 let print t =
698 lprintf_nl "VIEW FILES DIR: %s" t
700 let parse len s =
701 let dir, pos = get_string s 1 in
704 let write buf t =
705 buf_string buf t
709 module ViewFilesDirReply = struct
711 type t = string * tagged_file list
713 let names_of_tag = file_common_tags
715 let parse len s =
716 let dir, pos = get_string s 1 in
717 let n = get_int s (pos+1) in
718 let files, pos = ViewFilesReply.get_files s (pos+5) n in
719 dir, files
721 let print t =
722 lprintf_nl "VIEW FILES DIR REPLY:";
723 let dir, files = t in begin
724 lprintf_nl "DIR: %s" dir;
725 List.iter (fun file ->
726 lprintf_nl "FILE:";
727 lprintf_nl " MD4: %s" (Md4.to_string file.f_md4);
728 lprintf_nl " ip: %s" (Ip.to_string file.f_ip);
729 lprintf_nl " port: %d" file.f_port;
730 lprintf " tags: ";
731 print_tags file.f_tags;
732 lprint_newline ();) files
735 let write buf t =
736 let dir, files = t in begin
737 buf_string buf dir;
738 buf_int buf (List.length files);
739 ViewFilesReply.write_files buf files
744 module OtherLocations = struct
746 type t = Ip.t list
748 let parse len s =
749 let list = ref [] in
750 for i = 0 to len / 4 - 1 do
751 list := (get_ip s (i*4+1)) :: !list;
752 done;
753 !list
755 let print t =
756 lprintf_nl "OTHER LOCATIONS:\n";
757 List.iter (fun ip ->
758 lprintf_nl " ip: %s" (Ip.to_string ip);) t
760 let write buf t =
761 List.iter (buf_ip buf) t
764 module NewUserID = struct
766 type t = Ip.t * Ip.t
768 let parse len s =
769 get_ip s 1, get_ip s 5
771 let print (ip1,ip2) =
772 lprintf_nl "NEW USER ID: %s -> %s" (Ip.to_string ip1)
773 (Ip.to_string ip2)
775 let write buf (ip1,ip2) =
776 buf_ip buf ip1;
777 buf_ip buf ip2
781 module Sources = struct
783 type t = {
784 md4: Md4.t;
785 sources : (Ip.t * int * Ip.t) list;
788 let parse len s =
789 let len = get_int16 s 1 in
790 let md4 = get_md4 s 3 in
791 let list = ref [] in
792 (* let pos = 19 in *)
793 for i = 0 to len - 1 do
794 list := (get_ip s (19 + 10 * i), get_port s (23 + 10 * i),
795 get_ip s (25 + 10 * i)) :: !list;
796 done;
797 { md4 = md4;
798 sources = !list;
801 let print t =
802 lprintf_nl "SOURCES for %s:" (Md4.to_string t.md4);
803 List.iter (fun (ip1, port, ip2) ->
804 lprintf_nl " %s:%d:%s" (Ip.to_string ip1) port(Ip.to_string ip2)) t.sources
806 let write buf t =
807 buf_int16 buf (List.length t.sources);
808 buf_md4 buf t.md4;
809 List.iter (fun (ip1, port, ip2) ->
810 buf_ip buf ip1;
811 buf_port buf port;
812 buf_ip buf ip2) t.sources
815 module EmuleClientInfo = struct
817 type t = {
818 version : int; (* CURRENT_VERSION_SHORT = !!emule_protocol_version *)
819 protversion : int; (* EMULE_PROTOCOL_VERSION = 0x1 *)
820 mutable tags : tag list;
823 let names_of_tag = client_common_tags
825 let names_of_tag =
826 List.map (fun (v, name) -> (v, Field_KNOWN name)) names_of_tag
828 let parse len s =
829 let version = get_uint8 s 1 in
830 let protversion = get_uint8 s 2 in
831 let tags,_ = get_tags s 3 names_of_tag in
833 version = version;
834 protversion = protversion;
835 tags = tags;
838 let print m t =
839 let b1 = Buffer.create 50 in
840 lbprint_tags b1 t.tags;
841 lprintf_nl "%s: [version: %d] [protversion: %d] [tags:%s]" m t.version t.protversion (Buffer.contents b1)
843 let write buf t =
844 buf_int8 buf t.version;
845 buf_int8 buf t.protversion;
846 buf_tags buf t.tags names_of_tag;
850 module EmuleQueueRanking = struct
852 type t = int
854 let parse len s = get_int16 s 1
855 let print t =
856 lprintf_nl "EmuleQueueRanking: %d" t
858 let string_null10 = String.make 10 (char_of_int 0)
860 let write buf t =
861 buf_int16 buf t;
862 Buffer.add_string buf string_null10
866 module QueueRank = struct
868 type t = int
870 let parse len s = get_int s 1
871 let print t =
872 lprintf_nl "QueueRank: %d" t
874 let write buf t =
875 buf_int buf t
879 module EmuleRequestSources = struct
881 type t = Md4.t
883 let parse len s =
884 get_md4 s 1
886 let print t =
887 lprintf_nl "EmuleRequestSources: %s" (Md4.to_string t)
889 let write buf t =
890 buf_md4 buf t
895 let buf_estring buf s =
896 let len = String.length s in
897 buf_int8 buf len;
898 Buffer.add_string buf s
900 module EmuleSignatureReq = struct
902 type t = {
903 signature : string;
904 ip_type : int;
907 let print t =
908 lprintf_nl "EmuleSignatureReq [type %d] [sig(%d): %s]" t.ip_type (String.length t.signature) (String.escaped t.signature)
910 let parse len s =
911 let mlen = get_uint8 s 1 in
912 let slen = String.length s in
913 let signature = String.sub s 2 mlen in
914 let ip_type = if mlen = (slen-2) then 0 else get_uint8 s (2 + mlen) in
916 signature = signature;
917 ip_type = ip_type;
920 let write buf t =
921 buf_estring buf t.signature;
922 if (t.ip_type <> 0) then
923 buf_int8 buf t.ip_type;
928 module EmulePublicKeyReq = struct
930 type t = string
932 let print t =
933 lprintf_nl "EmulePublicKeyReq [key(%d): %s]" (String.length t) (String.escaped t)
935 let parse len s =
936 let len = get_uint8 s 1 in
937 String.sub s 2 len
939 let write buf t =
940 buf_estring buf t
944 module EmuleSecIdentStateReq = struct
946 type t = {
947 state : int;
948 challenge : int64;
951 let print t =
952 lprintf_nl "EmuleSecIdentStateReq [state: %d] [challenge: %Ld]" t.state t.challenge
954 let parse len s =
955 let state = get_uint8 s 1 in
956 let challenge = get_uint64_32 s 2 in
958 state = state;
959 challenge = challenge;
962 let write buf t =
963 buf_int8 buf t.state;
964 buf_int64_32 buf t.challenge
968 module EmuleRequestSourcesReply = struct
970 type source = {
971 src_ip : Ip.t;
972 src_port : int;
973 mutable src_server_ip : Ip.t;
974 mutable src_server_port : int;
975 mutable src_md4 : Md4.t;
976 mutable src_cc : int option;
979 type t = {
980 md4 : Md4.t;
981 sources : source array;
984 let dummy_source = {
985 src_ip = Ip.null;
986 src_port = 0;
987 src_server_ip = Ip.null;
988 src_server_port = 0;
989 src_md4 = Md4.null;
990 src_cc = None;
993 let parse e len s =
994 let md4 = get_md4 s 1 in
995 let ncount = get_int16 s 17 in
997 let sources =
998 if ncount = 0 then [||] else
999 let slen = (len - 19) / ncount in
1000 (* lprintf "PER SOURCES LEN: %d\n" slen; *)
1001 let sources = Array.create ncount dummy_source in
1002 let rec iter pos i =
1003 if i < ncount then
1004 let ss =
1005 let ip = get_ip s pos in
1007 dummy_source with
1008 src_ip = ip;
1009 src_port = get_int16 s (pos+4);
1010 src_cc = Geoip.get_country_code_option ip
1011 } in
1012 let pos =
1013 if slen > 6 then begin
1014 ss.src_server_ip <- get_ip s (pos+6);
1015 ss.src_server_port <- get_int16 s (pos+10);
1016 if slen > 12 && (sourceexchange e > 1) then begin
1017 ss.src_md4 <- get_md4 s (pos+12);
1018 pos + 28
1019 end else
1020 pos + 12
1022 else pos + 6
1024 sources.(i) <- ss;
1025 iter pos (i+1)
1027 iter 19 0;
1028 sources
1031 md4 = md4;
1032 sources = sources;
1035 let print t =
1036 let ncount = Array.length t.sources in
1037 lprintf_nl "EMULE SOURCES REPLY: %d sources for %s"
1038 ncount (Md4.to_string t.md4);
1039 for i = 0 to ncount - 1 do
1040 let s = t.sources.(i) in
1041 lprintf_nl "%s %s"
1042 (if Ip.valid s.src_ip then
1043 Printf.sprintf "%s:%d" (Ip.to_string s.src_ip) s.src_port
1044 else
1045 Printf.sprintf "%s:%d (Indirect)" (Ip.to_string s.src_server_ip) s.src_server_port)
1046 (if s.src_md4 != Md4.null then
1047 Printf.sprintf "MD4: %s" (Md4.to_string s.src_md4)
1048 else "")
1049 done
1051 let write e buf t =
1052 buf_md4 buf t.md4;
1053 let ncount = Array.length t.sources in
1054 buf_int16 buf ncount;
1056 for i = 0 to ncount - 1 do
1057 let s = t.sources.(i) in
1058 buf_ip buf s.src_ip;
1059 buf_port buf s.src_port;
1060 if sourceexchange e > 0 then begin
1061 buf_ip buf s.src_server_ip;
1062 buf_port buf s.src_server_port;
1063 if sourceexchange e > 1 then
1064 buf_md4 buf s.src_md4
1066 done
1069 module EmuleFileDesc = struct
1071 type t = {
1072 rating : int;
1073 comment : string;
1076 let parse len s =
1077 let rating = get_uint8 s 1 in
1078 let (comment, _) = get_string32 s 2 in
1080 rating = rating;
1081 comment = comment;
1084 let print t =
1085 lprintf_nl "EmuleFileDesc [%d][%s]" t.rating t.comment
1087 let write buf t =
1088 buf_int8 buf t.rating;
1089 buf_string buf t.comment
1092 module EmuleCompressedPart = struct
1094 type t = {
1095 md4 : Md4.t;
1096 usesixtyfour : bool;
1097 statpos : int64;
1098 newsize : int64;
1099 bloc : string;
1102 let parse usesixtyfour len s =
1104 md4 = get_md4 s 1;
1105 usesixtyfour = usesixtyfour;
1106 statpos = if usesixtyfour then get_int64 s 17 else get_uint64_32 s 17;
1107 newsize = if usesixtyfour then get_uint64_32 s 25 else get_uint64_32 s 21;
1108 bloc = if usesixtyfour then String.sub s 29 (len-29) else String.sub s 25 (len-25)
1111 let print t =
1112 lprintf_nl "EmuleCompressedPart for %s %Ld %Ld len %d"
1113 (Md4.to_string t.md4) t.statpos t.newsize (String.length t.bloc)
1115 let write buf t =
1116 buf_md4 buf t.md4;
1117 if t.usesixtyfour then buf_int64 buf t.statpos else buf_int64_32 buf t.statpos;
1118 buf_int64_32 buf t.newsize;
1119 Buffer.add_string buf t.bloc
1122 module EmulePortTestReq = struct
1124 type t = string
1126 let print s =
1127 lprintf_nl "Emule porttest request %s" (String.escaped s)
1129 let parse s = s
1131 let write buf =
1132 buf_int8 buf 0x12
1136 type t =
1137 | ConnectReq of Connect.t
1138 | ConnectReplyReq of Connect.t
1139 | QueryFileReq of QueryFile.t
1140 | QueryFileReplyReq of QueryFileReply.t
1141 | BlocReq of Bloc.t
1142 | QueryBlocReq of QueryBloc.t
1143 | JoinQueueReq of JoinQueue.t (* sent before queryBloc *)
1144 | AvailableSlotReq of AvailableSlot.t
1145 | ReleaseSlotReq of ReleaseSlot.t
1146 | OutOfPartsReq of OutOfParts.t
1147 | QueryChunksReq of QueryChunks.t
1148 | QueryChunksReplyReq of QueryChunksReply.t
1149 | QueryChunkMd4Req of QueryChunkMd4.t
1150 | QueryChunkMd4ReplyReq of QueryChunkMd4Reply.t
1151 | ViewFilesReq of ViewFiles.t
1152 | ViewFilesReplyReq of ViewFilesReply.t
1153 | ViewDirsReq of ViewDirs.t
1154 | ViewDirsReplyReq of ViewDirsReply.t
1155 | ViewFilesDirReq of ViewFilesDir.t
1156 | ViewFilesDirReplyReq of ViewFilesDirReply.t
1157 | QueueReq of OtherLocations.t
1158 | UnknownReq of int * string
1159 | OtherLocationsReq of OtherLocations.t
1160 | SayReq of Say.t
1161 | SourcesReq of Sources.t
1162 | EndOfDownloadReq of EndOfDownload.t
1163 | NewUserIDReq of NewUserID.t
1164 | NoSuchFileReq of NoSuchFile.t
1165 | QueueRankReq of QueueRank.t
1167 | EmuleClientInfoReq of EmuleClientInfo.t
1168 | EmuleClientInfoReplyReq of EmuleClientInfo.t
1169 | EmuleQueueRankingReq of EmuleQueueRanking.t
1170 | EmuleRequestSourcesReq of EmuleRequestSources.t
1171 | EmuleRequestSourcesReplyReq of EmuleRequestSourcesReply.t
1172 | EmuleFileDescReq of EmuleFileDesc.t
1173 | EmulePublicKeyReq of EmulePublicKeyReq.t
1174 | EmuleSignatureReq of EmuleSignatureReq.t
1175 | EmuleSecIdentStateReq of EmuleSecIdentStateReq.t
1176 | EmuleMultiPacketReq of Md4.t * t list
1177 | EmuleMultiPacketAnswerReq of Md4.t * t list
1178 | EmuleCompressedPart of EmuleCompressedPart.t
1179 | EmulePortTestReq of EmulePortTestReq.t
1181 let rec print t =
1182 begin
1183 match t with
1184 | ConnectReq t -> Connect.print t
1185 | ConnectReplyReq t -> Connect.print t
1186 | QueryFileReq t -> QueryFile.print t
1187 | QueryFileReplyReq t -> QueryFileReply.print t
1188 | BlocReq t -> Bloc.print t
1189 | QueryBlocReq t -> QueryBloc.print t
1190 | JoinQueueReq t -> JoinQueue.print t
1191 | AvailableSlotReq t -> AvailableSlot.print t
1192 | ReleaseSlotReq t -> ReleaseSlot.print t
1193 | OutOfPartsReq t -> OutOfParts.print t
1194 | QueryChunksReq t -> QueryChunks.print t
1195 | QueryChunksReplyReq t -> QueryChunksReply.print t
1196 | QueryChunkMd4Req t -> QueryChunkMd4.print t
1197 | QueryChunkMd4ReplyReq t -> QueryChunkMd4Reply.print t
1198 | ViewFilesReplyReq t -> ViewFilesReply.print t
1199 | ViewFilesReq t -> ViewFiles.print t
1200 | ViewDirsReq t -> ViewDirs.print t
1201 | ViewDirsReplyReq t -> ViewDirsReply.print t
1202 | ViewFilesDirReq t -> ViewFilesDir.print t
1203 | ViewFilesDirReplyReq t -> ViewFilesDirReply.print t
1204 | QueueReq t -> OtherLocations.print t
1205 | OtherLocationsReq t -> OtherLocations.print t
1206 | SayReq t -> Say.print t
1207 | SourcesReq t -> Sources.print t
1208 | EndOfDownloadReq t -> EndOfDownload.print t
1209 | NewUserIDReq t -> NewUserID.print t
1210 | NoSuchFileReq t -> NoSuchFile.print t
1211 | QueueRankReq t ->
1212 QueueRank.print t
1214 | EmuleClientInfoReq t ->
1215 EmuleClientInfo.print "EmuleClientInfo" t
1216 | EmuleClientInfoReplyReq t ->
1217 EmuleClientInfo.print "EmuleClientInfoReply" t
1218 | EmuleQueueRankingReq t ->
1219 EmuleQueueRanking.print t
1220 | EmuleRequestSourcesReq t ->
1221 EmuleRequestSources.print t
1222 | EmuleRequestSourcesReplyReq t ->
1223 EmuleRequestSourcesReply.print t
1225 | EmuleFileDescReq t ->
1226 EmuleFileDesc.print t
1228 | EmuleMultiPacketReq (md4, list) ->
1229 lprintf_nl "EmuleMultiPacket for %s:" (Md4.to_string md4);
1230 List.iter (fun t ->
1231 lprintf " ";
1232 print t
1233 ) list
1235 | EmuleMultiPacketAnswerReq (md4, list) ->
1236 lprintf_nl "EmuleMultiPacketAnswer for %s:" (Md4.to_string md4);
1237 List.iter (fun t ->
1238 lprintf " ";
1239 print t
1240 ) list
1241 | EmuleSecIdentStateReq t ->
1242 EmuleSecIdentStateReq.print t
1243 | EmuleSignatureReq t ->
1244 EmuleSignatureReq.print t
1245 | EmulePublicKeyReq t ->
1246 EmulePublicKeyReq.print t
1247 | EmuleCompressedPart t ->
1248 EmuleCompressedPart.print t
1249 | EmulePortTestReq t ->
1250 EmulePortTestReq.print t
1251 | UnknownReq (opcode, s) ->
1252 let len = String.length s in
1253 lprintf_nl "UnknownReq: magic (%d), opcode (%d) len (%d)" opcode
1254 (int_of_char s.[0])
1255 (String.length s);
1256 lprintf "ascii: [";
1257 for i = 0 to len - 1 do
1258 let c = s.[i] in
1259 let n = int_of_char c in
1260 if n > 31 && n < 127 then
1261 lprintf " %c" c
1262 else
1263 lprintf "(%d)" n
1264 done;
1265 lprintf "]\n";
1266 lprintf "dec: [";
1267 for i = 0 to len - 1 do
1268 let c = s.[i] in
1269 let n = int_of_char c in
1270 lprintf "(%d)" n
1271 done;
1272 lprintf "]\n"
1275 let rec parse_emule_packet emule opcode len s =
1277 lprintf "Emule magic: %d opcode %d:" magic opcode; lprint_newline ();
1278 dump s; lprint_newline ();
1280 let t = match opcode with
1281 | 1 -> EmuleClientInfoReq (EmuleClientInfo.parse len s)
1282 | 2 -> EmuleClientInfoReplyReq (EmuleClientInfo.parse len s)
1284 | 0x60 (* 96 *) -> EmuleQueueRankingReq (EmuleQueueRanking.parse len s)
1286 | 0x61 (* 97 *) -> EmuleFileDescReq (EmuleFileDesc.parse len s)
1288 | 0x81 (* 129 *) -> EmuleRequestSourcesReq (EmuleRequestSources.parse len s)
1289 | 0x82 (* 130 *) ->
1290 EmuleRequestSourcesReplyReq (
1291 EmuleRequestSourcesReply.parse emule len s)
1293 | 0x40 (* 64 *) ->
1294 (* OP_COMPRESSEDPART *)
1295 EmuleCompressedPart (EmuleCompressedPart.parse false len s)
1297 | 0x85 (* 133 *) ->
1298 EmulePublicKeyReq(EmulePublicKeyReq.parse len s)
1300 | 0x86 (* 134 *) ->
1301 EmuleSignatureReq(EmuleSignatureReq.parse len s)
1303 | 0x87 (* 135 *) ->
1304 EmuleSecIdentStateReq (EmuleSecIdentStateReq.parse len s)
1306 (* | 0x90 (* 144 *) -> RequestPreview *)
1307 (* | 0x91 (* 145 *) -> PreviewAnswer *)
1308 | 0x92 (* 146 *) ->
1309 let md4 = get_md4 s 1 in
1311 (* lprintf "MULTI EMULE VERSION %d"
1312 (extendedrequest emule); print_newline (); *)
1313 (* let pos = 17 in *)
1314 let rec iter pos =
1315 if pos < len then
1316 let opcode = get_uint8 s pos in
1317 match opcode with
1318 0x58 (* 88 *) ->
1319 let bitmap, pos = get_bitmap s (pos+1) in
1320 let ncompletesources, pos =
1321 if extendedrequest emule > 1 then
1322 get_int16 s pos, pos+2
1323 else -1, pos
1325 (QueryFileReq {
1326 QueryFile.md4 = md4;
1327 QueryFile.emule_extension = Some (bitmap, ncompletesources);
1328 }) :: (iter pos)
1329 | 0x4F (* 79 *) ->
1330 (QueryChunksReq md4) :: iter (pos+1)
1331 | 0x81 (* 129 *) ->
1332 (EmuleRequestSourcesReq md4) :: iter (pos+1)
1333 | _ ->
1334 lprintf_nl "Unknown short emule packet %d" opcode;
1335 raise Not_found
1336 else
1339 EmuleMultiPacketReq (md4, iter 17)
1341 | 0x93 (* 147 *) ->
1342 if String.length s < 16 then begin
1343 if !verbose_unknown_messages then lprintf_nl "EmuleMultiPacketAnswer: incomplete request";
1344 raise Not_found
1345 end;
1346 let md4 = get_md4 s 1 in
1348 (* lprintf "MULTI EMULE VERSION %d"
1349 (extendedrequest emule); print_newline (); *)
1350 let rec iter s pos len =
1351 if pos < len then
1352 let opcode = get_uint8 s pos in
1353 match opcode with
1354 | 89 ->
1355 let module Q = QueryFileReply in
1356 let name, pos = get_string s (pos+1) in
1357 let q = {
1358 Q.md4 = md4;
1359 Q.name = name;
1360 } in
1361 (QueryFileReplyReq q) :: (iter s pos len)
1362 | 80 ->
1363 let module Q = QueryChunksReply in
1364 let chunks, pos = get_bitmap s (pos+1) in
1365 let q = {
1366 Q.md4 = md4;
1367 Q.chunks = chunks;
1368 } in
1369 (QueryChunksReplyReq q) :: (iter s pos len)
1370 | _ ->
1371 lprintf_nl "Unknown packet in emule multipacket 0x93: %d" opcode;
1372 raise Not_found
1373 else
1376 EmuleMultiPacketAnswerReq (md4, iter s 17 len)
1378 | 0xa1 (* 161 *) -> (* OP_COMPRESSEDPART_I64 *)
1379 EmuleCompressedPart (EmuleCompressedPart.parse true len s)
1380 | 0xa2 -> BlocReq (Bloc.parse true len s) (* OP_SENDINGPART_I64 *)
1381 | 0xa3 -> QueryBlocReq (QueryBloc.parse true len s) (*OP_REQUESTPARTS_I64 *)
1382 | 0xfe (* 254 *) ->
1383 EmulePortTestReq s
1385 | code ->
1386 if !CommonOptions.verbose_unknown_messages then
1387 lprintf_nl "EDK: unknown eMule message %d" code;
1388 raise Not_found
1391 lprintf "EMULE MESSAGE: "; lprint_newline ();
1392 print t;
1393 lprint_newline (); *)
1396 and parse emule_version magic s =
1398 let len = String.length s in
1399 if len = 0 then raise Not_found;
1400 let opcode = int_of_char (s.[0]) in
1401 (*lprintf "opcode: %d" opcode; lprint_newline (); *)
1402 match magic with
1403 227 ->
1404 begin
1405 match opcode with
1406 | 1 -> ConnectReq (Connect.parse false len s)
1407 | 70 -> BlocReq (Bloc.parse false len s)
1408 | 71 -> QueryBlocReq (QueryBloc.parse false len s)
1409 | 72 -> NoSuchFileReq (NoSuchFile.parse len s)
1410 | 73 -> EndOfDownloadReq (EndOfDownload.parse len s)
1411 | 74 -> ViewFilesReq (ViewFiles.parse len s)
1412 | 75 -> ViewFilesReplyReq (ViewFilesReply.parse len s)
1413 | 76 -> ConnectReplyReq (Connect.parse true len s)
1414 | 77 -> NewUserIDReq (NewUserID.parse len s)
1415 | 78 -> SayReq (Say.parse len s)
1416 | 79 -> QueryChunksReq (QueryChunks.parse len s)
1417 | 80 -> QueryChunksReplyReq (QueryChunksReply.parse len s)
1418 | 81 -> QueryChunkMd4Req (QueryChunkMd4.parse len s)
1419 | 82 -> QueryChunkMd4ReplyReq (QueryChunkMd4Reply.parse len s)
1420 (* JoinQueue: the sender wants to join the upload queue *)
1421 | 84 -> JoinQueueReq (JoinQueue.parse len s)
1422 (* AvailableSlot: there is an available slot in upload queue *)
1423 | 85 -> AvailableSlotReq (AvailableSlot.parse len s)
1424 (* ReleaseSlot: the upload is finished *)
1425 | 86 -> ReleaseSlotReq (ReleaseSlot.parse len s)
1426 (* OutOfParts: the upload slot is not available *)
1427 | 87 -> OutOfPartsReq (OutOfParts.parse len s)
1428 | 88 -> QueryFileReq (QueryFile.parse emule_version len s)
1429 | 89 -> QueryFileReplyReq (QueryFileReply.parse len s)
1430 | 92 -> QueueRankReq (QueueRank.parse len s)
1431 | 93 -> ViewDirsReq (ViewDirs.parse len s)
1432 | 94 -> ViewFilesDirReq (ViewFilesDir.parse len s)
1434 | 95 -> ViewDirsReplyReq (ViewDirsReply.parse len s)
1435 | 96 -> ViewFilesDirReplyReq (ViewFilesDirReply.parse len s)
1437 | 250 -> SourcesReq (Sources.parse len s)
1439 | _ -> raise Not_found
1442 | 0xc5 -> (* 197: emule extended protocol *)
1443 parse_emule_packet emule_version opcode len s
1445 (* Compressed packet, probably sent by cDonkey ? *)
1447 | 0xD4 -> (* 212 *)
1449 let s = Zlib.uncompress_string2 (String.sub s 1 (len-1)) in
1450 let s = Printf.sprintf "%c%s" (char_of_int opcode) s in
1451 begin try
1452 parse_emule_packet emule_version opcode (String.length s) s
1453 with
1454 | e ->
1455 if !CommonOptions.verbose_unknown_messages then begin
1456 lprintf_nl "Unknown message From client: %s (magic %d)"
1457 (Printexc2.to_string e) magic;
1458 let tmp_file = Filename2.temp_file "comp" "pak" in
1459 File.from_string tmp_file s;
1460 lprintf_nl "Saved unknown packet %s" tmp_file;
1461 dump s;
1462 lprint_newline ();
1463 end;
1464 UnknownReq (magic,s)
1467 | _ ->
1468 if !CommonOptions.verbose_unknown_messages then
1469 lprintf_nl "Strange magic: %d" magic;
1470 raise Not_found
1471 with
1472 | e ->
1473 if !CommonOptions.verbose_unknown_messages then begin
1474 lprintf_nl "Unknown message From client: %s (magic %d)"
1475 (Printexc2.to_string e) magic;
1476 let tmp_file = Filename2.temp_file "comp" "pak" in
1477 File.from_string tmp_file s;
1478 lprintf_nl "Saved unknown packet %s" tmp_file;
1480 dump s;
1481 lprint_newline ();
1482 end;
1483 UnknownReq (magic,s)
1485 let write emule buf t =
1486 let magic = match t with
1487 EmuleMultiPacketAnswerReq _
1488 | EmuleMultiPacketReq _
1489 | EmuleSecIdentStateReq _
1490 | EmuleSignatureReq _
1491 | EmulePublicKeyReq _
1492 | EmuleRequestSourcesReplyReq _
1493 | EmuleRequestSourcesReq _
1494 | EmuleClientInfoReplyReq _
1495 | EmuleClientInfoReq _
1496 | EmuleFileDescReq _
1497 | EmuleQueueRankingReq _
1498 | EmuleCompressedPart _
1499 -> 0xC5
1500 | QueryBlocReq t when t.QueryBloc.usesixtyfour -> 0xC5
1501 | BlocReq t when t.Bloc.usesixtyfour -> 0xC5
1503 -> 227
1505 begin
1506 match t with
1507 | ConnectReq t ->
1508 buf_int8 buf 1;
1509 Connect.write false buf t
1510 | ConnectReplyReq t ->
1511 buf_int8 buf 76;
1512 Connect.write true buf t
1513 | QueryFileReq t ->
1514 buf_int8 buf 88;
1515 QueryFile.write emule buf t
1516 | QueryFileReplyReq t ->
1517 buf_int8 buf 89;
1518 QueryFileReply.write buf t
1519 | QueueReq t ->
1520 buf_int8 buf 77;
1521 OtherLocations.write buf t
1522 | QueryBlocReq t ->
1523 buf_int8 buf (if t.QueryBloc.usesixtyfour then 0xa3 else 71);
1524 QueryBloc.write buf t
1525 | BlocReq t ->
1526 buf_int8 buf (if t.Bloc.usesixtyfour then 0xa2 else 70);
1527 Bloc.write buf t
1528 | JoinQueueReq t ->
1529 buf_int8 buf 84;
1530 JoinQueue.write emule buf t
1531 | QueryChunksReq t ->
1532 buf_int8 buf 79;
1533 QueryChunks.write buf t
1534 | QueryChunksReplyReq t ->
1535 buf_int8 buf 80;
1536 QueryChunksReply.write buf t
1537 | QueryChunkMd4Req t ->
1538 buf_int8 buf 81;
1539 QueryChunkMd4.write buf t
1540 | QueryChunkMd4ReplyReq t ->
1541 buf_int8 buf 82;
1542 QueryChunkMd4Reply.write buf t
1543 | AvailableSlotReq t ->
1544 buf_int8 buf 85;
1545 AvailableSlot.write buf t
1546 | ReleaseSlotReq t ->
1547 buf_int8 buf 86;
1548 ReleaseSlot.write buf t
1549 | OutOfPartsReq t ->
1550 buf_int8 buf 87;
1551 OutOfParts.write buf t
1552 | ViewFilesReq t ->
1553 buf_int8 buf 74;
1554 ViewFiles.write buf t
1555 | ViewFilesReplyReq t ->
1556 buf_int8 buf 75;
1557 ViewFilesReply.write buf t
1558 | ViewDirsReq t ->
1559 buf_int8 buf 93;
1560 ViewDirs.write buf t
1561 | ViewDirsReplyReq t ->
1562 buf_int8 buf 95;
1563 ViewDirsReply.write buf t
1564 | ViewFilesDirReq t ->
1565 buf_int8 buf 94;
1566 ViewFilesDir.write buf t
1567 | ViewFilesDirReplyReq t ->
1568 buf_int8 buf 96;
1569 ViewFilesDirReply.write buf t
1570 | OtherLocationsReq t ->
1571 buf_int8 buf 72;
1572 OtherLocations.write buf t
1573 | SayReq t ->
1574 buf_int8 buf 78;
1575 Say.write buf t
1576 | SourcesReq t ->
1577 buf_int8 buf 250;
1578 Sources.write buf t
1579 | NewUserIDReq t ->
1580 buf_int8 buf 77;
1581 NewUserID.write buf t
1582 | EndOfDownloadReq t ->
1583 buf_int8 buf 73;
1584 EndOfDownload.write buf t
1585 | NoSuchFileReq t ->
1586 buf_int8 buf 72;
1587 NoSuchFile.write buf t
1588 | QueueRankReq t ->
1589 buf_int8 buf 92;
1590 QueueRank.write buf t
1592 | EmuleClientInfoReq t ->
1593 buf_int8 buf 1;
1594 EmuleClientInfo.write buf t
1595 | EmuleClientInfoReplyReq t ->
1596 buf_int8 buf 2;
1597 EmuleClientInfo.write buf t
1598 | EmuleQueueRankingReq t ->
1599 buf_int8 buf 0x60;
1600 EmuleQueueRanking.write buf t
1601 | EmuleRequestSourcesReq t ->
1602 buf_int8 buf 0x81;
1603 EmuleRequestSources.write buf t
1604 | EmuleRequestSourcesReplyReq t ->
1605 buf_int8 buf 0x82;
1606 EmuleRequestSourcesReply.write emule buf t
1607 | EmuleFileDescReq t ->
1608 buf_int8 buf 0x61;
1609 EmuleFileDesc.write buf t
1610 | EmuleCompressedPart t ->
1611 buf_int8 buf (if t.EmuleCompressedPart.usesixtyfour then 0xa1 else 0x40);
1612 EmuleCompressedPart.write buf t
1613 | EmuleMultiPacketReq (md4, list) ->
1614 buf_int8 buf 0x92;
1615 buf_md4 buf md4;
1616 List.iter (fun t ->
1617 match t with
1618 QueryFileReq t ->
1619 buf_int8 buf 0x58;
1620 (match t.QueryFile.emule_extension with
1621 None -> ()
1622 | Some (bitmap, ncompletesources) ->
1623 write_bitmap buf bitmap;
1624 if ncompletesources >= 0 && extendedrequest emule > 1 then
1625 buf_int16 buf ncompletesources)
1626 | QueryChunksReq _ ->
1627 buf_int8 buf 0x4F
1628 | EmuleRequestSourcesReq _ ->
1629 buf_int8 buf 0x81
1630 | _ ->
1631 lprintf_nl "WARNING: Don't know how to write short packet:";
1632 print t;
1633 print_newline ();
1634 ) list
1636 | EmuleMultiPacketAnswerReq (md4, list) ->
1637 buf_int8 buf 0x93;
1638 buf_md4 buf md4;
1639 List.iter (fun t ->
1640 match t with
1641 QueryFileReplyReq t ->
1642 buf_int8 buf 89;
1643 buf_string buf t.QueryFileReply.name
1644 | QueryChunksReplyReq t ->
1645 buf_int8 buf 80;
1646 write_bitmap buf t.QueryChunksReply.chunks
1647 | _ ->
1648 lprintf_nl "WARNING: Don't know how to write short packet:";
1649 print t;
1650 print_newline ();
1651 ) list
1653 | EmuleSecIdentStateReq t ->
1654 buf_int8 buf 0x87;
1655 EmuleSecIdentStateReq.write buf t
1657 | EmuleSignatureReq t ->
1658 buf_int8 buf 0x86;
1659 EmuleSignatureReq.write buf t
1661 | EmulePublicKeyReq t ->
1662 buf_int8 buf 0x85;
1663 EmulePublicKeyReq.write buf t
1665 | EmulePortTestReq t ->
1666 buf_int8 buf 0xfe;
1667 EmulePortTestReq.write buf;
1669 | UnknownReq (opcode, s) ->
1670 Buffer.add_string buf s
1672 end;
1673 magic
1676 ------------------------------------------------------
1677 1044008574.297 192.168.0.3:37522 -> 80.26.114.12:13842 of len 6
1678 ? Become Friend ? ping ?
1680 (227)(1)(0)(0)(0)
1681 (98)
1683 ------------------------------------------------------
1684 1044008576.274 80.26.114.12:13842 -> 192.168.0.3:37522 of len 6
1685 ? OK ? pong ?
1687 (227)(1)(0)(0)(0)(99)]
1689 ------------------------------------------------------
1690 1044008687.977 192.168.0.3:37522 -> 80.26.114.12:13842 of len 6
1691 Browse Main Dir
1693 (227)(1)(0)(0)(0)
1694 (93)
1696 ------------------------------------------------------
1697 1044008690.832 80.26.114.12:13842 -> 192.168.0.3:37522 of len 43
1698 Browse Main Dir Reply
1699 (227)(38)(0)(0)(0)
1700 (95)
1701 (2)(0)(0)(0) --------> 2 directories:
1702 (12)(0) C : \ D o w n l o a d s
1703 (17)(0) ! I n c o m p l e t e F i l e s
1706 ------------------------------------------------------
1707 1044008766.137 192.168.0.3:37522 -> 80.26.114.12:13842 of len 20
1708 Browse directory
1710 (227)(15)(0)(0)(0)
1711 (94)
1712 (12)(0) C : \ D o w n l o a d s
1714 ------------------------------------------------------
1715 1044008769.045 80.26.114.12:13842 -> 192.168.0.3:37522 of len 300
1716 (227) p(8)(0)(0) `(12)(0) C : \ D o w n l o a d s(21)(0)(0)(0)(152) 2(229)(158)(218)(141)(217)(138) n(181) 6 ( ) h V(179)(0)(0)(0)(0)(0)(0)(3)(0)(0)(0)(2)(1)(0)(1)(11)(0) d e s k t o p . i n i(3)(1)(0)(2)(180)(0)(0)(0)(3)(1)(0)(19)(0)(0)(0)(0) y(16)(15) 9 O Z(219) i e(200)(10) |(29)(27) F(128)(0)(0)(0)(0)(0)(0)(5)(0)(0)(0)(2)(1)(0)(1)(15)(0) u t b o n u s p a c k . z i p(3)(1)(0)(2) J(16)(221)(0)(2)(1)(0)(3)(3)(0) P r o(2)(1)(0)(4)(3)(0) z i p(3)(1)(0)(19)(0)(0)(0)(0)(178)(145)(161)(146) P(199)(228)(249) K a :(9)(237)(246)(233) v(0)(0)(0)(0)(0)(0)(5)(0)(0)(0)(2)(1)(0)(1)(11)(0) c t f m a p s . z i p(3)(1)(0)(2)(236)(239)(23)(0)(2)(1)(0)(3)(3)(0) P r o(2)(1)(0)(4)(3)(0) z i p(3)(1)(0)(19)(0)(0)(0)(0) a n(251)(225) ^ g(205)(133)(25)(12) # ' J A(221) `(0)(0)(0)(0)(0)(0)(5)(0)(0)(0)(2)(1)(0)(1)(23)(0) u t i n o x x p a c k - n o - u m o d . z i p(3)(1)(0)(2)]
1717 (227)(112)(8)(0)(0)
1719 (96)
1720 (12)(0) C : \ D o w n l o a d s
1721 (21)(0)(0)(0) 21 files
1723 (152)(50)(229)(158)(218)(141)(217)(138)(110)(181)(54)(40)(41)(104)(86)(179)
1724 (0)(0)(0)(0)
1725 (0)(0)
1726 (3)(0)(0)(0)
1728 (1)(0)(1)
1729 (11)(0) d e s k t o p . i n i
1731 (1)(0)(2)
1732 (180)(0)(0)(0)
1734 (1)(0)(19)
1735 (0)(0)(0)(0)
1737 (121)(16)(15)(57)(79)(90)(219)(105)(101)(200)(10)(124)(29)(27)(70)(128)
1738 (0)(0)(0)(0)
1739 (0)(0)
1740 (5)(0)(0)(0)
1742 (1)(0)(1)
1743 (15)(0) u t b o n u s p a c k . z i p
1745 (1)(0)(2)
1746 (74)(16)(221)(0)
1748 (1)(0)(3)
1749 (3)(0) Pro
1751 (1)(0)(4)
1752 (3)(0) zip
1754 (1)(0)(19)
1755 (0)(0)(0)(0)
1756 ....
1760 (* 92: Queue Rank *)