""" Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) Date: Wed Aug 17 13:32:50 2016 Model author: Yentl Van Tendeloo Model name: HTTP Server Model description: Example HTTP echo server. """ from sccd.runtime.statecharts_core import * import time import os import urllib import sys import json import sys # package "HTTP Server" class Echo(RuntimeClassBase): def __init__(self, controller, params): 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 Echo.user_defined_constructor(self, params) def user_defined_constructor(self, params): self.source = None def user_defined_destructor(self): pass # builds Statechart structure def build_statechart_structure(self): # state self.states[""] = State(0, self) # state /init_server self.states["/init_server"] = State(1, self) self.states["/init_server"].setEnter(self._init_server_enter) # state /wait_for_requests self.states["/wait_for_requests"] = State(2, self) # state /wait_for_requests/wait self.states["/wait_for_requests/wait"] = State(3, self) # add children self.states[""].addChild(self.states["/init_server"]) self.states[""].addChild(self.states["/wait_for_requests"]) self.states["/wait_for_requests"].addChild(self.states["/wait_for_requests/wait"]) self.states[""].fixTree() self.states[""].default_state = self.states["/init_server"] self.states["/wait_for_requests"].default_state = self.states["/wait_for_requests/wait"] # transition /init_server _init_server_0 = Transition(self, self.states["/init_server"], [self.states["/wait_for_requests"]]) _init_server_0.setAction(self._init_server_0_exec) _init_server_0.setTrigger(Event("instance_created", None)) self.states["/init_server"].addTransition(_init_server_0) # transition /wait_for_requests/wait _wait_for_requests_wait_0 = Transition(self, self.states["/wait_for_requests/wait"], [self.states["/wait_for_requests/wait"]]) _wait_for_requests_wait_0.setAction(self._wait_for_requests_wait_0_exec) _wait_for_requests_wait_0.setTrigger(Event("HTTP_output", None)) self.states["/wait_for_requests/wait"].addTransition(_wait_for_requests_wait_0) def _init_server_enter(self): self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_server', 'Server', '', 8080])) def _init_server_0_exec(self, parameters): instancename = parameters[0] self.big_step.outputEventOM(Event("start_instance", None, [self, instancename])) def _wait_for_requests_wait_0_exec(self, parameters): source = parameters[0] data = parameters[1] print("Got input: " + str(data)) self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_server/%s' % source, Event("HTTP_input", None, [data])])) def initializeStatechart(self): # enter default state self.default_targets = self.states["/init_server"].getEffectiveTargetStates() RuntimeClassBase.initializeStatechart(self) class Server(RuntimeClassBase): def __init__(self, controller, address, port): 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 Server.user_defined_constructor(self, address, port) def user_defined_constructor(self, address, port): self.socket = None self.address = address self.port = port def user_defined_destructor(self): pass # builds Statechart structure def build_statechart_structure(self): # state self.states[""] = State(0, self) # state /main self.states["/main"] = ParallelState(1, self) # state /main/forward self.states["/main/forward"] = State(2, self) # state /main/forward/forward self.states["/main/forward/forward"] = State(3, self) # state /main/server self.states["/main/server"] = State(4, self) # state /main/server/init self.states["/main/server/init"] = State(5, self) self.states["/main/server/init"].setEnter(self._main_server_init_enter) # state /main/server/binding self.states["/main/server/binding"] = State(6, self) self.states["/main/server/binding"].setEnter(self._main_server_binding_enter) # state /main/server/listening self.states["/main/server/listening"] = State(7, self) self.states["/main/server/listening"].setEnter(self._main_server_listening_enter) # state /main/server/accepting self.states["/main/server/accepting"] = State(8, self) self.states["/main/server/accepting"].setEnter(self._main_server_accepting_enter) self.states["/main/server/accepting"].setExit(self._main_server_accepting_exit) # state /main/close_socket self.states["/main/close_socket"] = State(9, self) # state /main/close_socket/close self.states["/main/close_socket/close"] = State(10, self) # add children self.states[""].addChild(self.states["/main"]) self.states["/main"].addChild(self.states["/main/forward"]) self.states["/main"].addChild(self.states["/main/server"]) self.states["/main"].addChild(self.states["/main/close_socket"]) self.states["/main/forward"].addChild(self.states["/main/forward/forward"]) self.states["/main/server"].addChild(self.states["/main/server/init"]) self.states["/main/server"].addChild(self.states["/main/server/binding"]) self.states["/main/server"].addChild(self.states["/main/server/listening"]) self.states["/main/server"].addChild(self.states["/main/server/accepting"]) self.states["/main/close_socket"].addChild(self.states["/main/close_socket/close"]) self.states[""].fixTree() self.states[""].default_state = self.states["/main"] self.states["/main/forward"].default_state = self.states["/main/forward/forward"] self.states["/main/server"].default_state = self.states["/main/server/init"] self.states["/main/close_socket"].default_state = self.states["/main/close_socket/close"] # transition /main/forward/forward _main_forward_forward_0 = Transition(self, self.states["/main/forward/forward"], [self.states["/main/forward/forward"]]) _main_forward_forward_0.setAction(self._main_forward_forward_0_exec) _main_forward_forward_0.setTrigger(Event("HTTP_output", None)) self.states["/main/forward/forward"].addTransition(_main_forward_forward_0) # transition /main/server/init _main_server_init_0 = Transition(self, self.states["/main/server/init"], [self.states["/main/server/binding"]]) _main_server_init_0.setAction(self._main_server_init_0_exec) _main_server_init_0.setTrigger(Event("created_socket", "socket_in")) self.states["/main/server/init"].addTransition(_main_server_init_0) # transition /main/server/binding _main_server_binding_0 = Transition(self, self.states["/main/server/binding"], [self.states["/main/server/listening"]]) _main_server_binding_0.setTrigger(Event("bound_socket", "socket_in")) _main_server_binding_0.setGuard(self._main_server_binding_0_guard) self.states["/main/server/binding"].addTransition(_main_server_binding_0) # transition /main/server/listening _main_server_listening_0 = Transition(self, self.states["/main/server/listening"], [self.states["/main/server/accepting"]]) _main_server_listening_0.setAction(self._main_server_listening_0_exec) _main_server_listening_0.setTrigger(Event("listened_socket", "socket_in")) _main_server_listening_0.setGuard(self._main_server_listening_0_guard) self.states["/main/server/listening"].addTransition(_main_server_listening_0) # transition /main/server/accepting _main_server_accepting_0 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]]) _main_server_accepting_0.setAction(self._main_server_accepting_0_exec) _main_server_accepting_0.setTrigger(Event("accepted_socket", "socket_in")) self.states["/main/server/accepting"].addTransition(_main_server_accepting_0) _main_server_accepting_1 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]]) _main_server_accepting_1.setAction(self._main_server_accepting_1_exec) _main_server_accepting_1.setTrigger(Event("instance_created", None)) self.states["/main/server/accepting"].addTransition(_main_server_accepting_1) _main_server_accepting_2 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]]) _main_server_accepting_2.setTrigger(Event("_0after")) self.states["/main/server/accepting"].addTransition(_main_server_accepting_2) # transition /main/close_socket/close _main_close_socket_close_0 = Transition(self, self.states["/main/close_socket/close"], [self.states["/main/close_socket/close"]]) _main_close_socket_close_0.setAction(self._main_close_socket_close_0_exec) _main_close_socket_close_0.setTrigger(Event("close_socket", None)) self.states["/main/close_socket/close"].addTransition(_main_close_socket_close_0) def _main_server_init_enter(self): self.big_step.outputEvent(Event("create_socket", "socket_out", [])) def _main_server_binding_enter(self): self.big_step.outputEvent(Event("bind_socket", "socket_out", [self.socket, (self.address, self.port)])) def _main_server_listening_enter(self): self.big_step.outputEvent(Event("listen_socket", "socket_out", [self.socket])) def _main_server_accepting_enter(self): self.addTimer(0, 1.0) def _main_server_accepting_exit(self): self.removeTimer(0) def _main_forward_forward_0_exec(self, parameters): association_name = parameters[0] data = parameters[1] print("Forward") self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [association_name, data])])) def _main_server_init_0_exec(self, parameters): socket = parameters[0] self.socket = socket def _main_server_binding_0_guard(self, parameters): socket = parameters[0] return self.socket == socket def _main_server_listening_0_exec(self, parameters): socket = parameters[0] self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket])) def _main_server_listening_0_guard(self, parameters): socket = parameters[0] return self.socket == socket def _main_server_accepting_0_exec(self, parameters): socket = parameters[0] connected_socket = parameters[1] self.big_step.outputEventOM(Event("create_instance", None, [self, 'sockets', 'Socket', connected_socket])) self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket])) def _main_server_accepting_1_exec(self, parameters): instancename = parameters[0] self.big_step.outputEventOM(Event("start_instance", None, [self, instancename])) self.big_step.outputEventOM(Event("narrow_cast", None, [self, instancename, Event("set_association_name", None, [instancename])])) def _main_close_socket_close_0_exec(self, parameters): association_name = parameters[0] self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name])) def initializeStatechart(self): # enter default state self.default_targets = self.states["/main"].getEffectiveTargetStates() RuntimeClassBase.initializeStatechart(self) class Socket(RuntimeClassBase): def __init__(self, controller, my_socket): 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 Socket.user_defined_constructor(self, my_socket) def user_defined_constructor(self, my_socket): self.socket = my_socket self.received_data = "" self.send_data = "" self.closed = False self.association_name = None 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, self) # state /connected self.states["/connected"] = ParallelState(2, self) # state /connected/listening self.states["/connected/listening"] = State(3, self) # state /connected/listening/listen self.states["/connected/listening/listen"] = State(4, self) self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter) # state /connected/listening/closed self.states["/connected/listening/closed"] = State(5, self) self.states["/connected/listening/closed"].setEnter(self._connected_listening_closed_enter) # state /connected/sending self.states["/connected/sending"] = State(6, self) # state /connected/sending/waiting_for_data self.states["/connected/sending/waiting_for_data"] = State(7, self) # state /connected/sending/transferring self.states["/connected/sending/transferring"] = State(8, self) # state /connected/queueing self.states["/connected/queueing"] = State(9, self) # state /connected/queueing/queueing self.states["/connected/queueing/queueing"] = State(10, self) # state /connected/parsing self.states["/connected/parsing"] = State(11, self) # state /connected/parsing/wait_for_header self.states["/connected/parsing/wait_for_header"] = State(12, self) # state /connected/parsing/closing self.states["/connected/parsing/closing"] = State(13, self) self.states["/connected/parsing/closing"].setEnter(self._connected_parsing_closing_enter) self.states["/connected/parsing/closing"].setExit(self._connected_parsing_closing_exit) # state /connected/parsing/wait_for_payload self.states["/connected/parsing/wait_for_payload"] = State(14, self) # state /close self.states["/close"] = State(15, self) self.states["/close"].setEnter(self._close_enter) # add children self.states[""].addChild(self.states["/init"]) self.states[""].addChild(self.states["/connected"]) self.states[""].addChild(self.states["/close"]) 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/closed"]) 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/closing"]) self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"]) self.states[""].fixTree() self.states[""].default_state = self.states["/init"] 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["/connected"]]) _init_0.setAction(self._init_0_exec) _init_0.setTrigger(Event("set_association_name", None)) self.states["/init"].addTransition(_init_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/closed"]]) _connected_listening_listen_1.setAction(self._connected_listening_listen_1_exec) _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", None)) 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) _connected_parsing_wait_for_header_1 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/closing"]]) _connected_parsing_wait_for_header_1.setTrigger(None) _connected_parsing_wait_for_header_1.setGuard(self._connected_parsing_wait_for_header_1_guard) self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_1) # transition /connected/parsing/closing _connected_parsing_closing_0 = Transition(self, self.states["/connected/parsing/closing"], [self.states["/connected/parsing/closing"]]) _connected_parsing_closing_0.setAction(self._connected_parsing_closing_0_exec) _connected_parsing_closing_0.setTrigger(Event("_0after")) self.states["/connected/parsing/closing"].addTransition(_connected_parsing_closing_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) # transition /connected _connected_0 = Transition(self, self.states["/connected"], [self.states["/close"]]) _connected_0.setTrigger(Event("close", None)) self.states["/connected"].addTransition(_connected_0) def _connected_listening_listen_enter(self): self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket])) def _connected_listening_closed_enter(self): self.closed = True def _connected_parsing_closing_enter(self): self.addTimer(0, 0.0) def _connected_parsing_closing_exit(self): self.removeTimer(0) def _close_enter(self): self.big_step.outputEvent(Event("close_socket", "socket_out", [self.socket])) self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("close_socket", None, [self.association_name])])) def _init_0_exec(self, parameters): association_name = parameters[0] self.association_name = association_name def _connected_listening_listen_0_exec(self, parameters): socket = parameters[0] data = parameters[1] self.received_data += data self.raiseInternalEvent(Event("received_data", None, [])) 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_exec(self, parameters): socket = parameters[0] data = parameters[1] self.raiseInternalEvent(Event("received_data", None, [])) 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] #post_data = "&".join(["%s=%s" % (urllib.quote(k), urllib.quote(v)) for k, v in data.iteritems()]) #post_data = "&".join(["%s=%s" % (k, v) for k, v in data.iteritems()]) post_data = data self.send_data += "HTTP/1.0 200 OK\r\n" self.send_data += "Content-Length: %s\r\n" % len(post_data) self.send_data += "Content-Type: %s; charset=UTF-8\r\n" % "text/plain" self.send_data += "\r\n" self.send_data += str(post_data) 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)[0] 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 and self.received_data.startswith('POST') def _connected_parsing_wait_for_header_1_guard(self, parameters): return self.closed and len(self.received_data) == 0 def _connected_parsing_closing_0_exec(self, parameters): self.raiseInternalEvent(Event("close", None, [])) def _connected_parsing_wait_for_payload_0_exec(self, parameters): if self.length == float('inf'): data = self.received_data self.received_data = "" else: data = self.received_data[:self.length] self.received_data = self.received_data[self.length:] print("Got data: " + str(data)) # We support POST data only, so everything is in the data #try: # params = dict([p.split('=') for p in data.split('&')]) # data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()} #except: # data = {} self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [self.association_name, data])])) def _connected_parsing_wait_for_payload_0_guard(self, parameters): return len(self.received_data) >= self.length or self.closed 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 == "Echo": instance = Echo(self.controller, construct_params[0]) instance.associations = {} instance.associations["to_server"] = Association("Server", 1, 1) elif class_name == "Server": instance = Server(self.controller, construct_params[0], construct_params[1]) instance.associations = {} instance.associations["sockets"] = Association("Socket", 0, -1) instance.associations["parent"] = Association("Echo", 1, 1) elif class_name == "Socket": instance = Socket(self.controller, construct_params[0]) instance.associations = {} instance.associations["parent"] = Association("Server", 1, 1) else: raise Exception("Cannot instantiate class " + class_name) return instance class Controller(ThreadsControllerBase): def __init__(self, params, 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.addOutputPort("socket_out") self.object_manager.createInstance("Echo", [params])