Advertisement
melzneni

TURTI_WebsocketProtocol

Oct 1st, 2021 (edited)
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 KB | None | 0 0
  1. Protocol = {}
  2. Protocol.__index = Protocol
  3.  
  4. ProtocolWebsocket = {}
  5. ProtocolWebsocket.__index = ProtocolWebsocket
  6.  
  7. function Protocol:new()
  8. local protocol = {}
  9. setmetatable(protocol, self)
  10. protocol.__index = protocol
  11. return protocol
  12. end
  13.  
  14. function Protocol:setOnOpen(f)
  15. self.onOpen = f
  16. end
  17.  
  18. function Protocol:setOnClose(f)
  19. self.onClose = f
  20. end
  21.  
  22. function Protocol:setOnMessage(f)
  23. self.onMessage = f
  24. end
  25.  
  26. function Protocol:send(msg)
  27. self.exSend(msg)
  28. end
  29.  
  30. function ProtocolWebsocket:new(url, protocol)
  31. local protocolWebsocket = {}
  32. setmetatable(protocolWebsocket, self)
  33. protocolWebsocket.__index = protocolWebsocket
  34. protocolWebsocket.url = url .. "?computer_id=" .. os.getComputerID()
  35. protocolWebsocket.startProtocol = protocol
  36. protocolWebsocket.protocolChangeHandshakeRunning = false
  37. protocolWebsocket.protocolChangeHandshakeDoneReceived = true
  38. protocolWebsocket.protocolChangeHandshakeClientDone = false
  39. return protocolWebsocket
  40. end
  41.  
  42. function ProtocolWebsocket:close()
  43. self.alive = false
  44. self.websocket.close()
  45. end
  46.  
  47. function ProtocolWebsocket:start(unsupportedEventHandler)
  48. local websocket, err = http.websocket(self.url)
  49. if not websocket then
  50. error(err)
  51. end
  52. self.websocket = websocket;
  53. self.alive = true
  54. self:setProtocol(self.startProtocol)
  55. if self.protocol.onOpen then
  56. self.protocol.onOpen()
  57. end
  58. while self.alive do
  59. local type, url, msg, arg = os.pullEvent()
  60. if type == "websocket_message" then
  61. if url == self.url then
  62. self:handleWebsocketMessage(msg)
  63. end
  64. elseif type == "websocket_closed" then
  65. if self.protocol.onClose then
  66. self.alive = false
  67. self.protocol.onClose(tonumber(arg), msg)
  68. end
  69. else
  70. if unsupportedEventHandler then
  71. unsupportedEventHandler(type, url, msg, arg)
  72. end
  73. end
  74. end
  75. end
  76.  
  77. function ProtocolWebsocket:handleWebsocketMessage(msg)
  78. if msg:sub(1, 1) == '&' then
  79. if msg:sub(2, 2) == '0' then
  80. if self.protocolChangeHandshakeRunning then
  81. error("io isn't available during protocol change handshake");
  82. elseif not self.protocolChangeHandshakeDoneReceived then
  83. self.protocolChangeHandshakeDoneReceived = true;
  84. if self.protocol.onOpen then
  85. self.protocol.onOpen()
  86. end
  87. end
  88. if self.protocol.onMessage then
  89. self.protocol.onMessage(msg:sub(3, #msg))
  90. end
  91. elseif msg:sub(2, 2) == '1' then
  92. msg = msg:sub(3, #msg)
  93. if msg:sub(1, 15) == "switchProtocol:" then
  94. local type = tonumber(msg.sub(16, #msg));
  95. self.protocolChangeHandshakeRunning = true;
  96. self.protocolChangeHandshakeDoneReceived = false;
  97. if self.protocol.onClose then
  98. self.alive = false
  99. self.protocol.onClose(1000, "protocol change")
  100. end
  101. if not self.switchProtocol then
  102. error("protocol-switch handler 'onSwitchProtocol' is not set")
  103. end
  104. self.setProtocol(self.onSwitchProtocol(type));
  105. self.sendInternalMessage("getProtocolDone");
  106. self.protocolChangeHandshakeRunning = false;
  107. end
  108. elseif msg == "getProtocolDone" then
  109. self.protocolChangeHandshakeClientDone = true;
  110. elseif msg == "switchProtocolDone" then
  111. if not self.protocolChangeHandshakeDoneReceived then
  112. self.protocolChangeHandshakeDoneReceived = true;
  113. if self.protocol.onOpen then
  114. self.protocol.onOpen()
  115. end
  116. end
  117. else
  118. error("invalid message" .. msg)
  119. end
  120. else
  121. error("invalid message" .. msg)
  122. end
  123. end
  124.  
  125. function ProtocolWebsocket:sendInternalMessage(msg)
  126. self.websocket:send("&1" + msg);
  127. end
  128.  
  129. function ProtocolWebsocket:setProtocol(protocol)
  130. if self.protocol then
  131. self.protocol.exSend = nil
  132. end
  133. self.protocol = protocol
  134. protocol.exSend = function(data)
  135. if (self.protocolChangeHandshakeRunning) then
  136. error("io isn't available during protocol change handshake")
  137. end
  138. self.websocket.send("&0" .. data)
  139. end
  140. end
  141.  
  142. ActionProtocol = Protocol:new()
  143.  
  144. function ActionProtocol:new()
  145. local ap = Protocol:new()
  146. setmetatable(ap, self)
  147. ap.__index = self
  148. ap.answers = {}
  149. ap.currentActionId = 0
  150. ap.argumentStorage = {}
  151. ap.argumentStorageSize = 0
  152. ap:setOnMessage(function(msg)
  153. if msg:sub(1, 1) ~= "@" then
  154. error("invalid message: " .. msg)
  155. end
  156. if msg:sub(2, 2) == "0" then
  157. local action = splitComma(msg, 3)
  158. if action[1] == "_newArgument" then
  159. table.insert(ap.argumentStorage, action[2])
  160. ap.argumentStorageSize = ap.argumentStorageSize + 1
  161. elseif action[1] == "_addToLastArgument" then
  162. ap.argumentStorage[ap.argumentStorageSize] = ap.argumentStorage[ap.argumentStorageSize] .. action[2]
  163. else
  164. if ap.onAction then
  165. ap.onAction(concatTables(
  166. concatTables({ action[1] }, ap.argumentStorage),
  167. subArray(action, 2)))
  168. end
  169. ap.argumentStorage = {}
  170. ap.argumentStorageSize = 0
  171. end
  172. elseif msg:sub(2, 2) == "1" then
  173. local action = splitComma(msg, 3)
  174. local actionId = tonumber(action[1])
  175. local answer
  176. if ap.onAction then
  177. answer = ap.onAction(subArray(action, 2))
  178. end
  179. if not answer then
  180. answer = {}
  181. end
  182. ap:send(createMessage("2" .. actionId .. ",", answer))
  183. elseif msg:sub(2, 2) == "2" then
  184. local action = splitComma(msg, 3)
  185. local actionId = tonumber(action[1])
  186. ap.answers[actionId] = subArray(action, 2)
  187. else
  188. print("unknownMessage: "..msg)
  189. end
  190. end)
  191. return ap
  192. end
  193.  
  194. function concatTables(t1, t2)
  195. if not t1 then
  196. return t2
  197. elseif not t2 then
  198. return t1
  199. end
  200. for _, v in ipairs(t2) do
  201. table.insert(t1, v)
  202. end
  203. return t1
  204. end
  205.  
  206. function subArray(array, from)
  207. local result = {}
  208. for i, v in ipairs(array) do
  209. if i >= from then
  210. table.insert(result, v)
  211. end
  212. end
  213. return result
  214. end
  215.  
  216. function splitComma(msg, start)
  217. local action = {}
  218. local current = ""
  219. local escaped = false
  220. for i = start, #msg do
  221. local c = msg:sub(i, i)
  222. if not escaped then
  223. if c == "\\" then
  224. escaped = true
  225. elseif c == "," then
  226. table.insert(action, current)
  227. current = ""
  228. else
  229. current = current .. c
  230. end
  231. else
  232. current = current .. c
  233. escaped = false
  234. end
  235. end
  236. table.insert(action, current)
  237. return action
  238. end
  239.  
  240. function ActionProtocol:setOnAction(f)
  241. self.onAction = f
  242. end
  243.  
  244. function createMessage(prefix, args)
  245. local result = "@" .. prefix
  246. for i, v in ipairs(args) do
  247. if i ~= 1 then
  248. result = result .. ","
  249. end
  250. result = result .. escapeInMessage(v, ",", "\\")
  251. end
  252. return result
  253. end
  254.  
  255. function ActionProtocol:execute(...)
  256. self:send(createMessage("0", { ... }))
  257. end
  258.  
  259. function ActionProtocol:executeGetAnswer(...)
  260. local id = self.currentActionId
  261. self.currentActionId = self.currentActionId + 1
  262. self:send(createMessage("1" .. id .. ",", { ... }))
  263. while true do
  264. local answer = self.answers[id]
  265. if answer then
  266. return answer
  267. end
  268. coroutine.yield()
  269. end
  270. end
  271.  
  272. function escapeInMessage(msg, ch, chEscape)
  273. local result = ""
  274. for i = 1, #msg do
  275. local c = msg:sub(i, i)
  276. if c == ch or c == chEscape then
  277. result = result .. "\\"
  278. end
  279. result = result .. c
  280. end
  281. return result
  282. end
  283.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement