diff options
-rw-r--r-- | src/library.js | 62 | ||||
-rwxr-xr-x | tests/runner.py | 63 | ||||
-rw-r--r-- | tests/websockets.c | 118 | ||||
-rw-r--r-- | tests/websockets_bi.c | 116 | ||||
-rw-r--r-- | tests/websockets_bi_bigdata.c | 117 | ||||
-rw-r--r-- | tests/websockets_bi_listener.c | 151 | ||||
-rw-r--r-- | tests/websockets_bi_side.c | 103 | ||||
-rw-r--r-- | tests/websockets_bi_side_bigdata.c | 89 | ||||
-rw-r--r-- | tests/websockets_gethostbyname.c | 114 | ||||
-rw-r--r-- | tests/websockets_partial.c | 112 | ||||
-rw-r--r-- | tests/websockets_select.c | 101 | ||||
-rw-r--r-- | tests/websockets_select_server_closes_connection.c | 124 | ||||
-rw-r--r-- | tests/websockets_select_server_closes_connection_rw.c | 176 |
13 files changed, 670 insertions, 776 deletions
diff --git a/src/library.js b/src/library.js index f48220bb..0a37f212 100644 --- a/src/library.js +++ b/src/library.js @@ -9439,17 +9439,30 @@ LibraryManager.library = { return -1; } - return 0; + // always "fail" in non-blocking mode + ___setErrNo(ERRNO_CODES.EINPROGRESS); + return -1; }, recv__deps: ['$FS'], recv: function(fd, buf, len, flags) { var info = FS.getStream(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 + if (!info) { + ___setErrNo(ERRNO_CODES.EBADF); return -1; } +#if SOCKET_WEBRTC == 0 + if (!info.hasData()) { + if (info.socket.readyState === WebSocket.CLOSING || info.socket.readyState === WebSocket.CLOSED) { + // socket has closed + return 0; + } else { + // else, our socket is in a valid state but truly has nothing available + ___setErrNo(ERRNO_CODES.EAGAIN); + return -1; + } + } +#endif var buffer = info.inQueue.shift(); #if SOCKET_DEBUG Module.print('recv: ' + [Array.prototype.slice.call(buffer)]); @@ -9471,7 +9484,19 @@ LibraryManager.library = { send__deps: ['$FS'], send: function(fd, buf, len, flags) { var info = FS.getStream(fd); - if (!info) return -1; + if (!info) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } +#if SOCKET_WEBRTC == 0 + if (info.socket.readyState === WebSocket.CLOSING || info.socket.readyState === WebSocket.CLOSED) { + ___setErrNo(ERRNO_CODES.ENOTCONN); + return -1; + } else if (info.socket.readyState === WebSocket.CONNECTING) { + ___setErrNo(ERRNO_CODES.EAGAIN); + return -1; + } +#endif info.sender(HEAPU8.subarray(buf, buf+len)); return len; }, @@ -9607,7 +9632,8 @@ LibraryManager.library = { bind__deps: ['connect'], bind: function(fd, addr, addrlen) { - return _connect(fd, addr, addrlen); + _connect(fd, addr, addrlen); + return 0; }, listen: function(fd, backlog) { @@ -9640,24 +9666,12 @@ LibraryManager.library = { var errorCondition = 0; function canRead(info) { - // make sure hasData exists. - // we do create it when the socket is connected, - // but other implementations may create it lazily - if ((info.socket.readyState == WebSocket.CLOSING || info.socket.readyState == WebSocket.CLOSED) && info.inQueue.length == 0) { - errorCondition = -1; - return false; - } - return info.hasData && info.hasData(); + return (info.hasData && info.hasData()) || + info.socket.readyState == WebSocket.CLOSING || // let recv return 0 once closed + info.socket.readyState == WebSocket.CLOSED; } function canWrite(info) { - // make sure socket exists. - // we do create it when the socket is connected, - // but other implementations may create it lazily - if ((info.socket.readyState == WebSocket.CLOSING || info.socket.readyState == WebSocket.CLOSED)) { - errorCondition = -1; - return false; - } return info.socket && (info.socket.readyState == info.socket.OPEN); } @@ -9676,7 +9690,11 @@ LibraryManager.library = { if (int_ & mask) { // index is in the set, check if it is ready for read var info = FS.getStream(fd); - if (info && can(info)) { + if (!info) { + ___setErrNo(ERRNO_CODES.EBADF); + return -1; + } + if (can(info)) { // set bit fd < 32 ? (dstLow = dstLow | mask) : (dstHigh = dstHigh | mask); bitsSet++; diff --git a/tests/runner.py b/tests/runner.py index b866cc08..2bd26eb7 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12330,6 +12330,24 @@ elif 'browser' in str(sys.argv): 'browser.test_freealut' ] + if 'sockets' in sys.argv: + print + print 'Running the browser socket tests.' + print + i = sys.argv.index('sockets') + sys.argv = sys.argv[:i] + sys.argv[i+1:] + i = sys.argv.index('browser') + sys.argv = sys.argv[:i] + sys.argv[i+1:] + sys.argv += [ + 'browser.test_sockets_bi', + 'browser.test_sockets_gethostbyname', + 'browser.test_sockets_bi_bigdata', + 'browser.test_sockets_select_server_down', + 'browser.test_sockets_select_server_closes_connection', + 'browser.test_sockets_select_server_closes_connection_rw', + 'browser.test_enet' + ] + # Run a server and a web page. When a test runs, we tell the server about it, # which tells the web page, which then opens a window with the test. Doing # it this way then allows the page to close() itself when done. @@ -13930,14 +13948,14 @@ Press any key to continue.''' # always run these tests last # make sure to use different ports in each one because it takes a while for the processes to be cleaned up - def test_websockets(self): + def test_sockets(self): try: with self.WebsockHarness(8990): - self.btest('websockets.c', expected='571') + self.btest('websockets.c', expected='571', args=['-DSOCKK=8991']) finally: self.clean_pids() - def test_websockets_partial(self): + def test_sockets_partial(self): def partial(q): import socket @@ -13960,7 +13978,7 @@ Press any key to continue.''' try: with self.WebsockHarness(8990, partial): - self.btest('websockets_partial.c', expected='165') + self.btest('websockets_partial.c', expected='165', args=['-DSOCKK=8991']) finally: self.clean_pids() @@ -13972,35 +13990,26 @@ Press any key to continue.''' proc.communicate() return relay_server - def test_websockets_bi(self): + def test_sockets_bi(self): for datagram in [0,1]: 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]) + 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', '-DTEST_DGRAM=%d' % datagram]).communicate() + self.btest('websockets_bi.c', expected='2499', args=['-DSOCKK=6993', '-DTEST_DGRAM=%d' % datagram, '-DTEST_FILE_OPS=%s' % fileops, '-DEMBED_SIDE']) 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', args=['-DSOCKK=6993']) - finally: - self.clean_pids() - - def test_websockets_gethostbyname(self): + def test_sockets_gethostbyname(self): try: with self.WebsockHarness(7000): - self.btest('websockets_gethostbyname.c', expected='571', args=['-O2']) + self.btest('websockets_gethostbyname.c', expected='571', args=['-O2', '-DSOCKK=7001']) finally: self.clean_pids() - def test_websockets_bi_bigdata(self): + def test_sockets_bi_bigdata(self): try: with self.WebsockHarness(3992, self.make_relay_server(3992, 3994)): with self.WebsockHarness(3994, no_server=True): @@ -14009,7 +14018,7 @@ Press any key to continue.''' finally: self.clean_pids() - def test_websockets_select_server_down(self): + def test_sockets_select_server_down(self): def closedServer(q): import socket @@ -14018,11 +14027,11 @@ Press any key to continue.''' ssock.bind(("127.0.0.1", 8994)) try: with self.WebsockHarness(8994, closedServer): - self.btest('websockets_select.c', expected='266') + self.btest('websockets_select.c', expected='266', args=['-DSOCKK=8995']) finally: self.clean_pids() - def test_websockets_select_server_closes_connection(self): + def test_sockets_select_server_closes_connection(self): def closingServer(q): import socket @@ -14038,11 +14047,11 @@ Press any key to continue.''' try: with self.WebsockHarness(8994, closingServer): - self.btest('websockets_select_server_closes_connection.c', expected='266') + self.btest('websockets_select_server_closes_connection.c', expected='266', args=['-DSOCKK=8995']) finally: self.clean_pids() - def test_websockets_select_server_closes_connection_rw(self): + def test_sockets_select_server_closes_connection_rw(self): def closingServer_rw(q): import socket @@ -14070,7 +14079,7 @@ Press any key to continue.''' try: with self.WebsockHarness(8998, closingServer_rw): - self.btest('websockets_select_server_closes_connection_rw.c', expected='266') + self.btest('websockets_select_server_closes_connection_rw.c', expected='266', args=['-DSOCKK=8999']) finally: self.clean_pids() diff --git a/tests/websockets.c b/tests/websockets.c index 8882f5ba..8845ef43 100644 --- a/tests/websockets.c +++ b/tests/websockets.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #include <assert.h> #if EMSCRIPTEN @@ -15,12 +16,18 @@ #define EXPECTED_BYTES 5 -int SocketFD; - +int sockfd; int not_always_data = 0; -unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) -{ +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} + +unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) { // select check for IO fd_set sett; FD_ZERO(&sett); @@ -35,6 +42,7 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) int bytes; if (ioctl(sock, FIONREAD, &bytes) || bytes == 0) { not_always_data = 1; + printf("ioctl says 0, FD_ISSET says %ld\n", FD_ISSET(sock, &sett)); assert(FD_ISSET(sock, &sett) == 0); return 0; } @@ -47,28 +55,42 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) 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); } + if(n > 0) { + if (((unsigned int) n)+offset > maxsize) { + fprintf(stderr, "too much data!"); + finish(EXIT_FAILURE); + } memcpy(output+offset, buffer, n); offset += n; } } - if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { fprintf(stderr, "error in get_all_buf! %d", errno); - exit(EXIT_FAILURE); + finish(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); + fd_set fdr; + int res; + + // make sure that sockfd is ready to read + FD_ZERO(&fdr); + FD_SET(sockfd, &fdr); + res = select(64, &fdr, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (!FD_ISSET(sockfd, &fdr)) { + return; + } + + // perform read write operations ... + int n = get_all_buf(sockfd, out+pos, 1024-pos); if (n) printf("read! %d\n", n); pos += n; if (pos >= EXPECTED_BYTES) { @@ -78,70 +100,44 @@ void iter(void *arg) { sum += out[i]; } - shutdown(SocketFD, SHUT_RDWR); - - close(SocketFD); + shutdown(sockfd, SHUT_RDWR); - done = 1; + close(sockfd); printf("sum: %d\n", sum); - -#if EMSCRIPTEN - //assert(not_always_data == 1); - - int result = sum; - REPORT_RESULT(); -#endif + finish(sum); } } -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +void main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8991 -#else - 8990 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } - - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif - - return EXIT_SUCCESS; } diff --git a/tests/websockets_bi.c b/tests/websockets_bi.c index fb60177b..e19f7fe8 100644 --- a/tests/websockets_bi.c +++ b/tests/websockets_bi.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #if EMSCRIPTEN #include <emscripten.h> @@ -14,14 +15,17 @@ #define EXPECTED_BYTES 28 -#ifndef SOCKK -#define SOCKK 8992 -#endif +int sockfd; -int SocketFD; +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} -unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) -{ +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; @@ -35,9 +39,11 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) while((errno = 0, (n = recv(sock, buffer, sizeof(buffer), 0))>0) || #endif errno == EINTR) { - if(n>0) - { - if (((unsigned int) n)+offset > maxsize) { fprintf(stderr, "too much data!"); exit(EXIT_FAILURE); } + if(n > 0) { + if (((unsigned int) n)+offset > maxsize) { + fprintf(stderr, "too much data!"); + finish(EXIT_FAILURE); + } memcpy(output+offset, buffer, n); offset += n; } @@ -45,18 +51,30 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { fprintf(stderr, "error in get_all_buf!"); - exit(EXIT_FAILURE); + finish(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); + fd_set fdr; + int res; + + // make sure that sockfd is ready to read + FD_ZERO(&fdr); + FD_SET(sockfd, &fdr); + res = select(64, &fdr, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (!FD_ISSET(sockfd, &fdr)) { + return; + } + + // perform read write operations ... + int n = get_all_buf(sockfd, out+pos, 1024-pos); if (n) printf("read! %d\n", n); pos += n; if (pos >= EXPECTED_BYTES) { @@ -66,75 +84,57 @@ void iter(void *arg) { sum += out[i]; } - shutdown(SocketFD, SHUT_RDWR); - - close(SocketFD); - - done = 1; + shutdown(sockfd, SHUT_RDWR); + close(sockfd); printf("sum: %d\n", sum); - - emscripten_cancel_main_loop(); - -#if EMSCRIPTEN - int result = sum; - REPORT_RESULT(); -#endif + finish(sum); } } -int main(void) -{ +int main() { + struct sockaddr_in addr; + int res; + printf("hello from main page\n"); - struct sockaddr_in stSockAddr; - int Res; #if !TEST_DGRAM - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); #else - SocketFD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); #endif - - if (-1 == SocketFD) - { + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons(SOCKK); - 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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } - - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN +#if EMBED_SIDE emscripten_run_script("console.log('adding iframe');" "var iframe = document.createElement('iframe');" "iframe.src = 'side.html';" "document.body.appendChild(iframe);" "console.log('added.');"); +#endif emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif return EXIT_SUCCESS; } - diff --git a/tests/websockets_bi_bigdata.c b/tests/websockets_bi_bigdata.c index 2039f83c..e3509649 100644 --- a/tests/websockets_bi_bigdata.c +++ b/tests/websockets_bi_bigdata.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #if EMSCRIPTEN #include <emscripten.h> @@ -16,10 +17,17 @@ #define EXPECTED_BYTES DATA_SIZE -int SocketFD; +int sockfd; -unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) -{ +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} + +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; @@ -29,41 +37,51 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) 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); } + if (n > 0) { + if (((unsigned int) n)+offset > maxsize) { + fprintf(stderr, "too much data!"); + finish(EXIT_FAILURE); + } memcpy(output+offset, buffer, n); offset += n; } } - if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { fprintf(stderr, "error in get_all_buf!"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } return offset; } -int done = 0; - void iter(void *arg) { - /* perform read write operations ... */ static char out[EXPECTED_BYTES]; static int pos = 0; + fd_set fdr; + int res; + + // make sure that sockfd has finished connecting and is ready to read + FD_ZERO(&fdr); + FD_SET(sockfd, &fdr); + res = select(64, &fdr, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + return; + } else if (!FD_ISSET(sockfd, &fdr)) { + return; + } + + // perform read write operations ... printf("so far %d, expecting up to %d\n", pos, EXPECTED_BYTES-pos); - int n = get_all_buf(SocketFD, out+pos, EXPECTED_BYTES-pos); - if (n) printf("read! %d\n", n); - pos += n; + res = get_all_buf(sockfd, out+pos, EXPECTED_BYTES-pos); + if (res) printf("read! %d\n", res); + pos += res; if (pos >= EXPECTED_BYTES) { - shutdown(SocketFD, SHUT_RDWR); - - close(SocketFD); - - done = 1; + shutdown(sockfd, SHUT_RDWR); - emscripten_cancel_main_loop(); + close(sockfd); -#if EMSCRIPTEN char *comp = generateData(); int result = strcmp(comp, out); if (result != 0) { @@ -71,52 +89,35 @@ void iter(void *arg) { printf("%d:%d\n", comp[i], out[i]); } } - REPORT_RESULT(); -#endif + finish(result); } } -int main(void) -{ - printf("hello from main page\n"); +int main() { + struct sockaddr_in addr; + int res; - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + printf("hello from main page\n"); - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 3993 -#else - 3992 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN @@ -129,7 +130,7 @@ int main(void) "console.log('added.');"); emscripten_set_main_loop(iter, 3, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif return EXIT_SUCCESS; diff --git a/tests/websockets_bi_listener.c b/tests/websockets_bi_listener.c deleted file mode 100644 index 6c3b17b1..00000000 --- a/tests/websockets_bi_listener.c +++ /dev/null @@ -1,151 +0,0 @@ -#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 && errno != EAGAIN && errno != EWOULDBLOCK) { - 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, 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 1d557ed8..b8910632 100644 --- a/tests/websockets_bi_side.c +++ b/tests/websockets_bi_side.c @@ -3,10 +3,12 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #if EMSCRIPTEN #include <emscripten.h> @@ -14,62 +16,77 @@ #define EXPECTED_BYTES 5 -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; -#if !TEST_DGRAM - int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); -#else - int SocketFD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); -#endif +int sockfd = -1; - if (-1 == SocketFD) - { - perror("cannot create socket"); - exit(EXIT_FAILURE); - } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); +void finish(int result) { + close(sockfd); + exit(result); +} - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons(SOCKK); - Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr); +void loop() { + fd_set fdw; + int res; - if (0 > Res) { - perror("error: first parameter is not a valid address family"); - close(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + // Make sure that sockfd has actually finished connecting + // and is ready to read. + FD_ZERO(&fdw); + FD_SET(sockfd, &fdw); + res = select(64, NULL, &fdw, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (!FD_ISSET(sockfd, &fdw)) { + return; } - printf("connect..\n"); + char data[] = "hello from the other siide\n"; - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { - perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); + printf("send..\n"); +#if TEST_FILE_OPS + res = write(sockfd, data, sizeof(data)); +#else + res = send(sockfd, data, sizeof(data), 0); +#endif + if (res == -1) { + if (errno != EAGAIN) { + perror("send error"); + finish(EXIT_FAILURE); + } + return; } -#if TEST_FILE_OPS - printf("write..\n"); + finish(EXIT_SUCCESS); +} - char data[] = "hello from the other siide (fileops)\n"; - write(SocketFD, data, sizeof(data)); +int main() { + struct sockaddr_in addr; + int res; +#if !TEST_DGRAM + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); #else - printf("send..\n"); - - char data[] = "hello from the other siide\n"; - send(SocketFD, data, sizeof(data), 0); + sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); #endif + if (sockfd == -1) { + perror("cannot create socket"); + finish(EXIT_FAILURE); + } + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); + } - printf("stall..\n"); + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { + perror("connect failed"); + finish(EXIT_FAILURE); + } - //int bytes; - //while (1) ioctl(SocketFD, FIONREAD, &bytes); + emscripten_set_main_loop(loop, 0, 0); return EXIT_SUCCESS; } diff --git a/tests/websockets_bi_side_bigdata.c b/tests/websockets_bi_side_bigdata.c index 9b67fe4c..d131e6e0 100644 --- a/tests/websockets_bi_side_bigdata.c +++ b/tests/websockets_bi_side_bigdata.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #if EMSCRIPTEN #include <emscripten.h> @@ -16,54 +17,74 @@ #define EXPECTED_BYTES 5 -void stall(void *arg) { -} +int sockfd = -1; +char *data = NULL; -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +void finish(int result) { + close(sockfd); + exit(result); +} - if (-1 == SocketFD) - { - perror("cannot create socket"); - exit(EXIT_FAILURE); +void loop() { + fd_set fdw; + int res; + + // make sure that sockfd has finished connecting and is ready to write + FD_ZERO(&fdw); + FD_SET(sockfd, &fdw); + res = select(64, NULL, &fdw, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + return; + } else if (!FD_ISSET(sockfd, &fdw)) { + return; } - memset(&stSockAddr, 0, sizeof(stSockAddr)); + printf("send..\n"); - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons(SOCKK); - Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr); + res = send(sockfd, data, DATA_SIZE, 0); + if (res == -1) { + if (errno != EAGAIN) { + perror("send error"); + finish(EXIT_FAILURE); + } + return; + } - if (0 > Res) { - perror("error: first parameter is not a valid address family"); - close(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); + finish(EXIT_SUCCESS); +} + +int main() { + struct sockaddr_in addr; + int res; + + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { + perror("cannot create socket"); exit(EXIT_FAILURE); } + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); + } printf("connect..\n"); - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } - printf("send..\n"); - - char *data = generateData(); - send(SocketFD, data, DATA_SIZE, 0); - - printf("stall..\n"); + data = generateData(); - emscripten_set_main_loop(stall, 1, 0); + emscripten_set_main_loop(loop, 1, 0); return EXIT_SUCCESS; -} - +}
\ No newline at end of file diff --git a/tests/websockets_gethostbyname.c b/tests/websockets_gethostbyname.c index 1580d9a7..59c55ba1 100644 --- a/tests/websockets_gethostbyname.c +++ b/tests/websockets_gethostbyname.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #if EMSCRIPTEN #include <emscripten.h> @@ -14,10 +15,17 @@ #define EXPECTED_BYTES 5 -int SocketFD; +int sockfd; -unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) -{ +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} + +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; @@ -27,28 +35,42 @@ unsigned int get_all_buf(int sock, char* output, unsigned int maxsize) 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); } + if (n > 0) { + if (((unsigned int) n)+offset > maxsize) { + fprintf(stderr, "too much data!"); + finish(EXIT_FAILURE); + } memcpy(output+offset, buffer, n); offset += n; } } - if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { - fprintf(stderr, "error in get_all_buf!"); - exit(EXIT_FAILURE); + if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + perror("error in get_all_buf!"); + finish(EXIT_FAILURE); } return offset; } -int done = 0; - void iter() { - /* perform read write operations ... */ static char out[1024*2]; static int pos = 0; - int n = get_all_buf(SocketFD, out+pos, 1024-pos); + fd_set fdr; + int res; + + // make sure that sockfd has finished connecting and is ready to read + FD_ZERO(&fdr); + FD_SET(sockfd, &fdr); + res = select(64, &fdr, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (!FD_ISSET(sockfd, &fdr)) { + return; + } + + // perform read write operations ... + int n = get_all_buf(sockfd, out+pos, 1024-pos); if (n) printf("read! %d\n", n); pos += n; if (pos >= EXPECTED_BYTES) { @@ -58,73 +80,57 @@ void iter() { sum += out[i]; } - shutdown(SocketFD, SHUT_RDWR); + shutdown(sockfd, SHUT_RDWR); - close(SocketFD); - - done = 1; + close(sockfd); printf("sum: %d\n", sum); -#if EMSCRIPTEN - int result = sum; - REPORT_RESULT(); -#endif + finish(sum); } } -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +int main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } + fcntl(sockfd, F_SETFL, O_NONBLOCK); - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons(7001); - + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); struct hostent *host0 = gethostbyname("test.com"); // increment hostname counter to check for possible but at 0,0 not differentiating low/high struct hostent *host = gethostbyname("localhost"); - char **addr_list = host->h_addr_list; - int *addr = (int*)*addr_list; - printf("raw addr: %d\n", *addr); + char **raw_addr_list = host->h_addr_list; + int *raw_addr = (int*)*raw_addr_list; + printf("raw addr: %d\n", *raw_addr); char name[INET_ADDRSTRLEN]; - if (!inet_ntop(AF_INET, addr, name, sizeof(name))) { + if (!inet_ntop(AF_INET, raw_addr, name, sizeof(name))) { printf("could not figure out name\n"); - return 0; + finish(EXIT_FAILURE); } printf("localhost has 'ip' of %s\n", name); - Res = inet_pton(AF_INET, name, &stSockAddr.sin_addr); - - if (0 > Res) { - perror("error: first parameter is not a valid address family"); - close(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + if (inet_pton(AF_INET, name, &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(); + while (1) iter(); #endif return EXIT_SUCCESS; diff --git a/tests/websockets_partial.c b/tests/websockets_partial.c index f71160b7..5fe34721 100644 --- a/tests/websockets_partial.c +++ b/tests/websockets_partial.c @@ -3,6 +3,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -13,107 +14,98 @@ #include <emscripten.h> #endif -int SocketFD; -int done = 0; +int sockfd = -1; int sum = 0; +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} + void iter(void *arg) { char buffer[1024]; char packetLength; - int n; + fd_set fdr; int i; - - if (done) { + int res; + + // make sure that sockfd is ready to read + FD_ZERO(&fdr); + FD_SET(sockfd, &fdr); + res = select(64, &fdr, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (!FD_ISSET(sockfd, &fdr)) { return; } - n = recv(SocketFD, buffer, 1, 0); - - if (n == -1) { + res = recv(sockfd, buffer, 1, 0); + if (res == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return; //try again } - fprintf(stderr, "unexcepted end of data"); - exit(EXIT_FAILURE); + perror("unexcepted end of data"); + finish(EXIT_FAILURE); } - if (n != 1) { - fprintf(stderr, "should read 1 byte"); - exit(EXIT_FAILURE); + if (res != 1) { + perror("should read 1 byte"); + finish(EXIT_FAILURE); } packetLength = buffer[0]; - n = recv(SocketFD, buffer, packetLength, 0); + res = recv(sockfd, buffer, packetLength, 0); - printf("got %d,%d\n", n, packetLength); + printf("got %d,%d\n", res, packetLength); - if (n != packetLength) { - fprintf(stderr, "lost packet data, expected: %d readed: %d", packetLength, n); - exit(EXIT_FAILURE); + if (res != packetLength) { + fprintf(stderr, "lost packet data, expected: %d readed: %d", packetLength, res); + finish(EXIT_FAILURE); } for (i = 0; i < packetLength; ++i) { if (buffer[i] != i+1) { fprintf(stderr, "packet corrupted, expected: %d, actual: %d", i+1, buffer[i]); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } sum += buffer[i]; } if (packetLength == buffer[0]) { // \x01\x01 - end marker - shutdown(SocketFD, SHUT_RDWR); - close(SocketFD); - done = 1; - - #if EMSCRIPTEN - printf("sum: %d\n", sum); - int result = sum; - REPORT_RESULT(); - #endif + printf("sum: %d\n", sum); + finish(sum); } } -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +int main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); exit(EXIT_FAILURE); } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8991 -#else - 8990 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN diff --git a/tests/websockets_select.c b/tests/websockets_select.c index b8ab9091..e05bd4c8 100644 --- a/tests/websockets_select.c +++ b/tests/websockets_select.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #include <assert.h> #if EMSCRIPTEN @@ -15,81 +16,83 @@ #define EXPECTED_BYTES 5 -int SocketFD; +int sockfd = -1; -int done = 0; +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} + +void iter(void *arg) { + static int retries = 0; -void iter(void *arg) { fd_set sett; FD_ZERO(&sett); - FD_SET(SocketFD, &sett); + FD_SET(sockfd, &sett); - // The error should happen here - int select_says_yes = select(64, &sett, NULL, NULL, NULL); - if( select_says_yes == -1 ){ - printf( "Connection to websocket server failed as expected." ); - perror( "Error message" ); - int result = 266; - REPORT_RESULT(); - done = 1; + // currently, we've connected to a closed server port. + // the initial async connect "succeeded" and select + // should say that the socket is ready for a non-blocking + // read, however, the read should be 0 sized signalling + // that the remote end has closed. + int handles = select(64, &sett, NULL, NULL, NULL); + if (handles == -1) { + perror("select failed"); + finish(EXIT_FAILURE); } - assert(!select_says_yes); - done = 1; + if (FD_ISSET(sockfd, &sett)) { + char buffer[1024]; + int n = recv(sockfd, buffer, sizeof(buffer), 0); + if (n == -1 && retries++ > 10) { + perror("revv failed"); + finish(EXIT_FAILURE); + } else if (!n) { + perror("Connection to websocket server failed as expected."); + finish(266); + } + } } // This is for testing a websocket connection to a closed server port. // The connect call will succeed (due to the asynchronous websocket // behavior) but once the underlying websocket system realized that // the connection cannot be established, the next select call will fail. -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +int main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } + fcntl(sockfd, F_SETFL, O_NONBLOCK); - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8995 -#else - 8994 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } // This call should succeed (even if the server port is closed) - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif - - return EXIT_SUCCESS; + + return EXIT_FAILURE; } diff --git a/tests/websockets_select_server_closes_connection.c b/tests/websockets_select_server_closes_connection.c index 6ce6d311..4181b12b 100644 --- a/tests/websockets_select_server_closes_connection.c +++ b/tests/websockets_select_server_closes_connection.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #include <assert.h> #if EMSCRIPTEN @@ -15,9 +16,15 @@ #define EXPECTED_BYTES 5 -int SocketFD; +int sockfd = -1; -int done = 0; +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} void iter(void *arg) { static char readbuf[1024]; @@ -25,44 +32,39 @@ void iter(void *arg) { fd_set sett; FD_ZERO(&sett); - FD_SET(SocketFD, &sett); + FD_SET(sockfd, &sett); + + int res = select(64, &sett, NULL, NULL, NULL); - if( readPos < 7 ){ - // still reading - int selectRes = select(64, &sett, NULL, NULL, NULL); + if (res == -1) { + perror("select failed"); + finish(EXIT_FAILURE); + } else if (res == 0) { + return; + } else if (res > 0) { + assert(FD_ISSET(sockfd, &sett)); - if( selectRes == 0 ) + int bytesRead = recv(sockfd, readbuf+readPos, 7-readPos, 0); + if (bytesRead == -1) { + if (errno != EAGAIN) { + perror("recv error"); + finish(EXIT_FAILURE); + } + // try again return; - - if( selectRes == -1 ){ - perror( "Connection to websocket server failed" ); - exit(EXIT_FAILURE); } - if( selectRes > 0 ){ - assert(FD_ISSET(SocketFD, &sett)); - - int bytesRead = recv( SocketFD, readbuf+readPos, 7-readPos, 0 ); + + if (readPos < 7) { readPos += bytesRead; + } else { + if (!bytesRead) { + perror("Connection to websocket server was closed as expected"); + finish(266); + } else { + perror("Connection to websocket server was not closed"); + finish(EXIT_FAILURE); + } } - } else { - // here the server should have closed the connection - int selectRes = select(64, &sett, NULL, NULL, NULL); - - if( selectRes == 0 ) - return; - - if( selectRes == -1 ){ - perror( "Connection to websocket server failed as expected" ); - int result = 266; - REPORT_RESULT(); - emscripten_cancel_main_loop(); - done = 1; - } - - if( selectRes > 0 ){ - printf( "Error: socket should not show up on select call anymore.\n" ); - exit(EXIT_FAILURE); - } } return; @@ -71,56 +73,40 @@ void iter(void *arg) { // Scenario: the server sends data and closes the connection after 7 bytes. // This test should provoke the situation in which the underlying // tcp connection has been torn down already but there is still data -// in the inQueue. The select call has to succeed as long the queue +// in the queue. The select call has to succeed as long the queue // still contains data and only then start to throw errors. -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +int main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } + fcntl(sockfd, F_SETFL, O_NONBLOCK); - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8995 -#else - 8994 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } // This call should succeed (even if the server port is closed) - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif - return EXIT_SUCCESS; + return EXIT_FAILURE; } diff --git a/tests/websockets_select_server_closes_connection_rw.c b/tests/websockets_select_server_closes_connection_rw.c index dd0913bf..f7e19aca 100644 --- a/tests/websockets_select_server_closes_connection_rw.c +++ b/tests/websockets_select_server_closes_connection_rw.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <sys/ioctl.h> #include <assert.h> #if EMSCRIPTEN @@ -15,9 +16,15 @@ #define EXPECTED_BYTES 5 -int SocketFD; +int sockfd = -1; -int done = 0; +void finish(int result) { + close(sockfd); +#if EMSCRIPTEN + REPORT_RESULT(); +#endif + exit(result); +} void iter(void *arg) { static int state = 0; @@ -27,42 +34,40 @@ void iter(void *arg) { static int readPos = 0; int selectRes; ssize_t transferAmount; - fd_set sett; + fd_set sett; - - switch( state ){ + switch (state) { case 0: // writing 10 bytes to the server - // the socket in the read file descriptors has to result in a 0 return value - // because the connection exists, but there is no data yet - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + // since the socket in the read file descriptors has no available data, + // select should tell us 0 handles are ready + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, &sett, NULL, NULL, NULL); - if( selectRes != 0 ){ - printf( "case 0: read select != 0\n" ); - exit(EXIT_FAILURE); + if (selectRes != 0) { + printf("case 0: read select != 0 (%d)\n", selectRes); + finish(EXIT_FAILURE); } // the socket in the write file descriptors has to result in either a 0 or 1 // the connection either is setting up or is established and writing is possible - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, NULL, &sett, NULL, NULL); - if( selectRes == -1 ){ - printf( "case 0: write select == -1\n" ); - exit(EXIT_FAILURE); - } - if( selectRes == 0 ){ + if (selectRes == -1) { + printf("case 0: write select == -1\n"); + finish(EXIT_FAILURE); + } else if (selectRes == 0) { return; } // send a single byte - transferAmount = send( SocketFD, writebuf+writePos, 1, 0 ); + transferAmount = send(sockfd, writebuf+writePos, 1, 0); writePos += transferAmount; // after 10 bytes switch to next state - if( writePos >= 10 ){ + if (writePos >= 10) { state = 1; } break; @@ -70,79 +75,86 @@ void iter(void *arg) { case 1: // wait until we can read one byte to make sure the server // has sent the data and then closed the connection - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, &sett, NULL, NULL, NULL); - if( selectRes == -1 ){ - printf( "case 1: read selectRes == -1\n" ); - exit(EXIT_FAILURE); - } - if( selectRes == 0 ) + if (selectRes == -1) { + printf("case 1: read selectRes == -1\n"); + finish(EXIT_FAILURE); + } else if (selectRes == 0) { return; + } // read a single byte - transferAmount = recv( SocketFD, readbuf+readPos, 1, 0 ); + transferAmount = recv(sockfd, readbuf+readPos, 1, 0); readPos += transferAmount; // if successfully reading 1 byte, switch to next state - if( readPos >= 1 ){ + if (readPos >= 1) { state = 2; } break; case 2: - // calling select with the socket in the write file descriptors has - // to fail because the tcp network connection is already down - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + // calling select with the socket in the write file descriptors should + // succeed, but the socket should not set in the set. + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, NULL, &sett, NULL, NULL); - if( selectRes != -1 ){ - printf( "case 2: write selectRes != -1\n" ); - exit(EXIT_FAILURE); + if (selectRes != 0 || FD_ISSET(sockfd, &sett)) { + printf("case 2: write selectRes != 0 || FD_ISSET(sockfd, &sett)\n"); + finish(EXIT_FAILURE); } // calling select with the socket in the read file descriptors // has to succeed because there is still data in the inQueue - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, &sett, NULL, NULL, NULL); - if( selectRes != 1 ){ - printf( "case 2: read selectRes != 1\n" ); - exit(EXIT_FAILURE); - } - if( selectRes == 0 ) + if (selectRes != 1) { + printf("case 2: read selectRes != 1\n"); + finish(EXIT_FAILURE); + } else if (selectRes == 0) { return; + } // read a single byte - transferAmount = recv( SocketFD, readbuf+readPos, 1, 0 ); + transferAmount = recv(sockfd, readbuf+readPos, 1, 0); readPos += transferAmount; // with 10 bytes read the inQueue is empty => switch state - if( readPos >= 10 ){ + if (readPos >= 10) { state = 3; } break; case 3: // calling select with the socket in the read file descriptors - // now also has to fail as the inQueue is empty - FD_ZERO( &sett ); - FD_SET(SocketFD, &sett); + // should succeed + FD_ZERO(&sett); + FD_SET(sockfd, &sett); selectRes = select(64, &sett, NULL, NULL, NULL); - if( selectRes != -1 ){ - printf( "case 3: read selectRes != -1\n" ); - exit(EXIT_FAILURE); + if (selectRes != 1) { + printf("case 3: read selectRes != 1\n"); + finish(EXIT_FAILURE); + } + + // but recv should return 0 signaling the remote + // end has closed the connection. + transferAmount = recv(sockfd, readbuf, 1, 0); + if (transferAmount) { + printf("case 3: read != 0\n"); + finish(EXIT_FAILURE); } // report back success, the 266 is just an arbitrary value without // deeper meaning - int result = 266; - REPORT_RESULT(); + finish(266); break; default: - printf( "Impossible state!\n" ); - exit(EXIT_FAILURE); + printf("Impossible state!\n"); + finish(EXIT_FAILURE); break; } @@ -160,52 +172,36 @@ void iter(void *arg) { // as there are still 10 bytes to read from the inQueue. So, for the same socket the // select call behaves differently depending on whether the socket is listed in the // read or write file descriptors. -int main(void) -{ - struct sockaddr_in stSockAddr; - int Res; - SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +int main() { + struct sockaddr_in addr; + int res; - if (-1 == SocketFD) - { + sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { perror("cannot create socket"); - exit(EXIT_FAILURE); + finish(EXIT_FAILURE); } - - memset(&stSockAddr, 0, sizeof(stSockAddr)); - - stSockAddr.sin_family = AF_INET; - stSockAddr.sin_port = htons( -#if EMSCRIPTEN - 8999 -#else - 8998 -#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(SocketFD); - exit(EXIT_FAILURE); - } else if (0 == Res) { - perror("char string (second parameter does not contain valid ipaddress)"); - close(SocketFD); - exit(EXIT_FAILURE); + fcntl(sockfd, F_SETFL, O_NONBLOCK); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SOCKK); + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) { + perror("inet_pton failed"); + finish(EXIT_FAILURE); } // This call should succeed (even if the server port is closed) - if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) { + res = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); + if (res == -1 && errno != EINPROGRESS) { perror("connect failed"); - close(SocketFD); - exit(EXIT_FAILURE); - + finish(EXIT_FAILURE); } #if EMSCRIPTEN emscripten_set_main_loop(iter, 0, 0); #else - while (!done) iter(NULL); + while (1) iter(NULL); #endif return EXIT_SUCCESS; |