1comm(n) Remote communication comm(n)
2
3
4
5______________________________________________________________________________
6
8 comm - A remote communication facility for Tcl (7.6, 8.0, and later)
9
11 package require Tcl 8.2
12
13 package require comm ?4.4?
14
15 ::comm::comm send ?-async? ?-command callback? id cmd ?arg arg ...?
16
17 ::comm::comm self
18
19 ::comm::comm interps
20
21 ::comm::comm connect ?id?
22
23 ::comm::comm new chan ?name value ...?
24
25 ::comm::comm channels
26
27 ::comm::comm config
28
29 ::comm::comm config name
30
31 ::comm::comm config ?name value ...?
32
33 ::comm::comm shutdown id
34
35 ::comm::comm abort
36
37 ::comm::comm destroy
38
39 ::comm::comm hook event ?+? ?script?
40
41 ::comm::comm remoteid
42
43 ::comm::comm_send
44
45_________________________________________________________________
46
48 The comm command provides an inter-interpreter remote execution facil‐
49 ity much like Tk's send(n), except that it uses sockets rather than the
50 X server for the communication path. As a result, comm works with mul‐
51 tiple interpreters, works on Windows and Macintosh systems, and pro‐
52 vides control over the remote execution path.
53
54 These commands work just like send and winfo interps :
55
56 ::comm::comm send ?-async? id cmd ?arg arg ...?
57 ::comm::comm interps
58
59
60 This is all that is really needed to know in order to use comm
61
62 COMMANDS
63 The package initializes ::comm::comm as the default chan.
64
65 comm names communication endpoints with an id unique to each machine.
66 Before sending commands, the id of another interpreter is needed.
67 Unlike Tk's send, comm doesn't implicitly know the id's of all the
68 interpreters on the system. The following four methods make up the
69 basic comm interface.
70
71 ::comm::comm send ?-async? ?-command callback? id cmd ?arg arg ...?
72 This invokes the given command in the interpreter named by id.
73 The command waits for the result and remote errors are returned
74 unless the -async or -command option is given. If -async is
75 given, send returns immediately and there is no further notifi‐
76 cation of result. If -command is used, callback specifies a
77 command to invoke when the result is received. These options
78 are mutually exclusive. The callback will receive arguments in
79 the form -option value, suitable for array set. The options
80 are: -id, the comm id of the interpreter that received the com‐
81 mand; -serial, a unique serial for each command sent to a par‐
82 ticular comm interpreter; -chan, the comm channel name; -code,
83 the result code of the command; -errorcode, the errorcode, if
84 any, of the command; -errorinfo, the errorinfo, if any, of the
85 command; and -result, the return value of the command. If con‐
86 nection is lost before a reply is received, the callback will be
87 invoked with a connection lost message with -code equal to -1.
88 When -command is used, the command returns the unique serial for
89 the command.
90
91 ::comm::comm self
92 Returns the id for this channel.
93
94 ::comm::comm interps
95 Returns a list of all the remote id's to which this channel is
96 connected. comm learns a new remote id when a command is first
97 issued it, or when a remote id first issues a command to this
98 comm channel. ::comm::comm ids is an alias for this method.
99
100 ::comm::comm connect ?id?
101 Whereas ::comm::comm send will automatically connect to the
102 given id, this forces a connection to a remote id without send‐
103 ing a command. After this, the remote id will appear in
104 ::comm::comm interps.
105
106 EVAL SEMANTICS
107 The evaluation semantics of ::comm::comm send are intended to match
108 Tk's send exactly. This means that comm evaluates arguments on the
109 remote side.
110
111 If you find that ::comm::comm send doesn't work for a particular com‐
112 mand, try the same thing with Tk's send and see if the result is dif‐
113 ferent. If there is a problem, please report it. For instance, there
114 was had one report that this command produced an error. Note that the
115 equivalent send command also produces the same error.
116
117 % ::comm::comm send id llength {a b c}
118 wrong # args: should be "llength list"
119 % send name llength {a b c}
120 wrong # args: should be "llength list"
121
122
123 The eval hook (described below) can be used to change from send's dou‐
124 ble eval semantics to single eval semantics.
125
126 MULTIPLE CHANNELS
127 More than one comm channel (or listener) can be created in each Tcl
128 interpreter. This allows flexibility to create full and restricted
129 channels. For instance, hook scripts are specific to the channel they
130 are defined against.
131
132 ::comm::comm new chan ?name value ...?
133 This creates a new channel and Tcl command with the given chan‐
134 nel name. This new command controls the new channel and takes
135 all the same arguments as ::comm::comm. Any remaining arguments
136 are passed to the config method. The fully qualified channel
137 name is returned.
138
139 ::comm::comm channels
140 This lists all the channels allocated in this Tcl interpreter.
141
142 The default configuration parameters for a new channel are:
143
144 "-port 0 -local 1 -listen 0 -silent 0"
145
146
147 The default channel ::comm::comm is created with:
148
149 "::comm::comm new ::comm::comm -port 0 -local 1 -listen 1 -silent 0"
150
151
152 CHANNEL CONFIGURATION
153 The config method acts similar to fconfigure in that it sets or queries
154 configuration variables associated with a channel.
155
156 ::comm::comm config
157
158 ::comm::comm config name
159
160 ::comm::comm config ?name value ...?
161 When given no arguments, config returns a list of all variables
162 and their value With one argument, config returns the value of
163 just that argument. With an even number of arguments, the given
164 variables are set to the given values.
165
166 These configuration variables can be changed (descriptions of them are
167 elsewhere in this manual page):
168
169 -listen ?0|1?
170
171 -local ?0|1?
172
173 -port ?port?
174
175 -silent ?0|1?
176
177 -interp ?interpreter?
178
179 -events ?eventlist?
180
181 These configuration variables are read only:
182
183 -chan chan
184
185 -serial n
186
187 -socket sockIn
188
189 When config changes the parameters of an existing channel (with the
190 exception of -interp and -events), it closes and reopens the listening
191 socket. An automatically assigned channel id will change when this
192 happens. Recycling the socket is done by invoking ::comm::comm abort,
193 which causes all active sends to terminate.
194
195 ID/PORT ASSIGNMENTS
196 comm uses a TCP port for endpoint id. The interps (or ids) method
197 merely lists all the TCP ports to which the channel is connected. By
198 default, each channel's id is randomly assigned by the operating system
199 (but usually starts at a low value around 1024 and increases each time
200 a new socket is opened). This behavior is accomplished by giving the
201 -port config option a value of 0. Alternately, a specific TCP port
202 number may be provided for a given channel. As a special case, comm
203 contains code to allocate a a high-numbered TCP port (>10000) by using
204 -port {}. Note that a channel won't be created and initialized unless
205 the specific port can be allocated.
206
207 As a special case, if the channel is configured with -listen 0, then it
208 will not create a listening socket and will use an id of 0 for itself.
209 Such a channel is only good for outgoing connections (although once a
210 connection is established, it can carry send traffic in both direc‐
211 tions). As another special case, if the channel is configured with
212 -silent 0, then the listening side will ignore connection attempts
213 where the protocol negotiation phase failed, instead of throwing an
214 error.
215
216 EXECUTION ENVIRONMENT
217 A communication channel in its default configuration will use the cur‐
218 rent interpreter for the execution of all received scripts, and of the
219 event scripts associated with the various hooks.
220
221 This insecure setup can be changed by the user via the two options
222 -interp, and -events.
223
224 When -interp is set all received scripts are executed in the slave
225 interpreter specified as the value of the option. This interpreter is
226 expected to exist before configuration. I.e. it is the responsibility
227 of the user to create it. However afterward the communication channel
228 takes ownership of this interpreter, and will destroy it when the com‐
229 munication channel is destroyed. Note that reconfiguration of the com‐
230 munication channel to either a different interpreter or the empty
231 string will release the ownership without destroying the previously
232 configured interpreter. The empty string has a special meaning, it
233 restores the default behaviour of executing received scripts in the
234 current interpreter.
235
236 Also of note is that replies and callbacks (a special form of reply)
237 are not considered as received scripts. They are trusted, part of the
238 internal machinery of comm, and therefore always executed in the cur‐
239 rent interpreter.
240
241 Even if an interpreter has been configured as the execution environment
242 for received scripts the event scripts associated with the various
243 hooks will by default still be executed in the current interpreter. To
244 change this use the option -events to declare a list of the events
245 whose scripts should be executed in the declared interpreter as well.
246 The contents of this option are ignored if the communication channel is
247 configured to execute received scripts in the current interpreter.
248
249 REMOTE INTERPRETERS
250 By default, each channel is restricted to accepting connections from
251 the local system. This can be overridden by using the -local 0 config‐
252 uration option For such channels, the id parameter takes the form { id
253 host }.
254
255 WARNING: The host must always be specified in the same form (e.g., as
256 either a fully qualified domain name, plain hostname or an IP address).
257
258 CLOSING CONNECTIONS
259 These methods give control over closing connections:
260
261 ::comm::comm shutdown id
262 This closes the connection to id, aborting all outstanding com‐
263 mands in progress. Note that nothing prevents the connection
264 from being immediately reopened by another incoming or outgoing
265 command.
266
267 ::comm::comm abort
268 This invokes shutdown on all open connections in this comm chan‐
269 nel.
270
271 ::comm::comm destroy
272 This aborts all connections and then destroys the this comm
273 channel itself, including closing the listening socket. Special
274 code allows the default ::comm::comm channel to be closed such
275 that the ::comm::comm command it is not destroyed. Doing so
276 closes the listening socket, preventing both incoming and outgo‐
277 ing commands on the channel. This sequence reinitializes the
278 default channel:
279
280
281 "::comm::comm destroy; ::comm::comm new ::comm::comm"
282
283
284 When a remote connection is lost (because the remote exited or called
285 shutdown), comm can invoke an application callback. This can be used
286 to cleanup or restart an ancillary process, for instance. See the lost
287 callback below.
288
289 CALLBACKS
290 This is a mechanism for setting hooks for particular events:
291
292 ::comm::comm hook event ?+? ?script?
293 This uses a syntax similar to Tk's bind command. Prefixing
294 script with a + causes the new script to be appended. Without
295 this, a new script replaces any existing script. When invoked
296 without a script, no change is made. In all cases, the new hook
297 script is returned by the command.
298
299 When an event occurs, the script associated with it is evaluated
300 with the listed variables in scope and available. The return
301 code (not the return value) of the script is commonly used
302 decide how to further process after the hook.
303
304 Common variables include:
305
306 chan the name of the comm channel (and command)
307
308 id the id of the remote in question
309
310 fid the file id for the socket of the connection
311
312 These are the defined events:
313
314 connecting
315 Variables: chan, id
316
317 This hook is invoked before making a connection to the remote
318 named in id. An error return (via error) will abort the connec‐
319 tion attempt with the error. Example:
320
321
322 % ::comm::comm hook connecting {
323 if {[string match {*[02468]} $id]} {
324 error "Can't connect to even ids"
325 }
326 }
327 % ::comm::comm send 10000 puts ok
328 Connect to remote failed: Can't connect to even ids
329 %
330
331
332 connected
333 Variables: chan, fid, id, host, and port.
334
335 This hook is invoked immediately after making a remote connec‐
336 tion to id, allowing arbitrary authentication over the socket
337 named by fid. An error return (via error ) will close the con‐
338 nection with the error. host and port are merely extracted from
339 the id; changing any of these will have no effect on the connec‐
340 tion, however. It is also possible to substitute and replace
341 fid.
342
343 incoming
344 Variables: chan, fid, addr, and remport.
345
346 Hook invoked when receiving an incoming connection, allowing
347 arbitrary authentication over socket named by fid. An error
348 return (via error) will close the connection with the error.
349 Note that the peer is named by remport and addr but that the
350 remote id is still unknown. Example:
351
352
353 ::comm::comm hook incoming {
354 if {[string match 127.0.0.1 $addr]} {
355 error "I don't talk to myself"
356 }
357 }
358
359
360 eval Variables: chan, id, cmd, and buffer.
361
362 This hook is invoked after collecting a complete script from a
363 remote but before evaluating it. This allows complete control
364 over the processing of incoming commands. cmd contains either
365 send or async. buffer holds the script to evaluate. At the
366 time the hook is called, $chan remoteid is identical in value to
367 id.
368
369 By changing buffer, the hook can change the script to be evalu‐
370 ated. The hook can short circuit evaluation and cause a value
371 to be immediately returned by using return result (or, from
372 within a procedure, return -code return result). An error
373 return (via error) will return an error result, as is if the
374 script caused the error. Any other return will evaluate the
375 script in buffer as normal. For compatibility with 3.2, break
376 and return -code break result is supported, acting similarly to
377 return {} and return -code return result.
378
379 Examples:
380
381 [1] augmenting a command
382
383
384 % ::comm::comm send [::comm::comm self] pid
385 5013
386 % ::comm::comm hook eval {puts "going to execute $buffer"}
387 % ::comm::comm send [::comm::comm self] pid
388 going to execute pid
389 5013
390
391
392 [2] short circuiting a command
393
394
395 % ::comm::comm hook eval {puts "would have executed $buffer"; return 0}
396 % ::comm::comm send [::comm::comm self] pid
397 would have executed pid
398 0
399
400
401 [3] Replacing double eval semantics
402
403
404 % ::comm::comm send [::comm::comm self] llength {a b c}
405 wrong # args: should be "llength list"
406 % ::comm::comm hook eval {return [uplevel #0 $buffer]}
407 return [uplevel #0 $buffer]
408 % ::comm::comm send [::comm::comm self] llength {a b c}
409 3
410
411
412 [4] Using a slave interpreter
413
414
415 % interp create foo
416 % ::comm::comm hook eval {return [foo eval $buffer]}
417 % ::comm::comm send [::comm::comm self] set myvar 123
418 123
419 % set myvar
420 can't read "myvar": no such variable
421 % foo eval set myvar
422 123
423
424
425 [5] Using a slave interpreter (double eval)
426
427
428 % ::comm::comm hook eval {return [eval foo eval $buffer]}
429
430
431 [6] Subverting the script to execute
432
433
434 % ::comm::comm hook eval {
435 switch -- $buffer {
436 a {return A-OK}
437 b {return B-OK}
438 default {error "$buffer is a no-no"}
439 }
440 }
441 % ::comm::comm send [::comm::comm self] pid
442 pid is a no-no
443 % ::comm::comm send [::comm::comm self] a
444 A-OK
445
446
447 reply Variables: chan, id, buffer, ret, and return().
448
449 This hook is invoked after collecting a complete reply script
450 from a remote but before evaluating it. This allows complete
451 control over the processing of replies to sent commands. The
452 reply buffer is in one of the following forms
453
454 · return result
455
456 · return -code code result
457
458 · return -code code -errorinfo info -errorcode ecode msg
459
460 For safety reasons, this is decomposed. The return result is in ret,
461 and the return switches are in the return array:
462
463 · return(-code)
464
465 · return(-errorinfo)
466
467 · return(-errorcode)
468
469 Any of these may be the empty string. Modifying these four variables
470 can change the return value, whereas modifying buffer has no effect.
471
472 callback
473 Variables: chan, id, buffer, ret, and return().
474
475 Similar to reply, but used for callbacks.
476
477 lost Variables: chan, id, and reason.
478
479 This hook is invoked when the connection to id is lost. Return
480 value (or thrown error) is ignored. reason is an explanatory
481 string indicating why the connection was lost. Example:
482
483
484 ::comm::comm hook lost {
485 global myvar
486 if {$myvar(id) == $id} {
487 myfunc
488 return
489 }
490 }
491
492
493 UNSUPPORTED
494 These interfaces may change or go away in subsequence releases.
495
496 ::comm::comm remoteid
497 Returns the id of the sender of the last remote command executed
498 on this channel. If used by a proc being invoked remotely, it
499 must be called before any events are processed. Otherwise,
500 another command may get invoked and change the value.
501
502 ::comm::comm_send
503 Invoking this procedure will substitute the Tk send and winfo
504 interps commands with these equivalents that use ::comm::comm.
505
506
507 proc send {args} {
508 eval ::comm::comm send $args
509 }
510 rename winfo tk_winfo
511 proc winfo {cmd args} {
512 if {![string match in* $cmd]} {
513 return [eval [list tk_winfo $cmd] $args]
514 }
515 return [::comm::comm interps]
516 }
517
518
519 SECURITY
520 Something here soon.
521
522 BLOCKING SEMANTICS
523 There is one outstanding difference between comm and send. When block‐
524 ing in a synchronous remote command, send uses an internal C hook
525 (Tk_RestrictEvents) to the event loop to look ahead for send-related
526 events and only process those without processing any other events. In
527 contrast, comm uses the vwait command as a semaphore to indicate the
528 return message has arrived. The difference is that a synchronous send
529 will block the application and prevent all events (including window
530 related ones) from being processed, while a synchronous ::comm::comm
531 send will block the application but still allow other events to get
532 processed. In particular, after idle handlers will fire immediately
533 when comm blocks.
534
535 What can be done about this? First, note that this behavior will come
536 from any code using vwait to block and wait for an event to occur. At
537 the cost of multiple channel support, comm could be changed to do
538 blocking I/O on the socket, giving send-like blocking semantics. How‐
539 ever, multiple channel support is a very useful feature of comm that it
540 is deemed too important to lose. The remaining approaches involve a
541 new loadable module written in C (which is somewhat against the philos‐
542 ophy of comm) One way would be to create a modified version of the
543 vwait command that allow the event flags passed to Tcl_DoOneEvent to be
544 specified. For comm, just the TCL_FILE_EVENTS would be processed.
545 Another way would be to implement a mechanism like Tk_RestrictEvents,
546 but apply it to the Tcl event loop (since comm doesn't require Tk).
547 One of these approaches will be available in a future comm release as
548 an optional component.
549
550 COMPATIBILITY
551 comm exports itself as a package. The package version number is in the
552 form major . minor, where the major version will only change when a
553 non-compatible change happens to the API or protocol. Minor bug fixes
554 and changes will only affect the minor version. To load comm this com‐
555 mand is usually used:
556
557 package require comm 3
558
559
560 Note that requiring no version (or a specific version) can also be
561 done.
562
563 The revision history of comm includes these releases:
564
565 4.4 Bugfixes in the handling of -interp for regular and hook
566 scripts. Bugfixes in channel cleanup.
567
568 4.3.1 Introduced -interp and -events to enable easy use of a slave
569 interp for execution of received scripts, and of event scripts.
570
571 4.3 Bugfixes, and introduces -silent to allow the user to force the
572 server/listening side to silently ignore connection attempts
573 where the protocol negotiation failed.
574
575 4.2 Bugfixes, and most important, switched to utf-8 as default
576 encoding for full i18n without any problems.
577
578 4.1 Rewrite of internal code to remove old pseudo-object model.
579 Addition of send -command asynchronous callback option.
580
581 4.0 Per request by John LoVerso. Improved handling of error for
582 async invoked commands.
583
584 3.7 Moved into tcllib and placed in a proper namespace.
585
586 3.6 A bug in the looking up of the remoteid for a executed command
587 could be triggered when the connection was closed while several
588 asynchronous sends were queued to be executed.
589
590 3.5 Internal change to how reply messages from a send are handled.
591 Reply messages are now decoded into the value to pass to return;
592 a new return statement is then cons'd up to with this value.
593 Previously, the return code was passed in from the remote as a
594 command to evaluate. Since the wire protocol has not changed,
595 this is still the case. Instead, the reply handling code
596 decodes the reply message.
597
598 3.4 Added more source commentary, as well as documenting config
599 variables in this man page. Fixed bug were loss of connection
600 would give error about a variable named pending rather than the
601 message about the lost connection. comm ids is now an alias for
602 comm interps (previously, it an alias for comm chans). Since
603 the method invocation change of 3.0, break and other exceptional
604 conditions were not being returned correctly from comm send.
605 This has been fixed by removing the extra level of indirection
606 into the internal procedure commSend. Also added propagation of
607 the errorCode variable. This means that these commands return
608 exactly as they would with send:
609
610
611 comm send id break
612 catch {comm send id break}
613 comm send id expr 1 / 0
614
615
616 Added a new hook for reply messages. Reworked method invocation
617 to avoid the use of comm:* procedures; this also cut the invoca‐
618 tion time down by 40%. Documented comm config (as this manual
619 page still listed the defunct comm init!)
620
621 3.3 Some minor bugs were corrected and the documentation was cleaned
622 up. Added some examples for hooks. The return semantics of the
623 eval hook were changed.
624
625 3.2 A new wire protocol, version 3, was added. This is backwards
626 compatible with version 2 but adds an exchange of supported pro‐
627 tocol versions to allow protocol negotiation in the future.
628 Several bugs with the hook implementation were fixed. A new
629 section of the man page on blocking semantics was added.
630
631 3.1 All the documented hooks were implemented. commLostHook was
632 removed. A bug in comm new was fixed.
633
634 3.0 This is a new version of comm with several major changes. There
635 is a new way of creating the methods available under the comm
636 command. The comm init method has been retired and is replaced
637 by comm configure which allows access to many of the well-
638 defined internal variables. This also generalizes the options
639 available to comm new. Finally, there is now a protocol version
640 exchanged when a connection is established. This will allow for
641 future on-wire protocol changes. Currently, the protocol ver‐
642 sion is set to 2.
643
644 2.3 comm ids was renamed to comm channels. General support for comm
645 hook was fully implemented, but only the lost hook exists, and
646 it was changed to follow the general hook API. commLostHook was
647 unsupported (replaced by comm hook lost) and commLost was
648 removed.
649
650 2.2 The died hook was renamed lost, to be accessed by commLostHook
651 and an early implementation of comm lost hook. As such, com‐
652 mDied is now commLost.
653
654 2.1 Unsupported method comm remoteid was added.
655
656 2.0 comm has been rewritten from scratch (but is fully compatible
657 with Comm 1.0, without the requirement to use obTcl).
658
660 John LoVerso, John@LoVerso.Southborough.MA.US
661
662 http://www.opengroup.org/~loverso/tcl-tk/#comm
663
665 Please see the file comm.LICENSE that accompanied this source, or
666 http://www.opengroup.org/www/dist_client/caubweb/COPYRIGHT.free.html.
667
668 This license for comm, new as of version 3.2, allows it to be used for
669 free, without any licensing fee or royalty.
670
672 · If there is a failure initializing a channel created with
673 ::comm::comm new, then the channel should be destroyed. Cur‐
674 rently, it is left in an inconsistent state.
675
676 · There should be a way to force a channel to quiesce when chang‐
677 ing the configuration.
678
679 The following items can be implemented with the existing hooks and are
680 listed here as a reminder to provide a sample hook in a future version.
681
682 · Allow easier use of a slave interp for actual command execution
683 (especially when operating in "not local" mode).
684
685 · Add host list (xhost-like) or "magic cookie" (xauth-like)
686 authentication to initial handshake.
687
688 The following are outstanding todo items.
689
690 · Add an interp discovery and name->port mapping. This is likely
691 to be in a separate, optional nameserver. (See also the related
692 work, below.)
693
694 · Fix the {id host} form so as not to be dependent upon canonical
695 hostnames. This requires fixes to Tcl to resolve hostnames!
696
697 This man page is bigger than the source file.
698
700 Tcl7.5 under Windows contains a bug that causes the interpreter to hang
701 when EOF is reached on non-blocking sockets. This can be triggered
702 with a command such as this:
703
704 "comm send $other exit"
705
706
707 Always make sure the channel is quiescent before closing/exiting or use
708 at least Tcl7.6 under Windows.
709
710 Tcl7.6 on the Mac contains several bugs. It is recommended you use at
711 least Tcl7.6p2.
712
713 Tcl8.0 on UNIX contains a socket bug that can crash Tcl. It is recom‐
714 mended you use Tcl8.0p1 (or Tcl7.6p2).
715
717 Tcl-DP provides an RPC-based remote execution interface, but is a com‐
718 piled Tcl extension. See http://www.cs.cor‐
719 nell.edu/Info/Projects/zeno/Projects/Tcl-DP.html.
720
721 Michael Doyle <miked@eolas.com> has code that implements the Tcl-DP RPC
722 interface using standard Tcl sockets, much like comm.
723
724 Andreas Kupries <andreas_kupries@users.sourceforge.net> uses comm and
725 has built a simple nameserver as part of his Pool library. See
726 http://www.purl.org/net/akupries/soft/pool/index.htm.
727
729 send(n)
730
732 Copyright (c) 1995-1998 The Open Group. All Rights Reserved.
733 Copyright (c) 2003-2004 ActiveState Corporation.
734 Copyright (c) 2006 Andreas Kupries <andreas_kupries@users.sourceforge.net>
735
736
737
738
739comm 4.4 comm(n)