peerlink/example/server.py
2014-08-28 14:52:31 +02:00

140 lines
3.6 KiB
Python
Executable file

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, print_function
import json
import os
import signal
import sys
import mimetypes
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import Application
import tornado
import websocket
from websocket import trigger_event
import state
from tasks import Tasks
from utils import json_dumps
import link
import logging
logger = logging.getLogger('server')
root_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
STATIC_PATH = os.path.join(root_dir, 'static')
class BaseHandler(tornado.web.RequestHandler):
def serve_static(self, path, mimetype=None, include_body=True):
if not mimetype:
mimetype = mimetypes.guess_type(path)[0]
logging.debug('serve %s', path)
if os.path.exists(path):
self.set_header('Content-Type', mimetype)
self.set_header('Content-Length', str(os.stat(path).st_size))
if include_body:
with open(path) as fd:
self.write(fd.read())
else:
self.set_status(404)
return
def render_json(self, response):
response = json_dumps(response)
self.set_header('Content-Type', 'application/json')
self.set_header('Content-Length', str(len(response)))
self.write(response)
self.finish()
class RemoteHandler(BaseHandler):
def post(self, action):
data = json.loads(self.request.body)
response = {}
print ('GOT remote request', action, data)
if action == 'info':
response = state.info
elif action == 'message':
data['from'] = self.request.headers['From']
trigger_event(action, data)
else:
response = {'error': 'unknown action'}
return self.render_json(response)
class MainHandler(BaseHandler):
def get(self, path):
path = path[1:]
if not path:
path = 'index.html'
path = os.path.join(STATIC_PATH, path)
self.serve_static(path)
def post(self, path):
action = path.split('/')[1]
data = json.loads(self.request.body)
response = {}
if action in ('info', 'ping'):
if 'id' in data:
id = data['id']
del data['id']
response = link.remote_json(id, action, data)
return self.render_json(response)
if __name__ == '__main__':
address = ''
port = 8000
if len(sys.argv) > 1:
port = int(sys.argv[1])
link.PEERLINK=sys.argv[2]
logging.basicConfig(level=logging.DEBUG)
options = {
'debug': True,
}
handlers = [
(r'/ws', websocket.Handler),
(r"/remote/(.*)", RemoteHandler),
(r"(.*)", MainHandler),
]
http_server = HTTPServer(Application(handlers, **options))
http_server.listen(port, address)
state.tasks = Tasks()
state.main = IOLoop.instance()
state._status = PeriodicCallback(lambda: state.info.update(link.post('info')), 60000)
state._status.start()
if ':' in address:
host = '[%s]' % address
elif not address:
host = '[::1]'
else:
host = address
url = 'http://%s:%s/' % (host, port)
link.add('chat', url + 'remote/')
state.info = link.post('info')
print('listening at %s' % url)
def shutdown():
state.tasks.join()
http_server.stop()
signal.signal(signal.SIGTERM, shutdown)
try:
state.main.start()
except:
print('shutting down...')
shutdown()