14
30
61
62
63
64:- module(pdt_console_server,[
65 pdt_current_console_server/1,
66 pdt_start_console_server/2,
67 pdt_stop_console_server/0,
68 console_thread_name/1
69]). 70:- use_module(library(socket)). 71:- use_module(library(lists)). 72
73
74console_thread_name(Name) :-
75 console_thread_name__(Name).
76
77:- dynamic(console_thread_name__/1). 78
79:- dynamic(pdt_console_client_id/1). 80
81reset_pdt_console_client_id :-
82 retractall(pdt_console_client_id(_)),
83 assertz(pdt_console_client_id(0)).
84
85next_pdt_console_client_id(Id) :-
86 retract(pdt_console_client_id(Id)),
87 !,
88 Next is Id + 1,
89 asserta(pdt_console_client_id(Next)).
90
91prolog_server(Port, Name, Options) :-
92 tcp_socket(ServerSocket),
93 tcp_setopt(ServerSocket, reuseaddr),
94 tcp_bind(ServerSocket, Port),
95 tcp_listen(ServerSocket, 5),
96 thread_create(server_loop(ServerSocket, Name, Options), _,
97 [ alias(pdt_console_server)
98 ]).
99
100server_loop(ServerSocket, Name, Options):-
101 server_loop_impl(ServerSocket, Name, Options),
102 thread_exit(0).
103server_loop_impl(ServerSocket, Name, Options) :-
104 tcp_accept(ServerSocket, Slave, Peer),
105 server_loop_impl_X(ServerSocket,Name,Options,Slave,Peer).
106
107server_loop_impl_X(ServerSocket,_,_,Slave,_) :-
108 recorded(pdt_console_server_flag,shutdown,Ref),
109 !,
110 erase(Ref),
111 112 tcp_close_socket(Slave),
113 114 tcp_close_socket(ServerSocket).
115server_loop_impl_X(ServerSocket,Name,Options,Slave,Peer):-
116 tcp_open_socket(Slave, InStream, OutStream),
117 set_stream(InStream,encoding(utf8)),
118 set_stream(OutStream,encoding(utf8)),
120 next_pdt_console_client_id(Id),
121 atomic_list_concat(['pdt_console_client_',Id,'_',Name],Alias),
122 thread_create(service_client(InStream, OutStream, Peer, Options),
123 ID,
124 [ alias(Alias)
125 ]),
126 retractall(console_thread_name__(_)),
127 assertz(console_thread_name__(ID)),
128 server_loop_impl(ServerSocket, Name, Options).
129
130service_client(InStream, OutStream, Peer, Options) :-
131 allow(Peer, Options), !,
132 thread_self(Id),
133 set_prolog_IO(InStream, OutStream, OutStream),
134 set_stream(user_error,encoding(utf8)),
135 catch(set_prolog_flag(color_term, false), _, true),
136 format(user_error,
137 'Welcome to the SWI-Prolog server on thread ~w~n~n',
138 [Id]),
139 run_prolog,
140 close(InStream),
141 close(OutStream),
142 thread_detach(Id).
143service_client(InStream, OutStream, _, _):-
144 thread_self(Id),
145 format(OutStream, 'Go away!!~n', []),
146 close(InStream),
147 close(OutStream),
148 thread_detach(Id).
149
150
151run_prolog :-
152 catch(prolog, E,
153 ( print_message(error, E),
155 run_prolog)).
156
157
158allow(Peer, Options) :-
159 ( member(allow(Allow), Options)
160 *-> Peer = Allow,
161 !
162 ; Peer = ip(127,0,0,1)
163 ).
164
167
171:- dynamic(server/1). 172
173:- initialization(mutex_create(pdt_console_server_mux)). 174:- at_halt(mutex_destroy(pdt_console_server_mux)). 175
178pdt_current_console_server(Port) :-
179 with_mutex(pdt_console_server_mux,
180 server(Port)
181 ).
182
183
187pdt_start_console_server(Port, Name) :-
188 with_mutex(pdt_console_server_mux,
189 start_server(Port, Name)
190 ).
191
194pdt_stop_console_server:-
195 with_mutex(pdt_console_server_mux,
196 stop_server
197 ).
198
199:- multifile(consult_server:process_shutdown_hook/0). 200:- dynamic(consult_server:process_shutdown_hook/0). 201consult_server:process_shutdown_hook:-
202 pdt_stop_console_server.
203
204start_server(Port, Name) :-
205 \+ thread_property(_, alias(pdt_console_server)),
206 reset_pdt_console_client_id,
207 prolog_server(Port, Name, []),
208 assertz(server(Port)).
209
210stop_server :-
211 server(Port),
212 !,
213 do_stop_server(Port).
214stop_server.
215
216do_stop_server(Port) :-
217 recordz(pdt_console_server_flag, shutdown, _),
218 tcp_socket(Socket),
219 tcp_connect(Socket, localhost:Port),
220 tcp_close_socket(Socket),
221 retractall(server(Port))