Chromium Code Reviews| 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 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 | 178 |
| 179 Args: | 179 Args: |
| 180 options: optparse based class returned by ParseArgs() | 180 options: optparse based class returned by ParseArgs() |
| 181 port_allocator: A port allocator instance. | 181 port_allocator: A port allocator instance. |
| 182 """ | 182 """ |
| 183 self._options = options | 183 self._options = options |
| 184 self._port_allocator = port_allocator | 184 self._port_allocator = port_allocator |
| 185 | 185 |
| 186 @cherrypy.expose | 186 @cherrypy.expose |
| 187 def ServeConstrained(self, f=None, bandwidth=None, latency=None, loss=None, | 187 def ServeConstrained(self, f=None, bandwidth=None, latency=None, loss=None, |
| 188 new_port=False): | 188 new_port=False, no_cache=False, **kwargs): |
| 189 """Serves the requested file with the requested constraints. | 189 """Serves the requested file with the requested constraints. |
| 190 | 190 |
| 191 Subsequent requests for the same constraints from the same IP will share the | 191 Subsequent requests for the same constraints from the same IP will share the |
| 192 previously created port unless new_port equals True. If no constraints | 192 previously created port unless new_port equals True. If no constraints |
| 193 are provided the file is served as is. | 193 are provided the file is served as is. |
| 194 | 194 |
| 195 Args: | 195 Args: |
| 196 f: path relative to http root of file to serve. | 196 f: path relative to http root of file to serve. |
| 197 bandwidth: maximum allowed bandwidth for the provided port (integer | 197 bandwidth: maximum allowed bandwidth for the provided port (integer |
| 198 in kbit/s). | 198 in kbit/s). |
| 199 latency: time to add to each packet (integer in ms). | 199 latency: time to add to each packet (integer in ms). |
| 200 loss: percentage of packets to drop (integer, 0-100). | 200 loss: percentage of packets to drop (integer, 0-100). |
| 201 new_port: whether to use a new port for this request or not. | 201 new_port: whether to use a new port for this request or not. |
| 202 no_cache: Set reponse's cache-control to no-cache. | |
| 202 """ | 203 """ |
| 203 cherrypy.log('Got request for %s, bandwidth=%s, latency=%s, loss=%s, ' | 204 cherrypy.log('Got request for %s, bandwidth=%s, latency=%s, loss=%s, ' |
| 204 'new_port=%s' % (f, bandwidth, latency, loss, new_port)) | 205 'new_port=%s' % (f, bandwidth, latency, loss, new_port)) |
| 206 if no_cache: | |
| 207 response = cherrypy.response | |
| 208 response.headers['Pragma'] = 'no-cache' | |
| 209 response.headers['Cache-Control'] = 'no-cache' | |
| 210 | |
|
shadi
2012/04/18 02:03:17
I do not use this yet since <video> caches anyway
| |
| 205 # CherryPy is a bit wonky at detecting parameters, so just make them all | 211 # CherryPy is a bit wonky at detecting parameters, so just make them all |
| 206 # optional and validate them ourselves. | 212 # optional and validate them ourselves. |
| 207 if not f: | 213 if not f: |
| 208 raise cherrypy.HTTPError(400, 'Invalid request. File must be specified.') | 214 raise cherrypy.HTTPError(400, 'Invalid request. File must be specified.') |
| 209 | 215 |
| 210 # Sanitize and check the path to prevent www-root escapes. | 216 # Sanitize and check the path to prevent www-root escapes. |
| 211 sanitized_path = os.path.abspath(os.path.join(self._options.www_root, f)) | 217 sanitized_path = os.path.abspath(os.path.join(self._options.www_root, f)) |
| 212 if not sanitized_path.startswith(self._options.www_root): | 218 if not sanitized_path.startswith(self._options.www_root): |
| 213 raise cherrypy.HTTPError(403, 'Invalid file requested.') | 219 raise cherrypy.HTTPError(403, 'Invalid file requested.') |
| 214 | 220 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 240 loss=loss, new_port=new_port) | 246 loss=loss, new_port=new_port) |
| 241 end_time = time.time() | 247 end_time = time.time() |
| 242 | 248 |
| 243 if not constrained_port: | 249 if not constrained_port: |
| 244 raise cherrypy.HTTPError(503, 'Service unavailable. Out of ports.') | 250 raise cherrypy.HTTPError(503, 'Service unavailable. Out of ports.') |
| 245 | 251 |
| 246 cherrypy.log('Time to set up port %d = %ssec.' % | 252 cherrypy.log('Time to set up port %d = %ssec.' % |
| 247 (constrained_port, end_time - start_time)) | 253 (constrained_port, end_time - start_time)) |
| 248 | 254 |
| 249 # Build constrained URL. Only pass on the file parameter. | 255 # Build constrained URL. Only pass on the file parameter. |
| 250 constrained_url = '%s?f=%s' % ( | 256 constrained_url = '%s?f=%s&no_cache=%s' % ( |
| 251 cherrypy.url().replace( | 257 cherrypy.url().replace( |
| 252 ':%d' % self._options.port, ':%d' % constrained_port), | 258 ':%d' % self._options.port, ':%d' % constrained_port), |
| 253 f) | 259 f, |
| 260 no_cache) | |
| 254 | 261 |
| 255 # Redirect request to the constrained port. | 262 # Redirect request to the constrained port. |
| 256 cherrypy.lib.cptools.redirect(constrained_url, internal=False) | 263 cherrypy.lib.cptools.redirect(constrained_url, internal=False) |
| 257 | 264 |
| 258 def _ParseIntParameter(self, param, msg, check): | 265 def _ParseIntParameter(self, param, msg, check): |
| 259 """Returns integer value of param and verifies it satisfies the check. | 266 """Returns integer value of param and verifies it satisfies the check. |
| 260 | 267 |
| 261 Args: | 268 Args: |
| 262 param: Parameter name to check. | 269 param: Parameter name to check. |
| 263 msg: Message in error if raised. | 270 msg: Message in error if raised. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 try: | 367 try: |
| 361 cherrypy.quickstart(ConstrainedNetworkServer(options, pa)) | 368 cherrypy.quickstart(ConstrainedNetworkServer(options, pa)) |
| 362 finally: | 369 finally: |
| 363 # Disable Ctrl-C handler to prevent interruption of cleanup. | 370 # Disable Ctrl-C handler to prevent interruption of cleanup. |
| 364 signal.signal(signal.SIGINT, lambda signal, frame: None) | 371 signal.signal(signal.SIGINT, lambda signal, frame: None) |
| 365 pa.Cleanup(options.interface, all_ports=True) | 372 pa.Cleanup(options.interface, all_ports=True) |
| 366 | 373 |
| 367 | 374 |
| 368 if __name__ == '__main__': | 375 if __name__ == '__main__': |
| 369 Main() | 376 Main() |
| OLD | NEW |