Add python-eventlet 0.16.1
[packages/trusty/python-eventlet.git] / eventlet / examples / distributed_websocket_chat.py
diff --git a/eventlet/examples/distributed_websocket_chat.py b/eventlet/examples/distributed_websocket_chat.py
new file mode 100644 (file)
index 0000000..526f3ab
--- /dev/null
@@ -0,0 +1,132 @@
+"""This is a websocket chat example with many servers. A client can connect to
+any of the servers and their messages will be received by all clients connected
+to any of the servers.
+
+Run the examples like this:
+
+$ python examples/chat_bridge.py tcp://127.0.0.1:12345 tcp://127.0.0.1:12346
+
+and the servers like this (changing the port for each one obviously):
+
+$ python examples/distributed_websocket_chat.py -p tcp://127.0.0.1:12345 -s tcp://127.0.0.1:12346 7000
+
+So all messages are published to port 12345 and the device forwards all the
+messages to 12346 where they are subscribed to
+"""
+import os
+import sys
+import eventlet
+from collections import defaultdict
+from eventlet import spawn_n, sleep
+from eventlet import wsgi
+from eventlet import websocket
+from eventlet.green import zmq
+from eventlet.hubs import get_hub, use_hub
+from uuid import uuid1
+
+use_hub('zeromq')
+ctx = zmq.Context()
+
+
+class IDName(object):
+
+    def __init__(self):
+        self.id = uuid1()
+        self.name = None
+
+    def __str__(self):
+        if self.name:
+            return self.name
+        else:
+            return str(self.id)
+
+    def pack_message(self, msg):
+        return self, msg
+
+    def unpack_message(self, msg):
+        sender, message = msg
+        sender_name = 'you said' if sender.id == self.id \
+            else '%s says' % sender
+        return "%s: %s" % (sender_name, message)
+
+
+participants = defaultdict(IDName)
+
+
+def subscribe_and_distribute(sub_socket):
+    global participants
+    while True:
+        msg = sub_socket.recv_pyobj()
+        for ws, name_id in participants.items():
+            to_send = name_id.unpack_message(msg)
+            if to_send:
+                try:
+                    ws.send(to_send)
+                except:
+                    del participants[ws]
+
+
+@websocket.WebSocketWSGI
+def handle(ws):
+    global pub_socket
+    name_id = participants[ws]
+    ws.send("Connected as %s, change name with 'name: new_name'" % name_id)
+    try:
+        while True:
+            m = ws.wait()
+            if m is None:
+                break
+            if m.startswith('name:'):
+                old_name = str(name_id)
+                new_name = m.split(':', 1)[1].strip()
+                name_id.name = new_name
+                m = 'Changed name from %s' % old_name
+            pub_socket.send_pyobj(name_id.pack_message(m))
+            sleep()
+    finally:
+        del participants[ws]
+
+
+def dispatch(environ, start_response):
+    """Resolves to the web page or the websocket depending on the path."""
+    global port
+    if environ['PATH_INFO'] == '/chat':
+        return handle(environ, start_response)
+    else:
+        start_response('200 OK', [('content-type', 'text/html')])
+        return [open(os.path.join(
+                     os.path.dirname(__file__),
+                     'websocket_chat.html')).read() % dict(port=port)]
+
+port = None
+
+if __name__ == "__main__":
+    usage = 'usage: websocket_chat -p pub address -s sub address port number'
+    if len(sys.argv) != 6:
+        print(usage)
+        sys.exit(1)
+
+    pub_addr = sys.argv[2]
+    sub_addr = sys.argv[4]
+    try:
+        port = int(sys.argv[5])
+    except ValueError:
+        print("Error port supplied couldn't be converted to int\n", usage)
+        sys.exit(1)
+
+    try:
+        pub_socket = ctx.socket(zmq.PUB)
+        pub_socket.connect(pub_addr)
+        print("Publishing to %s" % pub_addr)
+        sub_socket = ctx.socket(zmq.SUB)
+        sub_socket.connect(sub_addr)
+        sub_socket.setsockopt(zmq.SUBSCRIBE, "")
+        print("Subscribing to %s" % sub_addr)
+    except:
+        print("Couldn't create sockets\n", usage)
+        sys.exit(1)
+
+    spawn_n(subscribe_and_distribute, sub_socket)
+    listener = eventlet.listen(('127.0.0.1', port))
+    print("\nVisit http://localhost:%s/ in your websocket-capable browser.\n" % port)
+    wsgi.server(listener, dispatch)