dark theme

aMSN2's web frontend

aMSN2 is designed to offer multiple frontends so that it should be able to run on whatever you like. One such frontend is the web frontend.

The primary is not to provide you a website where you'd go and connect to MSN. Instead we want to let you host aMSN2 and run it in your web browser.

It was first designed using a webserver with php. It was working but I thought we could use directly python instead of php and embed directly a small webserver in amsn2-web.

aMSN2's design

Here is how I want to implement it, just like every other frontend:

papyon ↔ amsn2 ↔ the frontend

aMSN2 has an event loop to deal with events from papyon or the frontend. This works nicely for most of the frontends.

But the web is different.

Here is how it was working:

There are some issues here. Having to check every X ms to know if there is something to do isn't great. We have an event loop, let's use it!!

Cherrypy

First, aMSN2 should include directly the webserver and add it to it's event loop so that when the web frontend wants something, it can reply to it right away. I've tried to do that with cherrypy.

I tell my browser to go to http://127.0.0.1:8080/static/amsn2.html. After few seconds, I see in the logs that cherrypy got the query.

It's a static file. It should handle it easily. But I wait and wait again and nothing happens. When I send SIGINT (Ctrl+c) to aMSN2, then the page load correctly!! Even in its own thread, cherrypy is blocking on something.

Here is the code I use to do that:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Root(object):
    def __init__(self, inq, outq):
        self._inq  = inq
        self._outq = outq

    @cherrypy.expose
    def index(self):
        raise cherrypy.HTTPRedirect("static/amsn2.html")

    @cherrypy.expose
    def signin(self, u=None, p=None):
        self._inq.put_nowait(["signin", u, p])

    @cherrypy.expose
    def out(self):
        l = []
        while True:
            try:
                l.append(self._outq.get_nowait())
            except Queue.Empty:
                break;
        return l

current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'log.error_file': 'amsn2-web-error.log',
                       'log.access_file': 'amsn2-web-access.log',
                       'log.screen': False})

conf = {'/static': {'tools.staticdir.on': True,
        'tools.staticdir.dir': os.path.join(current_dir, 'static')},
       }
cherrypy.quickstart(Root(inq, outq), '/', config=conf)

How I want to handle that issue.

aMSN2 should listen to 127.0.0.1:8080 (or whatever you want). When something happens, it should have a tiny HTTP machine to process the query and act just like the web frontend was like every other frontend. Then we should use “long push”. jQuery sends a query to now what's new. aMSN2's doesn't answer yet but once there is something to tell the frontend, it replies. The browser updates whatever needed based on the answer and send right away a new query to know what's new.

If you want to help me with that, feel free to contact me.