WebSocket.jslib 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. var WebSocketLibrary =
  2. {
  3. $webSocketManager:
  4. {
  5. /*
  6. * Map of instances
  7. *
  8. * Instance structure:
  9. * {
  10. * url: string,
  11. * ws: WebSocket
  12. * }
  13. */
  14. instances: {},
  15. /* Last instance ID */
  16. lastId: 0,
  17. /* Event listeners */
  18. onOpen: null,
  19. onMessage: null,
  20. onError: null,
  21. onClose: null,
  22. },
  23. /**
  24. * Set onOpen callback
  25. *
  26. * @param callback Reference to C# static function
  27. */
  28. WebSocketSetOnOpen: function(callback)
  29. {
  30. webSocketManager.onOpen = callback;
  31. },
  32. /**
  33. * Set onMessage callback
  34. *
  35. * @param callback Reference to C# static function
  36. */
  37. WebSocketSetOnMessage: function(callback)
  38. {
  39. webSocketManager.onMessage = callback;
  40. },
  41. /**
  42. * Set onMessage callback
  43. *
  44. * @param callback Reference to C# static function
  45. */
  46. WebSocketSetOnMessageStr: function(callback)
  47. {
  48. webSocketManager.onMessageStr = callback;
  49. },
  50. /**
  51. * Set onError callback
  52. *
  53. * @param callback Reference to C# static function
  54. */
  55. WebSocketSetOnError: function(callback)
  56. {
  57. webSocketManager.onError = callback;
  58. },
  59. /**
  60. * Set onClose callback
  61. *
  62. * @param callback Reference to C# static function
  63. */
  64. WebSocketSetOnClose: function(callback)
  65. {
  66. webSocketManager.onClose = callback;
  67. },
  68. /**
  69. * Allocate new WebSocket instance struct
  70. *
  71. * @param url Server URL
  72. */
  73. WebSocketAllocate: function(url)
  74. {
  75. var urlStr = UTF8ToString(url);
  76. var id = ++webSocketManager.lastId;
  77. webSocketManager.instances[id] = {
  78. url: urlStr,
  79. ws: null
  80. };
  81. return id;
  82. },
  83. /**
  84. * Remove reference to WebSocket instance
  85. *
  86. * If socket is not closed function will close it but onClose event will not be emitted because
  87. * this function should be invoked by C# WebSocket destructor.
  88. *
  89. * @param instanceId Instance ID
  90. */
  91. WebSocketFree: function(instanceId)
  92. {
  93. var instance = webSocketManager.instances[instanceId];
  94. if (!instance) return 0;
  95. // Close if not closed
  96. if (instance.ws !== null && instance.ws.readyState < 2)
  97. instance.ws.close();
  98. // Remove reference
  99. delete webSocketManager.instances[instanceId];
  100. return 0;
  101. },
  102. /**
  103. * Connect WebSocket to the server
  104. *
  105. * @param instanceId Instance ID
  106. */
  107. WebSocketConnect: function(instanceId)
  108. {
  109. var instance = webSocketManager.instances[instanceId];
  110. if (!instance) return -1;
  111. if (instance.ws !== null) return -2;
  112. instance.ws = new WebSocket(instance.url);
  113. instance.ws.onopen = function()
  114. {
  115. if (webSocketManager.onOpen)
  116. Module.dynCall_vi(webSocketManager.onOpen, instanceId);
  117. };
  118. instance.ws.onmessage = function(ev)
  119. {
  120. if (webSocketManager.onMessage === null)
  121. return;
  122. if (ev.data instanceof ArrayBuffer)
  123. {
  124. var dataBuffer = new Uint8Array(ev.data);
  125. var buffer = _malloc(dataBuffer.length);
  126. HEAPU8.set(dataBuffer, buffer);
  127. try
  128. {
  129. Module.dynCall_viii(webSocketManager.onMessage, instanceId, buffer, dataBuffer.length);
  130. }
  131. finally
  132. {
  133. _free(buffer);
  134. }
  135. }
  136. else if(typeof ev.data == 'string')
  137. {
  138. var length = lengthBytesUTF8(ev.data) + 1;
  139. var buffer = _malloc(length);
  140. stringToUTF8(ev.data, buffer, length);
  141. try
  142. {
  143. Module.dynCall_vii(webSocketManager.onMessageStr, instanceId, buffer);
  144. }
  145. finally
  146. {
  147. _free(buffer);
  148. }
  149. }
  150. else if (ev.data instanceof Blob)
  151. {
  152. var reader = new FileReader();
  153. reader.addEventListener("loadend", function()
  154. {
  155. var dataBuffer = new Uint8Array(reader.result);
  156. var buffer = _malloc(dataBuffer.length);
  157. HEAPU8.set(dataBuffer, buffer);
  158. try
  159. {
  160. Module.dynCall_viii(webSocketManager.onMessage, instanceId, buffer, dataBuffer.length);
  161. }
  162. finally
  163. {
  164. reader = null;
  165. _free(buffer);
  166. }
  167. });
  168. reader.readAsArrayBuffer(ev.data);
  169. }
  170. else
  171. {
  172. console.log("[JSLIB WebSocket] not support message type: ", (typeof ev.data));
  173. }
  174. };
  175. instance.ws.onerror = function(ev)
  176. {
  177. if (webSocketManager.onError)
  178. {
  179. var msg = "WebSocket error.";
  180. var length = lengthBytesUTF8(msg) + 1;
  181. var buffer = _malloc(length);
  182. stringToUTF8(msg, buffer, length);
  183. try
  184. {
  185. Module.dynCall_vii(webSocketManager.onError, instanceId, buffer);
  186. }
  187. finally
  188. {
  189. _free(buffer);
  190. }
  191. }
  192. };
  193. instance.ws.onclose = function(ev)
  194. {
  195. if (webSocketManager.onClose)
  196. {
  197. var msg = ev.reason;
  198. var length = lengthBytesUTF8(msg) + 1;
  199. var buffer = _malloc(length);
  200. stringToUTF8(msg, buffer, length);
  201. try
  202. {
  203. Module.dynCall_viii(webSocketManager.onClose, instanceId, ev.code, buffer);
  204. }
  205. finally
  206. {
  207. _free(buffer);
  208. }
  209. }
  210. instance.ws = null;
  211. };
  212. return 0;
  213. },
  214. /**
  215. * Close WebSocket connection
  216. *
  217. * @param instanceId Instance ID
  218. * @param code Close status code
  219. * @param reasonPtr Pointer to reason string
  220. */
  221. WebSocketClose: function(instanceId, code, reasonPtr)
  222. {
  223. var instance = webSocketManager.instances[instanceId];
  224. if (!instance) return -1;
  225. if (instance.ws === null) return -3;
  226. if (instance.ws.readyState === 2) return -4;
  227. if (instance.ws.readyState === 3) return -5;
  228. var reason = ( reasonPtr ? UTF8ToString(reasonPtr) : undefined );
  229. try
  230. {
  231. instance.ws.close(code, reason);
  232. }
  233. catch(err)
  234. {
  235. return -7;
  236. }
  237. return 0;
  238. },
  239. /**
  240. * Send message over WebSocket
  241. *
  242. * @param instanceId Instance ID
  243. * @param bufferPtr Pointer to the message buffer
  244. * @param length Length of the message in the buffer
  245. */
  246. WebSocketSend: function(instanceId, bufferPtr, length)
  247. {
  248. var instance = webSocketManager.instances[instanceId];
  249. if (!instance) return -1;
  250. if (instance.ws === null) return -3;
  251. if (instance.ws.readyState !== 1) return -6;
  252. instance.ws.send(buffer.slice(bufferPtr, bufferPtr + length));
  253. return 0;
  254. },
  255. /**
  256. * Send message string over WebSocket
  257. *
  258. * @param instanceId Instance ID
  259. * @param stringPtr Pointer to the message string
  260. */
  261. WebSocketSendStr: function(instanceId, stringPtr)
  262. {
  263. var instance = webSocketManager.instances[instanceId];
  264. if (!instance) return -1;
  265. if (instance.ws === null) return -3;
  266. if (instance.ws.readyState !== 1) return -6;
  267. instance.ws.send(UTF8ToString(stringPtr));
  268. return 0;
  269. },
  270. /**
  271. * Return WebSocket readyState
  272. *
  273. * @param instanceId Instance ID
  274. */
  275. WebSocketGetState: function(instanceId)
  276. {
  277. var instance = webSocketManager.instances[instanceId];
  278. if (!instance) return -1;
  279. if (instance.ws === null) return 3;
  280. return instance.ws.readyState;
  281. }
  282. };
  283. autoAddDeps(WebSocketLibrary, '$webSocketManager');
  284. mergeInto(LibraryManager.library, WebSocketLibrary);