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
20 (** Communicating with the mldonkey client. *)
24 open TcpBufferedSocket
29 module M
= Gui_messages
30 module O
= Gui_options
36 set_connect_status
: string -> unit;
41 if !!Gui_options.copy_messages
then
42 Marshal.from_string
(Marshal.to_string t
[]) 0
45 let when_disconnected (gui
: gui
) =
50 let to_gui_protocol_used = Array.create
(to_gui_last_opcode
+1)
51 GuiProto.best_gui_version
52 let from_gui_protocol_used = Array.create
53 (from_gui_last_opcode
+1)
54 GuiProto.best_gui_version
56 module UseSocket
= struct
58 let (!!) = Options.(!!)
60 let connection = ref None
62 let disconnect gui reason
=
63 match !connection with
66 TcpBufferedSocket.close sock reason
;
71 match !connection with
73 lprintf
"Message not sent since not connected\n";
75 GuiEncoding.gui_send
(GuiEncoding.from_gui
from_gui_protocol_used) sock t
77 let reconnect (gui
: gui
) value_reader arg reason
=
78 (try disconnect gui reason
with _
-> ());
79 let hostname = if !!O.hostname = "" then Unix.gethostname
()
81 let token = create_token unlimited_connection_manager
in
82 (* lprintf "RECONNECTING...\n"; *)
83 let sock = TcpBufferedSocket.connect
token ""
85 let h = Ip.from_name
hostname in
89 lprintf
"Exception %s in gethostbyname" (Printexc2.to_string e
);
92 Unix.inet_addr_of_string
!!O.hostname
94 lprintf
"Exception %s in inet_addr_of_string"
95 (Printexc2.to_string e
);
98 lprintf
"mlgui was unable to find the IP address of the host [%s]" !!O.hostname; lprint_newline
();
101 lprintf
"Please, edit the $HOME/.mldonkey/mldonkey_gui.ini, and change the 'hostname' option\n";
102 lprintf
"to the correct IP address of the host running mldonkey.\n";
108 (* lprintf "CONNECTION STARTED\n"; *)
110 if not
(List.mem
(hostname,!!O.port
) !!O.history
) then
112 O.history
=:= (hostname, !!O.port
) :: !!O.history
;
113 G.new_scanned_port
:= true
117 connection := Some
sock;
118 TcpBufferedSocket.set_closer
sock (fun _ msg
->
119 match !connection with
122 if s
== sock then begin
124 gui#set_connect_status
(M.mW_lb_not_connected
);
125 when_disconnected gui
128 TcpBufferedSocket.set_max_output_buffer
sock !!O.interface_buffer
;
129 TcpBufferedSocket.set_max_input_buffer
sock !!O.interface_buffer
;
130 TcpBufferedSocket.set_handler
sock TcpBufferedSocket.BUFFER_OVERFLOW
132 lprintf
"BUFFER OVERFLOW\n";
133 TcpBufferedSocket.close
sock Closed_for_overflow
);
134 TcpBufferedSocket.set_reader
sock (
135 GuiDecoding.gui_cut_messages
138 let m = GuiDecoding.to_gui
to_gui_protocol_used opcode s
in
141 lprintf
"Exception %s in decode/exec\n" (Printexc2.to_string e
);
144 gui#set_connect_status
(M.mW_lb_connecting
);
145 send (GuiProto.GuiProtocol
GuiProto.best_gui_version
)
147 lprintf
"Exception %s in connecting\n" (Printexc2.to_string e
);
148 TcpBufferedSocket.close
sock (Closed_for_exception e
);
151 let connected _
= !connection <> None
155 module UseFifo
= struct
157 let timer_set = ref false
159 let send m = Fifo.put gui_core_fifo
(copy_message m)
161 let disconnect gui reason
=
162 when_disconnected gui
164 let reconnect ( gui
: gui
) value_reader arg reason
=
165 disconnect gui reason
;
166 gui_reconnected
:= true;
167 Fifo.clear core_gui_fifo
;
168 Fifo.clear gui_core_fifo
;
170 if not
!timer_set then begin
172 BasicSocket.add_infinite_timer
0.1 (fun _
->
176 let m = copy_message (Fifo.take core_gui_fifo
) in
180 with Fifo.Empty
-> ()
182 lprintf
"Exception %s in handle core message"
183 (Printexc2.to_string e
);
187 gui#set_connect_status
(M.mW_lb_connecting
);
188 send (GuiProto.GuiProtocol
GuiProto.best_gui_version
)
190 let connected _
= true
195 if !core_included
then UseFifo.disconnect
196 else UseSocket.disconnect
199 if !core_included
then UseFifo.connected
200 else UseSocket.connected
203 if !core_included
then UseFifo.reconnect
204 else UseSocket.reconnect
207 if !core_included
then UseFifo.send
211 let hostname = if !!O.hostname = "" then Unix.gethostname
() else !!O.hostname
213 let ip = Ip.from_name
hostname in
214 let addr = Ip.to_inet_addr
ip in
215 let rec scan_port prev_next i max
=
216 if !prev_next
&& i
< max
then
217 let next = ref true in
220 let token = create_token unlimited_connection_manager
in
221 let sock = TcpBufferedSocket.connect
token "" addr i
(fun sock e
->
223 BASIC_EVENT
(RTIMEOUT
) -> close
sock Closed_for_timeout
226 GuiEncoding.gui_send
(GuiEncoding.from_gui
from_gui_protocol_used) sock
227 (GuiProto.GuiProtocol
GuiProto.best_gui_version
);
228 set_closer
sock (fun _ _
->
229 scan_port next (i
+1) max
);
232 let console = ref "" in
233 TcpBufferedSocket.set_reader
sock (fun sock nread
->
234 GuiDecoding.gui_cut_messages
237 let m = GuiDecoding.to_gui
to_gui_protocol_used
240 CoreProtocol
(n
,_
,_
) ->
241 lprintf
"GUI version %d on port %d\n" n i
;
244 nets := n
.CommonTypes.network_netname
:: !nets
246 lprintf
"GUI:\n proto %d\nnets:\n" !proto;
251 lprintf
" motd:\n%s" m;
254 if not
(List.mem
(hostname,i
) !G.scanned_ports
) then
256 G.scanned_ports
:= (hostname, i
) :: !G.scanned_ports
;
257 G.new_scanned_port
:= true
261 | _
-> close
sock Closed_by_user
262 with e
-> close
sock Closed_by_user
267 set_rtimeout
sock 0.5;
269 scan_port next (i
+1) max
271 scan_port (ref true) 0 10000;
272 scan_port (ref true) 10000 20000;
273 scan_port (ref true) 20000 30000;
274 scan_port (ref true) 30000 40000;
275 scan_port (ref true) 40000 50000;
276 scan_port (ref true) 50000 60000;
277 scan_port (ref true) 60000 65536