""" Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) Date: Fri Aug 25 15:48:04 2017 Model author: Yentl Van Tendeloo Model name: HTTP client Model description: HTTP client. """ from sccd.runtime.statecharts_core import * import uuid # package "HTTP client" class HTTPClient(RuntimeClassBase): def __init__(self, controller): RuntimeClassBase.__init__(self, controller) self.semantics.big_step_maximality = StatechartSemantics.TakeMany self.semantics.internal_event_lifeline = StatechartSemantics.Queue self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep self.semantics.priority = StatechartSemantics.SourceParent self.semantics.concurrency = StatechartSemantics.Single # build Statechart structure self.build_statechart_structure() # call user defined constructor HTTPClient.user_defined_constructor(self) def user_defined_constructor(self): self.socket = None self.received_data = "" self.send_data = "" self.queue = [] self.IDs = [] def user_defined_destructor(self): pass # builds Statechart structure def build_statechart_structure(self): # state self.states[""] = State(0, "", self) # state /init self.states["/init"] = State(1, "/init", self) self.states["/init"].setEnter(self._init_enter) # state /waiting self.states["/waiting"] = State(2, "/waiting", self) self.states["/waiting"].setEnter(self._waiting_enter) # state /connecting self.states["/connecting"] = State(3, "/connecting", self) self.states["/connecting"].setEnter(self._connecting_enter) self.states["/connecting"].setExit(self._connecting_exit) # state /connecting/connecting self.states["/connecting/connecting"] = State(4, "/connecting/connecting", self) self.states["/connecting/connecting"].setEnter(self._connecting_connecting_enter) # state /connecting/cooldown self.states["/connecting/cooldown"] = State(5, "/connecting/cooldown", self) self.states["/connecting/cooldown"].setEnter(self._connecting_cooldown_enter) self.states["/connecting/cooldown"].setExit(self._connecting_cooldown_exit) # state /connected self.states["/connected"] = ParallelState(6, "/connected", self) # state /connected/listening self.states["/connected/listening"] = State(7, "/connected/listening", self) # state /connected/listening/listen self.states["/connected/listening/listen"] = State(8, "/connected/listening/listen", self) self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter) # state /connected/listening/close self.states["/connected/listening/close"] = State(9, "/connected/listening/close", self) # state /connected/sending self.states["/connected/sending"] = State(10, "/connected/sending", self) # state /connected/sending/waiting_for_data self.states["/connected/sending/waiting_for_data"] = State(11, "/connected/sending/waiting_for_data", self) # state /connected/sending/transferring self.states["/connected/sending/transferring"] = State(12, "/connected/sending/transferring", self) # state /connected/queueing self.states["/connected/queueing"] = State(13, "/connected/queueing", self) # state /connected/queueing/queueing self.states["/connected/queueing/queueing"] = State(14, "/connected/queueing/queueing", self) self.states["/connected/queueing/queueing"].setEnter(self._connected_queueing_queueing_enter) # state /connected/parsing self.states["/connected/parsing"] = State(15, "/connected/parsing", self) # state /connected/parsing/wait_for_header self.states["/connected/parsing/wait_for_header"] = State(16, "/connected/parsing/wait_for_header", self) # state /connected/parsing/wait_for_payload self.states["/connected/parsing/wait_for_payload"] = State(17, "/connected/parsing/wait_for_payload", self) # add children self.states[""].addChild(self.states["/init"]) self.states[""].addChild(self.states["/waiting"]) self.states[""].addChild(self.states["/connecting"]) self.states[""].addChild(self.states["/connected"]) self.states["/connecting"].addChild(self.states["/connecting/connecting"]) self.states["/connecting"].addChild(self.states["/connecting/cooldown"]) self.states["/connected"].addChild(self.states["/connected/listening"]) self.states["/connected"].addChild(self.states["/connected/sending"]) self.states["/connected"].addChild(self.states["/connected/queueing"]) self.states["/connected"].addChild(self.states["/connected/parsing"]) self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"]) self.states["/connected/listening"].addChild(self.states["/connected/listening/close"]) self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"]) self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"]) self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"]) self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"]) self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"]) self.states[""].fixTree() self.states[""].default_state = self.states["/init"] self.states["/connecting"].default_state = self.states["/connecting/connecting"] self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"] self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"] self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"] self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"] # transition /init _init_0 = Transition(self, self.states["/init"], [self.states["/waiting"]]) _init_0.setAction(self._init_0_exec) _init_0.setTrigger(Event("created_socket", "socket_in")) _init_0.setGuard(self._init_0_guard) self.states["/init"].addTransition(_init_0) # transition /waiting _waiting_0 = Transition(self, self.states["/waiting"], [self.states["/connecting"]]) _waiting_0.setAction(self._waiting_0_exec) _waiting_0.setTrigger(Event("connect", "request_in")) self.states["/waiting"].addTransition(_waiting_0) # transition /connecting/connecting _connecting_connecting_0 = Transition(self, self.states["/connecting/connecting"], [self.states["/connecting/cooldown"]]) _connecting_connecting_0.setTrigger(Event("error_socket", "socket_in")) self.states["/connecting/connecting"].addTransition(_connecting_connecting_0) _connecting_connecting_1 = Transition(self, self.states["/connecting/connecting"], [self.states["/connected"]]) _connecting_connecting_1.setAction(self._connecting_connecting_1_exec) _connecting_connecting_1.setTrigger(Event("connected_socket", "socket_in")) _connecting_connecting_1.setGuard(self._connecting_connecting_1_guard) self.states["/connecting/connecting"].addTransition(_connecting_connecting_1) # transition /connecting/cooldown _connecting_cooldown_0 = Transition(self, self.states["/connecting/cooldown"], [self.states["/connecting/connecting"]]) _connecting_cooldown_0.setTrigger(Event("_1after")) self.states["/connecting/cooldown"].addTransition(_connecting_cooldown_0) # transition /connected/listening/listen _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]]) _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec) _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in")) _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard) self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0) _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/close"]]) _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in")) _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard) self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1) # transition /connected/sending/waiting_for_data _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]]) _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec) _connected_sending_waiting_for_data_0.setTrigger(None) _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard) self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0) # transition /connected/sending/transferring _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]]) _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec) _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in")) _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard) self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0) # transition /connected/queueing/queueing _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]]) _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec) _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", "request_in")) self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0) # transition /connected/parsing/wait_for_header _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]]) _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec) _connected_parsing_wait_for_header_0.setTrigger(None) _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard) self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0) # transition /connected/parsing/wait_for_payload _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]]) _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec) _connected_parsing_wait_for_payload_0.setTrigger(None) _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard) self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0) _connected_parsing_wait_for_payload_1 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]]) _connected_parsing_wait_for_payload_1.setAction(self._connected_parsing_wait_for_payload_1_exec) _connected_parsing_wait_for_payload_1.setTrigger(None) _connected_parsing_wait_for_payload_1.setGuard(self._connected_parsing_wait_for_payload_1_guard) self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_1) # transition /connecting _connecting_0 = Transition(self, self.states["/connecting"], [self.states["/waiting"]]) _connecting_0.setAction(self._connecting_0_exec) _connecting_0.setTrigger(Event("_0after")) self.states["/connecting"].addTransition(_connecting_0) def _connecting_enter(self): self.addTimer(0, self.timeout) def _connecting_exit(self): self.removeTimer(0) def _init_enter(self): self.ID = str(uuid.uuid4()) self.big_step.outputEvent(Event("create_socket", "socket_out", [self.ID])) def _waiting_enter(self): self.big_step.outputEvent(Event("http_client_initialized", "request_out", [])) def _connecting_connecting_enter(self): self.big_step.outputEvent(Event("connect_socket", "socket_out", [self.socket, self.address])) def _connecting_cooldown_enter(self): self.addTimer(1, 0.1) def _connecting_cooldown_exit(self): self.removeTimer(1) def _connected_listening_listen_enter(self): self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket])) def _connected_queueing_queueing_enter(self): pass def _connecting_0_exec(self, parameters): self.big_step.outputEvent(Event("http_client_timeout", "request_out", [])) def _init_0_exec(self, parameters): socket = parameters[0] ID = parameters[1] self.socket = socket def _init_0_guard(self, parameters): socket = parameters[0] ID = parameters[1] return self.ID == ID def _waiting_0_exec(self, parameters): address = parameters[0] timeout = parameters[1] self.address = address self.timeout = timeout def _connecting_connecting_1_exec(self, parameters): socket = parameters[0] self.big_step.outputEvent(Event("http_client_ready", "request_out", [])) def _connecting_connecting_1_guard(self, parameters): socket = parameters[0] return self.socket == socket def _connected_listening_listen_0_exec(self, parameters): socket = parameters[0] data = parameters[1] self.received_data += data def _connected_listening_listen_0_guard(self, parameters): socket = parameters[0] data = parameters[1] return (self.socket == socket) and (len(data) > 0) def _connected_listening_listen_1_guard(self, parameters): socket = parameters[0] data = parameters[1] return (self.socket == socket) and (len(data) == 0) def _connected_sending_waiting_for_data_0_exec(self, parameters): self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data])) def _connected_sending_waiting_for_data_0_guard(self, parameters): return len(self.send_data) > 0 def _connected_sending_transferring_0_exec(self, parameters): socket = parameters[0] sent_bytes = parameters[1] self.send_data = self.send_data[sent_bytes:] def _connected_sending_transferring_0_guard(self, parameters): socket = parameters[0] sent_bytes = parameters[1] return self.socket == socket def _connected_queueing_queueing_0_exec(self, parameters): data = parameters[0] ID = parameters[1] self.send_data += "POST / HTTP/1.0\r\n" self.send_data += "Content-Length: %i\r\n" % len(str(data)) self.send_data += "\r\n" self.send_data += data self.IDs.append(ID) def _connected_parsing_wait_for_header_0_exec(self, parameters): header, self.received_data = self.received_data.split("\r\n\r\n", 1) header = header.lower() if "content-length" in header: _, after = header.split("content-length:", 1) after, _ = after.split("\r\n", 1) after = after.strip() self.length = int(after) else: self.length = float('inf') def _connected_parsing_wait_for_header_0_guard(self, parameters): return '\r\n\r\n' in self.received_data def _connected_parsing_wait_for_payload_0_exec(self, parameters): data = self.received_data[:self.length] self.received_data = self.received_data[self.length:] self.big_step.outputEvent(Event("HTTP_output", "request_out", [data, self.IDs.pop(0)])) def _connected_parsing_wait_for_payload_0_guard(self, parameters): return len(self.received_data) >= self.length and self.IDs[0] is not None def _connected_parsing_wait_for_payload_1_exec(self, parameters): # Drop data self.received_data = self.received_data[self.length:] self.IDs.pop(0) def _connected_parsing_wait_for_payload_1_guard(self, parameters): return len(self.received_data) >= self.length and self.IDs[0] is None def initializeStatechart(self): # enter default state self.default_targets = self.states["/init"].getEffectiveTargetStates() RuntimeClassBase.initializeStatechart(self) class ObjectManager(ObjectManagerBase): def __init__(self, controller): ObjectManagerBase.__init__(self, controller) def instantiate(self, class_name, construct_params): if class_name == "HTTPClient": instance = HTTPClient(self.controller) instance.associations = {} else: raise Exception("Cannot instantiate class " + class_name) return instance class Controller(ThreadsControllerBase): def __init__(self, keep_running = None, behind_schedule_callback = None): if keep_running == None: keep_running = True if behind_schedule_callback == None: behind_schedule_callback = None ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback) self.addInputPort("socket_in") self.addInputPort("request_in") self.addOutputPort("socket_out") self.addOutputPort("request_out") self.object_manager.createInstance("HTTPClient", [])