| 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 |