#!/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()