client.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. """
  2. Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
  3. Date: Fri Aug 05 16:08:35 2016
  4. Model author: Yentl Van Tendeloo
  5. Model name: HTTP client
  6. Model description:
  7. HTTP client in SCCD
  8. """
  9. from sccd.runtime.statecharts_core import *
  10. import time
  11. import os
  12. import urllib
  13. import sys
  14. import json
  15. # package "HTTP client"
  16. class Prompt(RuntimeClassBase):
  17. def __init__(self, controller):
  18. RuntimeClassBase.__init__(self, controller)
  19. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  20. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  21. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  22. self.semantics.priority = StatechartSemantics.SourceParent
  23. self.semantics.concurrency = StatechartSemantics.Single
  24. # build Statechart structure
  25. self.build_statechart_structure()
  26. # call user defined constructor
  27. Prompt.user_defined_constructor(self)
  28. def user_defined_constructor(self):
  29. self.counter = 0
  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, self)
  38. self.states["/init"].setEnter(self._init_enter)
  39. # state /initializing
  40. self.states["/initializing"] = State(2, self)
  41. self.states["/initializing"].setEnter(self._initializing_enter)
  42. self.states["/initializing"].setExit(self._initializing_exit)
  43. # state /send_request
  44. self.states["/send_request"] = State(3, self)
  45. self.states["/send_request"].setEnter(self._send_request_enter)
  46. self.states["/send_request"].setExit(self._send_request_exit)
  47. # state /wait_reply
  48. self.states["/wait_reply"] = State(4, self)
  49. self.states["/wait_reply"].setEnter(self._wait_reply_enter)
  50. self.states["/wait_reply"].setExit(self._wait_reply_exit)
  51. # add children
  52. self.states[""].addChild(self.states["/init"])
  53. self.states[""].addChild(self.states["/initializing"])
  54. self.states[""].addChild(self.states["/send_request"])
  55. self.states[""].addChild(self.states["/wait_reply"])
  56. self.states[""].fixTree()
  57. self.states[""].default_state = self.states["/init"]
  58. # transition /init
  59. _init_0 = Transition(self, self.states["/init"], [self.states["/initializing"]])
  60. _init_0.setAction(self._init_0_exec)
  61. _init_0.setTrigger(Event("instance_created", None))
  62. self.states["/init"].addTransition(_init_0)
  63. # transition /initializing
  64. _initializing_0 = Transition(self, self.states["/initializing"], [self.states["/initializing"]])
  65. _initializing_0.setTrigger(Event("_0after"))
  66. self.states["/initializing"].addTransition(_initializing_0)
  67. _initializing_1 = Transition(self, self.states["/initializing"], [self.states["/send_request"]])
  68. _initializing_1.setTrigger(Event("http_client_ready", None))
  69. self.states["/initializing"].addTransition(_initializing_1)
  70. # transition /send_request
  71. _send_request_0 = Transition(self, self.states["/send_request"], [self.states["/wait_reply"]])
  72. _send_request_0.setAction(self._send_request_0_exec)
  73. _send_request_0.setTrigger(Event("_1after"))
  74. self.states["/send_request"].addTransition(_send_request_0)
  75. # transition /wait_reply
  76. _wait_reply_0 = Transition(self, self.states["/wait_reply"], [self.states["/wait_reply"]])
  77. _wait_reply_0.setTrigger(Event("_2after"))
  78. self.states["/wait_reply"].addTransition(_wait_reply_0)
  79. _wait_reply_1 = Transition(self, self.states["/wait_reply"], [self.states["/send_request"]])
  80. _wait_reply_1.setAction(self._wait_reply_1_exec)
  81. _wait_reply_1.setTrigger(Event("HTTP_output", None))
  82. self.states["/wait_reply"].addTransition(_wait_reply_1)
  83. def _init_enter(self):
  84. self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_server', 'HTTPClient', '127.0.0.1', 8080]))
  85. def _initializing_enter(self):
  86. self.addTimer(0, 1.0)
  87. def _initializing_exit(self):
  88. self.removeTimer(0)
  89. def _send_request_enter(self):
  90. self.addTimer(1, 1)
  91. def _send_request_exit(self):
  92. self.removeTimer(1)
  93. def _wait_reply_enter(self):
  94. self.addTimer(2, 1.0)
  95. def _wait_reply_exit(self):
  96. self.removeTimer(2)
  97. def _init_0_exec(self, parameters):
  98. instancename = parameters[0]
  99. self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
  100. def _send_request_0_exec(self, parameters):
  101. self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_server', Event("HTTP_input", None, [str(self.counter), 'parent'])]))
  102. print("Sending request: %s" % self.counter)
  103. self.counter += 1
  104. def _wait_reply_1_exec(self, parameters):
  105. data = parameters[0]
  106. print("Got response: %s" % data)
  107. def initializeStatechart(self):
  108. # enter default state
  109. states = self.states["/init"].getEffectiveTargetStates()
  110. self.updateConfiguration(states)
  111. for state in states:
  112. if state.enter:
  113. state.enter()
  114. class HTTPClient(RuntimeClassBase):
  115. def __init__(self, controller, hostname, port):
  116. RuntimeClassBase.__init__(self, controller)
  117. self.semantics.big_step_maximality = StatechartSemantics.TakeMany
  118. self.semantics.internal_event_lifeline = StatechartSemantics.Queue
  119. self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
  120. self.semantics.priority = StatechartSemantics.SourceParent
  121. self.semantics.concurrency = StatechartSemantics.Single
  122. # build Statechart structure
  123. self.build_statechart_structure()
  124. # call user defined constructor
  125. HTTPClient.user_defined_constructor(self, hostname, port)
  126. def user_defined_constructor(self, hostname, port):
  127. self.socket = None
  128. self.destination = (hostname, port)
  129. self.received_data = ""
  130. self.send_data = ""
  131. self.queue = []
  132. self.destinations = []
  133. def user_defined_destructor(self):
  134. pass
  135. # builds Statechart structure
  136. def build_statechart_structure(self):
  137. # state <root>
  138. self.states[""] = State(0, self)
  139. # state /init
  140. self.states["/init"] = State(1, self)
  141. self.states["/init"].setEnter(self._init_enter)
  142. # state /connecting
  143. self.states["/connecting"] = State(2, self)
  144. self.states["/connecting"].setEnter(self._connecting_enter)
  145. # state /connected
  146. self.states["/connected"] = ParallelState(3, self)
  147. # state /connected/listening
  148. self.states["/connected/listening"] = State(4, self)
  149. # state /connected/listening/listen
  150. self.states["/connected/listening/listen"] = State(5, self)
  151. self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter)
  152. # state /connected/listening/close
  153. self.states["/connected/listening/close"] = State(6, self)
  154. # state /connected/sending
  155. self.states["/connected/sending"] = State(7, self)
  156. # state /connected/sending/waiting_for_data
  157. self.states["/connected/sending/waiting_for_data"] = State(8, self)
  158. # state /connected/sending/transferring
  159. self.states["/connected/sending/transferring"] = State(9, self)
  160. # state /connected/queueing
  161. self.states["/connected/queueing"] = State(10, self)
  162. # state /connected/queueing/queueing
  163. self.states["/connected/queueing/queueing"] = State(11, self)
  164. self.states["/connected/queueing/queueing"].setEnter(self._connected_queueing_queueing_enter)
  165. # state /connected/parsing
  166. self.states["/connected/parsing"] = State(12, self)
  167. # state /connected/parsing/wait_for_header
  168. self.states["/connected/parsing/wait_for_header"] = State(13, self)
  169. # state /connected/parsing/wait_for_payload
  170. self.states["/connected/parsing/wait_for_payload"] = State(14, self)
  171. # add children
  172. self.states[""].addChild(self.states["/init"])
  173. self.states[""].addChild(self.states["/connecting"])
  174. self.states[""].addChild(self.states["/connected"])
  175. self.states["/connected"].addChild(self.states["/connected/listening"])
  176. self.states["/connected"].addChild(self.states["/connected/sending"])
  177. self.states["/connected"].addChild(self.states["/connected/queueing"])
  178. self.states["/connected"].addChild(self.states["/connected/parsing"])
  179. self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"])
  180. self.states["/connected/listening"].addChild(self.states["/connected/listening/close"])
  181. self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"])
  182. self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"])
  183. self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"])
  184. self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"])
  185. self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"])
  186. self.states[""].fixTree()
  187. self.states[""].default_state = self.states["/init"]
  188. self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"]
  189. self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"]
  190. self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"]
  191. self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"]
  192. # transition /init
  193. _init_0 = Transition(self, self.states["/init"], [self.states["/connecting"]])
  194. _init_0.setAction(self._init_0_exec)
  195. _init_0.setTrigger(Event("created_socket", "socket_in"))
  196. self.states["/init"].addTransition(_init_0)
  197. # transition /connecting
  198. _connecting_0 = Transition(self, self.states["/connecting"], [self.states["/connected"]])
  199. _connecting_0.setAction(self._connecting_0_exec)
  200. _connecting_0.setTrigger(Event("connected_socket", "socket_in"))
  201. _connecting_0.setGuard(self._connecting_0_guard)
  202. self.states["/connecting"].addTransition(_connecting_0)
  203. # transition /connected/listening/listen
  204. _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]])
  205. _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec)
  206. _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in"))
  207. _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard)
  208. self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0)
  209. _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/close"]])
  210. _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in"))
  211. _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard)
  212. self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1)
  213. # transition /connected/sending/waiting_for_data
  214. _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]])
  215. _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec)
  216. _connected_sending_waiting_for_data_0.setTrigger(None)
  217. _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard)
  218. self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0)
  219. # transition /connected/sending/transferring
  220. _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]])
  221. _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec)
  222. _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in"))
  223. _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard)
  224. self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0)
  225. # transition /connected/queueing/queueing
  226. _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]])
  227. _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec)
  228. _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", None))
  229. self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0)
  230. # transition /connected/parsing/wait_for_header
  231. _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]])
  232. _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec)
  233. _connected_parsing_wait_for_header_0.setTrigger(None)
  234. _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard)
  235. self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0)
  236. # transition /connected/parsing/wait_for_payload
  237. _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
  238. _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec)
  239. _connected_parsing_wait_for_payload_0.setTrigger(None)
  240. _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard)
  241. self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0)
  242. def _init_enter(self):
  243. self.big_step.outputEvent(Event("create_socket", "", []))
  244. def _connecting_enter(self):
  245. self.big_step.outputEvent(Event("connect_socket", "", [self.socket, self.destination]))
  246. def _connected_listening_listen_enter(self):
  247. self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
  248. def _connected_queueing_queueing_enter(self):
  249. pass
  250. def _init_0_exec(self, parameters):
  251. socket = parameters[0]
  252. self.socket = socket
  253. def _connecting_0_exec(self, parameters):
  254. socket = parameters[0]
  255. self.big_step.outputEventOM(Event("broad_cast", None, [Event("http_client_ready", None, [])]))
  256. def _connecting_0_guard(self, parameters):
  257. socket = parameters[0]
  258. return self.socket == socket
  259. def _connected_listening_listen_0_exec(self, parameters):
  260. socket = parameters[0]
  261. data = parameters[1]
  262. self.received_data += data
  263. def _connected_listening_listen_0_guard(self, parameters):
  264. socket = parameters[0]
  265. data = parameters[1]
  266. return (self.socket == socket) and (len(data) > 0)
  267. def _connected_listening_listen_1_guard(self, parameters):
  268. socket = parameters[0]
  269. data = parameters[1]
  270. return (self.socket == socket) and (len(data) == 0)
  271. def _connected_sending_waiting_for_data_0_exec(self, parameters):
  272. self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
  273. def _connected_sending_waiting_for_data_0_guard(self, parameters):
  274. return len(self.send_data) > 0
  275. def _connected_sending_transferring_0_exec(self, parameters):
  276. socket = parameters[0]
  277. sent_bytes = parameters[1]
  278. self.send_data = self.send_data[sent_bytes:]
  279. def _connected_sending_transferring_0_guard(self, parameters):
  280. socket = parameters[0]
  281. sent_bytes = parameters[1]
  282. return self.socket == socket
  283. def _connected_queueing_queueing_0_exec(self, parameters):
  284. data = parameters[0]
  285. destination = parameters[1]
  286. self.send_data += "POST / HTTP/1.0\r\n"
  287. self.send_data += "Content-Length: %i\r\n" % len(str(data))
  288. self.send_data += "\r\n"
  289. self.send_data += data
  290. self.destinations.append(destination)
  291. def _connected_parsing_wait_for_header_0_exec(self, parameters):
  292. header, self.received_data = self.received_data.split("\r\n\r\n", 1)
  293. header = header.lower()
  294. if "content-length" in header:
  295. _, after = header.split("content-length:", 1)
  296. after, _ = after.split("\r\n", 1)
  297. after = after.strip()
  298. self.length = int(after)
  299. else:
  300. self.length = float('inf')
  301. def _connected_parsing_wait_for_header_0_guard(self, parameters):
  302. return '\r\n\r\n' in self.received_data
  303. def _connected_parsing_wait_for_payload_0_exec(self, parameters):
  304. data = self.received_data[:self.length]
  305. self.received_data = self.received_data[self.length:]
  306. #params = dict([p.split('=') for p in data.split('&')])
  307. #data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()}
  308. self.big_step.outputEventOM(Event("narrow_cast", None, [self, self.destinations.pop(0), Event("HTTP_output", None, [data])]))
  309. def _connected_parsing_wait_for_payload_0_guard(self, parameters):
  310. return len(self.received_data) >= self.length
  311. def initializeStatechart(self):
  312. # enter default state
  313. states = self.states["/init"].getEffectiveTargetStates()
  314. self.updateConfiguration(states)
  315. for state in states:
  316. if state.enter:
  317. state.enter()
  318. class ObjectManager(ObjectManagerBase):
  319. def __init__(self, controller):
  320. ObjectManagerBase.__init__(self, controller)
  321. def instantiate(self, class_name, construct_params):
  322. if class_name == "Prompt":
  323. instance = Prompt(self.controller)
  324. instance.associations = {}
  325. instance.associations["to_server"] = Association("HTTPClient", 1, 1)
  326. elif class_name == "HTTPClient":
  327. instance = HTTPClient(self.controller, construct_params[0], construct_params[1])
  328. instance.associations = {}
  329. instance.associations["parent"] = Association("Prompt", 1, 1)
  330. else:
  331. raise Exception("Cannot instantiate class " + class_name)
  332. return instance
  333. class Controller(ThreadsControllerBase):
  334. def __init__(self, keep_running = None):
  335. if keep_running == None: keep_running = True
  336. ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running)
  337. self.addInputPort("socket_in")
  338. self.addOutputPort("socket_out")
  339. self.object_manager.createInstance("Prompt", [])