SocketServer.py (8977B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\SocketServer.py 2 __version__ = '0.4' 3 import socket 4 import sys 5 import os 6 try: 7 import threading 8 except ImportError: 9 import dummy_threading as threading 10 11 __all__ = ['TCPServer', 12 'UDPServer', 13 'ForkingUDPServer', 14 'ForkingTCPServer', 15 'ThreadingUDPServer', 16 'ThreadingTCPServer', 17 'BaseRequestHandler', 18 'StreamRequestHandler', 19 'DatagramRequestHandler', 20 'ThreadingMixIn', 21 'ForkingMixIn'] 22 if hasattr(socket, 'AF_UNIX'): 23 __all__.extend(['UnixStreamServer', 24 'UnixDatagramServer', 25 'ThreadingUnixStreamServer', 26 'ThreadingUnixDatagramServer']) 27 28 class BaseServer: 29 timeout = None 30 31 def __init__(self, server_address, RequestHandlerClass): 32 self.server_address = server_address 33 self.RequestHandlerClass = RequestHandlerClass 34 self.__is_shut_down = threading.Event() 35 self.__shutdown_request = False 36 37 def server_activate(self): 38 pass 39 40 def serve_forever(self, poll_interval = 0.5): 41 self.__is_shut_down.clear() 42 try: 43 while not self.__shutdown_request: 44 if True: 45 self._handle_request_noblock() 46 47 finally: 48 self.__shutdown_request = False 49 self.__is_shut_down.set() 50 51 def shutdown(self): 52 self.__shutdown_request = True 53 self.__is_shut_down.wait() 54 55 def handle_request(self): 56 timeout = self.socket.gettimeout() 57 if timeout is None: 58 timeout = self.timeout 59 elif self.timeout is not None: 60 timeout = min(timeout, self.timeout) 61 self._handle_request_noblock() 62 63 def _handle_request_noblock(self): 64 try: 65 request, client_address = self.get_request() 66 except socket.error: 67 return 68 69 if self.verify_request(request, client_address): 70 try: 71 self.process_request(request, client_address) 72 except: 73 self.handle_error(request, client_address) 74 self.shutdown_request(request) 75 76 def handle_timeout(self): 77 pass 78 79 def verify_request(self, request, client_address): 80 return True 81 82 def process_request(self, request, client_address): 83 self.finish_request(request, client_address) 84 self.shutdown_request(request) 85 86 def server_close(self): 87 pass 88 89 def finish_request(self, request, client_address): 90 self.RequestHandlerClass(request, client_address, self) 91 92 def shutdown_request(self, request): 93 self.close_request(request) 94 95 def close_request(self, request): 96 pass 97 98 def handle_error(self, request, client_address): 99 print '-' * 40 100 print 'Exception happened during processing of request from', 101 print client_address 102 import traceback 103 traceback.print_exc() 104 print '-' * 40 105 106 107 class TCPServer(BaseServer): 108 address_family = socket.AF_INET 109 socket_type = socket.SOCK_STREAM 110 request_queue_size = 5 111 allow_reuse_address = False 112 113 def __init__(self, server_address, RequestHandlerClass, bind_and_activate = True): 114 BaseServer.__init__(self, server_address, RequestHandlerClass) 115 self.socket = socket.socket(self.address_family, self.socket_type) 116 if bind_and_activate: 117 self.server_bind() 118 self.server_activate() 119 120 def server_bind(self): 121 if self.allow_reuse_address: 122 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 123 self.socket.bind(self.server_address) 124 self.server_address = self.socket.getsockname() 125 126 def server_activate(self): 127 self.socket.listen(self.request_queue_size) 128 129 def server_close(self): 130 self.socket.close() 131 132 def fileno(self): 133 return self.socket.fileno() 134 135 def get_request(self): 136 return self.socket.accept() 137 138 def shutdown_request(self, request): 139 try: 140 request.shutdown(socket.SHUT_WR) 141 except socket.error: 142 pass 143 144 self.close_request(request) 145 146 def close_request(self, request): 147 request.shutdown(socket.SHUT_WR) 148 request.close() 149 150 151 class UDPServer(TCPServer): 152 allow_reuse_address = False 153 socket_type = socket.SOCK_DGRAM 154 max_packet_size = 8192 155 156 def get_request(self): 157 data, client_addr = self.socket.recvfrom(self.max_packet_size) 158 return ((data, self.socket), client_addr) 159 160 def server_activate(self): 161 pass 162 163 def shutdown_request(self, request): 164 self.close_request(request) 165 166 def close_request(self, request): 167 pass 168 169 170 class ForkingMixIn: 171 timeout = 300 172 active_children = None 173 max_children = 40 174 175 def collect_children(self): 176 if self.active_children is None: 177 return 178 while len(self.active_children) >= self.max_children: 179 try: 180 pid, status = os.waitpid(0, 0) 181 except os.error: 182 pid = None 183 184 if pid not in self.active_children: 185 continue 186 self.active_children.remove(pid) 187 188 for child in self.active_children: 189 try: 190 pid, status = os.waitpid(child, os.WNOHANG) 191 except os.error: 192 pid = None 193 194 if not pid: 195 continue 196 try: 197 self.active_children.remove(pid) 198 except ValueError as e: 199 raise ValueError('%s. x=%d and list=%r' % (e.message, pid, self.active_children)) 200 201 def handle_timeout(self): 202 self.collect_children() 203 204 def process_request(self, request, client_address): 205 self.collect_children() 206 pid = os.fork() 207 if pid: 208 if self.active_children is None: 209 self.active_children = [] 210 self.active_children.append(pid) 211 self.close_request(request) 212 return 213 try: 214 self.finish_request(request, client_address) 215 self.shutdown_request(request) 216 os._exit(0) 217 except: 218 try: 219 self.handle_error(request, client_address) 220 self.shutdown_request(request) 221 finally: 222 os._exit(1) 223 224 225 class ThreadingMixIn: 226 daemon_threads = False 227 228 def process_request_thread(self, request, client_address): 229 try: 230 self.finish_request(request, client_address) 231 self.shutdown_request(request) 232 except: 233 self.handle_error(request, client_address) 234 self.shutdown_request(request) 235 236 def process_request(self, request, client_address): 237 t = threading.Thread(target=self.process_request_thread, args=(request, client_address)) 238 if self.daemon_threads: 239 t.setDaemon(1) 240 t.start() 241 242 243 class ForkingUDPServer(ForkingMixIn, UDPServer): 244 pass 245 246 247 class ForkingTCPServer(ForkingMixIn, TCPServer): 248 pass 249 250 251 class ThreadingUDPServer(ThreadingMixIn, UDPServer): 252 pass 253 254 255 class ThreadingTCPServer(ThreadingMixIn, TCPServer): 256 pass 257 258 259 if hasattr(socket, 'AF_UNIX'): 260 261 class UnixStreamServer(TCPServer): 262 address_family = socket.AF_UNIX 263 264 265 class UnixDatagramServer(UDPServer): 266 address_family = socket.AF_UNIX 267 268 269 class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): 270 pass 271 272 273 class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): 274 pass 275 276 277 class BaseRequestHandler: 278 279 def __init__(self, request, client_address, server): 280 self.request = request 281 self.client_address = client_address 282 self.server = server 283 self.setup() 284 try: 285 self.handle() 286 finally: 287 self.finish() 288 289 def setup(self): 290 pass 291 292 def handle(self): 293 pass 294 295 def finish(self): 296 pass 297 298 299 class StreamRequestHandler(BaseRequestHandler): 300 rbufsize = -1 301 wbufsize = 0 302 timeout = None 303 disable_nagle_algorithm = False 304 305 def setup(self): 306 self.connection = self.request 307 if self.timeout is not None: 308 self.connection.settimeout(self.timeout) 309 if self.disable_nagle_algorithm: 310 self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) 311 self.rfile = self.connection.makefile('rb', self.rbufsize) 312 self.wfile = self.connection.makefile('wb', self.wbufsize) 313 314 def finish(self): 315 if not self.wfile.closed: 316 self.wfile.flush() 317 self.wfile.close() 318 self.rfile.close() 319 320 321 class DatagramRequestHandler(BaseRequestHandler): 322 323 def setup(self): 324 try: 325 from cStringIO import StringIO 326 except ImportError: 327 from StringIO import StringIO 328 329 self.packet, self.socket = self.request 330 self.rfile = StringIO(self.packet) 331 self.wfile = StringIO() 332 333 def finish(self): 334 self.socket.sendto(self.wfile.getvalue(), self.client_address)