2019-03-01 20:41:13 +01:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""!
|
|
|
|
|
____ ____ ______ __ __ __ _____
|
|
|
|
|
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
|
|
|
|
|
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
|
|
|
|
|
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
|
|
|
|
|
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
|
|
|
|
|
German BOS Information Script
|
|
|
|
|
by Bastian Schroll
|
|
|
|
|
|
|
|
|
|
@file: router.py
|
|
|
|
|
@date: 01.03.2019
|
|
|
|
|
@author: Bastian Schroll
|
|
|
|
|
@description: Class for the BOSWatch packet router
|
|
|
|
|
"""
|
2019-03-01 21:36:38 +01:00
|
|
|
# todo think about implement threading for routers and the plugin calls (THREAD SAFETY!!!)
|
2019-03-01 20:41:13 +01:00
|
|
|
import logging
|
|
|
|
|
import copy
|
|
|
|
|
import importlib
|
|
|
|
|
|
|
|
|
|
logging.debug("- %s loaded", __name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _Router:
|
2019-02-26 13:33:35 +01:00
|
|
|
def __init__(self, name):
|
2019-03-01 22:12:29 +01:00
|
|
|
self._name = name
|
|
|
|
|
self._route = []
|
|
|
|
|
logging.debug("[%s] new router", self._name)
|
2019-02-26 13:33:35 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
def addRoute(self, route):
|
2019-03-01 22:12:29 +01:00
|
|
|
logging.debug("[%s] add route: %s", self._name, route)
|
|
|
|
|
self._route.append(route)
|
2019-02-26 13:33:35 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
def runRouter(self, bwPacket):
|
2019-03-01 22:12:29 +01:00
|
|
|
logging.debug("[%s] started", self._name)
|
|
|
|
|
for routeCall in self._route:
|
|
|
|
|
logging.debug("[%s] -> run route: %s", self._name, routeCall)
|
2019-03-01 20:41:13 +01:00
|
|
|
bwPacket_tmp = routeCall(copy.deepcopy(bwPacket)) # copy bwPacket to prevent edit the original
|
2019-02-26 13:33:35 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
if bwPacket_tmp is None: # returning None doesnt change the bwPacket
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if bwPacket_tmp is False: # returning False stops the router immediately
|
2019-03-01 22:12:29 +01:00
|
|
|
logging.debug("[%s] stopped", self._name)
|
2019-03-01 20:41:13 +01:00
|
|
|
break
|
2019-02-26 13:33:35 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
bwPacket = bwPacket_tmp
|
2019-03-01 22:12:29 +01:00
|
|
|
logging.debug("[%s] <- bwPacket returned: %s", self._name, bwPacket)
|
|
|
|
|
logging.debug("[%s] ended", self._name)
|
2019-03-01 20:41:13 +01:00
|
|
|
return bwPacket
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def name(self):
|
2019-03-01 22:12:29 +01:00
|
|
|
return self._name
|
2019-03-01 20:41:13 +01:00
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def route(self):
|
2019-03-01 22:12:29 +01:00
|
|
|
return self._route
|
2019-03-01 20:41:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class RouterManager:
|
|
|
|
|
def __init__(self):
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict = {}
|
2019-03-01 20:41:13 +01:00
|
|
|
|
|
|
|
|
def __del__(self):
|
2019-03-01 22:12:29 +01:00
|
|
|
# destroy all routers (also destroys all instances of modules/plugins)
|
|
|
|
|
del self._routerDict
|
2019-03-01 21:36:38 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
def buildRouter(self, config):
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict = {} # all routers and instances of modules/plugins would be destroyed
|
2019-03-01 20:41:13 +01:00
|
|
|
logging.debug("build routers")
|
|
|
|
|
|
|
|
|
|
# first we have to init all routers
|
|
|
|
|
# because a router can be a valid target and we need his reference
|
|
|
|
|
for router in config.get("router"):
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict[router.get("name")] = _Router(router.get("name"))
|
2019-03-01 21:36:38 +01:00
|
|
|
|
2019-03-01 20:41:13 +01:00
|
|
|
for router in config.get("router"):
|
|
|
|
|
for route in router.get("route"):
|
2019-03-01 21:36:38 +01:00
|
|
|
|
|
|
|
|
routerName = router.get("name")
|
|
|
|
|
routeType = route.get("type")
|
|
|
|
|
routeName = route.get("name")
|
|
|
|
|
|
|
|
|
|
if routeType is None or routeName is None:
|
|
|
|
|
logging.error("type or name error in config: %s", route)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if routeType == "plugin":
|
|
|
|
|
importedFile = importlib.import_module(routeType + "." + routeName)
|
|
|
|
|
loadedClass = importedFile.BoswatchPlugin(route.get("config"))
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict[routerName].addRoute(loadedClass._run)
|
2019-03-01 21:36:38 +01:00
|
|
|
|
|
|
|
|
elif routeType == "module":
|
|
|
|
|
importedFile = importlib.import_module(routeType + "." + routeName)
|
|
|
|
|
loadedClass = importedFile.BoswatchModule(route.get("config"))
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict[routerName].addRoute(loadedClass._run)
|
2019-03-01 21:36:38 +01:00
|
|
|
|
|
|
|
|
elif routeType == "router":
|
2019-03-01 22:12:29 +01:00
|
|
|
self._routerDict[routerName].addRoute(self._routerDict[routeName].runRouter)
|
2019-03-01 21:36:38 +01:00
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
logging.warning("unknown type: %s", routeType)
|
|
|
|
|
|
|
|
|
|
except ModuleNotFoundError:
|
|
|
|
|
logging.error("%s not found: %s", route.get("type"), route.get("name"))
|
2019-03-01 22:12:29 +01:00
|
|
|
|
2019-03-01 21:36:38 +01:00
|
|
|
logging.debug("finished building routers")
|
|
|
|
|
self._showRouterRoute()
|
2019-03-01 20:41:13 +01:00
|
|
|
|
|
|
|
|
def runRouter(self, routerList, bwPacket):
|
2019-03-01 22:12:29 +01:00
|
|
|
if type(routerList) is str: # convert single string name to list
|
|
|
|
|
routerList = [routerList]
|
|
|
|
|
|
|
|
|
|
for routerName in routerList:
|
|
|
|
|
if routerName in self._routerDict:
|
|
|
|
|
self._routerDict[routerName].runRouter(bwPacket)
|
2019-03-01 20:41:13 +01:00
|
|
|
|
2019-03-01 21:36:38 +01:00
|
|
|
def _showRouterRoute(self):
|
2019-03-01 22:12:29 +01:00
|
|
|
for name, router in self._routerDict.items():
|
2019-03-01 20:41:13 +01:00
|
|
|
logging.debug("Route for %s", name)
|
2019-03-01 22:12:29 +01:00
|
|
|
for routePoint in router.route:
|
|
|
|
|
logging.debug(" | %s", routePoint)
|