n2n-httpd (n2n-3.0) | : | n2n-httpd (n2n-3.1.1) | ||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
import socket | import socket | |||
import json | import json | |||
import socketserver | import socketserver | |||
import http.server | import http.server | |||
import signal | import signal | |||
import functools | import functools | |||
import base64 | import base64 | |||
from http import HTTPStatus | from http import HTTPStatus | |||
class JsonUDP(): | import os | |||
"""encapsulate communication with the edge""" | import sys | |||
import importlib.machinery | ||||
def __init__(self, port): | import importlib.util | |||
self.address = "127.0.0.1" | ||||
self.port = port | def import_filename(modulename, filename): | |||
self.tag = 0 | # look in the same dir as this script | |||
self.key = None | pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), | |||
self.debug = False | filename) | |||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | loader = importlib.machinery.SourceFileLoader(modulename, pathname) | |||
self.sock.settimeout(1) | spec = importlib.util.spec_from_loader(modulename, loader) | |||
module = importlib.util.module_from_spec(spec) | ||||
def _next_tag(self): | ||||
tagstr = str(self.tag) | try: | |||
self.tag = (self.tag + 1) % 1000 | loader.exec_module(module) | |||
return tagstr | except FileNotFoundError: | |||
print("Script {} not found".format(pathname), file=sys.stderr) | ||||
def _cmdstr(self, msgtype, cmdline): | sys.exit(1) | |||
"""Create the full command string to send""" | return module | |||
tagstr = self._next_tag() | ||||
# We share the implementation of the RPC class with the n2n-ctl script. We | ||||
options = [tagstr] | # cannot just import the module as 'n2n-ctl' has a dash in its name :-( | |||
if self.key is not None: | JsonUDP = import_filename('n2nctl', 'n2n-ctl').JsonUDP | |||
options += ['1'] # Flags set for auth key field | ||||
options += [self.key] | ||||
optionsstr = ':'.join(options) | ||||
return tagstr, ' '.join((msgtype, optionsstr, cmdline)) | ||||
def _rx(self, tagstr): | ||||
"""Wait for rx packets""" | ||||
# TODO: there are no timeouts with any of the recv calls | ||||
data, _ = self.sock.recvfrom(1024) | ||||
data = json.loads(data.decode('utf8')) | ||||
# TODO: We assume the first packet we get will be tagged for us | ||||
# and be either an "error" or a "begin" | ||||
assert(data['_tag'] == tagstr) | ||||
if data['_type'] == 'error': | ||||
raise ValueError('Error: {}'.format(data['error'])) | ||||
assert(data['_type'] == 'begin') | ||||
# Ideally, we would confirm that this is our "begin", but that | ||||
# would need the cmd passed into this method, and that would | ||||
# probably require parsing the cmdline passed to us :-( | ||||
# assert(data['cmd'] == cmd) | ||||
result = list() | ||||
error = None | ||||
while True: | ||||
data, _ = self.sock.recvfrom(1024) | ||||
data = json.loads(data.decode('utf8')) | ||||
if data['_tag'] != tagstr: | ||||
# this packet is not for us, ignore it | ||||
continue | ||||
if data['_type'] == 'error': | ||||
# we still expect an end packet, so save the error | ||||
error = ValueError('Error: {}'.format(data['error'])) | ||||
continue | ||||
if data['_type'] == 'end': | ||||
if error: | ||||
raise error | ||||
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 self.debug: | ||||
print(data) | ||||
result.append(data) | ||||
def _call(self, msgtype, cmdline): | ||||
"""Perform a rpc call""" | ||||
tagstr, msgstr = self._cmdstr(msgtype, cmdline) | ||||
self.sock.sendto(msgstr.encode('utf8'), (self.address, self.port)) | ||||
return self._rx(tagstr) | ||||
def read(self, cmdline): | ||||
return self._call('r', cmdline) | ||||
def write(self, cmdline): | ||||
return self._call('w', cmdline) | ||||
pages = { | pages = { | |||
"/script.js": { | "/script.js": { | |||
"content_type": "text/javascript", | "content_type": "text/javascript", | |||
"content": """ | "content": """ | |||
var verbose=-1; | var verbose=-1; | |||
function rows2verbose(id, unused, data) { | function rows2verbose(id, unused, data) { | |||
row0 = data[0] | row0 = data[0] | |||
verbose = row0['traceLevel'] | verbose = row0['traceLevel'] | |||
End of changes. 1 change blocks. | ||||
95 lines changed or deleted | 23 lines changed or added |