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
23 open TcpBufferedSocket
39 let buf = TcpBufferedSocket.internal_buf
41 let client_msg_to_string emule_version msg
=
45 let magic = DonkeyProtoClient.write emule_version
buf msg
in
46 let s = Buffer.contents
buf in
47 let len = String.length
s - 5 in
48 s.[0] <- char_of_int
magic;
52 let server_msg_to_string msg
=
56 DonkeyProtoServer.write
buf msg
;
58 if !verbose_msg_servers
then begin
59 lprintf_nl
"MESSAGE TO SERVER:";
60 DonkeyProtoServer.print msg
;
64 let s = Buffer.contents
buf in
65 let len = String.length
s - 5 in
69 let server_send sock m
=
71 lprintf "Message to server"; lprint_newline ();
72 DonkeyProtoServer.print m;
74 write_string sock
(server_msg_to_string m
)
76 let direct_client_sock_send emule_version sock m
=
77 write_string sock
(client_msg_to_string emule_version m
)
80 let emule_version = c
.client_emule_proto
in
81 do_if_connected c
.client_source
.DonkeySources.source_sock
(fun sock
->
82 if !verbose_msg_clients
|| c
.client_debug
then begin
83 lprintf_nl
"Sent to client %s" (full_client_identifier c
);
84 DonkeyProtoClient.print m
;
87 direct_client_sock_send emule_version sock m
)
89 let servers_send socks m
=
90 let m = server_msg_to_string m in
91 List.iter
(fun s -> write_string
s m) socks
93 let client_handler2 c ff f
=
97 let module M
= DonkeyProtoClient
in
98 let b = TcpBufferedSocket.buf sock
in
101 let emule_version = match !c
with
102 None
-> emule_proto
();
103 | Some c
-> c
.client_emule_proto
105 let opcode = get_uint8
b.buf b.pos
in
106 let msg_len = get_int
b.buf (b.pos
+1) in
107 if b.len >= 5 + msg_len then
109 let s = String.sub
b.buf (b.pos
+5) msg_len in
110 buf_used
b (msg_len + 5);
111 let t = M.parse
emule_version opcode s in
113 lprint_newline (); *)
118 | Some c
-> f c
t sock
124 let cut_messages parse f sock nread
=
125 let b = TcpBufferedSocket.buf sock
in
128 let opcode = get_uint8
b.buf b.pos
in
129 let msg_len = get_int
b.buf (b.pos
+1) in
130 if b.len >= 5 + msg_len then
132 let s = String.sub
b.buf (b.pos
+5) msg_len in
133 buf_used
b (msg_len + 5);
134 let t = parse
opcode s in
141 let really_udp_send t ip port msg isping
=
143 if !verbose_udp
then begin
144 lprintf_nl
"Message UDP%s to %s:%d\n%s"
145 (if isping
then "(PING)" else "") (Ip.to_string ip
)
146 port
(DonkeyProtoUdp.print msg
);
151 DonkeyProtoUdp.write
buf msg
;
152 let s = Buffer.contents
buf in
153 UdpSocket.write
t isping
s ip port
155 lprintf_nl
"Exception %s in udp_send" (Printexc2.to_string e
)
157 let udp_send t ip port msg
=
158 really_udp_send t ip port msg
false
160 let udp_handler f sock event
=
161 let module M
= DonkeyProtoUdp
in
163 UdpSocket.READ_DONE
->
164 UdpSocket.read_packets sock
(fun p
->
166 let pbuf = p
.UdpSocket.udp_content
in
167 let len = String.length
pbuf in
169 let t = M.parse
(int_of_char
pbuf.[0])
170 (String.sub
pbuf 1 (len-1)) in
177 let udp_basic_handler f sock event
=
179 UdpSocket.READ_DONE
->
180 UdpSocket.read_packets sock
(fun p
->
182 let pbuf = p
.UdpSocket.udp_content
in
183 let len = String.length
pbuf in
185 int_of_char
pbuf.[0] <> DonkeyOpenProtocol.udp_magic
then begin
186 if !verbose_unknown_messages
then begin
187 lprintf_nl
"Received unknown UDP packet";
191 let t = String.sub
pbuf 1 (len-1) in
195 lprintf_nl
"Error %s in udp_basic_handler"
196 (Printexc2.to_string e
)
201 let new_string msg
s =
202 let len = String.length
s - 5 in
205 let empty_string = ""
208 (string_tag Field_Filename
210 let name = file_best_name file
in
211 let name = if String2.starts_with
name "hidden." then
212 String.sub
name 7 (String.length
name - 7)
214 if !verbose_share
then lprintf_nl
"tag_file: Sharing %s" name;
217 (int64_tag Field_Size_Hi
(Int64.shift_right_logical file
.file_file
.impl_file_size
32)) ::
218 (int64_tag Field_Size
(Int64.logand file
.file_file
.impl_file_size
0xffffffffL
)) ::
220 (match file
.file_format
with
221 FormatNotComputed next_time
when
222 next_time
< last_time
() ->
224 if !verbose_share
then lprintf_nl
"Find format %s"
225 (file_disk_name file
);
226 file
.file_format
<- (
228 CommonMultimedia.get_info
229 (file_disk_name file
)
231 FormatUnknown
-> FormatNotComputed
(last_time
() + 300)
237 match file
.file_format
with
238 FormatNotComputed _
| FormatUnknown
-> []
241 { tag_name
= Field_Type
; tag_value
= String
"Video" };
242 { tag_name
= Field_Format
; tag_value
= String
"avi" };
246 { tag_name
= Field_Type
; tag_value
= String
"Audio" };
247 { tag_name
= Field_Format
; tag_value
= String
"mp3" };
251 let max_st = ref OGG_INDEX_STREAM
in
253 if st
.stream_type
> !max_st
254 then max_st := st
.stream_type
;
258 | OGG_VORBIS_STREAM
->
260 { tag_name
= Field_Type
; tag_value
= String
"Audio" };
261 { tag_name
= Field_Format
; tag_value
= String
"ogg" };
264 | OGG_THEORA_STREAM
->
266 { tag_name
= Field_Type
; tag_value
= String
"Video" };
267 { tag_name
= Field_Format
; tag_value
= String
"ogg" };
271 | FormatType
(format
, kind
) ->
273 { tag_name
= Field_Type
; tag_value
= String kind
};
274 { tag_name
= Field_Format
; tag_value
= String format
};
278 (* Computes tags for shared files (for clients) *)
279 let make_tagged sock files
=
280 (List2.tail_map
(fun file
->
282 f_md4
= file
.file_md4
;
283 f_ip
= client_ip sock
;
284 f_port
= !!donkey_port
;
285 f_tags
= tag_file file
;
289 (* Computes tags for shared files with the special ip and
290 port values for newer servers. We should assume that the
291 server is newer if it supports compression, like emule
293 let make_tagged_server newer_server sock files
=
295 (List2.tail_map
(fun file
->
297 f_md4
= file
.file_md4
;
298 f_ip
= (if (file_state file
= FileShared
) then Ip.of_string
"251.251.251.251" else Ip.of_string
"252.252.252.252");
299 f_port
= (if (file_state file
= FileShared
) then 0xFBFB else 0xFCFC);
300 f_tags
= tag_file file
;
304 make_tagged sock files
306 let server_send_share compressed sock msg
=
308 !!client_buffer_size
- 100
309 - TcpBufferedSocket.remaining_to_write sock
314 let nfiles, prev_len
=
315 DonkeyProtoServer.Share.write_files_max
buf
316 ( make_tagged_server compressed
(Some sock
) msg
)
319 let s = Buffer.contents
buf in
321 let s = String.sub
s 0 prev_len
in
322 if !verbose_share
|| !verbose
then
323 lprintf_nl
"Sending %d share%s to server %s:%d%s"
324 nfiles (Printf2.print_plural_s
nfiles) (Ip.to_string
(peer_ip sock
)) (peer_port sock
)
325 (if compressed
then " (zlib)" else "");
329 Zlib.compress_string
s
333 (* Emule only sends the string compressed when it
334 is smaller in that state. *)
335 if compressed
&& ((String.length
s_c) < (String.length
s)) then
339 buf_int8
buf 21; (* ShareReq *)
340 Buffer.add_string
buf s_c;
347 buf_int8
buf 21; (* ShareReq *)
348 Buffer.add_string
buf s;
352 let len = String.length
s - 5 in
356 let client_send_files sock msg
=
357 let max_len = !!client_buffer_size
- 100 -
358 TcpBufferedSocket.remaining_to_write sock
in
362 buf_int8
buf 75; (* ViewFilesReply *)
364 let nfiles, prev_len
= DonkeyProtoClient.ViewFilesReply.write_files_max
buf (
365 make_tagged (Some sock
) msg
)
367 let s = Buffer.contents
buf in
368 let s = String.sub
s 0 prev_len
in
369 let len = String.length
s - 5 in
374 let client_send_dir sock dir files
=
375 let max_len = !!client_buffer_size
- 100 -
376 TcpBufferedSocket.remaining_to_write sock
in
380 buf_int8
buf 96; (* ViewFilesDirReply *)
383 let pos = Buffer.length
buf in
384 let nfiles, prev_len
= DonkeyProtoClient.ViewFilesReply.write_files_max
buf (
385 make_tagged (Some sock
) files
)
387 let s = Buffer.contents
buf in
388 let s = String.sub
s 0 prev_len
in
389 let len = String.length
s - 5 in begin
391 str_int
s (pos-4) nfiles;
395 let udp_server_send s t =
396 udp_send (get_udp_sock
()) s.server_ip
(s.server_port
+4) t
398 let udp_server_send_ping s t =
399 really_udp_send (get_udp_sock
()) s.server_ip
(s.server_port
+4) t true