Currently, I am looking into gevent — a nicely performing networking library for Python, based on the brilliant idea of greenlets. I try to use this for WebSocket communication with browsers. As of today, WebSockets are still not available or disabled in some browsers. That’s why there are Javascript implementations like web-socket-js providing a transparent “Flashbridge” as a fallback for the WebSocket communication. But the Flash plugin in the client’s browser does not simply communicate with any server on any port in the world. As a first step, it always tries to receive a so-called socket policy file from the same server the SWF file was received from; on port 843. This policy file tells the client from whom he is allowed to receive data. Today, I present a simple server based on gevent providing this policy file for connecting Flash clients.
By using gevent, you automatically get one of the highest performing Python servers you can get for this purpose. Due to the greenlet concept, it is able to handle a huge amount of concurrent connections without any threading overhead. Due to benchmarks like this, the server should be faster than comparable Python solutions (based on e.g. Twisted or Eventlet) while almost reaching the level of optimized C/C++ solutions. Of course, all this performance is not really necessary for a Flash policy server, but it is good to know what we are dealing with.
Now, the code. It is already “bloated” with comments and logging functionality. Due to the use of gevent, the server code itself is very simple:
#!/usr/bin/env python # Flash access policy server based on gevent # Jan-Philip Gehrcke, June 2011 # Listen on port 843; send acess policy to client; disconnect. from gevent.server import StreamServer import datetime import socket # Should we log something? Where to? LOG = 1 LOGFILE = "flash_access_policy_server.log" # The policy that is sent to the clients. POLICY = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\0""" # The string the client has to send in order to receive the policy. POLICYREQUEST = "<policy-file-request/>" # This function is called for each incoming connection # (in a non-blocking fashion in a greenlet) def client_handle(sock, address): log("%s:%s: Connection accepted." % address) # send and read functions should not wait longer than three seconds sock.settimeout(3) try: # try to receive at most 128 bytes (`POLICYREQUEST` is shorter) input = sock.recv(128) if input.startswith(POLICYREQUEST): sock.sendall(POLICY) log("%s:%s: Policy sent. Closing connection." % address) else: log("%s:%s: Crap received. Closing connection." % address) except socket.timeout: log("%s:%s: Timed out. Closing." % address) sock.close() # Write `msg` to file and stdout, prepended by a date/time string def log(msg): if LOG: l = "%s: %s" % (datetime.datetime.now().isoformat(), msg) lf.write("%s\n" % l) print l if __name__ == '__main__': if LOG: lf = open(LOGFILE, "a") server = StreamServer(('0.0.0.0', 843), client_handle) log('Starting server...') server.serve_forever()
Note that the policy in this case is not very sophisticated and basically allows everything;-)
Leave a Reply