add info/log connection to router

This commit is contained in:
2023-08-07 11:27:19 +02:00
parent 22b4fdb521
commit 9a782cb283
2 changed files with 66 additions and 8 deletions

View File

@ -1,2 +1,3 @@
pyserial pyserial
ipaddress ipaddress
dhcp-leases

View File

@ -18,6 +18,7 @@ iptables -A INPUT -i lo -j ACCEPT
sim = False sim = False
def unix_cmd(command): def unix_cmd(command):
if sim: if sim:
print('> %r' % command) print('> %r' % command)
@ -29,10 +30,15 @@ def unix_cmd(command):
class IoHandler: class IoHandler:
client = None client = None
handler = None handler = None
port = None
def __init__(self, client, handler): def __init__(self, client, handler):
self.handler = handler self.handler = handler
self.client = client self.client = client
self.sentchunks = 0
self.sentbytes = 0
self.rcvdchunks = 0
self.rcvdbytes = 0
def request(self): def request(self):
try: try:
@ -40,6 +46,8 @@ class IoHandler:
if data: if data:
# print('<', data) # print('<', data)
self.write(data) self.write(data)
self.sentbytes += len(data)
self.sentchunks += 1
return return
except Exception as e: except Exception as e:
print('ERROR in request: %s' % e) print('ERROR in request: %s' % e)
@ -51,6 +59,8 @@ class IoHandler:
data = self.read() data = self.read()
# print('>', data) # print('>', data)
self.client.sendall(data) self.client.sendall(data)
self.rcvdbytes += len(data)
self.rcvdchunks += 1
return return
except ConnectionResetError: except ConnectionResetError:
pass pass
@ -99,6 +109,44 @@ class SerialHandler(IoHandler):
self.serial.close() self.serial.close()
class InfoHandler(IoHandler):
clients = {}
def __init__(self, client, handler):
super().__init__(client, handler)
info = [f'{k} -> {v}' for k, v in AcceptHandler.routes.items()]
if AcceptHandler.handlers:
info.append('\nactive routings, statistics bytes/chunks')
info.append('fno port sent received')
for fno, h in AcceptHandler.handlers.items():
info.append(f'{fno} {h.port} {h.sentbytes:d}/{h.sentchunks:d} {h.rcvdbytes:d}/{h.rcvdchunks:d}')
info.append('')
self.client.sendall('\n'.join(info).encode('utf-8'))
self.clients[client.fileno()] = self
self.fno = None
def read(self):
return b''
def write(self, data):
pass
def close(self):
self.clients.pop(self.client.fileno())
@classmethod
def log(cls, line):
if cls.clients:
for c in cls.clients.values():
try:
c.client.sendall(line.encode('utf-8'))
c.client.sendall(b'\n')
except TimeoutError:
pass
else:
print(line)
class AcceptHandler: class AcceptHandler:
"""handler for routing """handler for routing
@ -112,6 +160,8 @@ class AcceptHandler:
reused: in this case maxcount has to be increased ... reused: in this case maxcount has to be increased ...
""" """
readers = {} readers = {}
handlers = {}
routes = {}
def __init__(self, port, addr, iocls, maxcount=1): def __init__(self, port, addr, iocls, maxcount=1):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -125,16 +175,18 @@ class AcceptHandler:
self.port = port self.port = port
self.available = maxcount self.available = maxcount
self.pending = 0 self.pending = 0
print('listening at port %d for %s(%r)' % (port, iocls.__name__, addr) )
def close_client(self, iohandler): def close_client(self, iohandler):
self.readers.pop(iohandler.fno, None) self.readers.pop(iohandler.fno, None)
client = iohandler.client
fno = client.fileno()
try: try:
client = iohandler.client self.readers.pop(fno)
self.readers.pop(client.fileno())
client.close() client.close()
InfoHandler.log(f'closed connection from port {self.port} fno {fno}')
except Exception as e: except Exception as e:
print('ERROR in close_client: %s' % e) InfoHandler.log(f'{e!r} in close_client')
self.handlers.pop(fno, None)
iohandler.client = None iohandler.client = None
iohandler.fno = None iohandler.fno = None
self.available += 1 self.available += 1
@ -148,18 +200,23 @@ class AcceptHandler:
return return
try: try:
client, addr = self.socket.accept() client, addr = self.socket.accept()
print('accepted', addr, 'on', self.port) InfoHandler.log(f'accepted {addr} on {self.port} fno {client.fileno()}')
handler = self.iocls(client, self) handler = self.iocls(client, self)
except Exception as e: except Exception as e:
print('ERROR creating %s(%r)' % (self.iocls.__name__, self.addr)) InfoHandler.log(f'{e!r} creating {self.iocls.__name__}({self.addr})')
client.close() client.close()
return return
self.readers[client.fileno()] = handler.request self.readers[client.fileno()] = handler.request
self.readers[handler.fno] = handler.reply if handler.fno is not None:
self.readers[handler.fno] = handler.reply
# statistics: number of chunks sent / received
handler.port = self.port
self.handlers[client.fileno()] = handler
self.available -= 1 self.available -= 1
@classmethod @classmethod
def run(cls, routes, restrict=None): def run(cls, routes, restrict=None):
cls.routes = dict(routes)
if restrict is not None: if restrict is not None:
lines = BASIC % dict(accept='DROP' if restrict else 'ACCEPT') lines = BASIC % dict(accept='DROP' if restrict else 'ACCEPT')
unix_cmd('iptables -F') unix_cmd('iptables -F')
@ -169,6 +226,7 @@ class AcceptHandler:
if restrict: if restrict:
unix_cmd(FILTER % 22) unix_cmd(FILTER % 22)
AcceptHandler(1111, None, InfoHandler, 5)
for port, dest in routes.items(): for port, dest in routes.items():
port=int(port) port=int(port)
if restrict: if restrict:
@ -196,7 +254,6 @@ class AcceptHandler:
cls.readers[fno]() cls.readers[fno]()
if __name__ == '__main__': if __name__ == '__main__':
parser = ConfigParser() parser = ConfigParser()
cfgfiles = glob('/root/aputools/servercfg/%s_*.cfg' % socket.gethostname()) cfgfiles = glob('/root/aputools/servercfg/%s_*.cfg' % socket.gethostname())