irciot_router.py
'''
'' PyIRCIoT-router (PyIRCIoT_router class)
''
'' Copyright (c) 2019-2021 Alexey Y. Woronov
''
'' By using this file, you agree to the terms and conditions set
'' forth in the LICENSE file which can be found at the top level
'' of this package
''
'' Authors:
'' Alexey Y. Woronov <alexey@woronov.ru>
'''
# Those Global options override default behavior and memory usage
#
CAN_debug_library = False
try: # insecure, but for development
from irciot import PyLayerIRCIoT
except:
from PyIRCIoT.irciot import PyLayerIRCIoT
from copy import deepcopy
from time import sleep
from time import time
import threading
import random
try:
import json
except:
import simplejson as json
class PyIRCIoT_router( PyLayerIRCIoT ):
class CONST( PyLayerIRCIoT.CONST ):
#
irciot_router_protocol_version = '0.3.33'
#
irciot_router_library_version = '0.0.229'
#
default_maximal_detect_dup_messages = 128
#
default_maximal_connection_tracking = 8192 # items
default_timeout_connection_tracking = 3600 # seconds
#
maximal_LMR_count = 256
maximal_GMR_count = 16
#
dir_in = 'i' # input traffic direction
dir_out = 'o' # output traffic direction
dir_both = 'b' # input and output directions
#
dir_any = [ dir_in, dir_out, dir_both ]
#
rgn_REQUEST_PARAMS = 'irciot_req_rgn_prm'
#
tag_IN_SCOPE = 'iscp'
tag_OUT_SCOPE = 'oscp'
tag_LMR_ID = 'lmri'
tag_GMR_ID = 'gmri'
tag_LMR_ver = 'ver'
tag_GMR_ver = 'ver'
#
err_ROUTER_DUP_DETECT = 10015
err_MISSING_PARAMETER = 10505
err_INVALID_PARAMETER = 10507
err_INVALID_DIRECTION = 10508
#
err_LMR_INCORRECT_VER = 10601
err_LMR_INVALID_PARAM = 10602
err_LMR_AUTHENTICATION = 10604
err_LMR_COMPATIBILITY = 10605
err_LMR_MAX_INSTANCES = 10607
err_LMR_INVALID_ID = 10608
err_LMR_LOOP_DETECTED = 10611
#
err_GMR_INCORRECT_VER = 10701
err_GMR_INVALID_PARAM = 10702
err_GMR_BAD_INTERACTOR = 10703
err_GMR_AUTHENTICATION = 10704
err_GMR_COMPATIBILITY = 10705
err_GMR_MAX_INSTANCES = 10707
err_GMR_INVALID_ID = 10708
err_GMR_LOOP_DETECTED = 10711
err_GMR_INVALID_ORIGIN = 10712
err_GMR_INVALID_PATH = 10713
err_GMR_INVALID_ATTR = 10714
#
err_DESCRIPTIONS = PyLayerIRCIoT.CONST.err_DESCRIPTIONS
err_DESCRIPTIONS.update({
err_ROUTER_DUP_DETECT: "Router detected a duplicate while forwarding the message",
err_MISSING_PARAMETER: "Missing required parameter for routing graph node",
err_INVALID_PARAMETER: "Invalid required parameter for routing graph node",
err_INVALID_DIRECTION: "Invalid direction parameter for routing graph node",
err_LMR_INVALID_ID: "Invalid LMR instance identificator",
err_LMR_INCORRECT_VER: "Incorrect protocol version for LMR intercommunication",
err_LMR_MAX_INSTANCES: "Cannot create LMR, maximum number of instances reached",
err_GMR_INVALID_ID: "Invalid GMR instance identificator",
err_GMR_INCORRECT_VER: "Incorrect protocol version for GMR intercommunication",
err_GMR_MAX_INSTANCES: "Cannot create GMR, maximum number of instances reached"
})
#
default_LMR_id = 1000
default_GMR_id = 5000
#
# permanent delay between iterations (in seconds):
default_LMR_latency = 0.1
default_GMR_latency = 0.5
# allowed values of latency:
min_LMR_latency = 0.01
max_LMR_latency = 3
min_GMR_latency = 0.3
max_GMR_latency = 30
# protocol speceific delays:
min_LMR_announce_interval = max_LMR_latency
max_LMR_announce_interval = 600
min_GMR_connect_try_interval = max_GMR_latency
max_GMR_connect_try_interval = 3600
default_LMR_announce_interval = 10
default_GMR_connect_try_interval = 60
#
intag_LMR_status = 'status'
intag_LMR_announce = 'announce'
#
intag_GMR_status = 'status'
intag_GMR_conn_try = 'conntry'
intag_GMR_conn_ok = 'connok'
intag_GMR_vuid = 'vuid'
#
state_LMR_stopped = 0
state_LMR_running = 1
state_LMR_paused = 3
#
state_GMR_stopped = 0
state_GMR_connecting = 1
state_GMR_connected = 2
state_GMR_paused = 3
state_GMR_stalled = 5
#
ot_LMR_INFO = 'lmrnfo'
ot_LMR_REQUEST = 'lmrreq'
ot_LMR_ACK = 'lmrack'
ot_LMR_UPDATE = 'lmrupd'
ot_LMR_ADVERT = 'lmradv'
#
ot_GMR_INFO = 'gmrnfo'
ot_GMR_UPDATE = 'gmrupd'
ot_GMR_CONNECT = 'gmrcon'
#
# End of PyIRCIoT_router.CONST()
def __init__(self):
#
self.input_plugin = None
# This is an object that defines routing and prefiltering
# of input messages at an external level outside of this
# IRC-IoT router class
#
self.input_routes = [ ( "*", "*" ) ]
# This is list of tuples each of which contains an source and
# destination IRC-IoT address or mask in the input messages
#
self.router_graphs = [ ( self.do_router_forwarding_, {} ) ]
# This is list of tuples each of which contains an function
# and it's required parameters. Each function sequentially
# performed on the message flow and must have a same inbound
# and outbound interface. If another list is used as a list
# item, then the first item of a nested list may contain a
# special tuple with a function that defining the conditions
# to perform the list, the remaining items in such a list are
# used to process IRC-IoT messages
#
self.output_routes = [ ( "*", "*" ) ]
# This is list of tuples each of which contains an source and
# destination IRC-IoT address or mask in the output messages
#
self.output_plugin = None
# This is an object that defines routing and postfiltering
# of output messages at an external level outside of this
# IRC-IoT router class
#
self.__connections_tracking = {}
#
self.__dup_detection_pipeline = []
#
self.__LMR_table = {}
#
self.__GMR_table = {}
#
super(PyIRCIoT_router, self).__init__()
#
self.maximal_detect_dup_messages \
= self.CONST.default_maximal_detect_dup_messages
#
self.maximal_connection_tracking \
= self.CONST.default_maximal_connection_tracking
self.timeout_connection_tracking \
= self.CONST.default_timeout_connection_tracking
#
self.irciot_crc16_init_()
#
if self.CONST.irciot_router_protocol_version \
!= self.CONST.irciot_protocol_version:
self.irciot_error_(self.CONST.err_PROTO_VER_MISMATCH, 0)
if self.CONST.irciot_router_library_version \
!= self.CONST.irciot_library_version:
self.irciot_error_(self.CONST.err_LIB_VER_MISMATCH, 0)
raise ValueError(self.CONST.irciot_library_version, \
self.CONST.irciot_router_library_version)
#
self.__encoding = self.CONST.irciot_default_encoding
#
self.errors = self.CONST.err_DESCRIPTIONS
#
self.irciot_set_locale_(self.lang)
#
self.__LMR_pool = {}
self.__GMR_pool = {}
#
self.__LMR_task = None
self.__GMR_task = None
#
self.__LMR_run = False
self.__GMR_run = False
#
self.__LMR_latency = self.CONST.default_LMR_latency
self.__GMR_latency = self.CONST.default_GMR_latency
#
self.__LMR_announce_interval \
= self.CONST.default_LMR_announce_interval
#
self.__GMR_connect_try_interval \
= self.CONST.default_GMR_connect_try_interval
#
self.__primary_irciot_address = ""
#
# End of PyIRCIoT_router.__init__()
def __del__(self):
if self.__LMR_run: self.__stop_LMR_()
if self.__GMR_run: self.__stop_GMR_()
def router_pointer (self, in_compatibility, in_messages_pack):
# Warning: interface may be changed while developing
return False
def __start_LMR_(self):
if self.__LMR_run: return
if self.__LMR_task != None: return
self.__LMR_task = threading.Thread(target = self.__local_message_router_)
self.__LMR_run = True
self.__LMR_task.start()
def __start_GMR_(self):
if self.__GMR_run: return
if self.__GMR_task != None: return
self.__GMR_task = threading.Thread(target = self.__global_message_router_)
self.__GMR_run = True
self.__GMR_task.start()
def __stop_LMR_(self):
self.__LMR_run = False
if self.__LMR_task != None:
sleep(self.__LMR_latecny)
try:
self.__LMR_task.join()
except:
pass
self.__LMR_task = None
def __stop_GMR_(self):
self.__GMR_run = False
if self.__GMR_task != None:
sleep(self.__GMR_latency)
try:
self.__GMR_task.join()
except:
pass
self.__GMR_task = None
def irciot_set_locale_(self, in_lang):
if not isinstance(in_lang, str):
return
self.lang = in_lang
my_desc = {}
try:
from PyIRCIoT.irciot_errors \
import irciot_get_common_error_descriptions_
my_desc = irciot_get_common_error_descriptions_(in_lang)
my_dsec = self.validate_descriptions_(my_desc)
if my_desc != {}:
self.errors.update(my_desc)
except:
pass
my_desc = {}
try:
from PyIRCIoT.irciot_errors \
import irciot_get_router_error_descriptions_
my_desc = irciot_get_router_error_descriptions_(in_lang)
my_desc = self.validate_descriptions_(my_desc)
if my_desc != {}:
self.errors.update(my_desc)
except:
pass
def irciot_get_LMR_latency_(self):
return self.__LMR_latency
def iricot_get_GMR_latency_(self):
return self.__GMR_latency
def irciot_set_LMR_latency_(self, in_latency):
if type(in_latency) not in [ int, float ]: return False
if in_latecny < self.CONST.min_LMR_latency \
or in_latency > self.CONST.max_LMR_latency: return False
self.__LMR_latency = in_latency
return True
def irciot_set_GMR_latency_(self, in_latency):
if type(in_latency) not in [ int, float ]: return False
if in_latency < self.CONST.min_GMR_latency \
or in_latency > self.CONST.max_GMR_latency: return False
self.__GMR_latency = in_latency
return True
def irciot_get_LMR_announce_interval_(self):
return self.__LMR_announce_interval
def irciot_set_LMR_announce_interval_(self, in_delay):
if type(in_delay) not in [ int, float ]: return False
if in_delay < self.CONST.min_LMR_announce_interval \
or in_delay > self.CONST.max_LMR_announce_interval:
return False
self.__LMR_announce_interval = in_delay
return True
def irciot_get_GMR_connect_try_interval_(self):
return self.__GMR_connect_try_interval
def irciot_set_GMR_connect_try_interval_(self, in_delay):
if type(in_delay) not in [ int, float ]: return False
if in_delay < self.CONST.min_GMR_connect_try_interval \
or in_delay > self.CONST.max_GMR_connect_try_interval:
return False
self.__GMR_connect_try_interval = in_delay
return True
def router_error_(self, in_error_code, in_addon = None):
# Warning: interface may be changed while developing
return
def is_router_route_(self, in_route):
try:
( left_addr, right_addr ) = in_route
except:
return False
if not isinstance(left_addr, str):
return False
if not isinstance(right_addr, str):
return False
return True
def is_router_routes_(self, in_routes):
if not isinstance(in_routes, list):
return False
for my_route in in_routes:
if not self.is_router_route_(my_route):
return False
return True
def is_router_graph_(self, in_graph):
try:
( my_func, my_params ) = in_graph
except:
return False
if not isinstance(my_func, object):
return False
if not isinstance(my_params, dict):
return False
return True
def is_router_graphs_(self, in_graphs):
if not isinstance(in_graphs, list):
return False
for my_item in in_graphs:
if isinstance(my_item, list):
if not self.is_router_graphs_(my_item):
return False
else:
if not self.is_router_graph_(my_item):
return False
return True
def do_router_graph_(self, in_datum, in_graph, \
in_direction, in_vuid = None):
if not isinstance(in_datum, dict):
return None
if not self.is_router_graph_(in_graph):
return None
if not self.is_irciot_datum_(in_datum, None, None, None):
return None
( my_function_, my_params ) = in_graph
my_keys = my_function_( None, self.CONST.rgn_REQUEST_PARAMS, None )
for my_key in my_keys:
if not my_key in my_params.keys():
self.irciot_error_(self.CONST.err_MISSING_PARAMETER, 0, \
in_addon = my_key)
return None
return my_function_( in_datum, my_params, in_direction, in_vuid )
def do_router_route_(self, in_datum, in_route, in_vuid = None):
if not isinstance(in_datum, dict):
return None
if not isinstance(in_route, tuple):
return None
if not self.is_irciot_datum_(in_datum, None, None, None):
return None
return in_datum
def do_router_graphs_(self, in_datum, in_graphs, \
in_direction, in_vuid = None):
if not isinstance(in_datum, dict):
return None
if not isinstance(in_graphs, list):
return None
my_datum = in_datum
for my_index, my_graph in enumerate(in_graphs):
if isinstance(my_graph, list):
if my_graph == []:
return None
my_datum = self.do_router_graphs_(my_datum, my_graph, \
in_derection, in_vuid)
else:
tmp_datum = self.do_router_graph_(my_datum, my_graph, \
in_direction, in_vuid)
if my_index == 0 and isinstance(tmp_datum, bool):
if not tmp_datum:
break
elif isinstance(tmp_datum, dict):
my_datum = tmp_datum
else:
return None
del tmp_datum
return my_datum
#
# End of PyIRCIoT_router.do_router_graphs_()
def do_router_routes_(self, in_datum, in_routes, in_vuid = None):
if not isinstance(in_datum, dict):
return None
if not isinstance(in_routes, list):
return None
for my_route in in_routes:
pass
return in_datum
def do_router_(self, in_message, in_direction, in_vuid = None):
if in_direction in [ self.CONST.dir_in, self.CONST.dir_both ] \
and not self.is_router_routes_(self.input_routes):
return ""
if in_direction in [ self.CONST.dir_out, self.CONST.dir_both ] \
and not self.is_router_routes_(self.output_routes):
return ""
if not self.is_router_graphs_(self.router_graphs):
return ""
self.irciot_check_encoding_()
my_json = self.irciot_deinencap_(in_message, in_vuid)
if my_json == "":
return ""
try:
my_datums = json.loads(my_json)
except:
return ""
if isinstance(my_datums, dict):
my_datums = [ my_datums ]
if not isinstance(my_datums, list):
return ""
my_outdat = []
for my_datum in my_datums:
if in_direction in [ self.CONST.dir_in, self.CONST.dir_both ]:
my_datum = self.do_router_routes_(my_datum, self.input_routes, in_vuid)
my_datum = self.do_router_graphs_(my_datum, self.router_graphs, \
in_direction, in_vuid)
if in_direction in [ self.CONST.dir_out, self.CONST.dir_both ]:
my_datum = self.do_router_routes_(my_datum, self.output_routes, in_vuid)
if my_datum != None:
my_outdat.append(my_datum)
if my_outdat == []:
return ""
out_message = ""
out_pack = self.irciot_encap_all_(my_outdat, in_vuid)
if isinstance(out_pack, list):
if len(out_pack) > 0:
( out_message, out_vuid ) = out_pack[0]
if not isinstance(out_message, str):
out_message = ""
return out_message
#
# End of PyIRCIoT_router.do_router_()
def dup_detection_(self, in_datum, in_direction, in_vuid = None):
if not isinstance(in_datum, dict):
return True # Drop invalid messages
if in_direction not in self.CONST.dir_any:
self.irciot_error_(self.CONST.err_INVALID_DIRECTION, 0)
return True
my_datum = deepcopy(in_datum)
if self.CONST.tag_DATE_TIME in in_datum:
my_dt = my_datum.pop(self.CONST.tag_DATE_TIME)
else:
my_dt = "{}".format(time())
if len(my_dt) > 11 and len(my_dt) < 21:
my_dt = my_dt[:11] # cut to POSIX timestamp
if len(my_dt) > 20:
my_dt = my_dt[:19] # cut to ISO 8601:2004
if in_vuid == None: my_string = self.CONST.api_vuid_all
else: my_string = "{}".format(in_vuid)
for my_key, my_value in sorted(my_datum.items()):
my_string += "{}{}".format(my_key, my_value)
del my_datum
my_bytes = bytes(my_string, self.__encoding)
my_string = "{}{}".format( \
self.irciot_crc16_(my_bytes), \
self.irciot_crc32_(my_bytes))
del my_bytes
my_string += "{}".format(my_dt)
if my_string in self.__dup_detection_pipeline:
return True # Drop duplicate messages
self.__dup_detection_pipeline.append(my_string)
if len(self.__dup_detection_pipeline) \
> self.maximal_detect_dup_messages:
self.__dup_detection_pipeline.pop(0)
return False
#
# End of PyIRCIoT_router.dup_detection_()
# incomplete
def __direct_router_message_(self, in_dict, in_vuid):
if not isinstance(in_dict, dict) \
or not isinstance(in_vuid, str):
return
my_message = json.dumps(in_dict, separators=(',',':'))
my_compat = self.irciot_compatibility_()
my_pack = (my_message, in_vuid)
if not self.irc_pointer (my_compat, my_pack):
# Warning; if transport handler was not attached,
# the message will be added to the output_pool,
# but delivering the message at a specified time
# is not guaranteed and the routing protocol
# may not work correctly !!!
self.output_pool.append(my_pack)
# incomplete
def __make_LMR_information_message_(self, in_LMR_id = None):
if not self.__check_LMR_id_(in_LMR_id):
return None
try:
my_LMR = self.__LMR_pool[in_LMR_id]
my_src = my_LMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_LMR_INFO,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_LMR_request_message_(self, in_LMR_id = None):
if not self.__check_LMR_id_(in_LMR_id):
return None
try:
my_LMR = self.__LMR_pool[in_LMR_id]
my_src = my_LMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_LMR_REQUEST,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_LMR_update_message_(self, in_LMR_id = None):
if not self.__check_LMR_id_(in_LMR_id):
return None
try:
my_LMR = self.__LMR_pool[in_LMR_id]
my_src = my_LMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_LMR_UPDATE,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_LMR_acknowledgement_message_(self, in_LMR_id = None):
if not self.__check_LMR_id_(in_LMR_id):
return None
try:
my_LMR = self.__LMR_pool[in_LMR_id]
my_src = my_LMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_LMR_ACK,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_LMR_advertisment_message_(self, in_LMR_id = None):
if not self.__check_LMR_id_(in_LMR_id):
return None
try:
my_LMR = self.__LMR_pool[in_LMR_id]
my_src = my_LMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_LMR_ADVERT,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_GMR_connect_message_(self, in_GMR_id = None):
if not self.__check_GMR_id_(in_GMR_id):
return None
try:
my_GMR = self._GMR_pool[in_GMR_id]
my_src = my_GMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_GMR_CONNECT,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_GMR_VER: self.irciot_protocol_version_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_GMR_information_message_(self, in_GMR_id = None):
if not self.__check_GMR_id_(in_GMR_id):
return None
try:
my_GMR = self.__GMR_pool[in_GMR_id]
my_src = my_GMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_GMR_INFO,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __make_GMR_update_message_(self, in_GMR_id = None):
if not self.__check_GMR_id_(in_GMR_id):
return None
try:
my_GMR = self.__GMR_pool[in_GMR_id]
my_src = my_GMR[self.CONST.tag_SRC_ADDR]
except:
return None
my_message = { self.CONST.tag_OBJECT_TYPE: self.CONST.ot_GMR_UPDATE,
self.CONST.tag_DATE_TIME: self.irciot_get_current_datetime_(),
self.CONST.tag_SRC_ADDR: my_src }
return my_message
# incomplete
def __local_message_router_(self):
while self.__LMR_run:
for my_LMR_id in self.__LMR_pool.keys():
my_LMR = self.__LMR_pool[ my_LMR_id ]
my_status = my_LMR[self.CONST.intag_LMR_status]
if my_status == self.CONST.state_LMR_running:
my_time = time()
my_announce = my_LMR[self.CONST.intag_LMR_announce]
if my_time - my_announce > self.__LMR_announce_interval:
my_LMR[self.CONST.intag_LMR_announce] = my_time
my_message = self.__make_LMR_information_message_(my_LMR_id)
self.__direct_router_message_(my_message, \
self.CONST.api_vuid_all)
elif my_status in [
self.CONST.state_LMR_stopped,
self.CONST.state_LMR_paused ]:
continue
sleep(self.__LMR_latency)
#
# End of PyIRCIoT_router.local_message_router_()
# incomplete
def __global_message_router_(self):
while self.__GMR_run:
for my_GMR_id in self.__GMR_pool.keys():
my_GMR = self.__GMR_pool[ my_GMR_id ]
my_status = my_GMR[self.CONST.intag_GMR_status]
my_time = time()
if my_status == self.CONST.state_GMR_connected:
pass
elif my_status == self.CONST.state_GMR_connecting:
my_conntry = my_GMR[self.CONST.intag_GMR_conn_try]
my_vuid = my_GMR[self.CONST.intag_GMR_vuid]
if my_time - my_conntry > self.__GMR_connect_try_interval:
my_GMR[self.CONST.intag_GMR_conn_try] = my_time
my_message = self.__make_GMR_connect_message_(my_GMR_id)
self.__direct_router_message_(my_message, my_vuid)
elif my_status == self.CONST.state_GMR_stalled:
pass
elif my_status in [
self.CONST.state_GMR_stopped,
self.CONST.state_GMR_paused ]:
continue
sleep(self.__GMR_latency)
#
# End of PyIRCIoT_router.global_message_router_()
def __invalid_LMR_id_(in_LMR_id):
self.irciot_error_(self.CONST.err_LMR_INVALID_ID, 0, \
in_addon = "{}".format(in_LMR_id))
def __invalid_GMR_id_(in_GMR_id):
self.irciot_error_(self.CONST.err_GMR_INVALID_ID, 0, \
in_addon = "{}".format(in_GMR_id))
# incomplete
def init_LMR_(self, in_src = None):
if in_src == None:
my_src = self.__primary_irciot_address
else:
my_src = in_src
if not self.is_irciot_address_(my_src):
return None
my_LMR_id = self.CONST.default_LMR_id
my_LMR_count = 0
for my_key in self.__LMR_pool.keys():
my_LMR_count += 1
if my_LMR_id < my_key:
my_LMR_id = my_key
my_LMR_id += 1
if my_LMR_count >= self.CONST.maximal_LMR_count:
self.irciot_error_(self.CONST.err_LMR_MAX_INSTANCES, \
0, in_addon = "{}".format(self.CONST.maximal_LMR_count))
return None
self.__LMR_pool.update({
my_LMR_id: {
self.CONST.tag_SRC_ADDR: my_src,
self.CONST.intag_LMR_status: self.CONST.state_LMR_stopped,
self.CONST.intag_LMR_announce: 0
}
})
return my_LMR_id
# incomplete
def init_GMR_(self, in_src = None):
if in_src == None:
my_src = self.__primary_irciot_address
else:
my_src = in_src
if not self.is_irciot_address_(my_src):
return None
my_GMR_id = self.CONST.default_GMR_id - 1
my_GMR_count = 0
for my_key in self.__GMR_pool.keys():
my_GMR_count += 1
if my_GMR_id < my_key:
my_GMR_id = my_key
my_GMR_id += 1
if my_GMR_count >= self.CONST.maximal_GMR_count:
self.irciot_error_(self.CONST.err_GMR_MAX_INSTANCES, \
0, in_addon = "{}".format(self.CONST.maximal_GMR_count))
return None
self.__GMR_pool.update({
my_GMR_id: {
self.CONST.tag_SRC_ADDR: my_src,
self.CONST.intag_GMR_status: self.CONST.state_GMR_stopped,
self.CONST.intag_GMR_conn_try: 0,
self.CONST.intag_GMR_conn_ok: None,
self.CONST.intag_GMR_vuid: None
}
})
return my_GMR_id
def get_LMR_list_(self):
my_LMR_list = []
for my_key in self.__LMR_pool.keys():
my_LMR_list.append(my_key)
return my_LMR_list
def get_GMR_list_(self):
my_GMR_list = []
for my_key in self.__GMR_pool.keys():
my_GMR_list.append(my_key)
return my_GMR_list
def __check_LMR_id_(self, in_LMR_id = None):
if in_LMR_id == None:
return False
if not isinstance(in_LMR_id, int):
self.__invalid_LMR_id_(in_LMR_id)
return False
if in_LMR_id not in self.__LMR_pool.keys():
self.__invalid_LMR_id_(in_LMR_id)
return False
return True
def __check_GMR_id_(self, in_GMR_id = None):
if in_GMR_id == None:
return False
if not isinstance(in_GMR_id, int):
self.__invalid_GMR_id_(in_GMR_id)
return False
if in_GMR_id not in self.__GMR_pool.keys():
self.__invalid_GMR_id_(in_GMR_id)
return False
return True
def __get_LMR_id_(self, in_LMR_id):
if in_LMR_id != None:
return in_LMR_id
if len(self.__LMR_pool) == 1:
return list(self.__LMR_pool)[0]
return None
def __get_GMR_id_(self, in_GMR_id):
if in_GMR_id != None:
return in_GMR_id
if len(self.__GMR_pool) == 1:
return list(self.__GMR_pool)[0]
return None
def get_LMR_status_(self, in_LMR_id = None):
my_LMR_id = self.__get_LMR_id_(in_LMR_id)
if not self.__check_LMR_id_(my_LMR_id): return None
return self.__LMR_pool[my_LMR_id][self.CONST.intag_LMR_status]
def get_GMR_status_(self, in_GMR_id = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id): return None
return self.__GMR_pool[my_GMR_id][self.CONST.intag_GMR_status]
def get_GMR_vuid_(self, in_GMR_id = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id): return None
return self.__GMR_pool[my_GMR_id][self.CONST.intag_GMR_vuid]
def set_GMR_vuid_(self, in_GMR_id = None, in_vuid = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id): return False
self.__GMR_pool[my_GMR_id][self.CONST.intag_GMR_vuid] = in_GMR_vuid
return True
# incomplete
def start_LMR_(self, in_LMR_id = None):
my_LMR_id = self.__get_LMR_id_(in_LMR_id)
if not self.__check_LMR_id_(my_LMR_id):
return False
self.__LMR_pool[my_LMR_id].update({
self.CONST.intag_LMR_status: self.CONST.state_LMR_running,
self.CONST.intag_LMR_announce: time()
})
return True
# incomplete
def start_GMR_(self, in_GMR_id = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id):
return False
self.__GMR_pool[my_GMR_id].update({
self.CONST.intag_GMR_status: self.CONST.state_GMR_connecting,
self.CONST.intag_GMR_conn_try: 0
})
if not self.__GMR_run: self.__start_GMR_()
return True
# incomplete
def pause_LMR_(self, in_LMR_id = None):
my_LMR_id = self.__get_LMR_id_(in_LMR_id)
if not self.__check_LMR_id_(my_LMR_id):
return False
self.__LMR_pool[my_LMR_id].update({
self.CONST.intag_LMR_status: self.CONST.state_LMR_running
})
if not self.__LMR_run: self.__start_LMR_()
return True
# incomplete
def pause_GMR_(self, in_GMR_id = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id):
return False
self.__GMR_pool[my_GMR_id].update({
self.CONST.intag_GMR_status: self.CONST.state_GMR_pasued
})
return True
# incomplete
def drop_LMR_(self, in_LMR_id = None):
my_LMR_id = self.__get_LMR_id_(in_LMR_id)
if not self.__check_LMR_id_(my_LMR_id):
return False
self.__LMR_pool.pop(my_LMR_id)
if self.__LMR_pool == {}:
self.__stop_LMR_()
return True
# incomplete
def drop_GMR_(self, in_GMR_id = None):
my_GMR_id = self.__get_GMR_id_(in_GMR_id)
if not self.__check_GMR_id_(my_GMR_id):
return False
self.__GMR_pool.pop(my_GMR_id)
del self.__GMR_table
self.__GMR_table = {}
self.__stop_GMR_()
return True
# incomplete
def do_router_LMR_(self, in_datum, in_params, \
in_direction, in_vuid = None):
if not isinstance(in_params, dict):
if in_params == self.CONST.rgn_REQUEST_PARAMS:
return [ self.CONST.tag_LMR_ID ]
return None
if in_direction not in self.CONST.dir_any:
self.irciot_error_(self.CONST.err_INVALID_DIRECTION, 0)
return None
my_id = in_params[ self.CONST.tag_LMR_ID ]
if my_id not in self.__LMR_pool.keys():
self.__invalid_LMR_id_(my_id)
return in_datum
my_LMR = self.__LMR_pool[my_id]
my_status = my_LMR[self.CONST.intag_LMR_status]
if my_status in [
self.CONST.state_LMR_stopped,
self.CONST.state_LMR_paused ]:
return in_datum
return in_datum
#
# End of do_router_LMR_()
# incomplete
def do_router_GMR_(self, in_datum, in_params, \
in_direction, in_vuid = None):
if not isinstance(in_params, dict):
if in_params == self.CONST.rgn_REQUEST_PARAMS:
return [ self.CONST.tag_GMR_ID ]
return None
if in_direction not in self.CONST.dir_any:
self.irciot_error_(self.CONST.err_INVALID_DIRECTION, 0)
return None
my_id = in_params[ self.CONST.tag_GMR_ID ]
if my_id not in self.__GMR_pool.keys():
self.__invalid_GMR_id_(my_id)
return in_datum
my_GMR = self.__GMR_pool[my_id]
my_status = my_GMR[self.CONST.intag_GMR_status]
if my_status in [
self.CONST.state_GMR_stopped,
self.CONST.state_GMR_paused ]:
return in_datum
elif my_status in [
self.CONST.state_GMR_connecting,
self.CONST.state_GMR_stalled ]:
pass
return in_datum
#
# End of do_router_GMR_()
def connections_tracking_cleaner_(self):
current_time = time()
minimal_time = current_time
minimal_key = None
my_count = 0
for my_key in self.__connections_tracking.keys():
( my_addr, my_time ) = self.__connections_tracking[ my_key ]
if current_time - my_time > self.timeout_connection_tracking:
del self.__connections_tracking[ my_key ]
else:
if my_time < minimal_time:
minimal_time = my_time
minimal_key = my_key
my_count += 1
if my_count > self.maximal_connection_tracking \
and minimal_key != None:
del self.__connections_tracking[ minimal_key ]
#
# End of connections_tracking_cleaner_()
def do_router_translation_(self, in_datum, in_params, \
in_direction, in_vuid = None):
if not isinstance(in_params, dict):
if in_params == self.CONST.rgn_REQUEST_PARAMS:
return [ self.CONST.tag_IN_SCOPE, self.CONST.tag_OUT_SCOPE ]
return None
if in_direction not in self.CONST.dir_any:
self.irciot_error_(self.CONST.err_INVALID_DIRECTION, 0)
return None
dst_addr = ''
try:
src_addr = in_datum[ self.CONST.tag_SRC_ADDR ]
except:
return None
self.connections_tracking_cleaner_()
if self.CONST.tag_DST_ADDR in in_datum.keys():
dst_addr = in_datum[ self.CONST.tag_DST_ADDR ]
if not self.is_irciot_address_(src_addr) \
or not self.is_irciot_address_(dst_addr):
self.irciot_error_(self.CONST.err_INVALID_ADDRESS, 0)
return None
in_scope = in_params[ self.CONST.tag_IN_SCOPE ]
out_scope = in_params[ self.CONST.tag_OUT_SCOPE ]
out_datum = in_datum
in_scope_len = len(in_scope)
src_addr_len = len(src_addr)
my_translate = False
#
if in_direction in [ self.CONST.dir_in, self.CONST.dir_both ]:
out_addr = src_addr
if src_addr_len >= in_scope_len:
if src_addr == in_scope:
out_addr = out_scope
my_translate == True
elif src_addr_len > in_scope_len:
if src_addr[:in_scope_len] == in_scope:
if src_addr[in_scope_len] == '/':
out_addr = out_scope + src_addr[in_scope_len:]
my_translate = True
if my_translate:
my_key = out_addr + '@@' + dst_addr;
if my_key in self.__connections_tracking.keys():
my_translation = self.__connections_tracking[ my_key ]
else:
my_translation = ( src_addr, time() )
self.__connections_tracking[ my_key ] = my_translation
out_datum[ self.CONST.tag_SRC_ADDR ] = out_addr
#
if in_direction in [ self.CONST.dir_out, self.CONST.dir_both ]:
my_key = dst_addr + '@@' + src_addr;
if my_key in self.__connections_tracking.keys():
( my_src_addr, my_time ) = self.__connections_tracking[ my_key ]
out_datum[ self.CONST.tag_DST_ADDR ] = my_src_addr
return out_datum
#
# End of do_router_translation_()
# incomplete
def do_router_hashcache_(self, in_datum, in_params, \
in_direction, in_vuid = None):
in_datum = out_datum
return out_datum
def do_router_forwarding_(self, in_datum, in_params, \
in_direction, in_vuid = None):
if not isinstance(in_params, dict):
if in_params == self.CONST.rgn_REQUEST_PARAMS:
return []
return None
if in_direction not in self.CONST.dir_any:
self.irciot_error_(self.CONST.err_INVALID_DIRECTION, 0)
return None
if self.dup_detection_(in_datum, in_direction):
self.irciot_error_(self.CONST.err_ROUTER_DUP_DETECT, 0)
return None
out_datum = in_datum
return out_datum
#
# End of do_router_forwarding_()
[ Get back ]
|
IRC-IoT
|