OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome. | 6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome. |
7 | 7 |
8 It supports several test URLs, as specified by the handlers in TestPageHandler. | 8 It supports several test URLs, as specified by the handlers in TestPageHandler. |
9 By default, it listens on an ephemeral port and sends the port number back to | 9 By default, it listens on an ephemeral port and sends the port number back to |
10 the originating process over a pipe. The originating process can specify an | 10 the originating process over a pipe. The originating process can specify an |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 | 106 |
107 | 107 |
108 class ClientRestrictingServerMixIn: | 108 class ClientRestrictingServerMixIn: |
109 """Implements verify_request to limit connections to our configured IP | 109 """Implements verify_request to limit connections to our configured IP |
110 address.""" | 110 address.""" |
111 | 111 |
112 def verify_request(self, _request, client_address): | 112 def verify_request(self, _request, client_address): |
113 return client_address[0] == self.server_address[0] | 113 return client_address[0] == self.server_address[0] |
114 | 114 |
115 | 115 |
| 116 class BrokenPipeHandlerMixIn: |
| 117 """Allows the server to deal with "broken pipe" errors (which happen if the |
| 118 browser quits with outstanding requests, like for the favicon). This mix-in |
| 119 requires the class to derive from SocketServer.BaseServer and not override its |
| 120 handle_error() method. """ |
| 121 |
| 122 def handle_error(self, request, client_address): |
| 123 value = sys.exc_info()[1] |
| 124 if isinstance(value, socket.error): |
| 125 err = value.args[0] |
| 126 if sys.platform in ('win32', 'cygwin'): |
| 127 # "An established connection was aborted by the software in your host." |
| 128 pipe_err = 10053 |
| 129 else: |
| 130 pipe_err = errno.EPIPE |
| 131 if err == pipe_err: |
| 132 print "testserver.py: Broken pipe" |
| 133 return |
| 134 SocketServer.BaseServer.handle_error(self, request, client_address) |
| 135 |
| 136 |
116 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | 137 class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
117 """This is a specialization of BaseHTTPServer to allow it | 138 """This is a specialization of BaseHTTPServer to allow it |
118 to be exited cleanly (by setting its "stop" member to True).""" | 139 to be exited cleanly (by setting its "stop" member to True).""" |
119 | 140 |
120 def serve_forever(self): | 141 def serve_forever(self): |
121 self.stop = False | 142 self.stop = False |
122 self.nonce_time = None | 143 self.nonce_time = None |
123 while not self.stop: | 144 while not self.stop: |
124 self.handle_request() | 145 self.handle_request() |
125 self.socket.close() | 146 self.socket.close() |
126 | 147 |
127 | 148 |
128 class HTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer): | 149 class HTTPServer(ClientRestrictingServerMixIn, |
| 150 BrokenPipeHandlerMixIn, |
| 151 StoppableHTTPServer): |
129 """This is a specialization of StoppableHTTPServer that adds client | 152 """This is a specialization of StoppableHTTPServer that adds client |
130 verification.""" | 153 verification.""" |
131 | 154 |
132 pass | 155 pass |
133 | 156 |
134 class OCSPServer(ClientRestrictingServerMixIn, BaseHTTPServer.HTTPServer): | 157 class OCSPServer(ClientRestrictingServerMixIn, |
| 158 BrokenPipeHandlerMixIn, |
| 159 BaseHTTPServer.HTTPServer): |
135 """This is a specialization of HTTPServer that serves an | 160 """This is a specialization of HTTPServer that serves an |
136 OCSP response""" | 161 OCSP response""" |
137 | 162 |
138 def serve_forever_on_thread(self): | 163 def serve_forever_on_thread(self): |
139 self.thread = threading.Thread(target = self.serve_forever, | 164 self.thread = threading.Thread(target = self.serve_forever, |
140 name = "OCSPServerThread") | 165 name = "OCSPServerThread") |
141 self.thread.start() | 166 self.thread.start() |
142 | 167 |
143 def stop_serving(self): | 168 def stop_serving(self): |
144 self.shutdown() | 169 self.shutdown() |
145 self.thread.join() | 170 self.thread.join() |
146 | 171 |
147 | 172 |
148 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, | 173 class HTTPSServer(tlslite.api.TLSSocketServerMixIn, |
149 ClientRestrictingServerMixIn, | 174 ClientRestrictingServerMixIn, |
| 175 BrokenPipeHandlerMixIn, |
150 StoppableHTTPServer): | 176 StoppableHTTPServer): |
151 """This is a specialization of StoppableHTTPServer that add https support and | 177 """This is a specialization of StoppableHTTPServer that add https support and |
152 client verification.""" | 178 client verification.""" |
153 | 179 |
154 def __init__(self, server_address, request_hander_class, pem_cert_and_key, | 180 def __init__(self, server_address, request_hander_class, pem_cert_and_key, |
155 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, | 181 ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers, |
156 record_resume_info, tls_intolerant): | 182 record_resume_info, tls_intolerant): |
157 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key) | 183 self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key) |
158 self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key, private=True) | 184 self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key, private=True) |
159 self.ssl_client_auth = ssl_client_auth | 185 self.ssl_client_auth = ssl_client_auth |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 tlsConnection.ignoreAbruptClose = True | 217 tlsConnection.ignoreAbruptClose = True |
192 return True | 218 return True |
193 except tlslite.api.TLSAbruptCloseError: | 219 except tlslite.api.TLSAbruptCloseError: |
194 # Ignore abrupt close. | 220 # Ignore abrupt close. |
195 return True | 221 return True |
196 except tlslite.api.TLSError, error: | 222 except tlslite.api.TLSError, error: |
197 print "Handshake failure:", str(error) | 223 print "Handshake failure:", str(error) |
198 return False | 224 return False |
199 | 225 |
200 | 226 |
201 class SyncHTTPServer(ClientRestrictingServerMixIn, StoppableHTTPServer): | 227 class SyncHTTPServer(ClientRestrictingServerMixIn, |
| 228 BrokenPipeHandlerMixIn, |
| 229 StoppableHTTPServer): |
202 """An HTTP server that handles sync commands.""" | 230 """An HTTP server that handles sync commands.""" |
203 | 231 |
204 def __init__(self, server_address, xmpp_port, request_handler_class): | 232 def __init__(self, server_address, xmpp_port, request_handler_class): |
205 # We import here to avoid pulling in chromiumsync's dependencies | 233 # We import here to avoid pulling in chromiumsync's dependencies |
206 # unless strictly necessary. | 234 # unless strictly necessary. |
207 import chromiumsync | 235 import chromiumsync |
208 import xmppserver | 236 import xmppserver |
209 StoppableHTTPServer.__init__(self, server_address, request_handler_class) | 237 StoppableHTTPServer.__init__(self, server_address, request_handler_class) |
210 self._sync_handler = chromiumsync.TestServer() | 238 self._sync_handler = chromiumsync.TestServer() |
211 self._xmpp_socket_map = {} | 239 self._xmpp_socket_map = {} |
(...skipping 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 'round-robin fashion. The server will ' | 2465 'round-robin fashion. The server will ' |
2438 'generate a random key if none is specified ' | 2466 'generate a random key if none is specified ' |
2439 'on the command line.') | 2467 'on the command line.') |
2440 self.option_parser.add_option('--auth-token', dest='auth_token', | 2468 self.option_parser.add_option('--auth-token', dest='auth_token', |
2441 help='Specify the auth token which should be ' | 2469 help='Specify the auth token which should be ' |
2442 'used in the authorization header for GData.') | 2470 'used in the authorization header for GData.') |
2443 | 2471 |
2444 | 2472 |
2445 if __name__ == '__main__': | 2473 if __name__ == '__main__': |
2446 sys.exit(ServerRunner().main()) | 2474 sys.exit(ServerRunner().main()) |
OLD | NEW |