128 lines
4.2 KiB
Python
128 lines
4.2 KiB
Python
|
|
# 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()
|