source: tol/tolbaseBLT/lib/rmtps_client/rmtps_client.tcl @ 56ade3b

1941-docker-image-to-testdevel
Last change on this file since 56ade3b was 56ade3b, checked in by Jorge Pérez <josp.jorge@…>, 10 years ago

fixes #1932, se ha creado la rama trunk/tolbaseBLT copia de trunk/tolbase

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@7330 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 11.3 KB
Line 
1###############################################################################
2#
3#   rmtps_client.tcl -- Remote process control client side.
4#
5#   Implement the client communication routines with RmtPS_Server via
6#   sockets.
7#
8###############################################################################
9
10package provide rmtps_client 1.0
11
12package require base64
13
14if { [ catch { package require tlogger } ] } {
15  namespace eval tlogger {
16    variable _level "error"
17
18    proc init { svc {logfile ""} } {
19    }
20   
21    proc level { svc l } {
22      variable _level $l
23    }
24
25    proc log { svc l msg } {
26      variable _level
27
28      if { $l eq $_level } {
29        puts $msg
30      }
31    }
32  }
33}
34
35###############################################################################
36#
37#   rmtps_client - encapsulate the client code and variable in a
38#   namespace
39#
40###############################################################################
41namespace eval ::rmtps_client {
42  # timeout to be used when waiting response from the server
43  variable timeout_id ""
44
45  # number of seconds to wait before canceling a server's request
46  # request, by default it is set to 3 seconds. If the maximun time is
47  # reached without answer from the server, the server channel is
48  # closed and the request results in an error with a timeout reason.
49  variable server_timeout 10
50
51  # variable to store the result read from the server
52  variable server_result
53
54  # reason of the last error
55  variable error_reason ""
56
57  variable asking_error 0
58
59  # Directory where I'm located. Will be used later to evaluate the
60  # client part written in TOL
61  #
62  variable mydir [file normalize [file dir [info script]]]
63
64 
65}
66
67proc ::rmtps_client::init { {logfile ""} } {
68  ::tlogger::init  rmtps_client $logfile
69  ::tlogger::level rmtps_client "error"
70}
71
72proc ::rmtps_client::log { level msg } {
73 
74  ::tlogger::log rmtps_client $level $msg
75}
76
77###############################################################################
78#
79#   get_error_reason --
80#
81#
82###############################################################################
83proc ::rmtps_client::get_error_reason { } {
84
85  variable error_reason
86 
87  set error_reason
88}
89
90###############################################################################
91#
92#   set_server_timeout -- change the current server's request timeout
93#
94#   Arguments --
95#
96#     timeout - maximun number of seconds to wait a request result from
97#     the server.
98#
99#   Return --
100#
101#     the previous timeout value
102#
103###############################################################################
104proc ::rmtps_client::set_server_timeout { timeout } {
105  variable server_timeout
106
107  old_timeout $server_timeout
108  set server_timeout $timeout
109  set old_timeout
110}
111
112###############################################################################
113#
114#   wait_result -- event to read result from server channel
115#
116#     This procedure is invoked whenever an input is available on the
117#     server channel. Every routine must use this event handler in
118#     order to
119#
120#   Arguments --
121#
122#     chan - channel from which we are waiting a line response
123#
124#   Return --
125#
126###############################################################################
127proc ::rmtps_client::wait_result { chan } {
128  variable timeout_id
129  variable server_result
130  variable server_timeout
131  variable error_reason
132
133  log "debug" "wait_result $chan"
134
135  if {![eof $chan]} {
136    if {[gets $chan data] == -1} {
137      log "debug" "wait_result : incomplete data"
138      return;                   # only handle complete lines
139    }
140  } else {
141    # Close the channel.
142    #
143    after cancel $timeout_id
144    fileevent $chan readable {}
145    set error_reason "end of channel from server"
146    log "warn" "wait_result : end of channel from server"
147    # Cancel vwait
148    #
149    set server_result ""
150    return
151  }
152  after cancel $timeout_id
153  fileevent $chan readable {}
154  set error_reason ""
155  # Return the data via the vwaited variable
156  #
157  log "debug" "wait_result read : $data"
158  set server_result $data
159}
160
161###############################################################################
162#
163#   handle_timeout --
164#
165#
166###############################################################################
167proc ::rmtps_client::handle_timeout { chan } {
168  variable server_result
169  variable error_reason
170
171  log "debug" "handle_timeout $chan"
172
173  # Set result from server to empty to return from vwait
174  #
175  set server_result ""
176 
177  # Set error reason to timeout
178  #
179  set error_reason "server timeout"
180}
181
182proc ask_server_channel { chan request } {
183
184  usado sobre todo para pedir la razon del fallo
185
186  el timeout quizas deba cerrar el channel, esa peticion se cancela
187
188  file channels puedo usarlo para verificar si un socket existe.
189}
190
191###############################################################################
192#
193#   ask_server --
194#
195#
196###############################################################################
197proc ::rmtps_client::ask_server { host port request } {
198
199  variable server_result
200  variable server_timeout
201  variable timeout_id
202  variable error_reason
203  variable asking_error
204
205  log "debug" "enter ask_server $host $port $request"
206
207  # open channel to server
208  #
209  set chan [socket $host $port]
210
211  # We want whole lines
212  #
213  fconfigure $chan -blocking 0 -buffering line
214
215  # Send the request to the server
216  #
217  puts $chan $request
218
219  # Remember that server is line oriented
220  #
221  flush $chan
222
223  # Set up a fileevent to handle input from server
224  #
225  fileevent $chan readable [namespace code "wait_result $chan"]
226
227  # Set up timeout handler
228  #
229  set timeout_id [after [expr {1000*$server_timeout}] \
230                      [namespace code "handle_timeout $chan"]]
231 
232  # Wait for result or timeout
233  #
234  vwait ::rmtps_client::server_result
235 
236  catch {close $chan}
237
238  log "debug" "enter ask_server $host $port $server_result"
239 
240  set server_result
241}
242
243###############################################################################
244#
245#   server_ping -- Check if a rmtps_server is listening on a remote
246#   host
247#
248#   Arguments --
249#
250#     host - computer where RmtPS_Server is running
251#     port - port where the server socket should be listening
252#
253#   Return --
254#
255#     1 if rmtps_server is running and listening
256#     0 if rmtps_server does not answer or give back the wrong answer
257#
258###############################################################################
259proc ::rmtps_client::server_ping { host port } {
260
261  log "debug" "enter server_ping $host $port"
262
263  # send request to server
264  #
265  set ans [ask_server $host $port "PING"]
266  set result [expr {$ans eq "RMTPS_SERVER WORKING"}]
267
268  log "debug" "leave server_ping $host $port"
269
270  set result
271}
272
273###############################################################################
274#
275#   ps_is_active -- Check if a process is active on a remote host
276#
277#   Arguments --
278#
279#     host - computer where RmtPS_Server is running
280#     port - port where the server socket is listening
281#     PID  - process identifier to check for activity
282#
283#   Return --
284#
285#     1 if process given by PID is active
286#     0 if process given by PID is not active
287#    -1 there was an error during the operation, don't know if its alive
288#
289###############################################################################
290proc ::rmtps_client::ps_is_active { host port PID } {
291
292  log "debug" "enter ps_is_active $host $port $PID"
293
294  # send request to server
295  #
296  set result [ask_server $host $port "ALIVE $PID"]
297
298  log "debug" "from ask_server = '$result'"
299
300  # Answer from server must be an integer value
301  #
302  if { $result eq "" || ![string is integer $result] ||
303      ![string is boolean $result] } {
304    set result -1
305  } else {
306    # Make sure 0 or 1 is returned
307    #
308    set result [expr {!!$result}]
309  }
310
311  log "debug" "leave ps_is_active $host $port $PID : $result"
312
313  set result
314}
315
316###############################################################################
317#
318#  ps_kill -- terminate a given process on a remote host
319#
320#   Arguments --
321#
322#     host - computer where RmtPS_Server is running
323#     port - port where the server socket is listening
324#     PID  - process identifier to terminate
325#
326#   Return --
327#
328#     1 if process given by PID could be terminated
329#     0 if process given by PID could not be terminated
330#
331#    -1 if there was an error during the kill, in any case don't know
332#       is the process was killed
333#
334###############################################################################
335proc ::rmtps_client::ps_kill { host port PID } {
336
337  log "debug" "enter ps_kill $host $port $PID"
338
339  # send request to server
340  #
341  set result [ask_server $host $port "KILL $PID"]
342  # Answer from server must be an integer or boolean value
343  #
344  if {![string is integer $result]} {
345    set result -1
346  } else {
347    # Make sure 0, 1 or -1 is returned
348    #
349    set result [expr {$result==-1?-1:$result!=0}]
350  }
351
352  log "debug" "leave ps_kill $host $port $PID : $result"
353
354  set result
355}
356
357###############################################################################
358#
359#  ps_run -- execute a program on a remote host
360#
361#   Arguments --
362#
363#     host     - computer (remote host) where RmtPS_Server is running
364#     port     - port where the server socket is listening
365#     cmdline  - command line (program + arguments) to run on a remote host
366#
367#   Return --
368#
369#     PID of the process if cmdline could be executed
370#     0 if the command line could not be executed
371#
372###############################################################################
373proc ::rmtps_client::ps_run { host port cmdline } {
374
375  log "debug" "enter ps_run $host $port $cmdline"
376
377  # send request to server
378  #
379  set result [ask_server $host $port "RUN $cmdline"]
380  # Make sure that 0 or PID>0 is returned
381  #
382  if {![string is integer $result] || $result<0} {
383    set result 0
384  }
385
386  log "debug" "leave ps_run $host $port $cmdline : $result"
387
388  set result
389}
390
391
392###############################################################################
393#
394#  ps_runtol -- execute a TOL process on a remote host
395#
396#   Arguments --
397#
398#     host        - computer (remote host) where RmtPS_Server is running
399#     port        - port where the server socket is listening
400#     cmdln_args  - TOL arguments
401#
402#   Return --
403#
404#     PID of the process if cmdline could be executed
405#     0 if the command line could not be executed
406#
407###############################################################################
408proc ::rmtps_client::ps_runtol { host port cmdln_args } {
409
410  log "debug" "enter ps_runtol $host $port $cmdln_args"
411
412  # send request to server
413  #
414  set cmdln64 [ base64::encode -wrapchar "" $cmdln_args ]
415  #set cmdln64 $cmdln_args
416  set result [ask_server $host $port "RUNTOL $cmdln64"]
417  # Make sure that 0 or PID>0 is returned
418  #
419  if {![string is integer $result] || $result<0} {
420    set result 0
421  }
422
423  log "debug" "leave ps_runtol $host $port $cmdln_args : $result"
424
425  set result
426}
427
428###############################################################################
429#
430#  define_TOLAPI --
431#
432#  This proc will evaluate in the protected stack the TOL code
433#  corresponding to the client part of rmtps.
434#
435###############################################################################
436proc ::rmtps_client::define_TOLAPI { } {
437  variable mydir
438
439  # check before if rmtps_client.tol has being loaded
440  #
441  if {[catch {::tol::info variable Code RemoteProcessInitTcl}]} {
442    set fd [open [file join $mydir "rmtps_client.tol"]]
443    set tol_code [read $fd]
444    close $fd
445    tol::console eval -hidden $tol_code
446  }
447}
Note: See TracBrowser for help on using the repository browser.