From d5ee60abf8def19164072d32446b887045c2d737 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 25 Jan 2018 19:13:32 -0500 Subject: [PATCH] http.py --- op25/gr-op25_repeater/apps/http.py | 127 +++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 op25/gr-op25_repeater/apps/http.py diff --git a/op25/gr-op25_repeater/apps/http.py b/op25/gr-op25_repeater/apps/http.py new file mode 100644 index 0000000..afce204 --- /dev/null +++ b/op25/gr-op25_repeater/apps/http.py @@ -0,0 +1,127 @@ + +# Copyright 2017, 2018 Max H. Parke KA1RBI +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. + +import sys +import os +import time +import re +import json +import socket +import traceback + +from gnuradio import gr +from waitress.server import create_server + +my_input_q = None +my_output_q = None +my_port = None + +""" +fake http and ajax server module +TODO: make less fake +""" + +def static_file(environ, start_response): + content_types = { 'png': 'image/png', 'jpeg': 'image/jpeg', 'jpg': 'image/jpeg', 'gif': 'image/gif', 'css': 'text/css', 'js': 'application/javascript', 'html': 'text/html'} + img_types = 'png jpg jpeg gif'.split() + if environ['PATH_INFO'] == '/': + filename = 'index.html' + else: + filename = re.sub(r'[^a-zA-Z0-9_.\-]', '', environ['PATH_INFO']) + suf = filename.split('.')[-1] + pathname = '../www/www-static' + if suf in img_types: + pathname = '../www/images' + pathname = '%s/%s' % (pathname, filename) + if suf not in content_types.keys() or '..' in filename or not os.access(pathname, os.R_OK): + sys.stderr.write('404 %s\n' % pathname) + status = '404 NOT FOUND' + content_type = 'text/plain' + output = status + else: + output = open(pathname).read() + content_type = content_types[suf] + status = '200 OK' + return status, content_type, output + +def post_req(environ, start_response, postdata): + global my_input_q, my_output_q, my_port + try: + data = json.loads(postdata) + msg = gr.message().make_from_string(str(data['command']), -2, data['data'], 0) + my_output_q.insert_tail(msg) + time.sleep(0.2) + except: + sys.stderr.write('post_req: error processing input: %s:\n' % (postdata)) + traceback.print_exc(limit=None, file=sys.stderr) + sys.stderr.write('*** end traceback ***\n') + + resp_msg = [] + while not my_input_q.empty_p(): + msg = my_input_q.delete_head() + if msg.type() == -4: + resp_msg.append(json.loads(msg.to_string())) + status = '200 OK' + content_type = 'application/json' + output = json.dumps(resp_msg) + return status, content_type, output + +def http_request(environ, start_response): + if environ['REQUEST_METHOD'] == 'GET': + status, content_type, output = static_file(environ, start_response) + elif environ['REQUEST_METHOD'] == 'POST': + postdata = environ['wsgi.input'].read() + status, content_type, output = post_req(environ, start_response, postdata) + else: + status = '200 OK' + content_type = 'text/plain' + output = status + sys.stderr.write('http_request: unexpected input %s\n' % environ['PATH_INFO']) + + response_headers = [('Content-type', content_type), + ('Content-Length', str(len(output)))] + start_response(status, response_headers) + + return [output] + +def application(environ, start_response): + failed = False + try: + result = http_request(environ, start_response) + except: + failed = True + sys.stderr.write('application: request failed:\n%s\n' % traceback.format_exc()) + sys.exit(1) + return result + +class http_server(object): + def __init__(self, input_q, output_q, endpoint, **kwds): + global my_input_q, my_output_q, my_port + host, port = endpoint.split(':') + if my_port is not None: + raise AssertionError('this server is already active on port %s' % my_port) + my_input_q = input_q + my_output_q = output_q + my_port = int(port) + + self.server = create_server(application, host=host, port=my_port) + + def run(self): + self.server.run()