diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-01-08 11:05:45 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-01-08 11:05:45 -0800 |
commit | 828a7ec1348919be61e55c4d55c23b4a148072ac (patch) | |
tree | fc74f919523f6701950274fa5b4c4dbd39703d87 | |
parent | 2d164ea8392eef8f863639cc71cff59c8305fc18 (diff) |
refactor networking code to start supporting multiple backends
-rw-r--r-- | src/library.js | 205 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 11 | ||||
-rw-r--r-- | tests/enet_client.c | 2 | ||||
-rw-r--r-- | tests/enet_server.c | 2 |
4 files changed, 126 insertions, 94 deletions
diff --git a/src/library.js b/src/library.js index 1e528d06..f4dd9ba7 100644 --- a/src/library.js +++ b/src/library.js @@ -6779,8 +6779,12 @@ LibraryManager.library = { $Sockets__deps: ['__setErrNo', '$ERRNO_CODES'], $Sockets: { + BACKEND_WEBSOCKETS: 0, + BACKEND_WEBRTC: 1, BUFFER_SIZE: 10*1024, // initial size MAX_BUFFER_SIZE: 10*1024*1024, // maximum size we will grow the buffer + + backend: 0, // default to websockets nextFd: 1, fds: {}, sockaddr_in_layout: Runtime.generateStructInfo([ @@ -6798,6 +6802,111 @@ LibraryManager.library = { ['i32', 'msg_controllen'], ['i32', 'msg_flags'], ]), + + backends: { + 0: { // websockets + connect: function(info) { + console.log('opening ws://' + info.host + ':' + info.port); + info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']); + info.socket.binaryType = 'arraybuffer'; + + var i32Temp = new Uint32Array(1); + var i8Temp = new Uint8Array(i32Temp.buffer); + + info.inQueue = []; + if (!info.stream) { + var partialBuffer = null; // inQueue contains full dgram messages; this buffers incomplete data. Must begin with the beginning of a message + } + + info.socket.onmessage = function(event) { + assert(typeof event.data !== 'string' && event.data.byteLength); // must get binary data! + var data = new Uint8Array(event.data); // make a typed array view on the array buffer +#if SOCKET_DEBUG + Module.print(['onmessage', data.length, '|', Array.prototype.slice.call(data)]); +#endif + if (info.stream) { + info.inQueue.push(data); + } else { + // we added headers with message sizes, read those to find discrete messages + if (partialBuffer) { + // append to the partial buffer + var newBuffer = new Uint8Array(partialBuffer.length + data.length); + newBuffer.set(partialBuffer); + newBuffer.set(data, partialBuffer.length); + // forget the partial buffer and work on data + data = newBuffer; + partialBuffer = null; + } + var currPos = 0; + while (currPos+4 < data.length) { + i8Temp.set(data.subarray(currPos, currPos+4)); + var currLen = i32Temp[0]; + assert(currLen > 0); + if (currPos + 4 + currLen > data.length) { + break; // not enough data has arrived + } + currPos += 4; +#if SOCKET_DEBUG + Module.print(['onmessage message', currLen, '|', Array.prototype.slice.call(data.subarray(currPos, currPos+currLen))]); +#endif + info.inQueue.push(data.subarray(currPos, currPos+currLen)); + currPos += currLen; + } + // If data remains, buffer it + if (currPos < data.length) { + partialBuffer = data.subarray(currPos); + } + } + } + function send(data) { + // TODO: if browser accepts views, can optimize this +#if SOCKET_DEBUG + Module.print('sender actually sending ' + Array.prototype.slice.call(data)); +#endif + // ok to use the underlying buffer, we created data and know that the buffer starts at the beginning + info.socket.send(data.buffer); + } + var outQueue = []; + var intervalling = false, interval; + function trySend() { + if (info.socket.readyState != info.socket.OPEN) { + if (!intervalling) { + intervalling = true; + console.log('waiting for socket in order to send'); + interval = setInterval(trySend, 100); + } + return; + } + for (var i = 0; i < outQueue.length; i++) { + send(outQueue[i]); + } + outQueue.length = 0; + if (intervalling) { + intervalling = false; + clearInterval(interval); + } + } + info.sender = function(data) { + if (!info.stream) { + // add a header with the message size + var header = new Uint8Array(4); + i32Temp[0] = data.length; + header.set(i8Temp); + outQueue.push(header); + } + outQueue.push(new Uint8Array(data)); + trySend(); + }; + } + }, + 1: { // webrtc + } + } + }, + + emscripten_set_network_backend__deps: ['$Sockets'], + emscripten_set_network_backend: function(backend) { + Sockets.backend = backend; }, socket__deps: ['$Sockets'], @@ -6808,6 +6917,9 @@ LibraryManager.library = { if (protocol) { assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if stream, must be tcp } + if (Sockets.backend == Sockets.BACKEND_WEBRTC) { + assert(!stream); // If WebRTC, we can only support datagram, not stream + } Sockets.fds[fd] = { connected: false, stream: stream @@ -6831,98 +6943,7 @@ LibraryManager.library = { info.host = _gethostbyname.table[low + 0xff*high]; assert(info.host, 'problem translating fake ip ' + parts); } - console.log('opening ws://' + info.host + ':' + info.port); - info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']); - info.socket.binaryType = 'arraybuffer'; - - var i32Temp = new Uint32Array(1); - var i8Temp = new Uint8Array(i32Temp.buffer); - - info.inQueue = []; - if (!info.stream) { - var partialBuffer = null; // inQueue contains full dgram messages; this buffers incomplete data. Must begin with the beginning of a message - } - - info.socket.onmessage = function(event) { - assert(typeof event.data !== 'string' && event.data.byteLength); // must get binary data! - var data = new Uint8Array(event.data); // make a typed array view on the array buffer -#if SOCKET_DEBUG - Module.print(['onmessage', data.length, '|', Array.prototype.slice.call(data)]); -#endif - if (info.stream) { - info.inQueue.push(data); - } else { - // we added headers with message sizes, read those to find discrete messages - if (partialBuffer) { - // append to the partial buffer - var newBuffer = new Uint8Array(partialBuffer.length + data.length); - newBuffer.set(partialBuffer); - newBuffer.set(data, partialBuffer.length); - // forget the partial buffer and work on data - data = newBuffer; - partialBuffer = null; - } - var currPos = 0; - while (currPos+4 < data.length) { - i8Temp.set(data.subarray(currPos, currPos+4)); - var currLen = i32Temp[0]; - assert(currLen > 0); - if (currPos + 4 + currLen > data.length) { - break; // not enough data has arrived - } - currPos += 4; -#if SOCKET_DEBUG - Module.print(['onmessage message', currLen, '|', Array.prototype.slice.call(data.subarray(currPos, currPos+currLen))]); -#endif - info.inQueue.push(data.subarray(currPos, currPos+currLen)); - currPos += currLen; - } - // If data remains, buffer it - if (currPos < data.length) { - partialBuffer = data.subarray(currPos); - } - } -#endif - } - function send(data) { - // TODO: if browser accepts views, can optimize this -#if SOCKET_DEBUG - Module.print('sender actually sending ' + Array.prototype.slice.call(data)); -#endif - // ok to use the underlying buffer, we created data and know that the buffer starts at the beginning - info.socket.send(data.buffer); - } - var outQueue = []; - var intervalling = false, interval; - function trySend() { - if (info.socket.readyState != info.socket.OPEN) { - if (!intervalling) { - intervalling = true; - console.log('waiting for socket in order to send'); - interval = setInterval(trySend, 100); - } - return; - } - for (var i = 0; i < outQueue.length; i++) { - send(outQueue[i]); - } - outQueue.length = 0; - if (intervalling) { - intervalling = false; - clearInterval(interval); - } - } - info.sender = function(data) { - if (!info.stream) { - // add a header with the message size - var header = new Uint8Array(4); - i32Temp[0] = data.length; - header.set(i8Temp); - outQueue.push(header); - } - outQueue.push(new Uint8Array(data)); - trySend(); - }; + Sockets.backends[Sockets.backend].connect(info); return 0; }, diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 6b254ee6..93551f39 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -322,6 +322,17 @@ void emscripten_worker_respond(char *data, int size); int emscripten_get_worker_queue_size(worker_handle worker); /* + * Select the networking backend to use. By default emscripten's + * socket/networking implementation will use websockets, with this + * function you can change that to WebRTC. + * This function must be called before any network functions are + * called. + */ +#define EMSCRIPTEN_NETWORK_WEBSOCKETS 0 +#define EMSCRIPTEN_NETWORK_WEBRTC 1 +void emscripten_set_network_backend(int backend); + +/* * Profiling tools. * INIT must be called first, with the maximum identifier that * will be used. BEGIN will add some code that marks diff --git a/tests/enet_client.c b/tests/enet_client.c index 78c8f314..601b8769 100644 --- a/tests/enet_client.c +++ b/tests/enet_client.c @@ -10,7 +10,7 @@ void main_loop() { #if EMSCRIPTEN counter++; #endif - if (counter == 10) { + if (counter == 100) { printf("stop!\n"); emscripten_cancel_main_loop(); return; diff --git a/tests/enet_server.c b/tests/enet_server.c index 87c64038..a8167e16 100644 --- a/tests/enet_server.c +++ b/tests/enet_server.c @@ -29,7 +29,7 @@ void main_loop() { #if EMSCRIPTEN counter++; #endif - if (counter == 10) { + if (counter == 100) { printf("stop!\n"); emscripten_cancel_main_loop(); return; |