target.py 20 KB

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