commit fbffb6fce47047c877d8dc4d2a83bcb4ee2926ea Author: Nate Hardison nate@rescomp-09-154551.stanford.edu Date: Thu Jun 2 19:49:49 2011 -0700
Using URLLoader in the FacilitatorSocket, Facilitator now speaks true HTTP --- facilitator.py | 55 +++++++++++++++++--- rtmfp/FacilitatorSocket.as | 121 ++++++++++++++++++++------------------------ rtmfpcat.as | 19 ++----- 3 files changed, 106 insertions(+), 89 deletions(-)
diff --git a/facilitator.py b/facilitator.py index c9859db..0ea86a1 100755 --- a/facilitator.py +++ b/facilitator.py @@ -10,6 +10,7 @@ import socket import sys import threading import time +import urllib
DEFAULT_ADDRESS = "0.0.0.0" DEFAULT_PORT = 9002 @@ -190,31 +191,47 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): log(u"proxy %s connects" % format_addr(self.client_address))
+ if self.path == "/crossdomain.xml": + self.send_crossdomain() + return + + client = "" reg = REGS.fetch() if reg: log(u"proxy %s gets %s (now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS))) - self.request.send(str(reg)) + client = str(reg) else: log(u"proxy %s gets none" % format_addr(self.client_address)) + client = "Registration list empty" + + response = "client=%s" % urllib.quote(client) + self.send_response(200) + self.send_header('Content-Type', 'text/html') + self.send_header('Content-Length', str(len(response))) + self.end_headers() + self.wfile.write(response)
def do_POST(self): - data = self.rfile.readline(1024).strip() - try: - vals = cgi.parse_qs(data, False, True) - except ValueError, e: - log(u"client %s POST syntax error: %s" % (format_addr(self.client_address), repr(str(e)))) + data = cgi.FieldStorage(fp = self.rfile, headers = self.headers, + environ = {'REQUEST_METHOD' : 'POST', + 'CONTENT_TYPE' : self.headers['Content-Type']}) + + if self.path == "/crossdomain.xml": + self.send_crossdomain() return
- client_specs = vals.get("client") - if client_specs is None or len(client_specs) != 1: + client_specs = data["client"] + if client_specs is None or client_specs.value is None: log(u"client %s missing "client" param" % format_addr(self.client_address)) + self.send_error(404) return - val = client_specs[0] + val = client_specs.value
try: reg = Reg.parse(val, self.client_address[0]) except ValueError, e: log(u"client %s syntax error in %s: %s" % (format_addr(self.client_address), repr(val), repr(str(e)))) + self.send_error(404) return
log(u"client %s regs %s -> %s" % (format_addr(self.client_address), val, unicode(reg))) @@ -222,10 +239,30 @@ class Handler(BaseHTTPServer.BaseHTTPRequestHandler): log(u"client %s %s (now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS))) else: log(u"client %s %s (already present, now %d)" % (format_addr(self.client_address), unicode(reg), len(REGS))) + + response = "" + + self.send_response(200) + self.send_header('Content-Type', 'text/html') + self.send_header('Content-Length', str(len(response))) + self.send_header('Connection', 'close') + self.end_headers() + self.wfile.write(response)
def log_message(self, format, *args): msg = format % args log(u"message from HTTP handler for %s: %s" % (format_addr(self.client_address), repr(msg))) + + def send_crossdomain(self): + crossdomain = """\ +<cross-domain-policy> + <allow-access-from domain="*" to-ports="%s"/> +</cross-domain-policy>\r\n""" % (address[1]) + self.send_response(200) + self.send_header('Content-Type', 'application/xml') + self.send_header('Content-Length', str(len(crossdomain))) + self.end_headers() + self.wfile.write(crossdomain)
REGS = RegSet()
diff --git a/rtmfp/FacilitatorSocket.as b/rtmfp/FacilitatorSocket.as index e175290..32c8a7d 100644 --- a/rtmfp/FacilitatorSocket.as +++ b/rtmfp/FacilitatorSocket.as @@ -1,108 +1,94 @@ package rtmfp { - import flash.net.Socket; import flash.events.Event; import flash.events.EventDispatcher; + import flash.events.HTTPStatusEvent; import flash.events.IOErrorEvent; - import flash.events.NetStatusEvent; - import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; - import flash.utils.clearInterval; - import flash.utils.setInterval; + import flash.net.URLLoader; + import flash.net.URLLoaderDataFormat; + import flash.net.URLRequest; + import flash.net.URLRequestMethod; + import flash.net.URLVariables; + import flash.system.Security;
import rtmfp.events.FacilitatorSocketEvent;
- [Event(name=FacilitatorSocketEvent.CONNECT_CLOSED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] [Event(name=FacilitatorSocketEvent.CONNECT_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] - [Event(name=FacilitatorSocketEvent.CONNECT_SUCCESS, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] [Event(name=FacilitatorSocketEvent.REGISTRATION_FAILED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] [Event(name=FacilitatorSocketEvent.REGISTRATION_RECEIVED, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] [Event(name=FacilitatorSocketEvent.REGISTRATIONS_EMPTY, type="com.flashproxy.rtmfp.events.FacilitatorSocketEvent")] public class FacilitatorSocket extends EventDispatcher { - private var socket:Socket; - private var connected:Boolean; - private var connection_timeout:uint; + private var host:String; + private var port:uint;
- public function FacilitatorSocket() - { - socket = null; - connected = false; - } - - public function close():void - { - connected = false; - if (socket != null) { - socket.removeEventListener(Event.CONNECT, on_connect_event); - socket.removeEventListener(Event.CLOSE, on_close_event); - socket.removeEventListener(IOErrorEvent.IO_ERROR, on_io_error_event); - socket.removeEventListener(ProgressEvent.SOCKET_DATA, on_progress_event); - socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event); - if (connected) { - socket.close(); - } - } - } - - public function connect(host:String, port:uint):void - { - if (socket != null || connected) { - return; - } - - socket = new Socket(); - socket.addEventListener(Event.CONNECT, on_connect_event); - socket.addEventListener(Event.CLOSE, on_close_event); - socket.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event); - socket.addEventListener(ProgressEvent.SOCKET_DATA, on_progress_event); - socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event); - socket.connect(host, port); + public function FacilitatorSocket(host:String, port:uint) + { + this.host = host; + this.port = port; }
public function get_registration():void { - if (!connected) return; - socket.writeUTFBytes("GET / HTTP/1.0\r\n\r\n"); + make_request(URLRequestMethod.GET); }
public function post_registration(registration_data:String):void - { - if (!connected) return; - socket.writeUTFBytes("POST / HTTP/1.0\r\n\r\nclient=" + registration_data + "\r\n"); + { + var data:URLVariables = new URLVariables(); + data.client = registration_data; + make_request(URLRequestMethod.POST, data); }
private function fail():void { - clearInterval(connection_timeout); dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_FAILED)); }
- private function on_close_event(event:Event):void + private function make_request(method:String, data:URLVariables = null):void { - close(); - dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_CLOSED)); + var request:URLRequest = new URLRequest(url) + request.data = data; + request.method = method; + + var url_loader:URLLoader = new URLLoader(); + url_loader = new URLLoader(); + url_loader.dataFormat = URLLoaderDataFormat.VARIABLES; + + url_loader.addEventListener(Event.COMPLETE, on_complete_event); + url_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, on_http_status_event); + url_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, on_security_error_event); + url_loader.addEventListener(IOErrorEvent.IO_ERROR, on_io_error_event); + + url_loader.load(request); }
- private function on_connect_event(event:Event):void + private function on_complete_event(event:Event):void { - connected = true; - dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.CONNECT_SUCCESS)); + try { + var client_id:String = event.target.data.client; + if (client_id == "Registration list empty") { + dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY)); + } else { + dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id)); + } + } catch (e:Error) { + /* error is thrown for POST when we don't care about + the response anyways */ + } + + event.target.close() }
- private function on_io_error_event(event:IOErrorEvent):void + private function on_http_status_event(event:HTTPStatusEvent):void { - fail(); + /* empty for now */ }
- private function on_progress_event(event:ProgressEvent):void + private function on_io_error_event(event:IOErrorEvent):void { - var client_id:String = socket.readUTFBytes(event.bytesLoaded); - if (client_id == "Registration list empty") { - dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATIONS_EMPTY)); - } else { - dispatchEvent(new FacilitatorSocketEvent(FacilitatorSocketEvent.REGISTRATION_RECEIVED, client_id)); - } + fail(); }
private function on_security_error_event(event:SecurityErrorEvent):void @@ -110,6 +96,9 @@ package rtmfp fail(); }
- + private function get url():String + { + return "http://" + host + ":" + port; + } } } \ No newline at end of file diff --git a/rtmfpcat.as b/rtmfpcat.as index 713fc45..224fe56 100644 --- a/rtmfpcat.as +++ b/rtmfpcat.as @@ -166,23 +166,11 @@ package
private function establish_facilitator_connection():void { - s_f = new FacilitatorSocket(); - s_f.addEventListener(FacilitatorSocketEvent.CONNECT_SUCCESS, function (e:Event):void { - if (proxy_mode) { - puts("Facilitator: getting registration."); - s_f.get_registration(); - } else { - puts("Facilitator: posting registration."); - s_f.post_registration(s_c.id); - } - }); + s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port); s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void { puts("Facilitator: connect failed."); setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL); }); - s_f.addEventListener(FacilitatorSocketEvent.CONNECT_CLOSED, function (e:Event):void { - puts("Facilitator: connect closed."); - });
if (proxy_mode) { s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void { @@ -194,13 +182,16 @@ package puts("Facilitator: no registrations available."); setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL); }); + puts("Facilitator: getting registration."); + s_f.get_registration(); } else { s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void { puts("Facilitator: registration failed."); setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL); }); + puts("Facilitator: posting registration."); + s_f.post_registration(s_c.id); } - s_f.connect(fac_addr.host, fac_addr.port); }
private function start_proxy_pair():void