blob: b5a5f06cbdadc845c4b94cc2b54f3cc71591a760 [file] [log] [blame]
#!/usr/bin/env python
"""
SSL server for Forge tests.
- The server changes to the directory of the server script.
- SSL uses "server.key" and "server.crt".
- Sever performs basic static file serving.
- Starts Flash cross domain policy file server.
- Defaults to HTTP/HTTPS port 19400.
- Defaults to Flash socket policy port 19945.
$ ./server.py [options]
If you just need a simple HTTP server, also consider:
$ python -m SimpleHTTPServer 19400
"""
from multiprocessing import Process
from optparse import OptionParser
import SimpleHTTPServer
import SocketServer
import os
import sys
import time
# Try to import special Forge SSL module with session cache support
# Using the built directory directly
python_version = "python" + sys.version[:3]
sys.path.insert(0, os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"..", "dist", "forge_ssl", "lib", python_version, "site-packages"))
try:
from forge import ssl
have_ssl_sessions = True
have_ssl = True
except ImportError:
have_ssl_sessions = False
try:
import ssl
have_ssl = True
except ImportError:
have_ssl = False
# Set address reuse for all TCPServers
SocketServer.TCPServer.allow_reuse_address = True
# The policy file
# NOTE: This format is very strict. Edit with care.
policy_file = """\
<?xml version="1.0"?>\
<!DOCTYPE cross-domain-policy\
SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">\
<cross-domain-policy>\
<allow-access-from domain="*" to-ports="*"/>\
</cross-domain-policy>\0"""
class PolicyHandler(SocketServer.BaseRequestHandler):
"""
The RequestHandler class for our server.
Returns a policy file when requested.
"""
def handle(self):
# get some data
# TODO: make this more robust (while loop, etc)
self.data = self.request.recv(1024).rstrip('\0')
#print "%s wrote:" % self.client_address[0]
#print repr(self.data)
# if policy file request, send the file.
if self.data == "<policy-file-request/>":
print "Policy server request from %s." % (self.client_address[0])
self.request.send(policy_file)
else:
print "Policy server received junk from %s: \"%s\"" % \
(self.client_address[0], repr(self.data))
def create_policy_server(options):
"""Start a policy server"""
print "Policy serving from %d." % (options.policy_port)
policyd = SocketServer.TCPServer((options.host, options.policy_port), PolicyHandler)
return policyd
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def create_http_server(options, script_dir):
"""Start a static file server"""
# use UTF-8 encoding for javascript files
m = SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map
m['.js'] = 'application/javascript;charset=UTF-8'
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
# httpd = SocketServer.TCPServer((options.host, options.port), Handler)
httpd = ThreadedTCPServer((options.host, options.port), Handler)
if options.tls:
if not have_ssl:
raise Exception("SSL support from Python 2.7 or later is required.")
# setup session args if we session support
sess_args = {}
if have_ssl_sessions:
sess_args["sess_id_ctx"] = "forgetest"
else:
print "Forge SSL with session cache not available, using standard version."
httpd.socket = ssl.wrap_socket(
httpd.socket,
keyfile="server.key",
certfile="server.crt",
server_side=True,
**sess_args)
print "Serving from \"%s\"." % (script_dir)
print "%s://%s:%d/" % \
(("https" if options.tls else "http"),
httpd.server_address[0],
options.port)
return httpd
def serve_forever(server):
"""Serve until shutdown or keyboard interrupt."""
try:
server.serve_forever()
except KeyboardInterrupt:
return
def main():
"""Start static file and policy servers"""
usage = "Usage: %prog [options]"
parser = OptionParser(usage=usage)
parser.add_option("", "--host", dest="host", metavar="HOST",
default="localhost", help="bind to HOST")
parser.add_option("-p", "--port", dest="port", type="int",
help="serve on PORT", metavar="PORT", default=19400)
parser.add_option("-P", "--policy-port", dest="policy_port", type="int",
help="serve policy file on PORT", metavar="PORT", default=19945)
parser.add_option("", "--tls", dest="tls", action="store_true",
help="serve HTTPS", default=False)
(options, args) = parser.parse_args()
# Change to script dir so SSL and test files are in current dir.
script_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(script_dir)
print "Forge Test Server. Use ctrl-c to exit."
# create policy and http servers
httpd = create_http_server(options, script_dir)
policyd = create_policy_server(options)
# start servers
server_p = Process(target=serve_forever, args=(httpd,))
policy_p = Process(target=serve_forever, args=(policyd,))
server_p.start()
policy_p.start()
processes = [server_p, policy_p]
while len(processes) > 0:
try:
for p in processes:
if p.is_alive():
p.join(1)
else:
processes.remove(p)
except KeyboardInterrupt:
print "\nStopping test server..."
# processes each receive interrupt
# so no need to shutdown
#httpd.shutdown();
#policyd.shutdown();
if __name__ == "__main__":
main()