+++ /dev/null
-"""RPC Client module."""\r
-\r
-import sys\r
-import socket\r
-import pickle\r
-import __builtin__\r
-import os\r
-\r
-\r
-# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)\r
-VERBOSE = 1\r
-\r
-\r
-class Client:\r
-\r
- """RPC Client class. No need to derive a class -- it's fully generic."""\r
-\r
- def __init__(self, address, verbose = VERBOSE):\r
- self._pre_init(address, verbose)\r
- self._post_init()\r
-\r
- def _pre_init(self, address, verbose = VERBOSE):\r
- if type(address) == type(0):\r
- address = ('', address)\r
- self._address = address\r
- self._verbose = verbose\r
- if self._verbose: print "Connecting to %s ..." % repr(address)\r
- self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r
- self._socket.connect(address)\r
- if self._verbose: print "Connected."\r
- self._lastid = 0 # Last id for which a reply has been received\r
- self._nextid = 1 # Id of next request\r
- self._replies = {} # Unprocessed replies\r
- self._rf = self._socket.makefile('r')\r
- self._wf = self._socket.makefile('w')\r
-\r
- def _post_init(self):\r
- self._methods = self._call('.methods')\r
-\r
- def __del__(self):\r
- self._close()\r
-\r
- def _close(self):\r
- if self._rf: self._rf.close()\r
- self._rf = None\r
- if self._wf: self._wf.close()\r
- self._wf = None\r
- if self._socket: self._socket.close()\r
- self._socket = None\r
-\r
- def __getattr__(self, name):\r
- if name in self._methods:\r
- method = _stub(self, name)\r
- setattr(self, name, method) # XXX circular reference\r
- return method\r
- raise AttributeError, name\r
-\r
- def _setverbose(self, verbose):\r
- self._verbose = verbose\r
-\r
- def _call(self, name, *args):\r
- return self._vcall(name, args)\r
-\r
- def _vcall(self, name, args):\r
- return self._recv(self._vsend(name, args))\r
-\r
- def _send(self, name, *args):\r
- return self._vsend(name, args)\r
-\r
- def _send_noreply(self, name, *args):\r
- return self._vsend(name, args, 0)\r
-\r
- def _vsend_noreply(self, name, args):\r
- return self._vsend(name, args, 0)\r
-\r
- def _vsend(self, name, args, wantreply = 1):\r
- id = self._nextid\r
- self._nextid = id+1\r
- if not wantreply: id = -id\r
- request = (name, args, id)\r
- if self._verbose > 1: print "sending request: %s" % repr(request)\r
- wp = pickle.Pickler(self._wf)\r
- wp.dump(request)\r
- return id\r
-\r
- def _recv(self, id):\r
- exception, value, rid = self._vrecv(id)\r
- if rid != id:\r
- raise RuntimeError, "request/reply id mismatch: %d/%d" % (id, rid)\r
- if exception is None:\r
- return value\r
- x = exception\r
- if hasattr(__builtin__, exception):\r
- x = getattr(__builtin__, exception)\r
- elif exception in ('posix.error', 'mac.error'):\r
- x = os.error\r
- if x == exception:\r
- exception = x\r
- raise exception, value\r
-\r
- def _vrecv(self, id):\r
- self._flush()\r
- if self._replies.has_key(id):\r
- if self._verbose > 1: print "retrieving previous reply, id = %d" % id\r
- reply = self._replies[id]\r
- del self._replies[id]\r
- return reply\r
- aid = abs(id)\r
- while 1:\r
- if self._verbose > 1: print "waiting for reply, id = %d" % id\r
- rp = pickle.Unpickler(self._rf)\r
- reply = rp.load()\r
- del rp\r
- if self._verbose > 1: print "got reply: %s" % repr(reply)\r
- rid = reply[2]\r
- arid = abs(rid)\r
- if arid == aid:\r
- if self._verbose > 1: print "got it"\r
- return reply\r
- self._replies[rid] = reply\r
- if arid > aid:\r
- if self._verbose > 1: print "got higher id, assume all ok"\r
- return (None, None, id)\r
-\r
- def _flush(self):\r
- self._wf.flush()\r
-\r
-\r
-from security import Security\r
-\r
-\r
-class SecureClient(Client, Security):\r
-\r
- def __init__(self, *args):\r
- import string\r
- apply(self._pre_init, args)\r
- Security.__init__(self)\r
- self._wf.flush()\r
- line = self._rf.readline()\r
- challenge = string.atoi(string.strip(line))\r
- response = self._encode_challenge(challenge)\r
- line = repr(long(response))\r
- if line[-1] in 'Ll': line = line[:-1]\r
- self._wf.write(line + '\n')\r
- self._wf.flush()\r
- self._post_init()\r
-\r
-class _stub:\r
-\r
- """Helper class for Client -- each instance serves as a method of the client."""\r
-\r
- def __init__(self, client, name):\r
- self._client = client\r
- self._name = name\r
-\r
- def __call__(self, *args):\r
- return self._client._vcall(self._name, args)\r