add jsonrpc service and test
[multitaskhttpd.git] / httpd.py
index e85058e6764183d75d904388313412920f08c6f3..6537ee0e6071358815a45bd18765dd269ff50155 100644 (file)
--- a/httpd.py
+++ b/httpd.py
@@ -71,7 +71,11 @@ from cStringIO import StringIO
 from cookielib import parse_ns_headers, CookieJar
 from Cookie import SimpleCookie
 
+global _debug
 _debug = False
+def set_debug(dbg):
+    global _debug
+    _debug = dbg
 
 class MultitaskHTTPRequestHandler(BaseHTTPRequestHandler):
 
@@ -107,13 +111,7 @@ class SockStream(object):
         self.bytesWritten = self.bytesRead = 0
     
     def close(self):
-        print "sock close"
-        fno = self.sock.fileno()
-        self.sock.close()
-        print "writable?", self.sock, fno
-        yield multitask.writable(fno, timeout=0.1)
-        print "is it?"
-        del self.sock
+        self.sock.shutdown(1) # can't just close it.
         self.sock = None
         
     def readline(self):
@@ -261,7 +259,7 @@ class Protocol(object):
     
     def parseRequests(self):
         '''Parses complete messages until connection closed. Raises ConnectionLost exception.'''
-        self.hr = MultitaskHTTPRequestHandler(self.stream, ("",0,), self.remote)
+        self.hr = MultitaskHTTPRequestHandler(self.stream, self.remote, None)
         self.hr.close_connection = 1
         self.cookies = CookieJar()
 
@@ -494,6 +492,21 @@ class Client(Protocol):
             msg.response_cookies['session']['path'] = '/'
             msg.response_cookies['session']['domain'] = self.remote[0]
             msg.response_cookies['session']['version'] = 0
+
+        if msg.headers.has_key('content-length'):
+            max_chunk_size = 10*1024*1024
+            size_remaining = int(msg.headers["content-length"])
+            L = []
+            while size_remaining:
+                chunk_size = min(size_remaining, max_chunk_size)
+                data = (yield self.stream.read(chunk_size))
+                L.append(data)
+                size_remaining -= len(L[-1])
+
+            pos = msg.rfile.tell()
+            msg.rfile.write(''.join(L))
+            msg.rfile.seek(pos)
+
         yield self.server.queue.put((self, msg)) # new connection
 
     def accept(self):
@@ -567,7 +580,7 @@ class Server(object):
             yield self.queue.put((None, None))
             self.queue = None
 
-class App(SimpleAppHTTPRequestHandler):
+class BaseApp(object):
     '''An application instance containing any number of streams. Except for constructor all methods are generators.'''
     count = 0
     def __init__(self):
@@ -580,13 +593,11 @@ class App(SimpleAppHTTPRequestHandler):
     def clients(self):
         '''everytime this property is accessed it returns a new list of clients connected to this instance.'''
         return self._clients[1:] if self._clients is not None else []
-    def onConnect(self, client, *args):
-        if _debug: print self.name, 'onConnect', client.path
-        return True
-    def onDisconnect(self, client):
-        if _debug: print self.name, 'onDisconnect', client.path
     
-class HttpServer(object):
+class App(BaseApp, SimpleAppHTTPRequestHandler):
+    pass
+    
+class HTTPServer(object):
     '''A RTMP server to record and stream Flash video.'''
     def __init__(self):
         '''Construct a new HttpServer. It initializes the local members.'''
@@ -622,7 +633,7 @@ class HttpServer(object):
                 # TODO: we should reject non-localhost client connections.
                 if not client:                # if the server aborted abnormally,
                     break                     #    hence close the listener.
-                if _debug: print 'client connection received', client, args
+                if _debug: print 'client connection received', client, msg
                 # if client.objectEncoding != 0 and client.objectEncoding != 3:
                 if client.objectEncoding != 0:
                     yield client.rejectConnection(reason='Unsupported encoding ' + str(client.objectEncoding) + '. Please use NetConnection.defaultObjectEncoding=ObjectEncoding.AMF0')
@@ -630,18 +641,23 @@ class HttpServer(object):
                 else:
                     print "cookies", str(msg.response_cookies)
                     session = msg.response_cookies['session'].value
-                    name, ignore, scope = msg.path.partition('/')
+                    name = msg.path
+                    print "serverlistener", name
                     if '*' not in self.apps and name not in self.apps:
                         yield client.rejectConnection(reason='Application not found: ' + name)
                     else: # create application instance as needed and add in our list
                         if _debug: print 'name=', name, 'name in apps', str(name in self.apps)
                         app = self.apps[name] if name in self.apps else self.apps['*'] # application class
                         print "clients", self.clients.keys()
-                        if session in self.clients: inst = self.clients[session][0]
-                        else: inst = app()
+                        if session in self.clients:
+                            inst = self.clients[session][0]
+                        else:
+                            inst = app()
+                        msg.server = inst # whew! just in time!
                         try: 
                             methodname = "on%s" % msg.command
-                            method =  getattr(inst, methodname, None)
+                            print methodname, dir(inst)
+                            method = getattr(inst, methodname, None)
                             result = method(client, msg)
                             close_connection = msg.close_connection
                             print "close connection", close_connection
@@ -846,7 +862,7 @@ if __name__ == '__main__':
     _debug = options.verbose
     try:
         if _debug: print time.asctime(), 'Options - %s:%d' % (options.host, options.port)
-        agent = HttpServer()
+        agent = HTTPServer()
         agent.root = options.root
         agent.start(options.host, options.port)
         if _debug: print time.asctime(), 'Flash Server Starts - %s:%d' % (options.host, options.port)