n2n/scripts/n2nhttpd

119 lines
3.2 KiB
Plaintext
Raw Normal View History

#!/usr/bin/env python3
# Licensed under GPLv3
#
# Simple http server to allow user control of n2n edge nodes
#
# Currently only for demonstration - needs javascript written to render the
# results properly.
#
# Try it out with
# http://localhost:8080/edge/peer
# http://localhost:8080/edge/super
import argparse
import socket
import json
import socketserver
import http.server
from http import HTTPStatus
next_tag = 0
def send_cmd(port, debug, cmd):
"""Send a text command to the edge and process the JSON reply packets"""
global next_tag
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tagstr = str(next_tag)
next_tag = (next_tag + 1) % 1000
message = "{} {}".format(cmd, tagstr).encode('utf8')
sock.sendto(message, ("127.0.0.1", 5644))
# FIXME:
# - there is no timeout for any of the socket handling
begin, _ = sock.recvfrom(1024)
begin = json.loads(begin.decode('utf8'))
assert(begin['_tag'] == tagstr)
assert(begin['_type'] == 'begin')
assert(begin['_cmd'] == cmd)
result = list()
while True:
data, _ = sock.recvfrom(1024)
data = json.loads(data.decode('utf8'))
assert(data['_tag'] == tagstr)
if data['_type'] == 'unknowncmd':
raise ValueError('Unknown command {}'.format(cmd))
if data['_type'] == 'end':
return result
if data['_type'] != 'row':
raise ValueError('Unknown data type {} from '
'edge'.format(data['_type']))
# remove our boring metadata
del data['_tag']
del data['_type']
if debug:
print(data)
result.append(data)
class SimpleHandler(http.server.BaseHTTPRequestHandler):
def log_request(self, code='-', size='-'):
# Dont spam the output
pass
def do_GET(self):
url_tail = self.path
if url_tail.startswith("/edge/"):
tail = url_tail.split('/')
cmd = 'j.' + tail[2]
try:
data = send_cmd(5644, False, cmd)
except ValueError:
self.send_response(HTTPStatus.BAD_REQUEST)
self.end_headers()
self.wfile.write(b'Bad Command')
return
self.send_response(HTTPStatus.OK)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode('utf8'))
def main():
ap = argparse.ArgumentParser(
description='Control the running local n2n edge via http')
# TODO - this needs to pass into the handler object
# ap.add_argument('-t', '--mgmtport', action='store', default=5644,
# help='Management Port (default=5644)')
# ap.add_argument('-d', '--debug', action='store_true',
# help='Also show raw internal data')
ap.add_argument('port', action='store',
default=8080, type=int, nargs='?',
help='Serve requests on TCP port (default 8080)')
args = ap.parse_args()
with socketserver.TCPServer(("", args.port), SimpleHandler) as httpd:
httpd.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
httpd.serve_forever()
if __name__ == '__main__':
main()