add info/log connection to router
This commit is contained in:
@ -1,2 +1,3 @@
|
|||||||
pyserial
|
pyserial
|
||||||
ipaddress
|
ipaddress
|
||||||
|
dhcp-leases
|
||||||
|
73
router.py
73
router.py
@ -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())
|
||||||
|
Reference in New Issue
Block a user