http_client.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. """
  2. Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
  3. Date: Thu Aug 24 10:10:13 2017
  4. Model author: Yentl Van Tendeloo
  5. Model name: HTTP client
  6. Model description:
  7. HTTP client.
  8. """
  9. from sccd.runtime.statecharts_core import *
  10. import uuid
  11. # package "HTTP client"
  12. class HTTPClient(RuntimeClassBase):
  13. def __init__(self, controller):
  14. RuntimeClassBase.__init__(self, controller)
  15. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  16. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  17. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  18. self.semantics.priority = StatechartSemantics.SourceParent
  19. self.semantics.concurrency = StatechartSemantics.Single
  20. # build Statechart structure
  21. self.build_statechart_structure()
  22. # call user defined constructor
  23. HTTPClient.user_defined_constructor(self)
  24. def user_defined_constructor(self):
  25. self.socket = None
  26. self.received_data = ""
  27. self.send_data = ""
  28. self.queue = []
  29. self.IDs = []
  30. def user_defined_destructor(self):
  31. pass
  32. # builds Statechart structure
  33. def build_statechart_structure(self):
  34. # state <root>
  35. self.states[""] = State(0, "", self)
  36. # state /init
  37. self.states["/init"] = State(1, "/init", self)
  38. self.states["/init"].setEnter(self._init_enter)
  39. # state /waiting
  40. self.states["/waiting"] = State(2, "/waiting", self)
  41. self.states["/waiting"].setEnter(self._waiting_enter)
  42. # state /connecting
  43. self.states["/connecting"] = State(3, "/connecting", self)
  44. self.states["/connecting"].setEnter(self._connecting_enter)
  45. self.states["/connecting"].setExit(self._connecting_exit)
  46. # state /connected
  47. self.states["/connected"] = ParallelState(4, "/connected", self)
  48. # state /connected/listening
  49. self.states["/connected/listening"] = State(5, "/connected/listening", self)
  50. # state /connected/listening/listen
  51. self.states["/connected/listening/listen"] = State(6, "/connected/listening/listen", self)
  52. self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter)
  53. # state /connected/listening/close
  54. self.states["/connected/listening/close"] = State(7, "/connected/listening/close", self)
  55. # state /connected/sending
  56. self.states["/connected/sending"] = State(8, "/connected/sending", self)
  57. # state /connected/sending/waiting_for_data
  58. self.states["/connected/sending/waiting_for_data"] = State(9, "/connected/sending/waiting_for_data", self)
  59. # state /connected/sending/transferring
  60. self.states["/connected/sending/transferring"] = State(10, "/connected/sending/transferring", self)
  61. # state /connected/queueing
  62. self.states["/connected/queueing"] = State(11, "/connected/queueing", self)
  63. # state /connected/queueing/queueing
  64. self.states["/connected/queueing/queueing"] = State(12, "/connected/queueing/queueing", self)
  65. self.states["/connected/queueing/queueing"].setEnter(self._connected_queueing_queueing_enter)
  66. # state /connected/parsing
  67. self.states["/connected/parsing"] = State(13, "/connected/parsing", self)
  68. # state /connected/parsing/wait_for_header
  69. self.states["/connected/parsing/wait_for_header"] = State(14, "/connected/parsing/wait_for_header", self)
  70. # state /connected/parsing/wait_for_payload
  71. self.states["/connected/parsing/wait_for_payload"] = State(15, "/connected/parsing/wait_for_payload", self)
  72. # add children
  73. self.states[""].addChild(self.states["/init"])
  74. self.states[""].addChild(self.states["/waiting"])
  75. self.states[""].addChild(self.states["/connecting"])
  76. self.states[""].addChild(self.states["/connected"])
  77. self.states["/connected"].addChild(self.states["/connected/listening"])
  78. self.states["/connected"].addChild(self.states["/connected/sending"])
  79. self.states["/connected"].addChild(self.states["/connected/queueing"])
  80. self.states["/connected"].addChild(self.states["/connected/parsing"])
  81. self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"])
  82. self.states["/connected/listening"].addChild(self.states["/connected/listening/close"])
  83. self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"])
  84. self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"])
  85. self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"])
  86. self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"])
  87. self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"])
  88. self.states[""].fixTree()
  89. self.states[""].default_state = self.states["/init"]
  90. self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"]
  91. self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"]
  92. self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"]
  93. self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"]
  94. # transition /init
  95. _init_0 = Transition(self, self.states["/init"], [self.states["/waiting"]])
  96. _init_0.setAction(self._init_0_exec)
  97. _init_0.setTrigger(Event("created_socket", "socket_in"))
  98. _init_0.setGuard(self._init_0_guard)
  99. self.states["/init"].addTransition(_init_0)
  100. # transition /waiting
  101. _waiting_0 = Transition(self, self.states["/waiting"], [self.states["/connecting"]])
  102. _waiting_0.setAction(self._waiting_0_exec)
  103. _waiting_0.setTrigger(Event("connect", "request_in"))
  104. self.states["/waiting"].addTransition(_waiting_0)
  105. # transition /connecting
  106. _connecting_0 = Transition(self, self.states["/connecting"], [self.states["/connected"]])
  107. _connecting_0.setAction(self._connecting_0_exec)
  108. _connecting_0.setTrigger(Event("connected_socket", "socket_in"))
  109. _connecting_0.setGuard(self._connecting_0_guard)
  110. self.states["/connecting"].addTransition(_connecting_0)
  111. _connecting_1 = Transition(self, self.states["/connecting"], [self.states["/waiting"]])
  112. _connecting_1.setAction(self._connecting_1_exec)
  113. _connecting_1.setTrigger(Event("_0after"))
  114. self.states["/connecting"].addTransition(_connecting_1)
  115. # transition /connected/listening/listen
  116. _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]])
  117. _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec)
  118. _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in"))
  119. _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard)
  120. self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0)
  121. _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/close"]])
  122. _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in"))
  123. _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard)
  124. self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1)
  125. # transition /connected/sending/waiting_for_data
  126. _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]])
  127. _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec)
  128. _connected_sending_waiting_for_data_0.setTrigger(None)
  129. _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard)
  130. self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0)
  131. # transition /connected/sending/transferring
  132. _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]])
  133. _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec)
  134. _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in"))
  135. _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard)
  136. self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0)
  137. # transition /connected/queueing/queueing
  138. _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]])
  139. _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec)
  140. _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", "request_in"))
  141. self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0)
  142. # transition /connected/parsing/wait_for_header
  143. _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]])
  144. _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec)
  145. _connected_parsing_wait_for_header_0.setTrigger(None)
  146. _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard)
  147. self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0)
  148. # transition /connected/parsing/wait_for_payload
  149. _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
  150. _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec)
  151. _connected_parsing_wait_for_payload_0.setTrigger(None)
  152. _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard)
  153. self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0)
  154. _connected_parsing_wait_for_payload_1 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
  155. _connected_parsing_wait_for_payload_1.setAction(self._connected_parsing_wait_for_payload_1_exec)
  156. _connected_parsing_wait_for_payload_1.setTrigger(None)
  157. _connected_parsing_wait_for_payload_1.setGuard(self._connected_parsing_wait_for_payload_1_guard)
  158. self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_1)
  159. def _init_enter(self):
  160. self.ID = str(uuid.uuid4())
  161. self.big_step.outputEvent(Event("create_socket", "socket_out", [self.ID]))
  162. def _waiting_enter(self):
  163. self.big_step.outputEvent(Event("http_client_initialized", "request_out", []))
  164. def _connecting_enter(self):
  165. self.addTimer(0, self.timeout)
  166. self.big_step.outputEvent(Event("connect_socket", "socket_out", [self.socket, self.address]))
  167. def _connecting_exit(self):
  168. self.removeTimer(0)
  169. def _connected_listening_listen_enter(self):
  170. self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
  171. def _connected_queueing_queueing_enter(self):
  172. pass
  173. def _init_0_exec(self, parameters):
  174. socket = parameters[0]
  175. ID = parameters[1]
  176. self.socket = socket
  177. def _init_0_guard(self, parameters):
  178. socket = parameters[0]
  179. ID = parameters[1]
  180. return self.ID == ID
  181. def _waiting_0_exec(self, parameters):
  182. address = parameters[0]
  183. timeout = parameters[1]
  184. self.address = address
  185. self.timeout = timeout
  186. print("Connecting")
  187. def _connecting_0_exec(self, parameters):
  188. socket = parameters[0]
  189. self.big_step.outputEvent(Event("http_client_ready", "request_out", []))
  190. def _connecting_0_guard(self, parameters):
  191. socket = parameters[0]
  192. return self.socket == socket
  193. def _connecting_1_exec(self, parameters):
  194. self.big_step.outputEvent(Event("http_client_timeout", "request_out", []))
  195. def _connected_listening_listen_0_exec(self, parameters):
  196. socket = parameters[0]
  197. data = parameters[1]
  198. self.received_data += data
  199. def _connected_listening_listen_0_guard(self, parameters):
  200. socket = parameters[0]
  201. data = parameters[1]
  202. return (self.socket == socket) and (len(data) > 0)
  203. def _connected_listening_listen_1_guard(self, parameters):
  204. socket = parameters[0]
  205. data = parameters[1]
  206. return (self.socket == socket) and (len(data) == 0)
  207. def _connected_sending_waiting_for_data_0_exec(self, parameters):
  208. self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
  209. def _connected_sending_waiting_for_data_0_guard(self, parameters):
  210. return len(self.send_data) > 0
  211. def _connected_sending_transferring_0_exec(self, parameters):
  212. socket = parameters[0]
  213. sent_bytes = parameters[1]
  214. self.send_data = self.send_data[sent_bytes:]
  215. def _connected_sending_transferring_0_guard(self, parameters):
  216. socket = parameters[0]
  217. sent_bytes = parameters[1]
  218. return self.socket == socket
  219. def _connected_queueing_queueing_0_exec(self, parameters):
  220. data = parameters[0]
  221. ID = parameters[1]
  222. self.send_data += "POST / HTTP/1.0\r\n"
  223. self.send_data += "Content-Length: %i\r\n" % len(str(data))
  224. self.send_data += "\r\n"
  225. self.send_data += data
  226. self.IDs.append(ID)
  227. def _connected_parsing_wait_for_header_0_exec(self, parameters):
  228. header, self.received_data = self.received_data.split("\r\n\r\n", 1)
  229. header = header.lower()
  230. if "content-length" in header:
  231. _, after = header.split("content-length:", 1)
  232. after, _ = after.split("\r\n", 1)
  233. after = after.strip()
  234. self.length = int(after)
  235. else:
  236. self.length = float('inf')
  237. def _connected_parsing_wait_for_header_0_guard(self, parameters):
  238. return '\r\n\r\n' in self.received_data
  239. def _connected_parsing_wait_for_payload_0_exec(self, parameters):
  240. data = self.received_data[:self.length]
  241. self.received_data = self.received_data[self.length:]
  242. print("Send out data with ID: " + str(data))
  243. self.big_step.outputEvent(Event("HTTP_output", "request_out", [data, self.IDs.pop(0)]))
  244. def _connected_parsing_wait_for_payload_0_guard(self, parameters):
  245. return len(self.received_data) >= self.length and self.IDs[0] is not None
  246. def _connected_parsing_wait_for_payload_1_exec(self, parameters):
  247. print("Ignore data: " + str(self.received_data[:self.length]))
  248. # Drop data
  249. self.received_data = self.received_data[self.length:]
  250. self.IDs.pop(0)
  251. def _connected_parsing_wait_for_payload_1_guard(self, parameters):
  252. return len(self.received_data) >= self.length and self.IDs[0] is None
  253. def initializeStatechart(self):
  254. # enter default state
  255. self.default_targets = self.states["/init"].getEffectiveTargetStates()
  256. RuntimeClassBase.initializeStatechart(self)
  257. class ObjectManager(ObjectManagerBase):
  258. def __init__(self, controller):
  259. ObjectManagerBase.__init__(self, controller)
  260. def instantiate(self, class_name, construct_params):
  261. if class_name == "HTTPClient":
  262. instance = HTTPClient(self.controller)
  263. instance.associations = {}
  264. else:
  265. raise Exception("Cannot instantiate class " + class_name)
  266. return instance
  267. class Controller(ThreadsControllerBase):
  268. def __init__(self, keep_running = None, behind_schedule_callback = None):
  269. if keep_running == None: keep_running = True
  270. if behind_schedule_callback == None: behind_schedule_callback = None
  271. ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
  272. self.addInputPort("socket_in")
  273. self.addInputPort("request_in")
  274. self.addOutputPort("socket_out")
  275. self.addOutputPort("request_out")
  276. self.object_manager.createInstance("HTTPClient", [])