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