dp_RPC, dp_RDO, dp_MakeRPCClient, dp_MakeRPCServer,
dp_CloseRPC, dp_CancelRPC, dp_Host, dp_SetCheckCmd
- Tcl-DP remote procedure call support


The commands described here are part of the Tcl-DP (Tcl Distributed Programming) extension to Tcl/Tk. These Tcl/Tk commands provide support for Tcl/Tk remote procedure calls (RPC's).
dp_MakeRPCServer ?port? ?loginProc? ?cmdCheckProc? ?retFile?
Dp_MakeRPCServer arranges for the current Tcl/Tk interpreter to accept RPC client connections. Clients will connect to the server at the given port (see dp_MakeRPCClient below). The port should be an unused port or 0 if you want a port number automatically chosen for you. If port is not supplied, a default value of 0 is used. The port number used is returned unless retFile in non-zero, in which case both the file identifier and the port number for the listening socket is returned.

LoginProc can be used to refuse connection attempts by unauthorized hosts. When a host attempts to connect, loginProc is called with the file handle of the new connection and the internet address of the connecting party as an argument. If loginProc calls the Tcl error function during evaluation, the connection is refused and the error message is returned to the client. The default loginProc is "dp_CheckHost."

Dp_CheckHost checks an internal access control list to verify that the host is allowed to connect. Host may be added to (or deleted from) this access control using the dp_Host command described below.

When a host attempts to connect, loginProc is called with the internet address of the connecting party as an argument. If loginProc calls the Tcl error function during evaluation, the connection is refused and the error message is returned to the client.

CmdCheckProc, if supplied, can be used to intercept the execution of unauthorized commands over an RPC channel. When an RPC request is received, the requested command will be passed as a string to cmdCheckProc before evaluation. If cmdCheckProc is the keyword "none," no command checking is performed. CmdCheckProc defaults to "none." See dp_SetCheckCmd for more details on security.

dp_Host [+/-]host
This command is used to modify the internal access control list used in Tcl-DP to determine if hosts are authorized to connect to this server. For backwards compatibilty, all hosts are initially allowed to connect. Dp_Host is functionally similar to xhost(1). New additions to the access control list override previous directives. Dp_Host accepts the following options:
dp_MakeRPCClient host port ?cmdCheckProc?
dp_MakeRPCClient establishes an RPC connection to the RPC server at the port running on the machine with the host network address. Port can be specified either by number or by service name (see services(5) for further information on specifying services by name). A sockId representing the RPC connection is returned. This sockId is refered to below as a peer, since RPC connections are peer to peer. The transmission protocol used for Tcl-DP RPC services is TCP/IP.

CmdCheckProc, if supplied, can be used to intercept the execution of unauthorized commands over the connection. See dp_MakeRPCServer and dp_SetCheckCmd for more details.

dp_SetCheckCmd peer cmdCheckProc
Dp_SetCheckCmd arranges for cmdCheckProc to be called when an RPC/RDO request comes from the specified peer. CmdCheckProc is passed the inbound RPC/RDO request as its args (cmdCheckProc should accept multiple arguments). If cmdCheckProc returns normally, the requested command is evaluated normally (i.e., no further checking). If cmdCheckProc returns with the "continue" code (see the Tcl return command for how to return with a special code) then the requested command will be executed, but any commands it issues will also be checked. If cmdCheckProc returns with a "return" code, then the result of cmdCheckProc is returned as the result of the requested command. If cmdCheckProc returns with an "error" code, the requested command will not be executed, and the error message from the check command will be used as the error message from the requested command. Any other return codes of cmdCheckProc ("break", etc.) will prevent the requested command from being executed, and an error message will be sent to the caller.

For example, the following procedure allows the commands "Safe" and "puts" to be executed without checking, "set" to be called with one argument (i.e., read, but not write, variables), and "eval" to be used with any resulting evaluations checked.

proc MyCheck {cmd args} {
    set argc [llength $args]
    case $cmd in {
        Safe    {return}
        puts    {return}
        eval    {return -code continue}
        set     {
                    if {$argc == 2} {
                        error "Permission to set variables denied"
                    } else {
                        return
                    }
                }
    }
    return -code break
}

dp_CloseRPC peer
This command arranges a clean closing of an RPC connection, on both sides of the connection.
dp_CancelRPC ?peer? ?peer? ...
This command cancels current RPC invocations that are presently waiting for a return value. If no peers are specified, then all current but waiting RPC invocations are canceled. These cancelled RPC's will return an error.
dp_RPC peer ?-events events? ?-timeout millisecs ??-timeoutReturn callback??? command ?args ...?
This command arranges for the Tcl/Tk command and its args to be evaluated in the remote Tcl/Tk interpreter, using the RPC connection specified by peer. Before the remote evaluation of command and args, the global variable dp_rpcFile in the remote Tcl/Tk interpreter is bound to the peer whose request is being evaluated. (Thus, in your command, you can access the dp_rpcFile variable to figure out the RPC peer that originated the command.)

The -events flag to the dp_RPC command lets you specify which events should be handled while waiting for the return value of a RPC. The -events parameter should be a list of the tokens X, rpc, file, timer, idle, all, or none, where each token represents an event type. Presently, a rpc token is the same as a file token. The none token is the default. See Tk_DoOneEvent(3) for more information on these event types.

The -timeout flag to the dp_RPC command lets you specify an integer millisecond timeout value for the RPC, which by default will return an error value if the timeout occurs. Supplying a -timeout value of zero or less than zero means that no timeout will be checked. If you want to use timeouts, you must also specify -events to be anything but none.

The -timeoutReturn callback, if specified, is evaluated when a timeout occurs. The callback is evaluated with the peer identifier appended. If a timeout occurs and a -timeoutReturn callback was specified, then the return value of the callback is used as the return value of the timed-out dp_RPC. Otherwise the timed-out RPC returns an error.

dp_RDO peer ?-callback resultCallback? ?-onerror errorCallback? command ?args ...?
This command arranges for command and its args to be remotely evaluated in the Tcl/Tk interpreter whose connection is specified by peer argument. Unlike the dp_RPC command, the dp_RDO command does not wait for a return value to be returned by the remote Tcl/Tk interpreter, but returns immediately. Before the remote evaluation, the global variable dp_rpcFile in the remote Tcl/Tk interpreter is set as described above for the dp_RPC command.

You can use the resultCallback parameter of dp_RDO to asynchronously retrieve the value of the remote evaluation. If specified, the callback command appended with the return value of the remote command evaluation is evaluated in the local Tcl/Tk interpreter.

If you specify an errorCallback and an error occurs during the remote evaluation, errorCallback will be evaluated with the error message as a parameter. The default value for errorCallback is tkerror. If you wish to ignore errors generated during RDO evaluation, specify the keyword "none" as errorCallback.

The following example creates an RPC server to return unique integer identifiers. On the host zonker (the server):

        dp_MakeRPCServer 4545

        dp_Host -
        dp_Host +128.32.149.*
        set myId 0
        proc GetId {} {global myId; incr myId; return $myId}
On host linus (the client, address 128.32.149.59):
        set server [dp_MakeRPCClient zonker 4545]
        dp_RPC $server GetId
On a host not on the 128.32.149 subnet:
        set server [dp_MakeRPCClient zonker 4545]
        error -> Connection refused: Host not authorized

Brian Smith (bsmith@cs.berkeley.edu)
Steve Yen (syen@cs.berkeley.edu)
Stephen Tu (tus@roger-rabbit.cs.berkeley.edu)