diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-06-04 12:19:23 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-06-04 12:35:56 -0700 |
commit | 020c6b72916ddfc09170ab4de0e8f5d2793edcbe (patch) | |
tree | 481376e8c48cb78de3168c595e6cbb559e8d3d50 | |
parent | 2ebaa5c8e1c3715c37ca72e6b687bd18bce14c10 (diff) | |
parent | 4c41c69f202a1b98e10a2a315c3b97bca7bcea04 (diff) |
Merge branch 'incoming' of github.com:kanaka/emscripten into incoming
-rw-r--r-- | src/library.js | 126 | ||||
-rwxr-xr-x | tests/runner.py | 20 | ||||
-rw-r--r-- | tests/websockets_bi.c | 16 | ||||
-rw-r--r-- | tests/websockets_bi_side.c | 7 |
4 files changed, 99 insertions, 70 deletions
diff --git a/src/library.js b/src/library.js index 08cb3baf..5608ea1e 100644 --- a/src/library.js +++ b/src/library.js @@ -63,6 +63,24 @@ LibraryManager.library = { // This is set to false when the runtime is initialized, allowing you // to modify the filesystem freely before run() is called. ignorePermissions: true, + createFileHandle: function(stream, fd) { + if (typeof stream === 'undefined') { + stream = null; + } + fd = (typeof fd !== 'undefined') ? fd : FS.streams.length; + for (var i = FS.streams.length; i < fd; i++) { + FS.streams[i] = null; // Keep dense + } + // Close WebSocket first if we are about to replace the fd (i.e. dup2) + if (FS.streams[fd] && FS.streams[fd].socket && FS.streams[fd].socket.close) { + FS.streams[fd].socket.close(); + } + FS.streams[fd] = stream; + return fd; + }, + removeFileHandle: function(fd) { + FS.streams[fd] = null; + }, joinPath: function(parts, forceRelative) { var ret = parts[0]; for (var i = 1; i < parts.length; i++) { @@ -677,10 +695,9 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.EACCES); return 0; } - var id = FS.streams.length; // Keep dense var contents = []; for (var key in target.contents) contents.push(key); - FS.streams[id] = { + var id = FS.createFileHandle({ path: path, object: target, // An index into contents. Special values: -2 is ".", -1 is "..". @@ -697,7 +714,7 @@ LibraryManager.library = { contents: contents, // Each stream has its own area for readdir() returns. currentEntry: _malloc(___dirent_struct_layout.__size__) - }; + }); #if ASSERTIONS FS.checkStreams(); #endif @@ -1215,7 +1232,7 @@ LibraryManager.library = { finalPath = path.parentPath + '/' + path.name; } // Actually create an open stream. - var id = FS.streams.length; // Keep dense + var id; if (target.isFolder) { var entryBuffer = 0; if (___dirent_struct_layout) { @@ -1223,7 +1240,7 @@ LibraryManager.library = { } var contents = []; for (var key in target.contents) contents.push(key); - FS.streams[id] = { + id = FS.createFileHandle({ path: finalPath, object: target, // An index into contents. Special values: -2 is ".", -1 is "..". @@ -1240,9 +1257,9 @@ LibraryManager.library = { contents: contents, // Each stream has its own area for readdir() returns. currentEntry: entryBuffer - }; + }); } else { - FS.streams[id] = { + id = FS.createFileHandle({ path: finalPath, object: target, position: 0, @@ -1252,7 +1269,7 @@ LibraryManager.library = { error: false, eof: false, ungotten: [] - }; + }); } #if ASSERTIONS FS.checkStreams(); @@ -1295,10 +1312,7 @@ LibraryManager.library = { newStream[member] = stream[member]; } arg = dup2 ? arg : Math.max(arg, FS.streams.length); // dup2 wants exactly arg; fcntl wants a free descriptor >= arg - for (var i = FS.streams.length; i < arg; i++) { - FS.streams[i] = null; // Keep dense - } - FS.streams[arg] = newStream; + FS.createFileHandle(newStream, arg); #if ASSERTIONS FS.checkStreams(); #endif @@ -1775,12 +1789,14 @@ LibraryManager.library = { return bytesRead; } }, - read__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'pread'], + read__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'recv', 'pread'], read: function(fildes, buf, nbyte) { // ssize_t read(int fildes, void *buf, size_t nbyte); // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html var stream = FS.streams[fildes]; - if (!stream) { + if ('socket' in stream) { + return _recv(fildes, buf, nbyte, 0); + } else if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; } else if (!stream.isRead) { @@ -1971,12 +1987,14 @@ LibraryManager.library = { return i; } }, - write__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'pwrite'], + write__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'send', 'pwrite'], write: function(fildes, buf, nbyte) { // ssize_t write(int fildes, const void *buf, size_t nbyte); // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html var stream = FS.streams[fildes]; - if (!stream) { + if ('socket' in stream) { + return _send(fildes, buf, nbyte, 0); + } else if (!stream) { ___setErrNo(ERRNO_CODES.EBADF); return -1; } else if (!stream.isWrite) { @@ -7291,7 +7309,13 @@ LibraryManager.library = { */ socket__deps: ['$Sockets'], socket: function(family, type, protocol) { - var fd = Sockets.nextFd++; + var fd = FS.createFileHandle({ + addr: null, + port: null, + inQueue: new CircularBuffer(INCOMING_QUEUE_LENGTH), + header: new Uint16Array(2), + bound: false + }; assert(fd < 64); // select() assumes socket fd values are in 0..63 var stream = type == {{{ cDefine('SOCK_STREAM') }}}; if (protocol) { @@ -7408,13 +7432,6 @@ LibraryManager.library = { }; }; - Sockets.fds[fd] = { - addr: null, - port: null, - inQueue: new CircularBuffer(INCOMING_QUEUE_LENGTH), - header: new Uint16Array(2), - bound: false - }; return fd; }, @@ -7436,7 +7453,7 @@ LibraryManager.library = { bind__deps: ['$Sockets', '_inet_ntop_raw', 'ntohs', 'mkport'], bind: function(fd, addr, addrlen) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; if (addr) { info.port = _ntohs(getValue(addr + Sockets.sockaddr_in_layout.sin_port, 'i16')); @@ -7457,7 +7474,7 @@ LibraryManager.library = { sendmsg__deps: ['$Sockets', 'bind', '_inet_ntop_raw', 'ntohs'], sendmsg: function(fd, msg, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; // if we are not connected, use the address info in the message if (!info.bound) { @@ -7513,7 +7530,7 @@ LibraryManager.library = { recvmsg__deps: ['$Sockets', 'bind', '__setErrNo', '$ERRNO_CODES', 'htons'], recvmsg: function(fd, msg, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; // if we are not connected, use the address info in the message if (!info.port) { @@ -7564,14 +7581,14 @@ LibraryManager.library = { }, shutdown: function(fd, how) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; info.close(); - Sockets.fds[fd] = null; + FS.removeFileHandle(fd); }, ioctl: function(fd, request, varargs) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; var bytes = 0; if (info.hasData()) { @@ -7591,7 +7608,7 @@ LibraryManager.library = { // TODO: webrtc queued incoming connections, etc. // For now, the model is that bind does a connect, and we "accept" that one connection, // which has host:port the same as ours. We also return the same socket fd. - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; if (addr) { setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32'); @@ -7632,7 +7649,7 @@ LibraryManager.library = { var mask = 1 << (fd % 32), int = fd < 32 ? srcLow : srcHigh; if (int & mask) { // index is in the set, check if it is ready for read - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (info && can(info)) { // set bit fd < 32 ? (dstLow = dstLow | mask) : (dstHigh = dstHigh | mask); @@ -7657,22 +7674,21 @@ LibraryManager.library = { #else socket__deps: ['$Sockets'], socket: function(family, type, protocol) { - var fd = Sockets.nextFd++; - assert(fd < 64); // select() assumes socket fd values are in 0..63 var stream = type == {{{ cDefine('SOCK_STREAM') }}}; if (protocol) { - assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if stream, must be tcp + assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if SOCK_STREAM, must be tcp } - Sockets.fds[fd] = { + var fd = FS.createFileHandle({ connected: false, stream: stream - }; + }); + assert(fd < 64); // select() assumes socket fd values are in 0..63 return fd; }, - connect__deps: ['$Sockets', '_inet_ntop_raw', 'htons', 'gethostbyname'], + connect__deps: ['$FS', '$Sockets', '_inet_ntop_raw', 'ntohs', 'gethostbyname'], connect: function(fd, addr, addrlen) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; info.connected = true; info.addr = getValue(addr + Sockets.sockaddr_in_layout.sin_addr, 'i32'); @@ -7788,9 +7804,9 @@ LibraryManager.library = { return 0; }, - recv__deps: ['$Sockets'], + recv__deps: ['$FS'], recv: function(fd, buf, len, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; if (!info.hasData()) { ___setErrNo(ERRNO_CODES.EAGAIN); // no data, and all sockets are nonblocking, so this is the right behavior @@ -7814,17 +7830,17 @@ LibraryManager.library = { return buffer.length; }, - send__deps: ['$Sockets'], + send__deps: ['$FS'], send: function(fd, buf, len, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; info.sender(HEAPU8.subarray(buf, buf+len)); return len; }, - sendmsg__deps: ['$Sockets', 'connect'], + sendmsg__deps: ['$FS', '$Sockets', 'connect'], sendmsg: function(fd, msg, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; // if we are not connected, use the address info in the message if (!info.connected) { @@ -7857,9 +7873,9 @@ LibraryManager.library = { return ret; }, - recvmsg__deps: ['$Sockets', 'connect', 'recv', '__setErrNo', '$ERRNO_CODES', 'htons'], + recvmsg__deps: ['$FS', '$Sockets', 'connect', 'recv', '__setErrNo', '$ERRNO_CODES', 'htons'], recvmsg: function(fd, msg, flags) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; // if we are not connected, use the address info in the message if (!info.connected) { @@ -7915,9 +7931,9 @@ LibraryManager.library = { return ret; }, - recvfrom__deps: ['$Sockets', 'connect', 'recv'], + recvfrom__deps: ['$FS', 'connect', 'recv'], recvfrom: function(fd, buf, len, flags, addr, addrlen) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; // if we are not connected, use the address info in the message if (!info.connected) { @@ -7928,14 +7944,14 @@ LibraryManager.library = { }, shutdown: function(fd, how) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; info.socket.close(); - Sockets.fds[fd] = null; + FS.removeFileHandle(fd); }, ioctl: function(fd, request, varargs) { - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; var bytes = 0; if (info.hasData()) { @@ -7960,11 +7976,12 @@ LibraryManager.library = { return 0; }, + accept__deps: ['$FS', '$Sockets'], accept: function(fd, addr, addrlen) { // TODO: webrtc queued incoming connections, etc. // For now, the model is that bind does a connect, and we "accept" that one connection, // which has host:port the same as ours. We also return the same socket fd. - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (!info) return -1; if (addr) { setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32'); @@ -7974,6 +7991,7 @@ LibraryManager.library = { return fd; }, + select__deps: ['$FS'], select: function(nfds, readfds, writefds, exceptfds, timeout) { // readfds are supported, // writefds checks socket open status @@ -8019,7 +8037,7 @@ LibraryManager.library = { var mask = 1 << (fd % 32), int = fd < 32 ? srcLow : srcHigh; if (int & mask) { // index is in the set, check if it is ready for read - var info = Sockets.fds[fd]; + var info = FS.streams[fd]; if (info && can(info)) { // set bit fd < 32 ? (dstLow = dstLow | mask) : (dstHigh = dstHigh | mask); diff --git a/tests/runner.py b/tests/runner.py index 86e97b19..9db26947 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12919,20 +12919,22 @@ elif 'browser' in str(sys.argv): def test_websockets_bi(self): for datagram in [0,1]: - try: - with self.WebsockHarness(8992, self.make_relay_server(8992, 8994)): - with self.WebsockHarness(8994, no_server=True): - Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995', '-DTEST_DGRAM=%d' % datagram]).communicate() - self.btest('websockets_bi.c', expected='2499', args=['-DTEST_DGRAM=%d' % datagram]) - finally: - self.clean_pids() + for fileops in [0,1]: + try: + print >> sys.stderr, 'test_websocket_bi datagram %d, fileops %d' % (datagram, fileops) + with self.WebsockHarness(8992, self.make_relay_server(8992, 8994)): + with self.WebsockHarness(8994, no_server=True): + Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995', '-DTEST_DGRAM=%d' % datagram]).communicate() + self.btest('websockets_bi.c', expected='2499', args=['-DSOCKK=8993', '-DTEST_DGRAM=%d' % datagram, '-DTEST_FILE_OPS=%s' % fileops]) + finally: + self.clean_pids() def test_websockets_bi_listen(self): try: with self.WebsockHarness(6992, self.make_relay_server(6992, 6994)): with self.WebsockHarness(6994, no_server=True): Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=6995']).communicate() - self.btest('websockets_bi_listener.c', expected='2499') + self.btest('websockets_bi_listener.c', expected='2499', args=['-DSOCKK=6993']) finally: self.clean_pids() @@ -12948,7 +12950,7 @@ elif 'browser' in str(sys.argv): with self.WebsockHarness(3992, self.make_relay_server(3992, 3994)): with self.WebsockHarness(3994, no_server=True): Popen([PYTHON, EMCC, path_from_root('tests', 'websockets_bi_side_bigdata.c'), '-o', 'side.html', '-DSOCKK=3995', '-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')]).communicate() - self.btest('websockets_bi_bigdata.c', expected='0', args=['-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')]) + self.btest('websockets_bi_bigdata.c', expected='0', args=['-DSOCKK=3993', '-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')]) finally: self.clean_pids() diff --git a/tests/websockets_bi.c b/tests/websockets_bi.c index 18cdd664..fb60177b 100644 --- a/tests/websockets_bi.c +++ b/tests/websockets_bi.c @@ -14,6 +14,10 @@ #define EXPECTED_BYTES 28 +#ifndef SOCKK +#define SOCKK 8992 +#endif + int SocketFD; unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) @@ -25,7 +29,11 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) char buffer[1024]; int n; unsigned int offset = 0; +#if TEST_FILE_OPS + while((errno = 0, (n = read(sock, buffer, sizeof(buffer)))>0) || +#else while((errno = 0, (n = recv(sock, buffer, sizeof(buffer), 0))>0) || +#endif errno == EINTR) { if(n>0) { @@ -96,13 +104,7 @@ int main(void) memset(&stSockAddr, 0, sizeof(stSockAddr)); stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8993 -#else - 8992 -#endif - ); + stSockAddr.sin_port = htons(SOCKK); Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr); if (0 > Res) { diff --git a/tests/websockets_bi_side.c b/tests/websockets_bi_side.c index 12b790fd..1d557ed8 100644 --- a/tests/websockets_bi_side.c +++ b/tests/websockets_bi_side.c @@ -54,10 +54,17 @@ int main(void) exit(EXIT_FAILURE); } +#if TEST_FILE_OPS + printf("write..\n"); + + char data[] = "hello from the other siide (fileops)\n"; + write(SocketFD, data, sizeof(data)); +#else printf("send..\n"); char data[] = "hello from the other siide\n"; send(SocketFD, data, sizeof(data), 0); +#endif printf("stall..\n"); |