BestHTTP_WebSocket.jslib 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. var Lib_BEST_HTTP_WebGL_WS_Bridge =
  2. {
  3. $ws: {
  4. webSocketInstances: {},
  5. nextInstanceId : 1,
  6. Set : function(socket) {
  7. ws.webSocketInstances[ws.nextInstanceId] = socket;
  8. return ws.nextInstanceId++;
  9. },
  10. Get : function(id) {
  11. return ws.webSocketInstances[id];
  12. },
  13. Remove: function(id) {
  14. delete ws.webSocketInstances[id];
  15. },
  16. _callOnClose: function(onClose, id, code, reason)
  17. {
  18. var length = lengthBytesUTF8(reason) + 1;
  19. var buffer = _malloc(length);
  20. stringToUTF8Array(reason, HEAPU8, buffer, length);
  21. Runtime.dynCall('viii', onClose, [id, code, buffer]);
  22. _free(buffer);
  23. },
  24. _callOnError: function(errCallback, id, reason)
  25. {
  26. var length = lengthBytesUTF8(reason) + 1;
  27. var buffer = _malloc(length);
  28. stringToUTF8Array(reason, HEAPU8, buffer, length);
  29. Runtime.dynCall('vii', errCallback, [id, buffer]);
  30. _free(buffer);
  31. }
  32. },
  33. WS_Create: function(url, protocol, onOpen, onText, onBinary, onError, onClose)
  34. {
  35. var urlStr = /*encodeURI*/(Pointer_stringify(url))
  36. .replace(/\+/g, '%2B')
  37. .replace(/%252[fF]/ig, '%2F');
  38. var proto = Pointer_stringify(protocol);
  39. console.log('WS_Create(' + urlStr + ', "' + proto + '")');
  40. var socket = {
  41. onError: onError,
  42. onClose: onClose
  43. };
  44. if (proto == '')
  45. socket.socketImpl = new WebSocket(urlStr);
  46. else
  47. socket.socketImpl = new WebSocket(urlStr, [proto]);
  48. var id = ws.nextInstanceId;
  49. socket.socketImpl.binaryType = "arraybuffer";
  50. socket.socketImpl.onopen = function(e) {
  51. console.log(id + ' WS_Create - onOpen');
  52. Runtime.dynCall('vi', onOpen, [id]);
  53. };
  54. socket.socketImpl.onmessage = function (e)
  55. {
  56. // Binary?
  57. if (e.data instanceof ArrayBuffer)
  58. {
  59. var byteArray = new Uint8Array(e.data);
  60. var buffer = _malloc(byteArray.length);
  61. HEAPU8.set(byteArray, buffer);
  62. Runtime.dynCall('viii', onBinary, [id, buffer, byteArray.length]);
  63. _free(buffer);
  64. }
  65. else // Text
  66. {
  67. var length = lengthBytesUTF8(e.data) + 1;
  68. var buffer = _malloc(length);
  69. stringToUTF8Array(e.data, HEAPU8, buffer, length);
  70. Runtime.dynCall('vii', onText, [id, buffer]);
  71. _free(buffer);
  72. }
  73. };
  74. socket.socketImpl.onerror = function (e)
  75. {
  76. console.log(id + ' WS_Create - onError');
  77. // Do not call this, onClose will be called with an apropriate error code and reason
  78. //ws._callOnError(onError, id, "Unknown error.");
  79. };
  80. socket.socketImpl.onclose = function (e) {
  81. console.log(id + ' WS_Create - onClose ' + e.code + ' ' + e.reason);
  82. //if (e.code != 1000)
  83. //{
  84. // if (e.reason != null && e.reason.length > 0)
  85. // ws._callOnError(onError, id, e.reason);
  86. // else
  87. // {
  88. // switch (e.code)
  89. // {
  90. // case 1001: ws._callOnError(onError, id, "Endpoint going away.");
  91. // break;
  92. // case 1002: ws._callOnError(onError, id, "Protocol error.");
  93. // break;
  94. // case 1003: ws._callOnError(onError, id, "Unsupported message.");
  95. // break;
  96. // case 1005: ws._callOnError(onError, id, "No status.");
  97. // break;
  98. // case 1006: ws._callOnError(onError, id, "Abnormal disconnection.");
  99. // break;
  100. // case 1009: ws._callOnError(onError, id, "Data frame too large.");
  101. // break;
  102. // default: ws._callOnError(onError, id, "Error " + e.code);
  103. // }
  104. // }
  105. //}
  106. //else
  107. ws._callOnClose(onClose, id, e.code, e.reason);
  108. };
  109. return ws.Set(socket);
  110. },
  111. WS_GetState: function (id)
  112. {
  113. var socket = ws.Get(id);
  114. if (typeof socket === 'undefined' ||
  115. socket == null ||
  116. typeof socket.socketImpl === 'undefined' ||
  117. socket.socketImpl == null)
  118. return 3; // closed
  119. return socket.socketImpl.readyState;
  120. },
  121. WS_GetBufferedAmount: function (id)
  122. {
  123. var socket = ws.Get(id);
  124. return socket.socketImpl.bufferedAmount;
  125. },
  126. WS_Send_String: function (id, str)
  127. {
  128. var socket = ws.Get(id);
  129. var str = Pointer_stringify(str);
  130. try
  131. {
  132. socket.socketImpl.send(str);
  133. }
  134. catch(e) {
  135. ws._callOnError(socket.onError, id, ' ' + e.name + ': ' + e.message);
  136. }
  137. return socket.socketImpl.bufferedAmount;
  138. },
  139. WS_Send_Binary: function(id, ptr, pos, length)
  140. {
  141. var socket = ws.Get(id);
  142. try
  143. {
  144. var buff = HEAPU8.subarray(ptr + pos, ptr + pos + length);
  145. socket.socketImpl.send(buff /*HEAPU8.buffer.slice(ptr + pos, ptr + pos + length)*/);
  146. }
  147. catch(e) {
  148. ws._callOnError(socket.onError, id, ' ' + e.name + ': ' + e.message);
  149. }
  150. return socket.socketImpl.bufferedAmount;
  151. },
  152. WS_Close: function (id, code, reason)
  153. {
  154. var socket = ws.Get(id);
  155. var reasonStr = Pointer_stringify(reason);
  156. console.log(id + ' WS_Close(' + code + ', ' + reasonStr + ')');
  157. socket.socketImpl.close(/*ulong*/code, reasonStr);
  158. },
  159. WS_Release: function(id)
  160. {
  161. console.log(id + ' WS_Release');
  162. ws.Remove(id);
  163. }
  164. };
  165. autoAddDeps(Lib_BEST_HTTP_WebGL_WS_Bridge, '$ws');
  166. mergeInto(LibraryManager.library, Lib_BEST_HTTP_WebGL_WS_Bridge);