Provided by: tcllib_1.15-dfsg-2_all bug

NAME

       comm - A remote communication facility for Tcl (8.3 and later)

SYNOPSIS

       package require Tcl  8.3

       package require comm  ?4.6.2?

       ::comm::comm send ?-async? ?-command callback? id cmd ?arg arg ...?

       ::comm::comm self

       ::comm::comm interps

       ::comm::comm connect ?id?

       ::comm::comm new chan ?name value ...?

       ::comm::comm channels

       ::comm::comm config

       ::comm::comm config name

       ::comm::comm config ?name value ...?

       ::comm::comm shutdown id

       ::comm::comm abort

       ::comm::comm destroy

       ::comm::comm hook event ?+? ?script?

       ::comm::comm remoteid

       ::comm::comm_send

       ::comm::comm return_async

       $future return ?-code code? ?value?

       $future configure ?-command ?cmdprefix??

       $future cget -command

_________________________________________________________________

DESCRIPTION

       The  comm  command  provides an inter-interpreter remote execution facility much like Tk's
       send(3tk), except that it uses sockets rather than the  X  server  for  the  communication
       path.   As a result, comm works with multiple interpreters, works on Windows and Macintosh
       systems, and provides control over the remote execution path.

       These commands work just like send and winfo interps :

              ::comm::comm send ?-async? id cmd ?arg arg ...?
              ::comm::comm interps

       This is all that is really needed to know in order to use comm

   COMMANDS
       The package initializes ::comm::comm as the default chan.

       comm names communication endpoints with an id unique  to  each  machine.   Before  sending
       commands,  the  id  of  another  interpreter  is  needed.   Unlike Tk's send, comm doesn't
       implicitly know the id's of all the  interpreters  on  the  system.   The  following  four
       methods make up the basic comm interface.

       ::comm::comm send ?-async? ?-command callback? id cmd ?arg arg ...?
              This  invokes  the given command in the interpreter named by id.  The command waits
              for the result and remote errors are returned unless the -async or -command  option
              is  given.   If  -async  is given, send returns immediately and there is no further
              notification of result.  If -command is  used,  callback  specifies  a  command  to
              invoke  when  the  result  is received.  These options are mutually exclusive.  The
              callback will receive arguments in the form -option value, suitable for array  set.
              The  options  are:  -id,  the comm id of the interpreter that received the command;
              -serial, a unique serial for each command sent to a  particular  comm  interpreter;
              -chan,  the  comm  channel name; -code, the result code of the command; -errorcode,
              the errorcode, if any, of the command; -errorinfo, the errorinfo, if  any,  of  the
              command;  and  -result,  the  return  value  of the command.  If connection is lost
              before a reply is received, the callback will be invoked  with  a  connection  lost
              message  with  -code  equal  to -1.  When -command is used, the command returns the
              unique serial for the command.

       ::comm::comm self
              Returns the id for this channel.

       ::comm::comm interps
              Returns a list of all the remote id's to which this  channel  is  connected.   comm
              learns a new remote id when a command is first issued it, or when a remote id first
              issues a command to this comm channel.  ::comm::comm  ids  is  an  alias  for  this
              method.

       ::comm::comm connect ?id?
              Whereas ::comm::comm send will automatically connect to the given id, this forces a
              connection to a remote id without sending a command.  After  this,  the  remote  id
              will appear in ::comm::comm interps.

   EVAL SEMANTICS
       The  evaluation  semantics  of  ::comm::comm send are intended to match Tk's send exactly.
       This means that comm evaluates arguments on the remote side.

       If you find that ::comm::comm send doesn't work for a particular  command,  try  the  same
       thing  with  Tk's  send and see if the result is different.  If there is a problem, please
       report it.  For instance, there was had one report that this command  produced  an  error.
       Note that the equivalent send command also produces the same error.

              % ::comm::comm send id llength {a b c}
              wrong # args: should be "llength list"
              % send name llength {a b c}
              wrong # args: should be "llength list"

       The eval hook (described below) can be used to change from send's double eval semantics to
       single eval semantics.

   MULTIPLE CHANNELS
       More than one comm channel (or listener) can be created in  each  Tcl  interpreter.   This
       allows flexibility to create full and restricted channels.  For instance, hook scripts are
       specific to the channel they are defined against.

       ::comm::comm new chan ?name value ...?
              This creates a new channel and Tcl command with the given channel name.   This  new
              command  controls the new channel and takes all the same arguments as ::comm::comm.
              Any remaining arguments are passed to  the  config  method.   The  fully  qualified
              channel name is returned.

       ::comm::comm channels
              This lists all the channels allocated in this Tcl interpreter.

       The default configuration parameters for a new channel are:

              "-port 0 -local 1 -listen 0 -silent 0"

       The default channel ::comm::comm is created with:

              "::comm::comm new ::comm::comm -port 0 -local 1 -listen 1 -silent 0"

   CHANNEL CONFIGURATION
       The  config  method  acts  similar  to fconfigure in that it sets or queries configuration
       variables associated with a channel.

       ::comm::comm config

       ::comm::comm config name

       ::comm::comm config ?name value ...?
              When given no arguments, config returns a list of all  variables  and  their  value
              With  one  argument,  config returns the value of just that argument.  With an even
              number of arguments, the given variables are set to the given values.

       These configuration variables can be changed (descriptions of them are elsewhere  in  this
       manual page):

       -listen ?0|1?

       -local  ?0|1?

       -port   ?port?

       -silent ?0|1?

       -socketcmd ?commandname?

       -interp ?interpreter?

       -events ?eventlist?

       These configuration variables are read only:

       -chan    chan

       -serial  n

       -socket  sockIn

       When  config  changes the parameters of an existing channel (with the exception of -interp
       and -events), it closes and reopens  the  listening  socket.   An  automatically  assigned
       channel  id  will  change  when  this  happens.   Recycling the socket is done by invoking
       ::comm::comm abort, which causes all active sends to terminate.

   ID/PORT ASSIGNMENTS
       comm uses a TCP port for endpoint id.  The interps (or ids) method merely  lists  all  the
       TCP  ports  to  which the channel is connected.  By default, each channel's id is randomly
       assigned by the operating system (but usually starts  at  a  low  value  around  1024  and
       increases  each time a new socket is opened).  This behavior is accomplished by giving the
       -port config option a value of 0.  Alternately, a specific TCP port number may be provided
       for  a given channel.  As a special case, comm contains code to allocate a a high-numbered
       TCP port (>10000) by using -port {}.  Note that a channel won't be created and initialized
       unless the specific port can be allocated.

       As  a special case, if the channel is configured with -listen 0, then it will not create a
       listening socket and will use an id of 0 for itself.  Such a  channel  is  only  good  for
       outgoing connections (although once a connection is established, it can carry send traffic
       in both directions).  As another special case, if the channel is configured  with  -silent
       0,  then the listening side will ignore connection attempts where the protocol negotiation
       phase failed, instead of throwing an error.

   EXECUTION ENVIRONMENT
       A communication channel in its default configuration will use the current interpreter  for
       the  execution  of  all  received  scripts,  and  of the event scripts associated with the
       various hooks.

       This insecure setup can be changed by the user via the two options -interp, and -events.

       When -interp is set all received scripts are executed in the slave  interpreter  specified
       as  the  value  of the option. This interpreter is expected to exist before configuration.
       I.e.  it  is  the  responsibility  of  the  user  to  create  it.  However  afterward  the
       communication  channel  takes  ownership of this interpreter, and will destroy it when the
       communication channel is  destroyed.   Note  that  reconfiguration  of  the  communication
       channel  to  either a different interpreter or the empty string will release the ownership
       without destroying the previously configured interpreter.  The empty string has a  special
       meaning,  it  restores  the default behaviour of executing received scripts in the current
       interpreter.

       Also of note is that replies and callbacks (a special form of reply) are not considered as
       received  scripts. They are trusted, part of the internal machinery of comm, and therefore
       always executed in the current interpreter.

       Even if an interpreter has been configured  as  the  execution  environment  for  received
       scripts  the  event  scripts  associated  with  the various hooks will by default still be
       executed in the current interpreter. To change this use the option -events  to  declare  a
       list  of  the events whose scripts should be executed in the declared interpreter as well.
       The contents of this option are ignored if the  communication  channel  is  configured  to
       execute received scripts in the current interpreter.

   REMOTE INTERPRETERS
       By  default,  each  channel  is restricted to accepting connections from the local system.
       This can be overridden by using the -local 0 configuration option For such  channels,  the
       id parameter takes the form { id host }.

       WARNING:  The  host  must  always  be  specified in the same form (e.g., as either a fully
       qualified domain name, plain hostname or an IP address).

   CLOSING CONNECTIONS
       These methods give control over closing connections:

       ::comm::comm shutdown id
              This closes the connection to id, aborting all outstanding  commands  in  progress.
              Note  that  nothing  prevents  the  connection  from  being immediately reopened by
              another incoming or outgoing command.

       ::comm::comm abort
              This invokes shutdown on all open connections in this comm channel.

       ::comm::comm destroy
              This aborts all connections  and  then  destroys  the  this  comm  channel  itself,
              including   closing   the  listening  socket.   Special  code  allows  the  default
              ::comm::comm channel to be closed such that the  ::comm::comm  command  it  is  not
              destroyed.   Doing  so  closes  the  listening socket, preventing both incoming and
              outgoing commands on the channel.  This sequence reinitializes the default channel:

              "::comm::comm destroy; ::comm::comm new ::comm::comm"

       When a remote connection is lost (because the remote exited or called shutdown), comm  can
       invoke  an  application  callback.   This  can  be used to cleanup or restart an ancillary
       process, for instance.  See the lost callback below.

   CALLBACKS
       This is a mechanism for setting hooks for particular events:

       ::comm::comm hook event ?+? ?script?
              This uses a syntax similar to Tk's bind command.  Prefixing script with a +  causes
              the  new  script  to be appended.  Without this, a new script replaces any existing
              script.  When invoked without a script, no change is made.  In all cases,  the  new
              hook script is returned by the command.

              When  an  event  occurs, the script associated with it is evaluated with the listed
              variables in scope and available.  The return code (not the return  value)  of  the
              script is commonly used decide how to further process after the hook.

              Common variables include:

              chan   the name of the comm channel (and command)

              id     the id of the remote in question

              fid    the file id for the socket of the connection

       These are the defined events:

       connecting
              Variables: chan, id

              This  hook  is  invoked  before  making a connection to the remote named in id.  An
              error return (via  error)  will  abort  the  connection  attempt  with  the  error.
              Example:

              % ::comm::comm hook connecting {
              if {[string match {*[02468]} $id]} {
              error "Can't connect to even ids"
              }
              }
              % ::comm::comm send 10000 puts ok
              Connect to remote failed: Can't connect to even ids
              %

       connected
              Variables: chan, fid, id, host, and port.

              This  hook  is invoked immediately after making a remote connection to id, allowing
              arbitrary authentication over the socket named by fid.  An error return (via  error
              )  will  close  the  connection with the error.  host and port are merely extracted
              from the id; changing any of these will have no effect on the connection,  however.
              It is also possible to substitute and replace fid.

       incoming
              Variables: chan, fid, addr, and remport.

              Hook   invoked   when   receiving   an   incoming  connection,  allowing  arbitrary
              authentication over socket named by fid.  An error return (via  error)  will  close
              the connection with the error.  Note that the peer is named by remport and addr but
              that the remote id is still unknown.  Example:

              ::comm::comm hook incoming {
              if {[string match 127.0.0.1 $addr]} {
              error "I don't talk to myself"
              }
              }

       eval   Variables: chan, id, cmd, and buffer.

              This hook is invoked after collecting a complete script from a  remote  but  before
              evaluating  it.   This  allows  complete  control  over  the processing of incoming
              commands.  cmd contains either send or async.  buffer holds the script to evaluate.
              At the time the hook is called, $chan remoteid is identical in value to id.

              By  changing  buffer, the hook can change the script to be evaluated.  The hook can
              short circuit evaluation and cause a value to  be  immediately  returned  by  using
              return  result (or, from within a procedure, return -code return result).  An error
              return (via error) will return an error result, as is  if  the  script  caused  the
              error.   Any  other  return  will  evaluate  the  script  in buffer as normal.  For
              compatibility with 3.2, break and return -code break result  is  supported,  acting
              similarly to return {} and return -code return result.

              Examples:

              [1]    augmenting a command

                     % ::comm::comm send [::comm::comm self] pid
                     5013
                     % ::comm::comm hook eval {puts "going to execute $buffer"}
                     % ::comm::comm send [::comm::comm self] pid
                     going to execute pid
                     5013

              [2]    short circuiting a command

                     % ::comm::comm hook eval {puts "would have executed $buffer"; return 0}
                     % ::comm::comm send [::comm::comm self] pid
                     would have executed pid
                     0

              [3]    Replacing double eval semantics

                     % ::comm::comm send [::comm::comm self] llength {a b c}
                     wrong # args: should be "llength list"
                     % ::comm::comm hook eval {return [uplevel #0 $buffer]}
                     return [uplevel #0 $buffer]
                     % ::comm::comm send [::comm::comm self] llength {a b c}
                     3

              [4]    Using a slave interpreter

                     % interp create foo
                     % ::comm::comm hook eval {return [foo eval $buffer]}
                     % ::comm::comm send [::comm::comm self] set myvar 123
                     123
                     % set myvar
                     can't read "myvar": no such variable
                     % foo eval set myvar
                     123

              [5]    Using a slave interpreter (double eval)

                     % ::comm::comm hook eval {return [eval foo eval $buffer]}

              [6]    Subverting the script to execute

                     % ::comm::comm hook eval {
                     switch -- $buffer {
                     a {return A-OK}
                     b {return B-OK}
                     default {error "$buffer is a no-no"}
                     }
                     }
                     % ::comm::comm send [::comm::comm self] pid
                     pid is a no-no
                     % ::comm::comm send [::comm::comm self] a
                     A-OK

       reply  Variables: chan, id, buffer, ret, and return().

              This  hook  is  invoked  after collecting a complete reply script from a remote but
              before evaluating it.  This allows complete control over the processing of  replies
              to sent commands.  The reply buffer is in one of the following forms

              •      return result

              •      return -code code result

              •      return -code code -errorinfo info -errorcode ecode msg

       For  safety  reasons,  this  is  decomposed.   The return result is in ret, and the return
       switches are in the return array:

              •      return(-code)return(-errorinfo)return(-errorcode)

       Any of these may be the empty string.  Modifying  these  four  variables  can  change  the
       return value, whereas modifying buffer has no effect.

       callback
              Variables: chan, id, buffer, ret, and return().

              Similar to reply, but used for callbacks.

       lost   Variables: chan, id, and reason.

              This  hook  is  invoked when the connection to id is lost.  Return value (or thrown
              error) is ignored.  reason is an explanatory string indicating why  the  connection
              was lost.  Example:

              ::comm::comm hook lost {
              global myvar
              if {$myvar(id) == $id} {
              myfunc
              return
              }
              }

   UNSUPPORTED
       These interfaces may change or go away in subsequence releases.

       ::comm::comm remoteid
              Returns  the  id of the sender of the last remote command executed on this channel.
              If used by a proc being invoked remotely, it must be called before any  events  are
              processed.  Otherwise, another command may get invoked and change the value.

       ::comm::comm_send
              Invoking this procedure will substitute the Tk send and winfo interps commands with
              these equivalents that use ::comm::comm.

              proc send {args} {
              eval ::comm::comm send $args
              }
              rename winfo tk_winfo
              proc winfo {cmd args} {
              if {![string match in* $cmd]} {
              return [eval [list tk_winfo $cmd] $args]
              }
              return [::comm::comm interps]
              }

   SECURITY
       Starting with version 4.6 of the package an option -socketcmd is supported,  allowing  the
       user  of  a  comm  channel to specify which command to use when opening a socket. Anything
       which is API-compatible with the builtin ::socket (the default) can be used.

       The envisioned main use is the specification of the tls::socket command, see package  tls,
       to secure the communication.

              # Load and initialize tls
              package require tls
              tls::init  -cafile /path/to/ca/cert -keyfile ...
              # Create secured comm channel
              ::comm::comm new SECURE -socketcmd tls::socket -listen 1

       The  sections Execution Environment and Callbacks are also relevant to the security of the
       system, providing means to restrict the  execution  to  a  specific  environment,  perform
       additional authentication, and the like.

   BLOCKING SEMANTICS
       There is one outstanding difference between comm and send.  When blocking in a synchronous
       remote command, send uses an internal C hook (Tk_RestrictEvents) to the event loop to look
       ahead  for send-related events and only process those without processing any other events.
       In contrast, comm uses the vwait command as a semaphore to indicate the return message has
       arrived.  The difference is that a synchronous send will block the application and prevent
       all events (including window related ones)  from  being  processed,  while  a  synchronous
       ::comm::comm  send  will  block  the  application  but  still  allow  other  events to get
       processed.  In particular, after idle handlers will fire immediately when comm blocks.

       What can be done about this?  First, note that this behavior will come from any code using
       vwait  to  block and wait for an event to occur.  At the cost of multiple channel support,
       comm could be changed to  do  blocking  I/O  on  the  socket,  giving  send-like  blocking
       semantics.   However, multiple channel support is a very useful feature of comm that it is
       deemed too important to lose.  The remaining approaches  involve  a  new  loadable  module
       written in C (which is somewhat against the philosophy of comm) One way would be to create
       a  modified  version  of  the  vwait  command  that  allow  the  event  flags  passed   to
       Tcl_DoOneEvent  to  be  specified.  For comm, just the TCL_FILE_EVENTS would be processed.
       Another way would be to implement a mechanism like Tk_RestrictEvents, but apply it to  the
       Tcl event loop (since comm doesn't require Tk).  One of these approaches will be available
       in a future comm release as an optional component.

   ASYNCHRONOUS RESULT GENERATION
       By default the result returned by a remotely invoked command is the result  sent  back  to
       the  invoker.  This  means  that  the  result  is  generated synchronously, and the server
       handling the call is blocked for the duration of the command.

       While this is tolerable as long as only short-running commands are invoked on  the  server
       long-running  commands, like database queries make this a problem. One command can prevent
       the processing requests of all other clients for an arbitrary period of time.

       Before version 4.5 of comm the only solution was to rewrite the server command to use  the
       Tcl  builtin  command vwait, or one of its relatives like tkwait, to open a new event loop
       which processes requests while the long-running operation is executed.  This  however  has
       its  own  perils,  as  this  makes it possible to both overflow the Tcl stack with a large
       number of event loop, and to have a newer requests block the return of older ones, as  the
       eventloop have to be unwound in the order of their creation.

       The proper solution is to have the invoked command indicate to comm that it cannot or will
       not deliver an immediate, synchronous result, but will do so  later.  At  that  point  the
       framework can put sending the actual result on hold and continue processing requests using
       the main event loop. No blocking, no nesting of event loops. At some future date the  long
       running  operation  delivers  the  result  to  comm,  via the future object, which is then
       forwarded to the invoker as usual.

       The necessary support for this solution has been added to comm since version 4.5,  in  the
       form of the new method return_async.

       ::comm::comm return_async
              This  command is used by a remotely invoked script to notify the comm channel which
              invoked it  that  the  result  to  send  back  to  the  invoker  is  not  generated
              synchronously. If this command is not called the default/standard behaviour of comm
              is to send the synchronously generated result of the script itself to the invoker.

              The result of return_async is an object. This object, called a future is where  the
              result  of  the  script  has  to  be  delivered to when it becomes ready. When that
              happens it will take all the necessary actions to deliver the result to the invoker
              of the script, and then destroy itself. Should comm have lost the connection to the
              invoker while the result is being computed the future will not try to  deliver  the
              result it got, but just destroy itself. The future can be configured with a command
              to call when the invoker is lost. This enables the user to implement an early abort
              of the long-running operation, should this be supported by it.

              An example:
              # Procedure invoked by remote clients to run database operations.
              proc select {sql} {
              # Signal the async generation of the result
              set future [::comm::comm return_async]
              # Generate an async db operation and tell it where to deliver the result.
              set query [db query -command [list $future return] $sql]
              # Tell the database system which query to cancel if the connection
              # goes away while it is running.
              $future configure -command [list db cancel $query]
              # Note: The above will work without problem only if the async
              # query will nover run its completion callback immediately, but
              # only from the eventloop. Because otherwise the future we wish to
              # configure may already be gone. If that is possible use 'catch'
              # to prevent the error from propagating.
              return
              }

       The API of a future object is:

              $future return ?-code code? ?value?
                     Use  this  method  to  tell  the  future  that  long-running  operation  has
                     completed. Arguments are an optional return value  (defaults  to  the  empty
                     string), and the Tcl return code (defaults to OK).

                     The  future  will deliver this information to invoker, if the connection was
                     not lost in the meantime, and then destroy itself.  If  the  connection  was
                     lost it will do nothing but destroy itself.

              $future configure ?-command ?cmdprefix??

              $future cget -command
                     These  methods  allow the user to retrieve and set a command to be called if
                     the connection the future belongs to has been lost.

   COMPATIBILITY
       comm exports itself as a package.  The package version number  is  in  the  form  major  .
       minor,  where  the  major version will only change when a non-compatible change happens to
       the API or protocol.  Minor bug fixes and changes will only affect the minor version.   To
       load comm this command is usually used:

              package require comm 3

       Note that requiring no version (or a specific version) can also be done.

       The revision history of comm includes these releases:

       4.6.2  Fixed  bugs  2972571  and  3066872,  the first a misdetection of quoted brace after
              double backslash, the other a blocking gets making for an  obvious  (hinsight)  DoS
              attack on comm channels.

       4.6.1  Changed  the  implementation  of  comm::commCollect  to  emulate lindex's pre-Tcl 8
              behaviour, i.e. it was given the ability to parse out the first  word  of  a  list,
              even  if  the whole buffer is not a well-formed list. Without this change the first
              word could only be extracted if the whole buffer was a well-formed list (ever since
              Tcl  8),  and in a ver-high-load situation, i.e. a server sending lots and/or large
              commands very fast, this may never happen, eventually crashing the receiver when it
              runs  out  of  memory.  With  the change the receiver is always able to process the
              first word when  it  becomes  well-formed,  regardless  of  the  structure  of  the
              remainder of the buffer.

       4.6    Added  the option -socketcmd enabling users to override how a socket is opened. The
              envisioned main use is the specification of the tls::socket  command,  see  package
              tls, to secure the communication.

       4.5.7  Changed handling of ports already in use to provide a proper error message.

       4.5.6  Bugfix  in  the  replacement  for  vwait,  made  robust  against  of variable names
              containing spaces.

       4.5.5  Bugfix in the handling of hooks, typo in variable name.

       4.5.4  Bugfix in the handling of the result received by the send method. Replaced an after
              idle  unset  result  with an immediate unset, with the information saved to a local
              variable.

              The after idle can spill into a forked child process if  there  is  no  event  loop
              between  its  setup and the fork. This may bork the child if the next event loop is
              the vwait of comm's send a few lines above the after idle, and the child  used  the
              same serial number for its next request. In that case the parent's after idle unset
              will delete the very array element the child is waiting for, unlocking  the  vwait,
              causing it to access a now missing array element, instead of the expected result.

       4.5.3  Bugfixes in the wrappers for the builtin update and vwait commands.

       4.5.2  Bugfix in the wrapper for the builtin update command.

       4.5.1  Bugfixes in the handling of -interp for regular scripts. The handling of the buffer
              was wrong for scripts which are a single statement as list. Fixed missing  argument
              to new command commSendReply, introduced by version 4.5. Affected debugging.

       4.5    New server-side feature. The command invoked on the server can now switch comm from
              the standard synchronous return of its result to an asynchronous (defered)  return.
              Due  to  the  use of snit to implement the future objects used by this feature from
              this version on comm requires at least Tcl 8.3 to  run.  Please  read  the  section
              Asynchronous Result Generation for more details.

       4.4.1  Bugfix in the execution of hooks.

       4.4    Bugfixes  in  the  handling  of  -interp  for regular and hook scripts. Bugfixes in
              channel cleanup.

       4.3.1  Introduced -interp and -events to enable easy use of a slave interp  for  execution
              of received scripts, and of event scripts.

       4.3    Bugfixes,  and  introduces  -silent to allow the user to force the server/listening
              side to silently ignore connection attempts where the protocol negotiation failed.

       4.2    Bugfixes, and most important, switched to utf-8 as default encoding for  full  i18n
              without any problems.

       4.1    Rewrite  of  internal  code  to  remove  old pseudo-object model.  Addition of send
              -command asynchronous callback option.

       4.0    Per request by John LoVerso. Improved handling of error for async invoked commands.

       3.7    Moved into tcllib and placed in a proper namespace.

       3.6    A bug in the looking up of the remoteid for a executed command could  be  triggered
              when  the  connection was closed while several asynchronous sends were queued to be
              executed.

       3.5    Internal change to how reply messages from a send are handled.  Reply messages  are
              now decoded into the value to pass to return; a new return statement is then cons'd
              up to with this value.  Previously, the return code was passed in from  the  remote
              as  a  command to evaluate.  Since the wire protocol has not changed, this is still
              the case.  Instead, the reply handling code decodes the reply message.

       3.4    Added more source commentary, as well as documenting config variables in  this  man
              page.   Fixed  bug  were loss of connection would give error about a variable named
              pending rather than the message about the lost connection.   comm  ids  is  now  an
              alias  for comm interps (previously, it an alias for comm chans).  Since the method
              invocation change of 3.0, break and other exceptional  conditions  were  not  being
              returned correctly from comm send.  This has been fixed by removing the extra level
              of indirection into the internal procedure commSend.  Also added propagation of the
              errorCode  variable.   This  means that these commands return exactly as they would
              with send:

              comm send id break
              catch {comm send id break}
              comm send id expr 1 / 0

       Added a new hook for reply messages.  Reworked method  invocation  to  avoid  the  use  of
       comm:*  procedures; this also cut the invocation time down by 40%.  Documented comm config
       (as this manual page still listed the defunct comm init!)

       3.3    Some minor bugs were corrected and the documentation was cleaned  up.   Added  some
              examples for hooks.  The return semantics of the eval hook were changed.

       3.2    A  new  wire  protocol,  version  3,  was added.  This is backwards compatible with
              version 2 but adds an exchange of supported protocol  versions  to  allow  protocol
              negotiation  in  the future.  Several bugs with the hook implementation were fixed.
              A new section of the man page on blocking semantics was added.

       3.1    All the documented hooks were implemented.  commLostHook was  removed.   A  bug  in
              comm new was fixed.

       3.0    This  is  a  new version of comm with several major changes.  There is a new way of
              creating the methods available under the comm command.  The comm  init  method  has
              been  retired  and is replaced by comm configure which allows access to many of the
              well-defined internal variables.  This also generalizes the  options  available  to
              comm  new.  Finally, there is now a protocol version exchanged when a connection is
              established.  This will allow for future on-wire protocol changes.  Currently,  the
              protocol version is set to 2.

       2.3    comm  ids  was  renamed  to comm channels.  General support for comm hook was fully
              implemented, but only the lost hook exists,  and  it  was  changed  to  follow  the
              general  hook  API.   commLostHook was unsupported (replaced by comm hook lost) and
              commLost was removed.

       2.2    The died hook was renamed lost,  to  be  accessed  by  commLostHook  and  an  early
              implementation of comm lost hook.  As such, commDied is now commLost.

       2.1    Unsupported method comm remoteid was added.

       2.0    comm  has  been  rewritten  from  scratch  (but  is fully compatible with Comm 1.0,
              without the requirement to use obTcl).

AUTHOR

       John LoVerso, John@LoVerso.Southborough.MA.US

       http://www.opengroup.org/~loverso/tcl-tk/#comm

LICENSE

       Please   see   the    file    comm.LICENSE    that    accompanied    this    source,    or
       http://www.opengroup.org/www/dist_client/caubweb/COPYRIGHT.free.html.

       This  license  for comm, new as of version 3.2, allows it to be used for free, without any
       licensing fee or royalty.

BUGS

       •      If there is a failure initializing a channel created with  ::comm::comm  new,  then
              the channel should be destroyed.  Currently, it is left in an inconsistent state.

       •      There   should  be  a  way  to  force  a  channel  to  quiesce  when  changing  the
              configuration.

       The following items can be implemented with the existing hooks and are listed  here  as  a
       reminder to provide a sample hook in a future version.

       •      Allow  easier  use  of a slave interp for actual command execution (especially when
              operating in "not local" mode).

       •      Add host list (xhost-like) or "magic cookie" (xauth-like) authentication to initial
              handshake.

       The following are outstanding todo items.

       •      Add  an  interp  discovery  and  name->port  mapping.   This  is  likely to be in a
              separate, optional nameserver.  (See also the related work, below.)

       •      Fix the {id host} form so as not to be dependent upon  canonical  hostnames.   This
              requires fixes to Tcl to resolve hostnames!

       This man page is bigger than the source file.

ON USING OLD VERSIONS OF TCL

       Tcl7.5  under  Windows  contains  a  bug  that  causes the interpreter to hang when EOF is
       reached on non-blocking sockets.  This can be triggered with a command such as this:

              "comm send $other exit"

       Always make sure the channel is quiescent before closing/exiting or use  at  least  Tcl7.6
       under Windows.

       Tcl7.6 on the Mac contains several bugs.  It is recommended you use at least Tcl7.6p2.

       Tcl8.0  on  UNIX  contains  a  socket  bug  that can crash Tcl.  It is recommended you use
       Tcl8.0p1 (or Tcl7.6p2).

RELATED WORK

       Tcl-DP provides an RPC-based remote execution interface, but is a compiled Tcl  extension.
       See http://www.cs.cornell.edu/Info/Projects/zeno/Projects/Tcl-DP.html.

       Michael  Doyle  <miked@eolas.com>  has code that implements the Tcl-DP RPC interface using
       standard Tcl sockets, much like comm.

       Andreas Kupries <andreas_kupries@users.sourceforge.net> uses comm and has built  a  simple
       nameserver        as        part        of        his       Pool       library.        See
       http://www.purl.org/net/akupries/soft/pool/index.htm.

BUGS, IDEAS, FEEDBACK

       This document, and the package it describes,  will  undoubtedly  contain  bugs  and  other
       problems.    Please   report  such  in  the  category  comm  of  the  Tcllib  SF  Trackers
       [http://sourceforge.net/tracker/?group_id=12883].   Please  also  report  any  ideas   for
       enhancements you may have for either package and/or documentation.

SEE ALSO

       send(3tk)

KEYWORDS

       comm,  communication,  ipc,  message, remote communication, remote execution, rpc, secure,
       send, socket, ssl, tls

CATEGORY

       Programming tools

COPYRIGHT

       Copyright (c) 1995-1998 The Open Group. All Rights Reserved.
       Copyright (c) 2003-2004 ActiveState Corporation.
       Copyright (c) 2006-2009 Andreas Kupries <andreas_kupries@users.sourceforge.net>