Mercurial > cpython-lru_cache-weakref
annotate Demo/pdist/server.py @ 5817:48b94de85bf3 legacy-trunk
Extensive changes by AMK.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Thu, 17 Jul 1997 16:29:42 +0000 |
| parents | a0a4afa39d7a |
| children | 71a294bd7950 |
| rev | line source |
|---|---|
| 2652 | 1 """RPC Server module.""" |
| 2 | |
| 3 import sys | |
| 4 import socket | |
| 5 import pickle | |
| 6 from fnmatch import fnmatch | |
| 7 from repr import repr | |
| 8 | |
| 9 | |
| 10 # Default verbosity (0 = silent, 1 = print connections, 2 = print requests too) | |
| 11 VERBOSE = 1 | |
| 12 | |
| 13 | |
| 14 class Server: | |
| 15 | |
| 16 """RPC Server class. Derive a class to implement a particular service.""" | |
| 17 | |
| 18 def __init__(self, address, verbose = VERBOSE): | |
| 19 if type(address) == type(0): | |
| 20 address = ('', address) | |
| 21 self._address = address | |
| 22 self._verbose = verbose | |
| 23 self._socket = None | |
| 24 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| 25 self._socket.bind(address) | |
| 26 self._socket.listen(1) | |
| 27 self._listening = 1 | |
| 28 | |
| 29 def _setverbose(self, verbose): | |
| 30 self._verbose = verbose | |
| 31 | |
| 32 def __del__(self): | |
| 33 self._close() | |
| 34 | |
| 35 def _close(self): | |
| 36 self._listening = 0 | |
| 37 if self._socket: | |
| 38 self._socket.close() | |
| 39 self._socket = None | |
| 40 | |
| 41 def _serverloop(self): | |
| 42 while self._listening: | |
| 43 self._serve() | |
| 44 | |
| 45 def _serve(self): | |
| 46 if self._verbose: print "Wait for connection ..." | |
| 47 conn, address = self._socket.accept() | |
| 48 if self._verbose: print "Accepted connection from %s" % repr(address) | |
| 49 if not self._verify(conn, address): | |
| 50 print "*** Connection from %s refused" % repr(address) | |
| 51 conn.close() | |
| 52 return | |
| 53 rf = conn.makefile('r') | |
| 54 wf = conn.makefile('w') | |
| 55 ok = 1 | |
| 56 while ok: | |
| 57 wf.flush() | |
| 58 if self._verbose > 1: print "Wait for next request ..." | |
| 59 ok = self._dorequest(rf, wf) | |
| 60 | |
|
2768
a0a4afa39d7a
import string; add 129.6.64 to security
Guido van Rossum <guido@python.org>
parents:
2763
diff
changeset
|
61 _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*'] |
| 2652 | 62 |
| 63 def _verify(self, conn, address): | |
| 64 host, port = address | |
| 65 for pat in self._valid: | |
| 66 if fnmatch(host, pat): return 1 | |
| 67 return 0 | |
| 68 | |
| 69 def _dorequest(self, rf, wf): | |
| 70 rp = pickle.Unpickler(rf) | |
| 71 try: | |
| 72 request = rp.load() | |
| 73 except EOFError: | |
| 74 return 0 | |
| 75 if self._verbose > 1: print "Got request: %s" % repr(request) | |
| 76 try: | |
| 77 methodname, args, id = request | |
| 78 if '.' in methodname: | |
| 79 reply = (None, self._special(methodname, args), id) | |
| 80 elif methodname[0] == '_': | |
| 81 raise NameError, "illegal method name %s" % repr(methodname) | |
| 82 else: | |
| 83 method = getattr(self, methodname) | |
| 84 reply = (None, apply(method, args), id) | |
| 85 except: | |
| 86 reply = (sys.exc_type, sys.exc_value, id) | |
| 87 if id < 0 and reply[:2] == (None, None): | |
| 88 if self._verbose > 1: print "Suppress reply" | |
| 89 return 1 | |
| 90 if self._verbose > 1: print "Send reply: %s" % repr(reply) | |
| 91 wp = pickle.Pickler(wf) | |
| 92 wp.dump(reply) | |
| 93 return 1 | |
| 94 | |
| 95 def _special(self, methodname, args): | |
| 96 if methodname == '.methods': | |
| 97 if not hasattr(self, '_methods'): | |
| 98 self._methods = tuple(self._listmethods()) | |
| 99 return self._methods | |
| 100 raise NameError, "unrecognized special method name %s" % repr(methodname) | |
| 101 | |
| 102 def _listmethods(self, cl=None): | |
| 103 if not cl: cl = self.__class__ | |
| 104 names = cl.__dict__.keys() | |
| 105 names = filter(lambda x: x[0] != '_', names) | |
| 106 names.sort() | |
| 107 for base in cl.__bases__: | |
| 108 basenames = self._listmethods(base) | |
| 109 basenames = filter(lambda x, names=names: x not in names, basenames) | |
| 110 names[len(names):] = basenames | |
| 111 return names | |
| 2763 | 112 |
| 113 | |
| 114 from security import Security | |
| 115 | |
| 116 | |
| 117 class SecureServer(Server, Security): | |
| 118 | |
| 119 def __init__(self, *args): | |
| 120 apply(Server.__init__, (self,) + args) | |
| 121 Security.__init__(self) | |
| 122 | |
| 123 def _verify(self, conn, address): | |
|
2768
a0a4afa39d7a
import string; add 129.6.64 to security
Guido van Rossum <guido@python.org>
parents:
2763
diff
changeset
|
124 import string |
| 2763 | 125 challenge = self._generate_challenge() |
| 126 conn.send("%d\n" % challenge) | |
| 127 response = "" | |
| 128 while "\n" not in response and len(response) < 100: | |
| 129 data = conn.recv(100) | |
| 130 if not data: | |
| 131 break | |
| 132 response = response + data | |
| 133 try: | |
| 134 response = string.atol(string.strip(response)) | |
| 135 except string.atol_error: | |
| 136 if self._verbose > 0: | |
| 137 print "Invalid response syntax", `response` | |
| 138 return 0 | |
| 139 if not self._compare_challenge_response(challenge, response): | |
| 140 if self._verbose > 0: | |
| 141 print "Invalid response value", `response` | |
| 142 return 0 | |
| 143 if self._verbose > 1: | |
| 144 print "Response matches challenge. Go ahead!" | |
| 145 return 1 |
