freifunkmanager/tools/respondd-sim.py

78 lines
2.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
#
# Return pre-generated respondd responses (read from a JSON file).
# The JSON file must contain a list of responses (one list entry for each simulated node).
#
import socketserver
import argparse
import socket
import struct
import json
from zlib import compress
def get_handler(inputFile):
class ResponddUDPHandler(socketserver.BaseRequestHandler):
def multi_request(self, providernames, nodeData):
ret = {}
for name in providernames:
if name in nodeData:
ret[name] = nodeData[name]
2019-06-23 03:02:29 +02:00
print("response: %s" % ret)
return compress(str.encode(json.dumps(ret)))[2:-4]
def handle(self):
requestString = self.request[0].decode('UTF-8').strip()
socket = self.request[1]
print("got request: '%s' from '%s'" % (requestString, self.client_address))
if not(requestString.startswith("GET ")):
print("unsupported old-style request")
return
fp = open(inputFile)
testData = json.load(fp)
fp.close()
response = None
for nodeData in testData:
response = self.multi_request(requestString.split(" ")[1:], nodeData)
socket.sendto(response, self.client_address)
return ResponddUDPHandler
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-p', dest='port',
default=1001, type=int, metavar='<port>',
help='port number to listen on (default 1001)')
parser.add_argument('-g', dest='group',
default='ff02::2:1001', metavar='<group>',
help='multicast group (default ff02::2:1001)')
parser.add_argument('-i', dest='mcast_ifaces',
action='append', metavar='<iface>',
help='interface on which the group is joined')
parser.add_argument('-f', dest='input_file',
type=str, metavar='<file>',
required=True,
help='JSON file to read responses from')
args = parser.parse_args()
socketserver.ThreadingUDPServer.address_family = socket.AF_INET6
server = socketserver.ThreadingUDPServer(("", args.port), get_handler(args.input_file))
if args.mcast_ifaces:
group_bin = socket.inet_pton(socket.AF_INET6, args.group)
for (inf_id, inf_name) in socket.if_nameindex():
if inf_name in args.mcast_ifaces:
mreq = group_bin + struct.pack('@I', inf_id)
server.socket.setsockopt(
socket.IPPROTO_IPV6,
socket.IPV6_JOIN_GROUP,
mreq
)
server.serve_forever()