comm

comm , a Tcllib module originally by John Robert LoVerso, is a remote communication facility.

Attributes

website
http://core.tcl.tk/tcllib/doc/trunk/embedded/www/tcllib/files/modules/comm/comm.html
website (old)
http://www.schooner.com/~loverso/tcl-tk/#comm

See Also

comm via ssh

Appearances

persistent itcl, by CmcC
persistence for [incr tcl]

Documentation

official reference ( alternate )

Description

comm is a communication package. It essentially reimplements send, known from Tk in terms of sockets.

Examples

tkinspect has this example (originally by John LoVerso):

# Provide non-send based support using tklib's comm package.
if {![catch {package require comm}]} {
    # defer the cleanup for 2 seconds to allow other events to process
    comm::comm hook lost {after 2000 set x 1; vwait x}

    # replace send with version that does both send and comm
    if {[string match send [info commands send]]} {
        rename send tk_send
    } else {
        proc tk_send args {}
    }
    proc send {app args} {
        if {[string match {[0-9]*} [lindex $app 0]]} {
            eval comm::comm send [list $app] $args
        } else {
            eval tk_send [list $app] $args
        }
    }
}

The above enables the use of both comm and send based upon the application id.

PT 2003-6-23: The send page has a somewhat more complete version of the above script.

Discussion

Can one use comm as an exact replacement for send? Apparently not - using send, an interpreter registers itself and other Tk applications can query this registry to find out what interpreters are available. If you are just using comm, this is not the case.

EE: Well then, how does an application using comm find out who it can talk to?

AK: Pool_Net is a little name server

Application have to explicitly register. In that way comm is not as automatic as tk's send.

LV: I wonder if someone would be interested in writing a namesever that gets invoked from some sort of comm init function - I don't know how it would work, but surely it would be worth brainstorming.

AK: Tk's send is simpler, since it has the X server automatically available as a hub for communication. Ok, back to a comm nameserver. The implementation in pool (s.a.) uses a fixed port number and also implictly assumes that nameserver and applications are on the same host. IOW, local machine. Do we need more flexibility ? If yes, some sort of global configuration file is required so that clients are able to find the server whereever it is and on whatever port it is running.


LV: In my mind, the ideal would be to do something similar to send - have comm transparently create an automatic hub for communication. One change I would make is to number the first interp registered as command #1, instead of just command. That might make distinguishing which command is available a bit more regular...

AK: Ok, the above implies a fixed port. As for naming the existing code asks for an explicit name and the server will reject it if that name is already registered. ... Automatic generation of a name is a tad more difficult. info nameofexecutable is not right, info script will give the wrong information too, ... Ok, our best bet is $argv0, right? So that problem is essentially solved too. I believe we are now ready to submit a tcllib FR. (I just added 'comm' as category to the FR tracker of tcllib. It will auto-assign to me).


CMcC: Has anyone thought of, or about, or done any work on putting a safetcl safe interpreter (with policies) behind comm?

AK: Thought about it ? Yes, definitely. Done something about it ? No, not yet. I will gladly review patches in this area.

CMcC: I've dabbled, and it's becoming necessary for me to do something about it for the persistent itcl stuff. As for the SSL wrapping below, it should be possible to make safe interpretation happen in a callback.

AK: Another thing to think about in this context would be the ability to use a different socket command (for example [tls::socket], see TLS). In the case of the example this would add SSL encryption to connections opened by comm.

CMcC: It won't be necessary to modify the socket command, as the comm package permits a callback on connect, in which one can wrap SSL around an open socket with tls::import.


LV: Has anyone experimented with sending and receiving data to a running Tcl interpreter from a non-Tcl application, making use of comm? Just curious - I've seen C/C++ apps that make use of the C API provided by tclXtSend .


UK: I have build something comm-like using UDP multicast, channels are differentiated by destination ports. Information is transfered mostly by sending scripts like {array set <arrname <list>} or {set <varname> <value>}. This works across Tcl, C and bash ( sending only by echo <script> >/dev/udp/<mcast-ip>/<d-port>. This allows for apps to be restarted or moved from one machine to another and very easy logging and monitoring. but it is unsave at any speed. I will make a wiki page in a couple of days. Look for GIN.


Using comm to remote hosts

When the comm package initialises it creates a self channel by opening a listening socket on the local network interface. That is the 127.0.0.1 interface. If you need to provide for remote access you should use comm::comm config and set -local to false.

On the client side, a remote comm channel is specified as a list where the second element is the hostname. So try using

comm::comm send [list $portnum $host] info hostname

PT: If you would like to see a remote service ala winfo interps you can pre-register the channel using comm::comm connect $connection. Then comm::comm interps will show this item.

hkoba: For this purpose, you may feel better with comm via ssh, like this:

set num [sshcomm::client::create $host]
comm::comm send $num {glob *}

Alex Caldwell

I used Tk appname to make this little server that registers the ID of each interpreter registered under the comm package and then broadcasts the name to the other interpreters using Tk appname, so the send command under comm will work the same as under Xwindow using the usual application name as per winfo interps instead of the ID no. I'm sure there are more efficient ways to do this, but it worked on Windows before I discovered the Winsend package. The Winsend package must be doing something like this internally. The main advantage of using the app name instead of an ID no. is you don't have to re-write code that uses the send command on unix when you want to port it to Windows or Mac.

# each interpreter  needs to have this proc added somewhere 
proc returnappname {} {
    return [tk appname]
}

package require comm
namespace import ::comm::*

label .label1 -text "Programs Found"
pack .label1
wm title . [comm self]
for {set x [expr {[comm self] - 10}]} {$x < [comm self]} {incr x} {
    frame .${x}frame
    entry .${x}frame.entry -textvariable value($x)
    pack .${x}frame -side top
    pack .${x}frame.entry -side left
    update idletasks

    catch {comm send $x returnappname} f
    set value($x) $f
    if ![regexp to $value($x)] {
        pack .${x}frame -side top
        pack .${x}frame.entry -side left
    }
}
update idletasks
button .commbutton -text commsetup -command {
    for {set x [expr {[comm self] - 10}]} {$x < [comm self]} {incr x} {
        update idletasks
        if {[lindex $value($x) 1] ne {to}} {
            puts [lindex $value($x) 0]
            puts [lindex $value($x) 1]
            for {set y [expr {[comm self] - 10}]} {$y < [comm self]} {incr y} {
                if {[lindex $value($y) 1] ne {to}} {
                    comm send [lindex $value($y) 1] "set [lindex $value($x) 0] [lindex $value($x) 1]"
                    puts "sending [lindex $value($y) 1] set [lindex $value($x) 0] [lindex $value($x) 1]"
                }
            }
        }
    }
}
pack .commbutton
update idletasks
after 10000
.commbutton invoke
after 10000
exit

Hermann Boeken:

The comm manual pages indicate that the 'connected' and 'incoming' hooks could be used for arbitrary authentication over the socket. Can someone provide more details on how to accomplish this?


skipper600:

This is crap: the listening interpreter stalls once it receives a tcp connection (not issued by another comm connection). Simply telnet such a comm::comm server, and it is locked until you either violate the protocol or terminate the connection. APN Nasty indeed. I believe this is fixed in latest CVS version (4.6.2).


AKgnome 2010-09-17 12:55:44:

DoS attack fixed for comm version 4.6.2.