def get_new_edge( self, socket, # type: _SocketUnion config # type: AutomotiveTestCaseExecutorConfiguration ): # type: (...) -> Optional[_Edge] """ Basic identification of a new edge. The last response is evaluated. If this response packet can modify the state of an Ecu, this new state is returned, otherwise None. :param socket: Socket to the DUT (unused) :param config: Global configuration of the executor (unused) :return: tuple of old EcuState and new EcuState, or None """ try: state, req, resp, _, _ = cast(ServiceEnumerator, self).results[-1] except IndexError: return None if resp is not None and EcuState.is_modifier_pkt(resp): new_state = EcuState.get_modified_ecu_state(resp, req, state) if new_state == state: return None else: edge = (state, new_state) self._edge_requests[edge] = req return edge else: return None
def get_state_paths(self): paths = [ Graph.dijsktra(self.state_graph, EcuState(), s) for s in self.state_graph.nodes if s != EcuState() ] return sorted([p for p in paths if p is not None] + [[EcuState()]], key=lambda x: x[-1])
def _evaluate_ecu_state_modifications(self, state, # type: EcuState request, # type: Packet response, # type: Packet ): # type: (...) -> bool if EcuState.is_modifier_pkt(response): if state != EcuState.get_modified_ecu_state( response, request, state): log_interactive.debug( "[-] Exit execute. Ecu state was modified!") return True return False
def __init__(self, socket, reset_handler=None, enumerators=None, **kwargs): # The TesterPresentSender can interfere with a enumerator, since a # target may only allow one request at a time. # The SingleConversationSocket prevents interleaving requests. if not isinstance(socket, SingleConversationSocket): self.socket = SingleConversationSocket(socket) else: self.socket = socket self.tps = None # TesterPresentSender self.target_state = EcuState() self.reset_handler = reset_handler self.verbose = kwargs.get("verbose", False) if enumerators: # enumerators can be a mix of classes or instances self.enumerators = [ e(self.socket) for e in enumerators if not isinstance(e, Enumerator) ] + [e for e in enumerators if isinstance(e, Enumerator) ] # noqa: E501 else: self.enumerators = [ e(self.socket) for e in self.default_enumerator_clss ] # noqa: E501 self.enumerator_classes = [e.__class__ for e in self.enumerators] self.state_graph = Graph() self.state_graph.add_edge(EcuState(), EcuState()) self.configuration = \ {"dynamic_timeout": kwargs.pop("dynamic_timeout", False), "enumerator_classes": self.enumerator_classes, "verbose": self.verbose, "state_graph": self.state_graph, "delay_state_change": kwargs.pop("delay_state_change", 0.5)} for e in self.enumerators: self.configuration[e.__class__] = kwargs.pop( e.__class__.__name__ + "_kwargs", dict()) for conf_key in self.enumerators: conf_val = self.configuration[conf_key.__class__] for kwargs_key, kwargs_val in kwargs.items(): if kwargs_key not in conf_val.keys(): conf_val[kwargs_key] = kwargs_val self.configuration[conf_key.__class__] = conf_val log_interactive.debug("The following configuration was created") log_interactive.debug(self.configuration)
def reset_target(self): log_interactive.info("[i] Target reset") self.reset_tps() if self.reset_handler: try: self.reset_handler(self) except TypeError: self.reset_handler() self.target_state = EcuState()
def enter_state_path(self, path): if path[0] != EcuState(): raise Scapy_Exception( "Initial state of path not equal reset state of the target") self.reset_target() if len(path) == 1: return True for s in path[1:]: if not self.enter_state(s): return False return True
def __initial_ecu_state(self): # type: () -> EcuState return EcuState(session=1)