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
24 open TcpBufferedSocket
28 open CommonInteractive
31 open CommonComplexOptions
39 open DonkeyComplexOptions
48 let log_prefix = "[EDK]"
51 lprintf_nl2
log_prefix fmt
54 network
.op_network_is_enabled
<- (fun _ -> !!enable_donkey
);
55 option_hook enable_donkey
(fun _ ->
56 if !CommonOptions.start_running_plugins
then
57 if !!enable_donkey
then network_enable network
58 else network_disable network
);
59 network
.network_config_file
<- [
62 let hourly_timer timer
=
63 DonkeyClient.clean_groups
();
64 DonkeyClient.clean_requests
();
65 Hashtbl.clear udp_servers_replies
;
66 DonkeyThieves.clean_thieves
()
68 let quarter_timer timer
=
69 clean_join_queue_tables
()
71 let fivemin_timer timer
=
74 let second_timer timer
=
76 DonkeySources.connect_sources connection_manager
;
78 if !verbose_sources
> 2 then
79 lprintf_nl "Exception %s while checking sources"
80 (Printexc2.to_string e
)
83 let five_second_timer timer
=
84 DonkeyServers.check_server_connections
();
85 DonkeyServers.walker_timer
();
86 DonkeyOneFile.check_files_downloaded
();
87 DonkeyServers.udp_walker_timer
();
88 DonkeyShare.check_shared_files
()
91 DonkeySources.clean_sources
(); (* Moved here from fivemin_timer. *)
92 DonkeyServers.update_master_servers
();
93 DonkeyServers.check_for_preferred_servers
();
95 DonkeyServers.query_locations_timer
();
97 DonkeyShare.send_new_shared
()
100 if !!login
= "" then !!global_login
else !!login
102 let is_enabled = ref false
104 let disable enabler
() =
105 if !enabler
then begin
108 if !!enable_donkey
then enable_donkey
=:= false;
109 Hashtbl2.safe_iter
(fun s
-> DonkeyServers.disconnect_server s Closed_by_user
)
111 H.iter
(fun c
-> DonkeyClient.disconnect_client c Closed_by_user
)
113 (match !listen_sock
with None
-> ()
116 TcpServerSocket.close sock Closed_by_user
);
117 (match !udp_sock
with None
-> ()
120 UdpSocket.close sock Closed_by_user
);
122 if !!enable_donkey
then enable_donkey
=:= false;
123 DonkeyProtoOvernet.Overnet.disable ();
124 DonkeyProtoKademlia.Kademlia.disable ()
128 let module D
= DonkeyProtoClient
in
129 let m = D.mldonkey_emule_proto
in
131 let secident = if sec_ident_enabled
() then 3 else 0 in
132 m.emule_secident
<- secident;
133 m.emule_features
<- secident;
135 let advertise_browse =
136 match !!allow_browse_share
with
140 m.emule_noviewshared
<- advertise_browse;
142 let emule_miscoptions1 = D.emule_miscoptions1 m in
143 let emule_miscoptions2 = D.emule_miscoptions2 m in
144 let emule_compatoptions = D.emule_compatoptions m in
145 client_to_client_tags
:=
147 string_tag
(Field_KNOWN
"name") (local_login ());
148 int_tag
(Field_KNOWN
"port") !!donkey_port
;
149 int_tag
(Field_KNOWN
"version") protocol_version
;
150 int_tag
(Field_KNOWN
"emule_udpports") (!!donkey_port
+4);
151 int_tag
(Field_KNOWN
"emule_version") m.emule_version
;
152 int64_tag
(Field_KNOWN
"emule_miscoptions1") emule_miscoptions1;
153 int64_tag
(Field_KNOWN
"emule_miscoptions2") emule_miscoptions2;
154 int_tag
(Field_KNOWN
"emule_compatoptions") emule_compatoptions;
157 (* server capabilities *)
158 let extended = ref 0x0 in
159 extended := !extended lor 0x01; (* support of compression *)
160 (*extended := !extended lor 0x02; IP in login, deprecated *)
161 extended := !extended lor 0x04; (* support of auxport *)
162 extended := !extended lor 0x08; (* newtags *)
163 (*extended := !extended lor 0x10; (* unicode *) *)
164 extended := !extended lor 0x100; (* files > 4GB *)
165 (*extended := !extended lor 0x200; (* support crypt *) *)
166 (*extended := !extended lor 0x400; (* request crypt *) *)
167 (*extended := !extended lor 0x800; (* require crypt *) *)
169 client_to_server_tags
:=
171 string_tag
(Field_KNOWN
"name") (local_login ());
172 int_tag
(Field_KNOWN
"version") protocol_version
;
173 int_tag
(Field_KNOWN
"extended") !extended;
174 int_tag
(Field_KNOWN
"emule_version") m.emule_version
;
177 client_to_server_reply_tags
:=
179 string_tag
(Field_KNOWN
"name") (local_login ());
180 int_tag
(Field_KNOWN
"version") protocol_version
;
181 int_tag
(Field_KNOWN
"emule_udpports") (!!donkey_port
+4);
182 int64_tag
(Field_KNOWN
"emule_miscoptions1") emule_miscoptions1;
183 int64_tag
(Field_KNOWN
"emule_miscoptions2") emule_miscoptions2;
184 int_tag
(Field_KNOWN
"emule_version") m.emule_version
;
187 emule_info
.DonkeyProtoClient.EmuleClientInfo.tags
<- [
188 int_tag
(Field_KNOWN
"compression") m.emule_compression
;
189 int_tag
(Field_KNOWN
"udpver") m.emule_udpver
;
190 int_tag
(Field_KNOWN
"udpport") (!!donkey_port
+4);
191 int_tag
(Field_KNOWN
"sourceexchange") m.emule_sourceexchange
;
192 int_tag
(Field_KNOWN
"comments") m.emule_comments
;
193 int_tag
(Field_KNOWN
"compatibleclient") !DonkeyProtoClient.compatibleclient
;
194 int_tag
(Field_KNOWN
"extendedrequest") m.emule_extendedrequest
;
195 int_tag
(Field_KNOWN
"features") m.emule_features
;
198 overnet_connect_tags
:=
200 string_tag
(Field_KNOWN
"name") (local_login ());
201 int_tag
(Field_KNOWN
"version") !!DonkeyProtoOvernet.overnet_protocol_connect_version
;
203 overnet_connectreply_tags
:=
205 string_tag
(Field_KNOWN
"name") (local_login ());
206 int_tag
(Field_KNOWN
"version") !!DonkeyProtoOvernet.overnet_protocol_connectreply_version
;
210 if not
!is_enabled then
211 let enabler = ref true in
213 network
.op_network_disable
<- disable enabler;
214 if Autoconf.donkey_sui_works
() then
216 client_public_key
:= DonkeySui.SUI.load_key
(!!client_private_key
)
218 if not
!!enable_donkey
then enable_donkey
=:= true;
221 (* DonkeyClient.verbose := true; *)
223 (**** LOAD OTHER OPTIONS ****)
225 (* TODO INDEX DonkeyIndexer.load_comments comment_filename; *)
226 (* TODO INDEX DonkeyIndexer.install_hooks (); *)
227 (* TODO INDEX x CommonGlobals.do_at_exit (fun _ -> DonkeyIndexer.save_history ()); *)
230 BasicSocket.add_timer 10. (fun timer ->
231 BasicSocket.reactivate_timer timer;
234 | Some (t_in, t_out) ->
235 if TcpBufferedSocket.can_write t_out then begin
236 TcpBufferedSocket.close t_out "timed";
241 Hashtbl.iter
(fun _ file
->
243 if file_state file
<> FileDownloaded
then begin (* add not finished files *)
244 current_files
:= file
:: !current_files
;
245 (* set_file_size file (file_size file) *)
248 let file_disk_name = file_disk_name file
in
249 if Unix32.file_exists
file_disk_name &&
250 Unix32.getsize
file_disk_name <> Int64.zero
then begin
251 (* getsize writable=false is ok because file has state FileDownloaded *)
252 lprintf_nl "FILE DOWNLOADED";
254 DonkeyOneFile.declare_completed_file file
;
258 file_commit
(as_file file
)
261 lprintf_nl "Exception %s while recovering download %s"
262 (Printexc2.to_string e
) (file_disk_name file
);
265 (* Normally, we should check that downloaded files are still there. *)
267 List.iter
(fun file
->
269 (* Hum, maybe we should not remove all these descriptions, as they might
270 be useful when users want to share files that they had already previously
272 let key = (file
.sh_name
, file
.sh_size
, file
.sh_mtime
) in
274 if Unix32.file_exists file
.sh_name
&&
275 not
(Hashtbl.mem shared_files_info
key)
277 Hashtbl.add shared_files_info
key file
;
278 list := file
:: !list
281 lprintf_nl "ignoring share: %s" (Printexc2.to_string e
))
282 ) !!known_shared_files
;
283 known_shared_files
=:= !list;
285 (**** CREATE WAITING SOCKETS ****)
286 let rec find_port new_port
=
288 let sock = TcpServerSocket.create
289 "donkey client server"
290 (Ip.to_inet_addr
!!client_bind_addr
)
291 !!donkey_port ~backlog
:!!max_upload_slots
(client_connection_handler
false) in
293 TcpServerSocket.set_accept_controler
sock connections_controler
;
294 listen_sock
:= Some
sock;
295 donkey_port
=:= new_port
;
299 (UdpSocket.create
(Ip.to_inet_addr
!!client_bind_addr
)
301 (udp_handler
DonkeyUdp.udp_client_handler
))
303 udp_sock
:= Some
sock;
304 UdpSocket.set_write_controler
sock udp_write_controler
;
306 lprintf_nl "Exception %s while binding UDP socket"
307 (Printexc2.to_string e
);
311 if !find_other_port
then find_port (new_port
+1)
314 let sock = find_port !!donkey_port
in
315 DonkeyProtoOvernet.Overnet.enable ();
316 DonkeyProtoKademlia.Kademlia.enable ();
319 match Unix.getsockname
(BasicSocket.fd
(TcpServerSocket.sock sock)) with
320 Unix.ADDR_INET
(ip
, port
) ->
321 assert (!!donkey_port
= port
);
322 | _ -> failwith
"Bad socket address"
327 Options.option_hook global_login
reset_tags;
328 Options.option_hook login
reset_tags;
329 Options.option_hook enable_sui
reset_tags;
330 Options.option_hook allow_browse_share
reset_tags;
332 (**** START TIMERS ****)
333 add_session_option_timer
enabler check_client_connections_delay
335 DonkeyUdp.extent_search
();
336 DonkeyServers.udp_query_sources
()
339 add_session_timer
enabler 3600. hourly_timer;
340 add_session_timer
enabler 60. min_timer;
341 add_session_timer
enabler 300. fivemin_timer;
342 add_session_timer
enabler 900. quarter_timer;
343 add_session_timer
enabler 1. second_timer;
344 add_session_timer
enabler 5. five_second_timer;
345 add_session_option_timer
enabler remove_old_servers_delay
346 DonkeyServers.remove_old_servers
;
348 DonkeyComplexOptions.load_sources
();
350 (**** START PLAYING ****)
351 (* removed, just wait for timer to start the action *)
353 (try DonkeyUdp.force_check_locations () with _ -> ());
354 (try force_check_server_connections true with _ -> ());
358 lprintf_nl "Error: Exception %s during startup"
359 (Printexc2.to_string e
)
362 let rec update_options () =
364 lprintf_nl "Updating options to version %i" v
;
365 options_version
=:= v
;
369 match !!options_version
with
371 if !!max_sources_per_file
= 20000 then
372 max_sources_per_file
=:= 5000;
375 if !!upload_timeout
= 1800. then
376 upload_timeout
=:= 60.;
379 if !!upload_timeout
= 60. then
380 upload_timeout
=:= 600.;
383 propagate_sources
=:= false;
384 update_server_list_server
=:= false;
385 upload_full_chunks
=:= true;
392 (* TODO INDEX DonkeyIndexer.init (); *)
395 file_ops.op_file_commit <- (fun file ->
396 DonkeyInteractive.save_file file
397 (DonkeyInteractive.saved_name file);
401 network
.op_network_enable
<- enable;
402 network
.op_network_update_options
<- update_options;
403 (* network.network_config_file <- []; *)
404 network
.op_network_info
<- (fun n
->
406 network_netnum
= network
.network_num
;
407 network_config_filename
= (match network
.network_config_file
with
408 [] -> "" | opfile
:: _ -> options_file_name opfile
);
409 network_netname
= network
.network_name
;
410 network_netflags
= network
.network_flags
;
411 network_enabled
= network_is_enabled network
;
412 network_uploaded
= !donkey_upload_counter
;
413 network_downloaded
= !donkey_download_counter
;
414 network_connected_servers
= List.length
(connected_servers
());
416 network
.op_network_ports
<- (fun _ ->
418 !!donkey_port
, "client_port TCP";
419 !!donkey_port
+4, "client_port UDP";
420 !overnet_port_info
, "overnet_port TCP+UDP";
421 !kademlia_port_info
, "kademlia_port UDP";
423 network
.op_network_porttest_result
<-
424 (fun _ -> match !DonkeyInteractive.porttest_result
with
425 | PorttestResult
(time
, s
) ->
426 PorttestResult
(time
, (String2.dehtmlize s
))
427 | _ -> !DonkeyInteractive.porttest_result
);
428 CommonInteractive.register_gui_options_panel
"eDonkey"
429 gui_donkey_options_panel
;
430 CommonInteractive.register_gui_options_panel
"Overnet"
431 DonkeyProtoOvernet.Overnet.gui_overnet_options_panel
;
432 CommonInteractive.register_gui_options_panel
"Kademlia"
433 DonkeyProtoKademlia.Kademlia.gui_overnet_options_panel
437 CommonInteractive.add_main_options
440 "-dump", Arg.String
(fun file
->
441 DonkeyImport.dump_file file
), " <filename> : dump file";
442 "-known", Arg.String
(fun file
->
443 let module K
= DonkeyImport.Known
in
444 let s = File.to_string file
in
448 ), " <filename> : print a known.met file";
449 "-part", Arg.String
(fun file
->
450 let module K
= DonkeyImport.Part
in
451 let s = File.to_string file
in
455 ), " <filename> : print a .part.met file";
456 "-server", Arg.String
(fun file
->
457 let module K
= DonkeyImport.Server
in
458 let s = File.to_string file
in
463 ), " <filename> : print a server.met file";
464 "-pref", Arg.String
(fun file
->
465 let module K
= DonkeyImport.Pref
in
466 let s = File.to_string file
in
470 ), " <filename> : print a server.met file";
471 "-peers", Arg.String
(fun file
->
472 let module K
= DonkeyOvernetImport.Peer
in
473 let s = File.to_string file
in
478 ), " <filename> : print a contact.dat file";