1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 module QueryReplyUdp
= struct
35 type t
= tagged_file list
37 let names_of_tag = file_common_tags
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
53 let rec iter pos list
=
55 let file, pos
= get_file s pos
in
57 iter pos (file :: list
)
63 Printf.bprintf oc
"FOUND:\n";
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"
74 List.iter (fun file ->
75 buf_md4 buf
file.f_md4
;
77 buf_port buf
file.f_port
;
78 buf_tags buf
file.f_tags
names_of_tag
83 module QueryCallUdp
= struct
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; }
97 Printf.bprintf oc
"QueryCall %s : %d --> %Ld\n" (Ip.to_string t
.ip)
103 buf_ip buf
(ip_of_id t
.id)
107 module PingServerUdp
= struct (* client -> serveur pour identification ? *)
112 get_uint64_32 s
1 (*, get_int8 s 2, get_int8 s 3*)
116 Printf.bprintf oc
"PING %s\n" (Int64.to_string 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) =
131 module PingServerReplyUdp
= struct (* reponse du serveur a 150 *)
137 soft_limit
: int64
option;
138 hard_limit
: int64
option;
139 max_users
: int64
option;
140 lowid_users
: int64
option;
147 udp_obfuscation
: bool;
148 tcp_obfuscation
: bool;
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;
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;
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
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
-> ()
197 match t
.soft_limit with Some x
-> x
| None
-> 0L);
199 match t
.hard_limit with Some x
-> x
| None
-> 0L);
201 match t
.max_users with Some x
-> x
| None
-> 0L)
205 module ServerDescUdp
= struct
208 let invalid_len = Int64.of_int
0xF0FF
210 let parse len s
= Int64.of_string s
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!
227 module ServerDescReplyUdp
= struct
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
261 challenge = challenge;
264 let parse2 len s
challenge =
265 let stags,pos = get_tags s
5 names_of_tag in
268 List.iter (fun tag
->
270 | { tag_name
= Field_KNOWN
"servername"; tag_value
= String v
} ->
272 | { tag_name
= Field_KNOWN
"description"; tag_value
= String v
} ->
280 challenge = challenge;
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
290 Printf.bprintf b
"ServerDescReplyUdpReq\n";
291 Printf.bprintf b
"name : %s\n" t
.name;
292 Printf.bprintf b
"desc : %s\n" t
.desc
295 buf_string buf t
.name;
296 buf_string buf t
.desc
300 module ServerListUdp
= struct
307 let ip = get_ip s
1 in
317 Printf.bprintf b
"ServerListUdp %s\n" (Ip.to_string t
.ip)
324 module QueryServersUdp
= DonkeyProtoServer.QueryServers
325 module QueryServersReplyUdp
= DonkeyProtoServer.QueryServersReply
326 module QueryLocationUdp
= struct
331 let rec iter pos list
=
333 iter (pos+16) (get_md4 s
pos :: list
)
340 Printf.bprintf b
"UDP QUERY LOCATIONS: ";
341 List.iter (fun md4 -> Printf.bprintf b
"%s " (Md4.to_string
md4)) 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 *)
353 let rec iter pos list
=
355 iter (pos+20) ( (get_md4 s
pos, get_uint64_32 s
(pos+16)) :: list
)
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"
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
377 let rec iter_len pos list
=
379 let md4 = get_md4 s
pos in
380 let n = get_uint8 s
(pos+16) in
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))
388 let pos = pos+17+6*n + 2 in
389 iter_len pos ({ locs =locs; md4 = md4 } :: list
)
396 Printf.bprintf b
"UDP LOCATION: %d\n" (List.length t
);
398 Printf.bprintf b
" of %s:\n" (Md4.to_string t
.md4);
400 Printf.bprintf b
"%s:%d " (Ip.to_string l
.ip) l
.port;
402 Printf.bprintf b
"\n") t
407 buf_int8 buf
(List.length t
.locs);
417 module QueryUdp
= DonkeyProtoServer.Query
421 let rec iter list pos =
423 let t, pos = parse_query s pos in
430 Printf.bprintf b "UDP QUERY: %d\n" (List.length t);
431 List.iter (bprint_query b) t
439 module QueryIDReplyUdp
= DonkeyProtoServer.QueryIDReply
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
468 | UnknownUdpReq
of int * string
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 (); *)
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
501 if !verbose_unknown_messages
then begin lprintf
"Unknown UDP request:\n"; dump s
end;
502 UnknownUdpReq
(magic
, s
)
505 let b = Buffer.create
100 in
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
;
543 Printf.bprintf
b "\n";
549 | UnknownUdpReq
(magic
, s
) ->
551 Buffer.add_string buf s
553 | EmuleReaskFilePingUdpReq
md4 ->
558 | EmuleReaskAckUdpReq
md4 ->
563 | EmuleFileNotFoundUdpReq
->
567 | EmuleQueueFullUdpReq
->
574 | QueryServersUdpReq
t ->
576 QueryServersUdp.write buf
t
577 | QueryServersReplyUdpReq
t ->
579 QueryServersReplyUdp.write buf
t
581 | ServerDescUdpReq
t ->
583 ServerDescUdp.write buf
t
584 | ServerDescReplyUdpReq
t ->
586 ServerDescReplyUdp.write buf
t
587 | ServerListUdpReq
t ->
589 ServerListUdp.write buf
t
591 | PingServerUdpReq
t ->
593 PingServerUdp.write buf
t
594 | PingServerReplyUdpReq
t ->
596 PingServerReplyUdp.write buf
t
598 | QueryLocationUdpReq
t ->
600 QueryLocationUdp.write buf
t
601 | QueryLocationUdpReq2
t ->
603 QueryLocationUdpReq2.write buf
t
604 | QueryLocationReplyUdpReq
t ->
606 QueryLocationReplyUdp.write buf
t
610 | QueryMultipleUdpReq
t ->
613 | QueryReplyUdpReq
t ->
615 QueryReplyUdp.write buf
t
616 | QueryCallUdpReq
t ->
618 QueryCallUdp.write buf
t
619 | FileGroupInfoUdpReq
t ->
621 QueryLocationReplyUdp.write buf
t
623 | QueryIDReplyUdpReq
t ->
625 QueryIDReplyUdp.write buf
t
627 | EmulePortTestReq
->
635 | EmuleQueueFullUdpReq
636 | EmuleFileNotFoundUdpReq
637 | EmuleReaskAckUdpReq _
638 | EmuleReaskFilePingUdpReq _
639 | UnknownUdpReq _
-> assert false