-
Notifications
You must be signed in to change notification settings - Fork 5
/
webserver.py
104 lines (79 loc) · 2.72 KB
/
webserver.py
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import os
import sys
import redis
import json
import subprocess
import hashlib
from time import sleep
from bottle import request, template, Bottle, abort, static_file
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketError
from geventwebsocket.handler import WebSocketHandler
app = Bottle()
HOST, PORT = ("0.0.0.0", 80)
NODE_BINARY = 'target/debug/server'
WEBSOCKETS_KEY = 'storycoin-websockets'
@app.route('/')
def noname():
return 'Please go to /yournickname to create a node with your chosen nickname.'
@app.route('/<name>')
def index(name='anon'):
html = 'static/index.html'
print("[HTTP]: %s" % html)
print('request.query')
context = {
'name': name,
}
return template(html, **context)
@app.get('/static/<path:path>')
def static_files(path):
return static_file(path, root='static/')
@app.route('/websocket/<name>')
def handle_websocket(name='anon'):
wsock = request.environ.get('wsgi.websocket')
if not wsock:
abort(400, 'Expected WebSocket request.')
recv_key = 'node-recv'.format(name)
send_key = 'node-send'.format(name)
nodeq = redis.Redis(host='127.0.0.1', port=6379, db=0)
num_sockets = int(nodeq.get(WEBSOCKETS_KEY) or 0)
nodeq.set(WEBSOCKETS_KEY, num_sockets + 1)
nodeq.rpush(send_key, json.dumps({'name': name}))
newpid = os.fork()
if newpid == 0:
send_loop(wsock, nodeq, send_key)
else:
recv_loop(wsock, nodeq, recv_key)
def recv_loop(wsock, nodeq, recv_key):
while True:
try:
recv = wsock.receive()
if recv and recv.strip():
print("[>]: {}".format(recv)[:100])
nodeq.rpush(recv_key, recv)
sleep(0.02)
except WebSocketError:
break
def send_loop(wsock, nodeq, send_key):
last_msg = None
while True:
try:
msg = nodeq.rpop(send_key)
if msg and msg.strip() and msg != last_msg:
print("[<]: {}".format(msg.decode())[:100])
msg_key = hashlib.md5(msg).hexdigest()
num_sends = int(nodeq.get(msg_key) or 0)
num_nodes = int(nodeq.get(WEBSOCKETS_KEY) or 0)
if num_sends < num_nodes:
wsock.send(msg.decode())
nodeq.rpush(send_key, msg)
nodeq.set(msg_key, num_sends + 1)
elif msg and msg == last_msg:
nodeq.rpush(send_key, msg)
last_msg = msg
sleep(0.02)
except WebSocketError:
break
server = WSGIServer((HOST, PORT), app, handler_class=WebSocketHandler)
print("Starting bottle WSGI + Websocket server %s:%s..." % (HOST, PORT))
server.serve_forever()