diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-10-03 17:38:19 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-10-03 17:38:19 -0700 |
commit | 4f2f867026315a33a30344a9cedc500568e9cb04 (patch) | |
tree | 2ce5753fd55eb8f7d310d3f4c9692accaa3004b7 | |
parent | 363ce16a8980f08b9c81fea4d51d3356cbad21a9 (diff) |
socket listen faking
-rw-r--r-- | src/library.js | 28 | ||||
-rwxr-xr-x | tests/runner.py | 11 | ||||
-rw-r--r-- | tests/websockets_bi_listener.c | 151 | ||||
-rw-r--r-- | tests/websockets_bi_side.c | 17 |
4 files changed, 200 insertions, 7 deletions
diff --git a/src/library.js b/src/library.js index 72fb07e7..6c0a67a0 100644 --- a/src/library.js +++ b/src/library.js @@ -1209,7 +1209,7 @@ LibraryManager.library = { return 0; case {{{ cDefine('F_SETOWN') }}}: case {{{ cDefine('F_GETOWN') }}}: - // These are for sockets. We don't have them implemented (yet?). + // These are for sockets. We don't have them fully implemented yet. ___setErrNo(ERRNO_CODES.EINVAL); return -1; default: @@ -6398,7 +6398,8 @@ LibraryManager.library = { }, // ========================================================================== - // sockets + // sockets. Note that the implementation assumes all sockets are always + // nonblocking // ========================================================================== $Sockets__deps: ['__setErrNo', '$ERRNO_CODES'], @@ -6575,6 +6576,29 @@ LibraryManager.library = { return 0; }, + bind__deps: ['connect'], + bind: function(fd, addr, addrlen) { + return _connect(fd, addr, addrlen); + }, + + listen: function(fd, backlog) { + return 0; + }, + + 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]; + if (!info) return -1; + if (addr) { + setValue(addr + Sockets.sockaddr_in_layout.sin_addr, info.addr, 'i32'); + setValue(addr + Sockets.sockaddr_in_layout.sin_port, info.port, 'i32'); + setValue(addrlen, Sockets.sockaddr_in_layout.__size__, 'i32'); + } + return fd; + }, + // ========================================================================== // emscripten.h // ========================================================================== diff --git a/tests/runner.py b/tests/runner.py index 02e0428e..9608f24d 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8798,11 +8798,20 @@ elif 'browser' in str(sys.argv): 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']).communicate() + Popen(['python', EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995']).communicate() self.btest('websockets_bi.c', expected='2499') finally: self.clean_pids() + def test_zz_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') + finally: + self.clean_pids() + def test_zz_websockets_gethostbyname(self): try: with self.WebsockHarness(7000): diff --git a/tests/websockets_bi_listener.c b/tests/websockets_bi_listener.c new file mode 100644 index 00000000..21005cc5 --- /dev/null +++ b/tests/websockets_bi_listener.c @@ -0,0 +1,151 @@ +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#if EMSCRIPTEN +#include <emscripten.h> +#endif + +#define EXPECTED_BYTES 28 + +int ListenFD, SocketFD; + +unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) +{ + int bytes; + if (ioctl(sock, FIONREAD, &bytes)) return 0; + if (bytes == 0) return 0; + + char buffer[1024]; + int n; + unsigned int offset = 0; + while((errno = 0, (n = recv(sock, buffer, sizeof(buffer), 0))>0) || + errno == EINTR) { + if(n>0) + { + if (((unsigned int) n)+offset > maxsize) { fprintf(stderr, "too much data!"); exit(EXIT_FAILURE); } + memcpy(output+offset, buffer, n); + offset += n; + } + } + + if(n < 0) { + fprintf(stderr, "error in get_all_buf!"); + exit(EXIT_FAILURE); + } + return offset; +} + +int done = 0; + +void iter(void *arg) { + /* perform read write operations ... */ + static char out[1024*2]; + static int pos = 0; + int n = get_all_buf(SocketFD, out+pos, 1024-pos); + if (n) printf("read! %d\n", n); + pos += n; + if (pos >= EXPECTED_BYTES) { + int i, sum = 0; + for (i=0; i < pos; i++) { + printf("%x\n", out[i]); + sum += out[i]; + } + + shutdown(SocketFD, SHUT_RDWR); + + close(SocketFD); + + done = 1; + + printf("sum: %d\n", sum); + +#if EMSCRIPTEN + int result = sum; + REPORT_RESULT(); + emscripten_cancel_main_loop(); +#endif + } +} + +int main(void) +{ + struct sockaddr_in stSockAddr; + int Res; + ListenFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (-1 == ListenFD) + { + perror("cannot create socket"); + exit(EXIT_FAILURE); + } + + memset(&stSockAddr, 0, sizeof(stSockAddr)); + + stSockAddr.sin_family = AF_INET; + stSockAddr.sin_port = htons( +#if EMSCRIPTEN + 6993 +#else + 6995 +#endif + ); + Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr); + + if (0 > Res) { + perror("error: first parameter is not a valid address family"); + close(ListenFD); + exit(EXIT_FAILURE); + } else if (0 == Res) { + perror("char string (second parameter does not contain valid ipaddress)"); + close(ListenFD); + exit(EXIT_FAILURE); + } + + printf("bind..\n"); + + if (-1 == bind(ListenFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + perror("bind failed"); + close(ListenFD); + exit(EXIT_FAILURE); + } + + printf("listen..\n"); + + if (-1 == listen(ListenFD, 50)) { + perror("listen failed"); + close(ListenFD); + exit(EXIT_FAILURE); + } + + printf("accept..\n"); + + struct sockaddr_in stSockAddr2; + socklen_t temp; + + if (-1 == (SocketFD = accept(ListenFD, (struct sockaddr *)&stSockAddr2, &temp))) { + perror("accept failed"); + close(ListenFD); + exit(EXIT_FAILURE); + } + +#if EMSCRIPTEN + emscripten_run_script("console.log('adding iframe');" + "var iframe = document.createElement('iframe');" + "iframe.src = 'side.html';" + "document.body.appendChild(iframe);" + "console.log('added.');"); + emscripten_set_main_loop(iter, 0); +#else + while (!done) iter(NULL); +#endif + + return EXIT_SUCCESS; +} + diff --git a/tests/websockets_bi_side.c b/tests/websockets_bi_side.c index ab9fa86a..c9c50618 100644 --- a/tests/websockets_bi_side.c +++ b/tests/websockets_bi_side.c @@ -7,15 +7,15 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/ioctl.h> +#if EMSCRIPTEN #include <emscripten.h> +#endif #define EXPECTED_BYTES 5 int main(void) { -emscripten_run_script("console.log('hallo from siide')"); - printf("hello from side page\n"); - struct sockaddr_in stSockAddr; int Res; int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -29,7 +29,7 @@ emscripten_run_script("console.log('hallo from siide')"); memset(&stSockAddr, 0, sizeof(stSockAddr)); stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons(8995); + stSockAddr.sin_port = htons(SOCKK); Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr); if (0 > Res) { @@ -42,15 +42,24 @@ emscripten_run_script("console.log('hallo from siide')"); exit(EXIT_FAILURE); } + printf("connect..\n"); + if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { perror("connect failed"); close(SocketFD); exit(EXIT_FAILURE); } + printf("send..\n"); + char data[] = "hello from the other siide\n"; send(SocketFD, data, sizeof(data), 0); + printf("stall..\n"); + + //int bytes; + //while (1) ioctl(SocketFD, FIONREAD, &bytes); + return EXIT_SUCCESS; } |