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
26 open TcpBufferedSocket
29 (*************************************************************************)
33 (*************************************************************************)
35 (* Store the result of a computation for a very short time to avoid
36 recomputing it too often. Each value is associated with a uniq
37 '(string, int1, int2)' that should be provided by the caller.
40 module ShortLazy
: sig
41 val compute
: string * int * int -> ('a
-> 'b
) -> 'a
-> 'b
46 let short_lazy_values = Hashtbl.create
111
47 let compute name f x
=
48 let f = (Obj.magic
f : t
-> t
) in
49 let x = (Obj.magic
x : t
) in
51 let (f'
,x'
,v
) = Hashtbl.find
short_lazy_values name
in
53 if f'
!= f || x <> x'
then
54 (Hashtbl.remove
short_lazy_values name
; raise Not_found
);
58 Hashtbl.add
short_lazy_values name
(f,x,v);
62 add_infinite_timer
5. (fun _ -> Hashtbl.clear
short_lazy_values)
65 (*************************************************************************)
69 (*************************************************************************)
71 (* ripped from gui_misc *)
78 let size_of_int64 size
=
79 if !!html_mods_human_readable
then
80 let f = Int64.to_float size
in
82 Printf.sprintf
"%.2fT" (f /. tob)
85 Printf.sprintf
"%.2fG" (f /. go)
88 Printf.sprintf
"%.1fM" (f /. mo)
91 Printf.sprintf
"%.1fk" (f /. ko)
97 let networks_string = ref ""
99 let patches_string = ref ""
101 let is_startup_phase = ref true
104 Printf.sprintf
"MLNet %s: Multi-Network p2p client (%s)"
105 Autoconf.current_version
!networks_string
107 (* Should we try to find another port when we cannot bind to the one set
108 in an option, and then change the option accordingly. ?> *)
109 let find_other_port = ref false
111 let upnp_port_forwarding () = !!upnp_port_forwarding && Autoconf.upnp_natpmp
113 let shorten str limit
=
114 (* TODO: we should change all strings to utf8 when
115 they come into the core instead. *)
116 let name = Charset.Locale.to_utf8
(* String.escaped *) str
in
117 let slen = String.length str
in
120 Charset.utf8_length str
123 let diff_len_utf8_ascii = slen - len in
124 let max_len = max limit
10 in
125 if len > max_len then
126 let prefix = String.sub
name 0 (max_len - 7 + diff_len_utf8_ascii) in
127 let suffix = String.sub
name (len - 4 + diff_len_utf8_ascii) 4 in
128 Printf.sprintf
"%s...%s" prefix suffix
131 let client_short_name c
=
132 shorten c
!!max_client_name_len
134 let find_port server_name bind_addr port_option handler
=
135 if !!port_option
<> 0 then
138 let sock = TcpServerSocket.create server_name
139 (Ip.to_inet_addr bind_addr
)
141 port_option
=:= port
;
144 if !find_other_port then iter (port
+1)
146 lprintf_nl
"Exception %s while starting %s" server_name
147 (Printexc2.to_string e
);
154 let new_connection_control () = {
157 control_last_try
= 0;
158 control_min_reask
= !!min_reask_delay
;
161 let new_connection_control_recent_ok () = {
162 control_last_ok
= last_time
() - (Date.minute_in_secs
* 25);
164 control_last_try
= 0;
165 control_min_reask
= !!min_reask_delay
;
168 let connection_ok cc
=
169 cc
.control_last_ok
<- last_time
();
170 cc
.control_state
<- 0
172 let connection_try cc
=
173 cc
.control_last_try
<- last_time
()
175 let connection_failed cc
=
176 cc
.control_state
<- cc
.control_state
+ 1
178 let connection_next_try cc
=
179 cc
.control_last_try
+ min
(cc
.control_min_reask
* cc
.control_state
)
182 let connection_can_try cc
=
183 connection_next_try cc
< last_time
()
185 let connection_was_tried cc
=
186 cc
.control_last_try
> 0
188 let print_control c
=
189 lprintf_nl
"Connection Control: ok = %d seconds ago, state = %d, last tried = %d seconds ago, delay = %d, next in %d seconds"
190 (last_time
() - c
.control_last_ok
) c
.control_state
(last_time
() - c
.control_last_try
) c
.control_min_reask
(connection_next_try c
- last_time
())
192 let connection_must_try cc
=
193 cc
.control_state
<- 0
195 let connection_set_last_conn cc lc
=
196 cc
.control_last_ok
<- lc
198 let connection_last_conn cc
=
201 let connection_delay cc
=
202 cc
.control_last_try
<- last_time
();
203 cc
.control_state
<- 0
205 let upload_control = TcpBufferedSocket.create_write_bandwidth_controler
207 (!!max_hard_upload_rate
* 1024)
209 let download_control = TcpBufferedSocket.create_read_bandwidth_controler
211 (!!max_hard_download_rate
* 1024)
213 let payload_bandwidth = ref 0.
215 let check_ul_dl_ratio () =
216 if !!max_hard_upload_rate
< 0 then max_hard_upload_rate
=:= 0;
217 if !!max_hard_download_rate
< 0 then max_hard_download_rate
=:= 0;
218 let max_max_hard_download_rate =
219 match !!max_hard_upload_rate
with
221 | x when x < 4 -> Some
(x * 3)
222 | x when x < 10 -> Some
(x * 4)
224 match max_max_hard_download_rate with
227 if !!max_hard_download_rate
= 0 ||
228 !!max_hard_download_rate
> limit
then
229 max_hard_download_rate
=:= limit
232 option_hook max_hard_upload_rate
(fun _ ->
233 check_ul_dl_ratio ();
234 TcpBufferedSocket.change_rate
upload_control
235 (!!max_hard_upload_rate
* 1024);
237 float_of_int
(if !!max_hard_upload_rate
= 0 then
240 max
(!!max_hard_upload_rate
* 1024) 1024) *. 0.90;
242 option_hook max_hard_download_rate
(fun _ ->
243 check_ul_dl_ratio ();
244 TcpBufferedSocket.change_rate
download_control
245 (!!max_hard_download_rate
* 1024))
247 let udp_write_controler = UdpSocket.new_bandwidth_controler
upload_control
249 let udp_read_controler = UdpSocket.new_bandwidth_controler
download_control
251 let pid = Unix.getpid
()
254 Pervasives.at_exit
(fun _ ->
255 if Unix.getpid
() = pid then
256 try f () with e
-> ())
258 let exit_properly n
= Pervasives.exit n
260 let user_socks = ref ([] : TcpBufferedSocket.t list
)
261 let dialog_history = ref ([] : (int * string * string) list
)
263 exception Incoming_full
265 let want_and_not andnot
f none
value =
266 (* lprintf "want_and_not [%s]\n" value; *)
267 let ws = String2.split_simplify
value ' '
in
268 if ws = [] then raise Not_found
;
269 let wanted = ref "" in
270 let not_wanted = ref "" in
272 let len = String.length w
in
273 if len>1 && w
.[0] = '
-'
then
274 let w = String.sub
w 1 (len-1) in
275 if !not_wanted = "" then not_wanted := w
276 else not_wanted := !not_wanted ^
" " ^
w
278 if !wanted = "" then wanted := w
279 else wanted := !wanted ^
" " ^
w
281 let wanted = if !wanted <> "" then f !wanted else none
in
282 if !not_wanted = "" then wanted else
283 andnot
wanted (f !not_wanted)
285 let want_comb_not andnot comb
f none
value =
286 (* lprintf "want_comb_not [%s]\n" value; *)
287 let ws = String2.split_simplify
value ' '
in
288 let wanted = ref [] in
289 let not_wanted = ref [] in
291 let len = String.length
w in
292 if len>1 && w.[0] = '
-'
then
293 let w = String.sub
w 1 (len-1) in
294 not_wanted := w :: !not_wanted
295 else wanted := w :: !wanted
297 let wanted = match !wanted with
300 List.fold_left
(fun q
w ->
304 match !not_wanted with
308 (List.fold_left
(fun q
w ->
313 let string_of_tags tags
=
314 let buf = Buffer.create
100 in
316 Buffer.add_string
buf (Printf.sprintf
"%-3s "
317 (match t
.tag_value
with
319 | Uint64 i
-> Int64.to_string i
320 | Fint64 i
-> Int64.to_string i
326 let rec find_tag name tags
=
328 [] -> raise Not_found
329 | { tag_name
= tag_name
; tag_value
= v } :: _ when tag_name
= name -> v
330 | _ :: tail
-> find_tag name tail
335 (* first GUI have gui_num = 2, since newly created objects have _update = 1 *)
336 let gui_counter = ref 2
338 let upload_counter = ref Int64.zero
339 let download_counter = ref Int64.zero
340 let nshared_files = ref 0
341 let nshared_bytes = ref Int64.zero
342 let shared_counter = ref Int64.zero
343 let has_upload = ref 0
344 let upload_credit = ref 0
346 let string_of_field t
=
348 | Field_Artist
-> "artist"
349 | Field_Title
-> "title"
350 | Field_Album
-> "album"
351 | Field_Format
-> "format"
352 | Field_Type
-> "type"
353 | Field_Length
-> "length"
354 | Field_Availability
-> "availability"
355 | Field_Completesources
-> "completesources"
356 | Field_Filename
-> "filename"
357 | Field_Size
-> "size"
358 | Field_Size_Hi
-> "size_hi"
360 | Field_Bitrate
-> "bitrate"
361 | Field_Codec
-> "codec"
362 | Field_Filerating
-> "rating"
363 | Field_Lastseencomplete
-> "lastcompl"
364 | Field_Medialength
-> "mlen"
365 | Field_Mediacodec
-> "mediacodec"
367 | Field_UNKNOWN s
-> s
369 let field_of_string t
=
370 match String.lowercase t
with
371 | "artist" -> Field_Artist
372 | "title" -> Field_Title
373 | "album" -> Field_Album
374 | "format" -> Field_Format
375 | "type" -> Field_Type
376 | "length" -> Field_Length
377 | "availability" -> Field_Availability
378 | "completesources" -> Field_Completesources
379 | "filename" -> Field_Filename
380 | "size" -> Field_Size
381 | "size_hi" -> Field_Size_Hi
383 | "bitrate" -> Field_Bitrate
384 | "codec" -> Field_Codec
385 | "rating" -> Field_Filerating
386 | "lastcompl" -> Field_Lastseencomplete
387 | "mlen" -> Field_Medialength
388 | "mediacodec" -> Field_Mediacodec
391 let escaped_string_of_field tag
=
392 match tag
.tag_name
with
393 | Field_KNOWN s
-> String.escaped s
394 | Field_UNKNOWN s
-> String.escaped s
395 | t
-> string_of_field t
398 let string_of_tag tag
=
399 Printf.sprintf
" \"%s\" = %s" (escaped_string_of_field tag
)
400 (string_of_tag_value tag
.tag_value
)
402 let hexstring_of_tag tag
=
403 Printf.sprintf
" \"%s\" = %s" (String2.hex_string_of_string
(escaped_string_of_field tag
))
404 (string_of_tag_value tag
.tag_value
)
406 let rec print_tags tags
=
410 lprintf
" \"%s\" = %s" (escaped_string_of_field tag
)
411 (string_of_tag_value tag
.tag_value
);
414 let rec fprint_tags oc tags
=
416 [] -> Printf.fprintf oc
"\n"
418 Printf.fprintf oc
"%s = %s" (escaped_string_of_field tag
)
419 (string_of_tag_value tag
.tag_value
);
422 let rec bprint_tags buf tags
=
424 [] -> Printf.bprintf
buf "\n"
426 Printf.bprintf
buf "%s = %s" (escaped_string_of_field tag
)
427 (string_of_tag_value tag
.tag_value
);
430 (* let searches = ref ([] : search list) *)
432 let core_included = ref false
433 let gui_included = ref false
435 let gui_reconnected = ref false
437 let core_gui_fifo = (Fifo.create
() : GuiProto.to_gui
Fifo.t
)
438 let gui_core_fifo = (Fifo.create
() : GuiProto.from_gui
Fifo.t
)
440 let init_hooks = ref ([] : (unit -> unit) list
)
442 let add_init_hook f =
443 init_hooks := f :: !init_hooks
445 let chat_message_fifo = (Fifo.create
() : (int * string * int * string * string) Fifo.t
)
447 let log_chat_message i num n s
=
448 Fifo.put
chat_message_fifo (last_time
(),i
,num
,n
,s
);
450 Unix2.tryopen_write_gen messages_log
[Open_creat
; Open_wronly
; Open_append
]
452 Printf.fprintf oc
"%s: %s (%s): %s\n" (Date.simple
(BasicSocket.date_of_int
(last_time
()))) n i s
)
454 lprintf_nl
"[ERROR] Exception %s while trying to log message to %s"
455 (Printexc2.to_string e
) messages_log
);
457 while (Fifo.length
chat_message_fifo) > !!html_mods_max_messages
do
458 ignore
(Fifo.take
chat_message_fifo)
461 let last_message_log = ref 0
463 let debug_clients = ref Intset.empty
465 (* control_: means that it is the limited bandwidth, not the unlimited one
466 used by the interfaces. tcp_: the full bandwidth (limited+unlimited) *)
468 let udp_upload_rate = ref 0
469 (* let tcp_upload_rate = ref 0 *)
470 let control_upload_rate = ref 0
471 let udp_download_rate = ref 0
472 (* let tcp_download_rate = ref 0 *)
473 let control_download_rate = ref 0
475 let sd_udp_upload_rate = ref 0
476 let sd_tcp_upload_rate = ref 0
477 let sd_control_upload_rate = ref 0
479 let bandwidth_samples = Fifo.create
()
480 let short_delay_bandwidth_samples = Fifo.create
()
483 let dummy_sample = Array.make
nmeasures 0.
485 let trimto n samples
=
486 let len = ref (Fifo.length samples
) in
488 ignore
(Fifo.take samples
);
496 (last_time
(), dummy_sample)
498 let derive (t1
, sample1
) (t2
, sample2
) =
501 let fdt = float_of_int
dt in
502 (dt, Array.init
nmeasures
503 (fun i
-> int_of_float
((sample2
.(i
) -. sample1
.(i
)) /. fdt)))
505 (0, Array.make
nmeasures 0)
507 let update_link_stats () =
509 let put time sample samples
=
510 assert (Array.length sample
= nmeasures);
511 Fifo.put samples
(time
, sample
) in
513 let last_count_time, last_sample
=
514 last bandwidth_samples in
515 let time = last_time
() in
517 Int64.to_float
!tcp_uploaded_bytes
;
518 Int64.to_float
!tcp_downloaded_bytes
;
519 Int64.to_float
(moved_bytes
upload_control);
520 Int64.to_float
(moved_bytes
download_control);
521 Int64.to_float
!udp_uploaded_bytes
;
522 Int64.to_float
!udp_downloaded_bytes
;|] in
524 (match derive (last_count_time, last_sample
) (time, sample) with
525 _, [|tur
; tdr
; cur
; cdr
; uur
; udr
|] ->
528 tcp_upload_rate := tur;
529 tcp_download_rate := tdr;
531 control_upload_rate := cur
;
532 control_download_rate := cdr
;
533 udp_upload_rate := uur
;
534 udp_download_rate := udr
535 | _ -> failwith
"wrong number of measures");
538 lprintf "BANDWIDTH %d/%d %d/%d\n" !control_upload_rate !tcp_upload_rate
539 !control_download_rate !tcp_download_rate ;
541 put time sample bandwidth_samples;
542 trimto 20 bandwidth_samples;
544 let sd_last_count_time, sd_last_sample
=
545 last short_delay_bandwidth_samples in
546 (match derive (sd_last_count_time, sd_last_sample
) (time, sample) with
547 _, [|tur
; _; cur
; _; uur
; _|] ->
548 sd_tcp_upload_rate := tur
;
549 sd_control_upload_rate := cur
;
550 sd_udp_upload_rate := uur
551 | _ -> failwith
"wrong number of measures");
553 put time sample short_delay_bandwidth_samples;
554 trimto 5 short_delay_bandwidth_samples
557 let history_size = 720
558 let history_size_for_h_graph = ref 0 (* history_size * !!html_mods_vd_gfx_h_intervall / 60 *)
559 let history_h_step = ref 0 (* 60 * !!html_mods_vd_gfx_h_intervall <= history_size * history_step *)
560 let history_h_size = 1440
561 let history_timeflag = ref 0.
562 let history_h_timeflag = ref 0.
564 let upload_history = Fifo.create
()
565 let download_history = Fifo.create
()
566 let upload_h_history = Fifo.create
()
567 let download_h_history = Fifo.create
()
569 let upload_usage () =
570 !udp_upload_rate + !control_upload_rate
572 let short_delay_upload_usage () =
573 !sd_udp_upload_rate + !sd_control_upload_rate
575 let download_usage () =
576 !udp_download_rate + !control_download_rate
578 let update_download_history () =
579 Fifo.put download_history (download_usage ());
580 let len = ref (Fifo.length
download_history) in
581 while !len > history_size+1 do
582 ignore
(Fifo.take
download_history);
586 let update_upload_history () =
587 Fifo.put upload_history (upload_usage ());
588 let len = ref (Fifo.length
upload_history) in
589 while !len > history_size+1 do
590 ignore
(Fifo.take
upload_history);
594 let update_h_download_history () =
595 if (!history_h_step = history_size * history_step) or ( (Fifo.length
download_history) <= (!history_size_for_h_graph+1)) then
596 Fifo.put download_h_history ((List.fold_left
(+) 0 (Fifo.to_list
download_history)) / ((Fifo.length
download_history)))
598 Fifo.put download_h_history ((List.fold_left
(+) 0
599 (snd
(List2.cut
((Fifo.length
download_history) - !history_size_for_h_graph - 1) (Fifo.to_list
download_history))))
600 / (!history_size_for_h_graph + 1) );
601 let len = ref (Fifo.length
download_h_history) in
602 while !len > history_h_size+1 do
603 ignore
(Fifo.take
download_h_history);
607 let update_h_upload_history () =
608 (* Fifo.put upload_h_history ((Fifo.length upload_history) / 720); *)
609 if (!history_h_step = history_size * history_step) or ((Fifo.length
upload_history) <= (!history_size_for_h_graph+1)) then
610 Fifo.put upload_h_history ((List.fold_left
(+) 0 (Fifo.to_list
upload_history)) / ((Fifo.length
upload_history)))
612 Fifo.put upload_h_history ((List.fold_left
(+) 0
613 (snd
(List2.cut
((Fifo.length
upload_history) - !history_size_for_h_graph - 1) (Fifo.to_list
upload_history))))
614 / (!history_size_for_h_graph+1) );
615 let len = ref (Fifo.length
upload_h_history) in
616 while !len > history_h_size+1 do
617 ignore
(Fifo.take
upload_h_history);
621 let detected_link_capacity link
=
622 List.fold_left max
0 (Fifo.to_list link
)
624 let detected_uplink_capacity () =
625 List.fold_left max
0 (Fifo.to_list
upload_history)
627 let detected_downlink_capacity () =
628 List.fold_left max
0 (Fifo.to_list
download_history)
632 { tag_name
= name; tag_value
= v }
635 { tag_name
= s
; tag_value
= Uint64
(Int64.of_int i
) }
638 { tag_name
= s
; tag_value
= Uint64 i
}
641 { tag_name
= s
; tag_value
= String i
}
643 let for_int_tag tag
f =
644 match tag
.tag_value
with
645 Uint64 i
| Fint64 i
-> f (Int64.to_int i
)
649 | Uint16 n
| Uint8 n
-> f n
651 let for_int64_tag tag
f =
652 match tag
.tag_value
with
653 Uint64 i
| Fint64 i
-> f i
657 | Uint8 n
| Uint16 n
-> f (Int64.of_int n
)
659 let for_two_int16_tag tag
f =
660 match tag
.tag_value
with
661 Uint64 i
| Fint64 i
->
662 let i1 = Int64.to_int
(Int64ops.right64 i
16) in
663 let i0 = Int64.to_int i
in
664 let i0 = i0 land 0xffff in
665 let i1 = i1 land 0xffff in
670 | Uint8 n
| Uint16 n
-> f n
0
672 let for_string_tag tag
f =
673 match tag
.tag_value
with
674 Uint64
_ | Fint64
_ -> ()
678 | Uint16
_ | Uint8
_ -> ()
680 let partial_chunk c
=
682 | VerificationBitmap.State_missing
| VerificationBitmap.State_partial
->
684 | VerificationBitmap.State_complete
| VerificationBitmap.State_verified
->
688 module CanBeCompressed = struct
690 let to_deflate = ref []
691 let to_deflate_len = ref 0
693 let compression_buffer_len = 20000
694 let compression_buffer = String.create compression_buffer_len
696 let deflate_connection sock =
697 lprintf "Creating deflate connection\n";
698 let comp = Deflate (Zlib.inflate_init true, Zlib.deflate_init 6 true) in
699 CompressedConnection (comp,
700 buf_create !max_buffer_size, buf_create !max_buffer_size, sock)
702 let rec iter_deflate sock zs wbuf =
703 if wbuf.len > 0 then begin
704 lprintf "iter_deflate\n";
705 let (_, used_in, used_out) = Zlib.deflate zs
706 wbuf.buf wbuf.pos wbuf.len
707 compression_buffer 0 compression_buffer_len
709 lprintf "deflated %d/%d -> %d\n" used_in wbuf.len used_out;
710 lprintf "[%s]\n" (String.escaped (String.sub compression_buffer 0 used_out));
711 write sock compression_buffer 0 used_out;
712 buf_used wbuf used_in;
713 if used_in > 0 || used_out > 0 then
714 iter_deflate sock zs wbuf
717 let deflate_timer _ =
718 List.iter (fun conn ->
721 CompressedConnection (comp, _, wbuf, sock) ->
722 if closed sock then raise Exit;
723 let Deflate (_, zs) = comp in
724 iter_deflate sock zs wbuf
727 lprintf "[ERROR] Exception %s in CanBeCompressed.deflate_timer\n"
728 (Printexc2.to_string e)
733 let to_deflate conn =
734 if not (List.memq conn !to_deflate) then
735 to_deflate := conn :: !to_deflate;
736 if !to_deflate_len > 1000000 then
739 let write_string conn s =
740 lprintf "write_string\n";
741 let len = String.length s in
743 Connection sock -> write_string sock s
744 | CompressedConnection (_,_,wbuf,sock) ->
745 lprintf "CanBeCompressed.write_string %d\n" len;
746 to_deflate_len := !to_deflate_len + len;
748 buf_add sock wbuf s 0 len
751 let rec iter_inflate zs sock b rbuf =
752 if b.len > 0 then begin
753 lprintf "iter_inflate %d\n" b.len;
754 lprintf "[%s]\n" (String.escaped (String.sub b.buf b.pos b.len));
755 let (_, used_in, used_out) = Zlib.inflate zs b.buf b.pos b.len
756 compression_buffer 0 compression_buffer_len
758 lprintf "inflated %d/%d -> %d\n" used_in b.len used_out;
759 lprintf "[%s]\n" (String.escaped (String.sub compression_buffer 0 used_out));
760 buf_add sock rbuf compression_buffer 0 used_out;
762 if used_in > 0 || used_out > 0 then
763 iter_inflate zs sock b rbuf
767 lprintf "CanBeCompressed.buf\n";
770 Connection sock -> buf sock
771 | CompressedConnection (comp,rbuf,_,sock) ->
774 let Deflate (zs, _) = comp in
775 if b.len > 0 then iter_inflate zs sock b rbuf;
779 lprintf "[ERROR] Exception %s in CanBeCompressed.buf\n"
780 (Printexc2.to_string e);
785 let do_if_connected tcp_connection
f =
786 match tcp_connection
with
787 Connection
sock -> f sock
790 let new_activity () = {
791 activity_begin
= BasicSocket.last_time
();
792 activity_client_overnet_connections
= 0;
793 activity_client_overnet_indirect_connections
= 0;
794 activity_client_overnet_successful_connections
= 0;
795 activity_client_edonkey_connections
= 0;
796 activity_client_edonkey_indirect_connections
= 0;
797 activity_client_edonkey_successful_connections
= 0;
798 activity_server_edonkey_connections
= 0;
799 activity_server_edonkey_successful_connections
= 0;
802 let nactivities = ref 0
803 let activities = Fifo.create
()
804 let activity = ref (new_activity ())
807 add_infinite_timer
60. (fun _ ->
808 Fifo.put activities !activity;
810 if !nactivities > 2000 then begin
811 ignore
(Fifo.take
activities);
814 activity := new_activity ()
817 module StringIntern
= Weak.Make
(struct
819 let hash s
= Hashtbl.hash s
820 let equal x y
= x = y
823 let intern_table = StringIntern.create
1000
824 let intern s
= StringIntern.merge
intern_table s
826 let print_command_result o result
=
827 if use_html_mods o
then
828 html_mods_table_one_row o
.conn_buf
"serversTable" "servers" [
829 ("", "srh", result
); ]
831 Printf.bprintf o
.conn_buf
"%s" result
833 let discover_ip force
=
834 if !!discover_ip || force
then
836 if !verbose
then lprintf_nl
"started IP discovery";
837 let module H
= Http_client
in
838 let r = { H.basic_request
with
839 H.req_url
= Url.of_string
"http://dynupdate.no-ip.com/ip.php";
840 H.req_proxy
= !CommonOptions.http_proxy
;
841 H.req_max_retry
= 10;
842 H.req_user_agent
= get_user_agent
() }
844 H.wget
r (fun file
->
845 if !verbose
then lprintf_nl
"downloaded IP discovery page, parsing...";
846 Unix2.tryopen_read file
(fun cin
->
849 let line = input_line cin
in
851 let ip = Ip.of_string
line in
853 set_client_ip
=:= ip;
854 last_high_id
:= !!set_client_ip
;
855 if !verbose
then lprintf_nl
"discovered IP %s" (Ip.to_string
!!set_client_ip
)
857 with e
-> lprintf_nl
"IP discovery parse error: %s" (Printexc2.to_string e
)
859 with End_of_file
-> ())
864 Heap.add_memstat
"CommonGlobals" (fun level
buf ->
865 let counter = ref 0 in
866 StringIntern.iter (fun f -> incr
counter;) intern_table;
867 Printf.bprintf
buf " intern_table: %d\n" !counter;
868 Printf.bprintf
buf " core_gui_fifo: %d\n" (Fifo.length
core_gui_fifo);
869 Printf.bprintf
buf " gui_core_fifo: %d\n" (Fifo.length
gui_core_fifo);
870 Printf.bprintf
buf " chat_message_fifo: %d\n" (Fifo.length
chat_message_fifo);
871 Printf.bprintf
buf " upload_history: %d\n" (Fifo.length
upload_history);
872 Printf.bprintf
buf " download_history: %d\n" (Fifo.length
download_history);
873 Printf.bprintf
buf " upload_h_history: %d\n" (Fifo.length
upload_h_history);
874 Printf.bprintf
buf " download_h_history: %d\n" (Fifo.length
download_h_history);
875 Printf.bprintf
buf " bandwidth_samples: %d\n" (Fifo.length
bandwidth_samples);
876 Printf.bprintf
buf " short_delay_bandwidth_samples: %d\n" (Fifo.length
short_delay_bandwidth_samples);
877 Printf.bprintf
buf " dummy_sample: %d\n" (Array.length
dummy_sample);
878 Printf.bprintf
buf " activities: %d\n" (Fifo.length
activities);