def mock_receive(self, path: str, sender: str, payload: dict): buf_req = Request(path, None, sender, self._hostname, payload) buf_req.set_callback_method(self._get_mock_response_function()) self.receive(buf_req)
class RestServerRequestManager: _request: Request _response: Optional[Request] def __init__(self, hostname: str, path: str, payload: dict, auth: Optional[AuthContainer]): self._response = None self._create_incoming_request(hostname, path, payload, auth) def __del__(self): pass def _create_incoming_request(self, hostname: str, path: str, payload: dict, auth: Optional[AuthContainer]): session_id = random.randint(0, 30000) sender = f"rest_client_{session_id}" self._request = Request(path=path, session_id=session_id, sender=sender, receiver=hostname, payload=payload) if auth is not None: self._request.set_auth(auth) self._request.set_callback_method(self._get_response_function()) def _get_response_function(self) -> response_callback_type: def respond(req: Request, payload: dict, path: Optional[str]): if req.get_session_id() != self._request.get_session_id(): raise IllegalResponseException( f"Session IDs {req.get_session_id()} and " f"{self._request.get_session_id()} are not matching") if path is not None: res_path = path else: res_path = req.get_path() self._response = Request(path=res_path, session_id=req.get_session_id(), sender=self._request.get_receiver(), receiver=req.get_sender(), payload=payload) return respond def get_request(self) -> Request: return self._request def await_response(self, timeout: int = 2) -> Request: start_time = datetime.now() while self._response is None: time.sleep(0.1) now = datetime.now() if now > (start_time + timedelta(seconds=timeout)): break if self._response is None: raise NoResponseReceivedError(self._request.get_path()) return self._response
def _handle_split_request(self, received_request: Request) -> Optional[Request]: req_payload = received_request.get_payload() id_str = str(received_request.get_session_id()) p_index = req_payload["package_index"] split_payload = req_payload["split_payload"] if p_index == 0: if "last_index" in req_payload: l_index = req_payload["last_index"] buf_json = { "start_req": received_request, "last_index": l_index, "payload_bits": [] } for i in range(l_index + 1): buf_json["payload_bits"].append(None) buf_json["payload_bits"][0] = split_payload self._part_data[id_str] = buf_json else: self._logger.error( "Received first block of split request without last_index") else: if id_str in self._part_data: req_data = self._part_data[id_str] req_data["payload_bits"][p_index] = split_payload if p_index >= req_data["last_index"] - 1: # TODO: Split requests should be recognized whether the last package is received last or not end_data = "" for str_data in req_data["payload_bits"]: if str_data is None: self._logger.error( "Detected missing data block in split request") break end_data += str_data try: end_data = end_data.replace("$*$", '"') json_data = json.loads(end_data) first_req: Request = req_data["start_req"] out_req = Request(first_req.get_path(), first_req.get_session_id(), first_req.get_sender(), first_req.get_receiver(), json_data) out_req.set_callback_method(first_req.get_callback()) del self._part_data[id_str] return out_req except json.decoder.JSONDecodeError: self._logger.error("Received illegal payload") else: self._logger.error( "Received a followup-block with no entry in storage") return None
def buf_callback(client, userdata, message): """Callback to attach to mqtt object, mqtt_res_queue gets catched in closure""" topic = message.topic try: json_str = message.payload.decode("utf-8") except UnicodeDecodeError: self._logger.warning("Couldn't format json string") return try: body = json.loads(json_str) except json.decoder.JSONDecodeError: self._logger.warning( "Couldn't decode json: '{}'".format(json_str)) return try: self._validator.validate(body, REQ_VALIDATION_SCHEME_NAME) except ValidationError: self._logger.warning( "Could not decode Request, Schema Validation failed.") topic_without_channel = topic[len(self._channel):].strip("/") try: inc_req = Request(topic_without_channel, body["session_id"], body["sender"], body["receiver"], body["payload"], connection_type=f"MQTT") inc_req.set_auth(MqttAuthContainer()) inc_req.set_callback_method(self._respond_to) self._add_req_to_queue(inc_req) except ValueError: self._logger.error("Error creating Request")