| 
									
										
										
										
											1995-04-10 11:40:52 +00:00
										 |  |  | """RPC Server module.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import socket | 
					
						
							|  |  |  | import pickle | 
					
						
							|  |  |  | from fnmatch import fnmatch | 
					
						
							|  |  |  | from repr import repr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Default verbosity (0 = silent, 1 = print connections, 2 = print requests too) | 
					
						
							|  |  |  | VERBOSE = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Server: | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	"""RPC Server class.  Derive a class to implement a particular service.""" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self, address, verbose = VERBOSE): | 
					
						
							|  |  |  | 		if type(address) == type(0): | 
					
						
							|  |  |  | 			address = ('', address) | 
					
						
							|  |  |  | 		self._address = address | 
					
						
							|  |  |  | 		self._verbose = verbose | 
					
						
							|  |  |  | 		self._socket = None | 
					
						
							|  |  |  | 		self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
					
						
							|  |  |  | 		self._socket.bind(address) | 
					
						
							|  |  |  | 		self._socket.listen(1) | 
					
						
							|  |  |  | 		self._listening = 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _setverbose(self, verbose): | 
					
						
							|  |  |  | 		self._verbose = verbose | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __del__(self): | 
					
						
							|  |  |  | 		self._close() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _close(self): | 
					
						
							|  |  |  | 		self._listening = 0 | 
					
						
							|  |  |  | 		if self._socket: | 
					
						
							|  |  |  | 			self._socket.close() | 
					
						
							|  |  |  | 		self._socket = None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _serverloop(self): | 
					
						
							|  |  |  | 		while self._listening: | 
					
						
							|  |  |  | 			self._serve() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _serve(self): | 
					
						
							|  |  |  | 		if self._verbose: print "Wait for connection ..." | 
					
						
							|  |  |  | 		conn, address = self._socket.accept() | 
					
						
							|  |  |  | 		if self._verbose: print "Accepted connection from %s" % repr(address) | 
					
						
							|  |  |  | 		if not self._verify(conn, address): | 
					
						
							|  |  |  | 			print "*** Connection from %s refused" % repr(address) | 
					
						
							|  |  |  | 			conn.close() | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		rf = conn.makefile('r') | 
					
						
							|  |  |  | 		wf = conn.makefile('w') | 
					
						
							|  |  |  | 		ok = 1 | 
					
						
							|  |  |  | 		while ok: | 
					
						
							|  |  |  | 			wf.flush() | 
					
						
							|  |  |  | 			if self._verbose > 1: print "Wait for next request ..." | 
					
						
							|  |  |  | 			ok = self._dorequest(rf, wf) | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:12 +00:00
										 |  |  | 	_valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*'] | 
					
						
							| 
									
										
										
										
											1995-04-10 11:40:52 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def _verify(self, conn, address): | 
					
						
							|  |  |  | 		host, port = address | 
					
						
							|  |  |  | 		for pat in self._valid: | 
					
						
							|  |  |  | 			if fnmatch(host, pat): return 1 | 
					
						
							|  |  |  | 		return 0 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _dorequest(self, rf, wf): | 
					
						
							|  |  |  | 		rp = pickle.Unpickler(rf) | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			request = rp.load() | 
					
						
							|  |  |  | 		except EOFError: | 
					
						
							|  |  |  | 			return 0 | 
					
						
							|  |  |  | 		if self._verbose > 1: print "Got request: %s" % repr(request) | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			methodname, args, id = request | 
					
						
							|  |  |  | 			if '.' in methodname: | 
					
						
							|  |  |  | 				reply = (None, self._special(methodname, args), id) | 
					
						
							|  |  |  | 			elif methodname[0] == '_': | 
					
						
							|  |  |  | 				raise NameError, "illegal method name %s" % repr(methodname) | 
					
						
							|  |  |  | 			else: | 
					
						
							|  |  |  | 				method = getattr(self, methodname) | 
					
						
							|  |  |  | 				reply = (None, apply(method, args), id) | 
					
						
							|  |  |  | 		except: | 
					
						
							|  |  |  | 			reply = (sys.exc_type, sys.exc_value, id) | 
					
						
							|  |  |  | 		if id < 0 and reply[:2] == (None, None): | 
					
						
							|  |  |  | 			if self._verbose > 1: print "Suppress reply" | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 		if self._verbose > 1: print "Send reply: %s" % repr(reply) | 
					
						
							|  |  |  | 		wp = pickle.Pickler(wf) | 
					
						
							|  |  |  | 		wp.dump(reply) | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _special(self, methodname, args): | 
					
						
							|  |  |  | 		if methodname == '.methods': | 
					
						
							|  |  |  | 			if not hasattr(self, '_methods'): | 
					
						
							|  |  |  | 				self._methods = tuple(self._listmethods()) | 
					
						
							|  |  |  | 			return self._methods | 
					
						
							|  |  |  | 		raise NameError, "unrecognized special method name %s" % repr(methodname) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def _listmethods(self, cl=None): | 
					
						
							|  |  |  | 		if not cl: cl = self.__class__ | 
					
						
							|  |  |  | 		names = cl.__dict__.keys() | 
					
						
							|  |  |  | 		names = filter(lambda x: x[0] != '_', names) | 
					
						
							|  |  |  | 		names.sort() | 
					
						
							|  |  |  | 		for base in cl.__bases__: | 
					
						
							|  |  |  | 			basenames = self._listmethods(base) | 
					
						
							|  |  |  | 			basenames = filter(lambda x, names=names: x not in names, basenames) | 
					
						
							|  |  |  | 			names[len(names):] = basenames | 
					
						
							|  |  |  | 		return names |