| 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 """Constrained Network Server. Serves files with supplied network constraints. | 6 """Constrained Network Server. Serves files with supplied network constraints. |
| 7 | 7 |
| 8 The CNS exposes a web based API allowing network constraints to be imposed on | 8 The CNS exposes a web based API allowing network constraints to be imposed on |
| 9 file serving. | 9 file serving. |
| 10 | 10 |
| 11 TODO(dalecurtis): Add some more docs here. | 11 TODO(dalecurtis): Add some more docs here. |
| 12 | 12 |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import logging |
| 15 import mimetypes | 16 import mimetypes |
| 16 import optparse | 17 import optparse |
| 17 import os | 18 import os |
| 18 import signal | 19 import signal |
| 19 import sys | 20 import sys |
| 20 import threading | 21 import threading |
| 21 import time | 22 import time |
| 22 import traffic_control | 23 import traffic_control |
| 23 | 24 |
| 24 try: | 25 try: |
| 25 import cherrypy | 26 import cherrypy |
| 26 except ImportError: | 27 except ImportError: |
| 27 print ('CNS requires CherryPy v3 or higher to be installed. Please install\n' | 28 print ('CNS requires CherryPy v3 or higher to be installed. Please install\n' |
| 28 'and try again. On Linux: sudo apt-get install python-cherrypy3\n') | 29 'and try again. On Linux: sudo apt-get install python-cherrypy3\n') |
| 29 sys.exit(1) | 30 sys.exit(1) |
| 30 | 31 |
| 31 # Add webm file types to mimetypes map since cherrypy's default type is text. | 32 # Add webm file types to mimetypes map since cherrypy's default type is text. |
| 32 mimetypes.types_map['.webm'] = 'video/webm' | 33 mimetypes.types_map['.webm'] = 'video/webm' |
| 33 | 34 |
| 35 # Default logging is ERROR. Use --verbose to enable DEBUG logging. |
| 36 _DEFAULT_LOG_LEVEL = logging.ERROR |
| 37 |
| 34 # Default port to serve the CNS on. | 38 # Default port to serve the CNS on. |
| 35 _DEFAULT_SERVING_PORT = 9000 | 39 _DEFAULT_SERVING_PORT = 9000 |
| 36 | 40 |
| 37 # Default port range for constrained use. | 41 # Default port range for constrained use. |
| 38 _DEFAULT_CNS_PORT_RANGE = (50000, 51000) | 42 _DEFAULT_CNS_PORT_RANGE = (50000, 51000) |
| 39 | 43 |
| 40 # Default number of seconds before a port can be torn down. | 44 # Default number of seconds before a port can be torn down. |
| 41 _DEFAULT_PORT_EXPIRY_TIME_SECS = 5 * 60 | 45 _DEFAULT_PORT_EXPIRY_TIME_SECS = 5 * 60 |
| 42 | 46 |
| 43 | 47 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 parser.add_option('--interface', default='eth0', | 284 parser.add_option('--interface', default='eth0', |
| 281 help=('Interface to setup constraints on. Use lo for a ' | 285 help=('Interface to setup constraints on. Use lo for a ' |
| 282 'local client. Default: %default')) | 286 'local client. Default: %default')) |
| 283 parser.add_option('--threads', type='int', | 287 parser.add_option('--threads', type='int', |
| 284 default=cherrypy._cpserver.Server.thread_pool, | 288 default=cherrypy._cpserver.Server.thread_pool, |
| 285 help=('Number of threads in the thread pool. Default: ' | 289 help=('Number of threads in the thread pool. Default: ' |
| 286 '%default')) | 290 '%default')) |
| 287 parser.add_option('--www-root', default=os.getcwd(), | 291 parser.add_option('--www-root', default=os.getcwd(), |
| 288 help=('Directory root to serve files from. Defaults to the ' | 292 help=('Directory root to serve files from. Defaults to the ' |
| 289 'current directory: %default')) | 293 'current directory: %default')) |
| 294 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', |
| 295 default=False, help='Turn on verbose output.') |
| 290 | 296 |
| 291 options = parser.parse_args()[0] | 297 options = parser.parse_args()[0] |
| 292 | 298 |
| 293 # Convert port range into the desired tuple format. | 299 # Convert port range into the desired tuple format. |
| 294 try: | 300 try: |
| 295 if isinstance(options.port_range, str): | 301 if isinstance(options.port_range, str): |
| 296 options.port_range = [int(port) for port in options.port_range.split(',')] | 302 options.port_range = [int(port) for port in options.port_range.split(',')] |
| 297 except ValueError: | 303 except ValueError: |
| 298 parser.error('Invalid port range specified.') | 304 parser.error('Invalid port range specified.') |
| 299 | 305 |
| 300 # Convert the path to an absolute to remove any . or .. | 306 # Convert the path to an absolute to remove any . or .. |
| 301 options.www_root = os.path.abspath(options.www_root) | 307 options.www_root = os.path.abspath(options.www_root) |
| 302 | 308 |
| 309 # Required so that cherrypy logs do not get propagated to root logger causing |
| 310 # the logs to be printed twice. |
| 311 cherrypy.log.error_log.propagate = False |
| 312 |
| 313 _SetLogger(options.verbose) |
| 314 |
| 303 return options | 315 return options |
| 304 | 316 |
| 305 | 317 |
| 318 def _SetLogger(verbose): |
| 319 # Logging is used for traffic_control debug statements. |
| 320 log_level = _DEFAULT_LOG_LEVEL |
| 321 if verbose: |
| 322 log_level = logging.DEBUG |
| 323 logging.basicConfig(level=log_level, format='[%(threadName)s] %(message)s') |
| 324 |
| 325 |
| 306 def Main(): | 326 def Main(): |
| 307 """Configure and start the ConstrainedNetworkServer.""" | 327 """Configure and start the ConstrainedNetworkServer.""" |
| 308 options = ParseArgs() | 328 options = ParseArgs() |
| 309 | 329 |
| 310 cherrypy.config.update( | 330 cherrypy.config.update( |
| 311 {'server.socket_host': '::', 'server.socket_port': options.port}) | 331 {'server.socket_host': '::', 'server.socket_port': options.port}) |
| 312 | 332 |
| 313 if options.threads: | 333 if options.threads: |
| 314 cherrypy.config.update({'server.thread_pool': options.threads}) | 334 cherrypy.config.update({'server.thread_pool': options.threads}) |
| 315 | 335 |
| 316 # Setup port allocator here so we can call cleanup on failures/exit. | 336 # Setup port allocator here so we can call cleanup on failures/exit. |
| 317 pa = PortAllocator(options.port_range, expiry_time_secs=options.expiry_time) | 337 pa = PortAllocator(options.port_range, expiry_time_secs=options.expiry_time) |
| 318 | 338 |
| 319 try: | 339 try: |
| 320 cherrypy.quickstart(ConstrainedNetworkServer(options, pa)) | 340 cherrypy.quickstart(ConstrainedNetworkServer(options, pa)) |
| 321 finally: | 341 finally: |
| 322 # Disable Ctrl-C handler to prevent interruption of cleanup. | 342 # Disable Ctrl-C handler to prevent interruption of cleanup. |
| 323 signal.signal(signal.SIGINT, lambda signal, frame: None) | 343 signal.signal(signal.SIGINT, lambda signal, frame: None) |
| 324 pa.Cleanup(options.interface, all_ports=True) | 344 pa.Cleanup(options.interface, all_ports=True) |
| 325 | 345 |
| 326 | 346 |
| 327 if __name__ == '__main__': | 347 if __name__ == '__main__': |
| 328 Main() | 348 Main() |
| OLD | NEW |