OLD | NEW |
1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
2 # Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2010 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 server used for testing Chrome. | 6 """This is a simple HTTP 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 |
11 explicit port if necessary. | 11 explicit port if necessary. |
12 It can use https if you specify the flag --https=CERT where CERT is the path | 12 It can use https if you specify the flag --https=CERT where CERT is the path |
13 to a pem file containing the certificate and private key that should be used. | 13 to a pem file containing the certificate and private key that should be used. |
14 """ | 14 """ |
15 | 15 |
| 16 import asyncore |
16 import base64 | 17 import base64 |
17 import BaseHTTPServer | 18 import BaseHTTPServer |
18 import cgi | 19 import cgi |
| 20 import errno |
19 import optparse | 21 import optparse |
20 import os | 22 import os |
21 import re | 23 import re |
22 import shutil | 24 import select |
23 import simplejson | 25 import simplejson |
24 import SocketServer | 26 import SocketServer |
| 27 import socket |
25 import sys | 28 import sys |
26 import struct | 29 import struct |
27 import time | 30 import time |
28 import urlparse | 31 import urlparse |
29 import warnings | 32 import warnings |
30 | 33 |
31 # Ignore deprecation warnings, they make our output more cluttered. | 34 # Ignore deprecation warnings, they make our output more cluttered. |
32 warnings.filterwarnings("ignore", category=DeprecationWarning) | 35 warnings.filterwarnings("ignore", category=DeprecationWarning) |
33 | 36 |
34 import pyftpdlib.ftpserver | 37 import pyftpdlib.ftpserver |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 return False | 113 return False |
111 | 114 |
112 | 115 |
113 class SyncHTTPServer(StoppableHTTPServer): | 116 class SyncHTTPServer(StoppableHTTPServer): |
114 """An HTTP server that handles sync commands.""" | 117 """An HTTP server that handles sync commands.""" |
115 | 118 |
116 def __init__(self, server_address, request_handler_class): | 119 def __init__(self, server_address, request_handler_class): |
117 # We import here to avoid pulling in chromiumsync's dependencies | 120 # We import here to avoid pulling in chromiumsync's dependencies |
118 # unless strictly necessary. | 121 # unless strictly necessary. |
119 import chromiumsync | 122 import chromiumsync |
| 123 import xmppserver |
| 124 StoppableHTTPServer.__init__(self, server_address, request_handler_class) |
120 self._sync_handler = chromiumsync.TestServer() | 125 self._sync_handler = chromiumsync.TestServer() |
121 StoppableHTTPServer.__init__(self, server_address, request_handler_class) | 126 self._xmpp_socket_map = {} |
| 127 self._xmpp_server = xmppserver.XmppServer( |
| 128 self._xmpp_socket_map, ('localhost', 0)) |
| 129 self.xmpp_port = self._xmpp_server.getsockname()[1] |
122 | 130 |
123 def HandleCommand(self, query, raw_request): | 131 def HandleCommand(self, query, raw_request): |
124 return self._sync_handler.HandleCommand(query, raw_request) | 132 return self._sync_handler.HandleCommand(query, raw_request) |
125 | 133 |
| 134 def HandleRequestNoBlock(self): |
| 135 """Handles a single request. |
| 136 |
| 137 Copied from SocketServer._handle_request_noblock(). |
| 138 """ |
| 139 try: |
| 140 request, client_address = self.get_request() |
| 141 except socket.error: |
| 142 return |
| 143 if self.verify_request(request, client_address): |
| 144 try: |
| 145 self.process_request(request, client_address) |
| 146 except: |
| 147 self.handle_error(request, client_address) |
| 148 self.close_request(request) |
| 149 |
| 150 def serve_forever(self): |
| 151 """This is a merge of asyncore.loop() and SocketServer.serve_forever(). |
| 152 """ |
| 153 |
| 154 def RunDispatcherHandler(dispatcher, handler): |
| 155 """Handles a single event for an asyncore.dispatcher. |
| 156 |
| 157 Adapted from asyncore.read() et al. |
| 158 """ |
| 159 try: |
| 160 handler(dispatcher) |
| 161 except (asyncore.ExitNow, KeyboardInterrupt, SystemExit): |
| 162 raise |
| 163 except: |
| 164 dispatcher.handle_error() |
| 165 |
| 166 while True: |
| 167 read_fds = [ self.fileno() ] |
| 168 write_fds = [] |
| 169 exceptional_fds = [] |
| 170 |
| 171 for fd, xmpp_connection in self._xmpp_socket_map.items(): |
| 172 is_r = xmpp_connection.readable() |
| 173 is_w = xmpp_connection.writable() |
| 174 if is_r: |
| 175 read_fds.append(fd) |
| 176 if is_w: |
| 177 write_fds.append(fd) |
| 178 if is_r or is_w: |
| 179 exceptional_fds.append(fd) |
| 180 |
| 181 try: |
| 182 read_fds, write_fds, exceptional_fds = ( |
| 183 select.select(read_fds, write_fds, exceptional_fds)) |
| 184 except select.error, err: |
| 185 if err.args[0] != errno.EINTR: |
| 186 raise |
| 187 else: |
| 188 continue |
| 189 |
| 190 for fd in read_fds: |
| 191 if fd == self.fileno(): |
| 192 self.HandleRequestNoBlock() |
| 193 continue |
| 194 xmpp_connection = self._xmpp_socket_map.get(fd) |
| 195 RunDispatcherHandler(xmpp_connection, |
| 196 asyncore.dispatcher.handle_read_event) |
| 197 |
| 198 for fd in write_fds: |
| 199 xmpp_connection = self._xmpp_socket_map.get(fd) |
| 200 RunDispatcherHandler(xmpp_connection, |
| 201 asyncore.dispatcher.handle_write_event) |
| 202 |
| 203 for fd in exceptional_fds: |
| 204 xmpp_connection = self._xmpp_socket_map.get(fd) |
| 205 RunDispatcherHandler(xmpp_connection, |
| 206 asyncore.dispatcher.handle_expt_event) |
| 207 |
126 | 208 |
127 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 209 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
128 | 210 |
129 def __init__(self, request, client_address, socket_server, | 211 def __init__(self, request, client_address, socket_server, |
130 connect_handlers, get_handlers, post_handlers, put_handlers): | 212 connect_handlers, get_handlers, post_handlers, put_handlers): |
131 self._connect_handlers = connect_handlers | 213 self._connect_handlers = connect_handlers |
132 self._get_handlers = get_handlers | 214 self._get_handlers = get_handlers |
133 self._post_handlers = post_handlers | 215 self._post_handlers = post_handlers |
134 self._put_handlers = put_handlers | 216 self._put_handlers = put_handlers |
135 BaseHTTPServer.BaseHTTPRequestHandler.__init__( | 217 BaseHTTPServer.BaseHTTPRequestHandler.__init__( |
(...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 self.__fd1.flush() | 1340 self.__fd1.flush() |
1259 self.__fd2.flush() | 1341 self.__fd2.flush() |
1260 | 1342 |
1261 def main(options, args): | 1343 def main(options, args): |
1262 logfile = open('testserver.log', 'w') | 1344 logfile = open('testserver.log', 'w') |
1263 sys.stdout = FileMultiplexer(sys.stdout, logfile) | 1345 sys.stdout = FileMultiplexer(sys.stdout, logfile) |
1264 sys.stderr = FileMultiplexer(sys.stderr, logfile) | 1346 sys.stderr = FileMultiplexer(sys.stderr, logfile) |
1265 | 1347 |
1266 port = options.port | 1348 port = options.port |
1267 | 1349 |
| 1350 server_data = {} |
| 1351 |
1268 if options.server_type == SERVER_HTTP: | 1352 if options.server_type == SERVER_HTTP: |
1269 if options.cert: | 1353 if options.cert: |
1270 # let's make sure the cert file exists. | 1354 # let's make sure the cert file exists. |
1271 if not os.path.isfile(options.cert): | 1355 if not os.path.isfile(options.cert): |
1272 print 'specified server cert file not found: ' + options.cert + \ | 1356 print 'specified server cert file not found: ' + options.cert + \ |
1273 ' exiting...' | 1357 ' exiting...' |
1274 return | 1358 return |
1275 for ca_cert in options.ssl_client_ca: | 1359 for ca_cert in options.ssl_client_ca: |
1276 if not os.path.isfile(ca_cert): | 1360 if not os.path.isfile(ca_cert): |
1277 print 'specified trusted client CA file not found: ' + ca_cert + \ | 1361 print 'specified trusted client CA file not found: ' + ca_cert + \ |
1278 ' exiting...' | 1362 ' exiting...' |
1279 return | 1363 return |
1280 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, | 1364 server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert, |
1281 options.ssl_client_auth, options.ssl_client_ca, | 1365 options.ssl_client_auth, options.ssl_client_ca, |
1282 options.ssl_bulk_cipher) | 1366 options.ssl_bulk_cipher) |
1283 print 'HTTPS server started on port %d...' % server.server_port | 1367 print 'HTTPS server started on port %d...' % server.server_port |
1284 else: | 1368 else: |
1285 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) | 1369 server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) |
1286 print 'HTTP server started on port %d...' % server.server_port | 1370 print 'HTTP server started on port %d...' % server.server_port |
1287 | 1371 |
1288 server.data_dir = MakeDataDir() | 1372 server.data_dir = MakeDataDir() |
1289 server.file_root_url = options.file_root_url | 1373 server.file_root_url = options.file_root_url |
1290 listen_port = server.server_port | 1374 server_data['port'] = server.server_port |
1291 server._device_management_handler = None | 1375 server._device_management_handler = None |
1292 elif options.server_type == SERVER_SYNC: | 1376 elif options.server_type == SERVER_SYNC: |
1293 server = SyncHTTPServer(('127.0.0.1', port), SyncPageHandler) | 1377 server = SyncHTTPServer(('127.0.0.1', port), SyncPageHandler) |
1294 print 'Sync HTTP server started on port %d...' % server.server_port | 1378 print 'Sync HTTP server started on port %d...' % server.server_port |
1295 listen_port = server.server_port | 1379 print 'Sync XMPP server started on port %d...' % server.xmpp_port |
| 1380 server_data['port'] = server.server_port |
| 1381 server_data['xmpp_port'] = server.xmpp_port |
1296 # means FTP Server | 1382 # means FTP Server |
1297 else: | 1383 else: |
1298 my_data_dir = MakeDataDir() | 1384 my_data_dir = MakeDataDir() |
1299 | 1385 |
1300 # Instantiate a dummy authorizer for managing 'virtual' users | 1386 # Instantiate a dummy authorizer for managing 'virtual' users |
1301 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() | 1387 authorizer = pyftpdlib.ftpserver.DummyAuthorizer() |
1302 | 1388 |
1303 # Define a new user having full r/w permissions and a read-only | 1389 # Define a new user having full r/w permissions and a read-only |
1304 # anonymous user | 1390 # anonymous user |
1305 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') | 1391 authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') |
1306 | 1392 |
1307 authorizer.add_anonymous(my_data_dir) | 1393 authorizer.add_anonymous(my_data_dir) |
1308 | 1394 |
1309 # Instantiate FTP handler class | 1395 # Instantiate FTP handler class |
1310 ftp_handler = pyftpdlib.ftpserver.FTPHandler | 1396 ftp_handler = pyftpdlib.ftpserver.FTPHandler |
1311 ftp_handler.authorizer = authorizer | 1397 ftp_handler.authorizer = authorizer |
1312 | 1398 |
1313 # Define a customized banner (string returned when client connects) | 1399 # Define a customized banner (string returned when client connects) |
1314 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % | 1400 ftp_handler.banner = ("pyftpdlib %s based ftpd ready." % |
1315 pyftpdlib.ftpserver.__ver__) | 1401 pyftpdlib.ftpserver.__ver__) |
1316 | 1402 |
1317 # Instantiate FTP server class and listen to 127.0.0.1:port | 1403 # Instantiate FTP server class and listen to 127.0.0.1:port |
1318 address = ('127.0.0.1', port) | 1404 address = ('127.0.0.1', port) |
1319 server = pyftpdlib.ftpserver.FTPServer(address, ftp_handler) | 1405 server = pyftpdlib.ftpserver.FTPServer(address, ftp_handler) |
1320 listen_port = server.socket.getsockname()[1] | 1406 server_data['port'] = server.socket.getsockname()[1] |
1321 print 'FTP server started on port %d...' % listen_port | 1407 print 'FTP server started on port %d...' % server_data['port'] |
1322 | 1408 |
1323 # Notify the parent that we've started. (BaseServer subclasses | 1409 # Notify the parent that we've started. (BaseServer subclasses |
1324 # bind their sockets on construction.) | 1410 # bind their sockets on construction.) |
1325 if options.startup_pipe is not None: | 1411 if options.startup_pipe is not None: |
1326 server_data = { | |
1327 'port': listen_port | |
1328 } | |
1329 server_data_json = simplejson.dumps(server_data) | 1412 server_data_json = simplejson.dumps(server_data) |
1330 server_data_len = len(server_data_json) | 1413 server_data_len = len(server_data_json) |
1331 print 'sending server_data: %s (%d bytes)' % ( | 1414 print 'sending server_data: %s (%d bytes)' % ( |
1332 server_data_json, server_data_len) | 1415 server_data_json, server_data_len) |
1333 if sys.platform == 'win32': | 1416 if sys.platform == 'win32': |
1334 fd = msvcrt.open_osfhandle(options.startup_pipe, 0) | 1417 fd = msvcrt.open_osfhandle(options.startup_pipe, 0) |
1335 else: | 1418 else: |
1336 fd = options.startup_pipe | 1419 fd = options.startup_pipe |
1337 startup_pipe = os.fdopen(fd, "w") | 1420 startup_pipe = os.fdopen(fd, "w") |
1338 # First write the data length as an unsigned 4-byte value. This | 1421 # First write the data length as an unsigned 4-byte value. This |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 'option may appear multiple times, indicating ' | 1467 'option may appear multiple times, indicating ' |
1385 'multiple algorithms should be enabled.'); | 1468 'multiple algorithms should be enabled.'); |
1386 option_parser.add_option('', '--file-root-url', default='/files/', | 1469 option_parser.add_option('', '--file-root-url', default='/files/', |
1387 help='Specify a root URL for files served.') | 1470 help='Specify a root URL for files served.') |
1388 option_parser.add_option('', '--startup-pipe', type='int', | 1471 option_parser.add_option('', '--startup-pipe', type='int', |
1389 dest='startup_pipe', | 1472 dest='startup_pipe', |
1390 help='File handle of pipe to parent process') | 1473 help='File handle of pipe to parent process') |
1391 options, args = option_parser.parse_args() | 1474 options, args = option_parser.parse_args() |
1392 | 1475 |
1393 sys.exit(main(options, args)) | 1476 sys.exit(main(options, args)) |
OLD | NEW |