mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
	
	
		
			112 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			112 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | """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) | ||
|  | 	 | ||
|  | 	_valid = ['192.16.201.*', '192.16.197.*'] | ||
|  | 	 | ||
|  | 	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 |