Filesystem, RCS and CVS client and server classes | |
================================================= | |
*** See the security warning at the end of this file! *** | |
This directory contains various modules and classes that support | |
remote file system operations. | |
CVS stuff | |
--------- | |
rcvs Script to put in your bin directory | |
rcvs.py Remote CVS client command line interface | |
cvslib.py CVS admin files classes (used by rrcs) | |
cvslock.py CVS locking algorithms | |
RCS stuff | |
--------- | |
rrcs Script to put in your bin directory | |
rrcs.py Remote RCS client command line interface | |
rcsclient.py Return an RCSProxyClient instance | |
(has reasonable default server/port/directory) | |
RCSProxy.py RCS proxy and server classes (on top of rcslib.py) | |
rcslib.py Local-only RCS base class (affects stdout & | |
local work files) | |
FSProxy stuff | |
------------- | |
sumtree.py Old demo for FSProxy | |
cmptree.py First FSProxy client (used to sync from the Mac) | |
FSProxy.py Filesystem interface classes | |
Generic client/server stuff | |
--------------------------- | |
client.py Client class | |
server.py Server class | |
security.py Security mix-in class (not very secure I think) | |
Other generic stuff | |
------------------- | |
cmdfw.py CommandFrameWork class | |
(used by rcvs, should be used by rrcs as well) | |
Client/Server operation | |
----------------------- | |
The Client and Server classes implement a simple-minded RPC protocol, | |
using Python's pickle module to transfer arguments, return values and | |
exceptions with the most generality. The Server class is instantiated | |
with a port number on which it should listen for requests; the Client | |
class is instantiated with a host name and a port number where it | |
should connect to. Once a client is connected, a TCP connection is | |
maintained between client and server. | |
The Server class currently handles only one connection at a time; | |
however it could be rewritten to allow various modes of operations, | |
using multiple threads or processes or the select() system call as | |
desired to serve multiple clients simultaneously (when using select(), | |
still handling one request at a time). This would not require | |
rewriting of the Client class. It may also be possible to adapt the | |
code to use UDP instead of TCP, but then both classes will have to be | |
rewritten (and unless extensive acknowlegements and request serial | |
numbers are used, the server should handle duplicate requests, so its | |
semantics should be idempotent -- shrudder). | |
Even though the FSProxy and RCSProxy modules define client classes, | |
the client class is fully generic -- what methods it supports is | |
determined entirely by the server. The server class, however, must be | |
derived from. This is generally done as follows: | |
from server import Server | |
from client import Client | |
# Define a class that performs the operations locally | |
class MyClassLocal: | |
def __init__(self): ... | |
def _close(self): ... | |
# Derive a server class using multiple inheritance | |
class MyClassServer(MyClassLocal, Server): | |
def __init__(self, address): | |
# Must initialize MyClassLocal as well as Server | |
MyClassLocal.__init__(self) | |
Server.__init__(self, address) | |
def _close(self): | |
Server._close() | |
MyClassLocal._close() | |
# A dummy client class | |
class MyClassClient(Client): pass | |
Note that because MyClassLocal isn't used in the definition of | |
MyClassClient, it would actually be better to place it in a separate | |
module so the definition of MyClassLocal isn't executed when we only | |
instantiate a client. | |
The modules client and server should probably be renamed to Client and | |
Server in order to match the class names. | |
*** Security warning: this version requires that you have a file | |
$HOME/.python_keyfile at the server and client side containing two | |
comma- separated numbers. The security system at the moment makes no | |
guarantees of actuallng being secure -- however it requires that the | |
key file exists and contains the same numbers at both ends for this to | |
work. (You can specify an alternative keyfile in $PYTHON_KEYFILE). | |
Have a look at the Security class in security.py for details; | |
basically, if the key file contains (x, y), then the security server | |
class chooses a random number z (the challenge) in the range | |
10..100000 and the client must be able to produce pow(z, x, y) | |
(i.e. z**x mod y). |