media/webrtc/trunk/build/android/lighttpd_server.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #!/usr/bin/env python
michael@0 2 #
michael@0 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 4 # Use of this source code is governed by a BSD-style license that can be
michael@0 5 # found in the LICENSE file.
michael@0 6
michael@0 7 """Provides a convenient wrapper for spawning a test lighttpd instance.
michael@0 8
michael@0 9 Usage:
michael@0 10 lighttpd_server PATH_TO_DOC_ROOT
michael@0 11 """
michael@0 12
michael@0 13 import codecs
michael@0 14 import contextlib
michael@0 15 import httplib
michael@0 16 import os
michael@0 17 import random
michael@0 18 import shutil
michael@0 19 import socket
michael@0 20 import subprocess
michael@0 21 import sys
michael@0 22 import tempfile
michael@0 23 import time
michael@0 24
michael@0 25 from pylib import constants
michael@0 26 from pylib import pexpect
michael@0 27
michael@0 28 class LighttpdServer(object):
michael@0 29 """Wraps lighttpd server, providing robust startup.
michael@0 30
michael@0 31 Args:
michael@0 32 document_root: Path to root of this server's hosted files.
michael@0 33 port: TCP port on the _host_ machine that the server will listen on. If
michael@0 34 ommitted it will attempt to use 9000, or if unavailable it will find
michael@0 35 a free port from 8001 - 8999.
michael@0 36 lighttpd_path, lighttpd_module_path: Optional paths to lighttpd binaries.
michael@0 37 base_config_path: If supplied this file will replace the built-in default
michael@0 38 lighttpd config file.
michael@0 39 extra_config_contents: If specified, this string will be appended to the
michael@0 40 base config (default built-in, or from base_config_path).
michael@0 41 config_path, error_log, access_log: Optional paths where the class should
michael@0 42 place temprary files for this session.
michael@0 43 """
michael@0 44
michael@0 45 def __init__(self, document_root, port=None,
michael@0 46 lighttpd_path=None, lighttpd_module_path=None,
michael@0 47 base_config_path=None, extra_config_contents=None,
michael@0 48 config_path=None, error_log=None, access_log=None):
michael@0 49 self.temp_dir = tempfile.mkdtemp(prefix='lighttpd_for_chrome_android')
michael@0 50 self.document_root = os.path.abspath(document_root)
michael@0 51 self.fixed_port = port
michael@0 52 self.port = port or constants.LIGHTTPD_DEFAULT_PORT
michael@0 53 self.server_tag = 'LightTPD ' + str(random.randint(111111, 999999))
michael@0 54 self.lighttpd_path = lighttpd_path or '/usr/sbin/lighttpd'
michael@0 55 self.lighttpd_module_path = lighttpd_module_path or '/usr/lib/lighttpd'
michael@0 56 self.base_config_path = base_config_path
michael@0 57 self.extra_config_contents = extra_config_contents
michael@0 58 self.config_path = config_path or self._Mktmp('config')
michael@0 59 self.error_log = error_log or self._Mktmp('error_log')
michael@0 60 self.access_log = access_log or self._Mktmp('access_log')
michael@0 61 self.pid_file = self._Mktmp('pid_file')
michael@0 62 self.process = None
michael@0 63
michael@0 64 def _Mktmp(self, name):
michael@0 65 return os.path.join(self.temp_dir, name)
michael@0 66
michael@0 67 def _GetRandomPort(self):
michael@0 68 # The ports of test server is arranged in constants.py.
michael@0 69 return random.randint(constants.LIGHTTPD_RANDOM_PORT_FIRST,
michael@0 70 constants.LIGHTTPD_RANDOM_PORT_LAST)
michael@0 71
michael@0 72 def StartupHttpServer(self):
michael@0 73 """Starts up a http server with specified document root and port."""
michael@0 74 # If we want a specific port, make sure no one else is listening on it.
michael@0 75 if self.fixed_port:
michael@0 76 self._KillProcessListeningOnPort(self.fixed_port)
michael@0 77 while True:
michael@0 78 if self.base_config_path:
michael@0 79 # Read the config
michael@0 80 with codecs.open(self.base_config_path, 'r', 'utf-8') as f:
michael@0 81 config_contents = f.read()
michael@0 82 else:
michael@0 83 config_contents = self._GetDefaultBaseConfig()
michael@0 84 if self.extra_config_contents:
michael@0 85 config_contents += self.extra_config_contents
michael@0 86 # Write out the config, filling in placeholders from the members of |self|
michael@0 87 with codecs.open(self.config_path, 'w', 'utf-8') as f:
michael@0 88 f.write(config_contents % self.__dict__)
michael@0 89 if (not os.path.exists(self.lighttpd_path) or
michael@0 90 not os.access(self.lighttpd_path, os.X_OK)):
michael@0 91 raise EnvironmentError(
michael@0 92 'Could not find lighttpd at %s.\n'
michael@0 93 'It may need to be installed (e.g. sudo apt-get install lighttpd)'
michael@0 94 % self.lighttpd_path)
michael@0 95 self.process = pexpect.spawn(self.lighttpd_path,
michael@0 96 ['-D', '-f', self.config_path,
michael@0 97 '-m', self.lighttpd_module_path],
michael@0 98 cwd=self.temp_dir)
michael@0 99 client_error, server_error = self._TestServerConnection()
michael@0 100 if not client_error:
michael@0 101 assert int(open(self.pid_file, 'r').read()) == self.process.pid
michael@0 102 break
michael@0 103 self.process.close()
michael@0 104
michael@0 105 if self.fixed_port or not 'in use' in server_error:
michael@0 106 print 'Client error:', client_error
michael@0 107 print 'Server error:', server_error
michael@0 108 return False
michael@0 109 self.port = self._GetRandomPort()
michael@0 110 return True
michael@0 111
michael@0 112 def ShutdownHttpServer(self):
michael@0 113 """Shuts down our lighttpd processes."""
michael@0 114 if self.process:
michael@0 115 self.process.terminate()
michael@0 116 shutil.rmtree(self.temp_dir, ignore_errors=True)
michael@0 117
michael@0 118 def _TestServerConnection(self):
michael@0 119 # Wait for server to start
michael@0 120 server_msg = ''
michael@0 121 for timeout in xrange(1, 5):
michael@0 122 client_error = None
michael@0 123 try:
michael@0 124 with contextlib.closing(httplib.HTTPConnection(
michael@0 125 '127.0.0.1', self.port, timeout=timeout)) as http:
michael@0 126 http.set_debuglevel(timeout > 3)
michael@0 127 http.request('HEAD', '/')
michael@0 128 r = http.getresponse()
michael@0 129 r.read()
michael@0 130 if (r.status == 200 and r.reason == 'OK' and
michael@0 131 r.getheader('Server') == self.server_tag):
michael@0 132 return (None, server_msg)
michael@0 133 client_error = ('Bad response: %s %s version %s\n ' %
michael@0 134 (r.status, r.reason, r.version) +
michael@0 135 '\n '.join([': '.join(h) for h in r.getheaders()]))
michael@0 136 except (httplib.HTTPException, socket.error) as client_error:
michael@0 137 pass # Probably too quick connecting: try again
michael@0 138 # Check for server startup error messages
michael@0 139 ix = self.process.expect([pexpect.TIMEOUT, pexpect.EOF, '.+'],
michael@0 140 timeout=timeout)
michael@0 141 if ix == 2: # stdout spew from the server
michael@0 142 server_msg += self.process.match.group(0)
michael@0 143 elif ix == 1: # EOF -- server has quit so giveup.
michael@0 144 client_error = client_error or 'Server exited'
michael@0 145 break
michael@0 146 return (client_error or 'Timeout', server_msg)
michael@0 147
michael@0 148 def _KillProcessListeningOnPort(self, port):
michael@0 149 """Checks if there is a process listening on port number |port| and
michael@0 150 terminates it if found.
michael@0 151
michael@0 152 Args:
michael@0 153 port: Port number to check.
michael@0 154 """
michael@0 155 if subprocess.call(['fuser', '-kv', '%d/tcp' % port]) == 0:
michael@0 156 # Give the process some time to terminate and check that it is gone.
michael@0 157 time.sleep(2)
michael@0 158 assert subprocess.call(['fuser', '-v', '%d/tcp' % port]) != 0, \
michael@0 159 'Unable to kill process listening on port %d.' % port
michael@0 160
michael@0 161 def _GetDefaultBaseConfig(self):
michael@0 162 return """server.tag = "%(server_tag)s"
michael@0 163 server.modules = ( "mod_access",
michael@0 164 "mod_accesslog",
michael@0 165 "mod_alias",
michael@0 166 "mod_cgi",
michael@0 167 "mod_rewrite" )
michael@0 168
michael@0 169 # default document root required
michael@0 170 #server.document-root = "."
michael@0 171
michael@0 172 # files to check for if .../ is requested
michael@0 173 index-file.names = ( "index.php", "index.pl", "index.cgi",
michael@0 174 "index.html", "index.htm", "default.htm" )
michael@0 175 # mimetype mapping
michael@0 176 mimetype.assign = (
michael@0 177 ".gif" => "image/gif",
michael@0 178 ".jpg" => "image/jpeg",
michael@0 179 ".jpeg" => "image/jpeg",
michael@0 180 ".png" => "image/png",
michael@0 181 ".svg" => "image/svg+xml",
michael@0 182 ".css" => "text/css",
michael@0 183 ".html" => "text/html",
michael@0 184 ".htm" => "text/html",
michael@0 185 ".xhtml" => "application/xhtml+xml",
michael@0 186 ".xhtmlmp" => "application/vnd.wap.xhtml+xml",
michael@0 187 ".js" => "application/x-javascript",
michael@0 188 ".log" => "text/plain",
michael@0 189 ".conf" => "text/plain",
michael@0 190 ".text" => "text/plain",
michael@0 191 ".txt" => "text/plain",
michael@0 192 ".dtd" => "text/xml",
michael@0 193 ".xml" => "text/xml",
michael@0 194 ".manifest" => "text/cache-manifest",
michael@0 195 )
michael@0 196
michael@0 197 # Use the "Content-Type" extended attribute to obtain mime type if possible
michael@0 198 mimetype.use-xattr = "enable"
michael@0 199
michael@0 200 ##
michael@0 201 # which extensions should not be handle via static-file transfer
michael@0 202 #
michael@0 203 # .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
michael@0 204 static-file.exclude-extensions = ( ".php", ".pl", ".cgi" )
michael@0 205
michael@0 206 server.bind = "127.0.0.1"
michael@0 207 server.port = %(port)s
michael@0 208
michael@0 209 ## virtual directory listings
michael@0 210 dir-listing.activate = "enable"
michael@0 211 #dir-listing.encoding = "iso-8859-2"
michael@0 212 #dir-listing.external-css = "style/oldstyle.css"
michael@0 213
michael@0 214 ## enable debugging
michael@0 215 #debug.log-request-header = "enable"
michael@0 216 #debug.log-response-header = "enable"
michael@0 217 #debug.log-request-handling = "enable"
michael@0 218 #debug.log-file-not-found = "enable"
michael@0 219
michael@0 220 #### SSL engine
michael@0 221 #ssl.engine = "enable"
michael@0 222 #ssl.pemfile = "server.pem"
michael@0 223
michael@0 224 # Autogenerated test-specific config follows.
michael@0 225
michael@0 226 cgi.assign = ( ".cgi" => "/usr/bin/env",
michael@0 227 ".pl" => "/usr/bin/env",
michael@0 228 ".asis" => "/bin/cat",
michael@0 229 ".php" => "/usr/bin/php-cgi" )
michael@0 230
michael@0 231 server.errorlog = "%(error_log)s"
michael@0 232 accesslog.filename = "%(access_log)s"
michael@0 233 server.upload-dirs = ( "/tmp" )
michael@0 234 server.pid-file = "%(pid_file)s"
michael@0 235 server.document-root = "%(document_root)s"
michael@0 236
michael@0 237 """
michael@0 238
michael@0 239
michael@0 240 def main(argv):
michael@0 241 server = LighttpdServer(*argv[1:])
michael@0 242 try:
michael@0 243 if server.StartupHttpServer():
michael@0 244 raw_input('Server running at http://127.0.0.1:%s -'
michael@0 245 ' press Enter to exit it.' % server.port)
michael@0 246 else:
michael@0 247 print 'Server exit code:', server.process.exitstatus
michael@0 248 finally:
michael@0 249 server.ShutdownHttpServer()
michael@0 250
michael@0 251
michael@0 252 if __name__ == '__main__':
michael@0 253 sys.exit(main(sys.argv))

mercurial