diff --git a/tests/wsecho.html b/tests/wsecho.html deleted file mode 100644 index 9e3c6d6c..00000000 --- a/tests/wsecho.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - WebSockets Echo Test - - - - - - - - - - - - Host:   - Port:   - Encrypt:   -   - - -
- Log:
- - - - - - - diff --git a/tests/wsecho.html b/tests/wsecho.html new file mode 120000 index 00000000..28c636a1 --- /dev/null +++ b/tests/wsecho.html @@ -0,0 +1 @@ +../utils/wsecho.html \ No newline at end of file diff --git a/tests/wstest.html b/tests/wstest.html deleted file mode 100644 index c56c4c72..00000000 --- a/tests/wstest.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - WebSockets Test - - - - - - - - - - - - Host:   - Port:   - Encrypt:   - Send Delay (ms):   -   - -

- - - - - - - - - - - -
Packets sent:
0
Good Packets Received:
0
Errors (Bad Packets Received:)
0
- -
- Errors:
- - - - - - - diff --git a/tests/wstest.html b/tests/wstest.html new file mode 120000 index 00000000..13d6ff0a --- /dev/null +++ b/tests/wstest.html @@ -0,0 +1 @@ +../utils/wstest.html \ No newline at end of file diff --git a/utils/wsecho.html b/utils/wsecho.html new file mode 100644 index 00000000..9e3c6d6c --- /dev/null +++ b/utils/wsecho.html @@ -0,0 +1,176 @@ + + + + WebSockets Echo Test + + + + + + + + + + + + Host:   + Port:   + Encrypt:   +   + + +
+ Log:
+ + + + + + + diff --git a/utils/wstest.html b/utils/wstest.html new file mode 100644 index 00000000..c56c4c72 --- /dev/null +++ b/utils/wstest.html @@ -0,0 +1,252 @@ + + + + WebSockets Test + + + + + + + + + + + + Host:   + Port:   + Encrypt:   + Send Delay (ms):   +   + +

+ + + + + + + + + + + +
Packets sent:
0
Good Packets Received:
0
Errors (Bad Packets Received:)
0
+ +
+ Errors:
+ + + + + + + diff --git a/utils/wswrapper.c b/utils/wswrapper.c index 7d4c9c99..76e931e1 100644 --- a/utils/wswrapper.c +++ b/utils/wswrapper.c @@ -11,11 +11,12 @@ * Limitations: * - multi-threaded programs may not work * - programs using ppoll or epoll will not work correctly + * - doesn't support fopencookie, streams, putc, etc. */ #define DO_MSG 1 -//#define DO_DEBUG 1 -//#define DO_TRACE 1 +#define DO_DEBUG 1 +#define DO_TRACE 1 #include #include @@ -78,6 +79,55 @@ int _WS_subtract_time (result, x, y, ts) return x->tv_sec <= y->tv_sec; } +int _WS_alloc(int fd) { + if (_WS_connections[fd]) { + RET_ERROR(ENOMEM, "Memory already allocated for fd %d\n", fd); + } + if (! (_WS_connections[fd] = malloc(sizeof(_WS_connection)))) { + RET_ERROR(ENOMEM, "Could not allocate interposer memory\n"); + } + _WS_connections[fd]->rcarry_cnt = 0; + _WS_connections[fd]->rcarry[0] = '\0'; + _WS_connections[fd]->newframe = 1; + _WS_connections[fd]->refcnt = 1; + + /* Add to search list for select/pselect */ + _WS_fds[_WS_nfds] = fd; + _WS_nfds++; + + return 0; +} + +int _WS_free(int fd) { + int i; + _WS_connection * wsptr; + wsptr = _WS_connections[fd]; + if (wsptr) { + TRACE(">> _WS_free(%d)\n", fd); + + wsptr->refcnt--; + if (wsptr->refcnt <= 0) { + free(wsptr); + DEBUG("freed memory for fd %d\n", fd); + } + _WS_connections[fd] = NULL; + + /* Remove from the search list for select/pselect */ + for (i = 0; i < _WS_nfds; i++) { + if (_WS_fds[i] == fd) { + break; + } + } + if (_WS_nfds - i - 1 > 0) { + memmove(_WS_fds + i, _WS_fds + i + 1, _WS_nfds - i - 1); + } + _WS_nfds--; + + MSG("finished interposing on fd %d\n", fd); + TRACE("<< _WS_free(%d)\n", fd); + } +} + /* * WebSocket handshake routines @@ -619,8 +669,10 @@ int _WS_select(int mode, int nfds, fd_set *readfds, } TRACE(">> _WS_select(%d, %d, _, _, _, _)\n", mode, nfds); - memcpy(&savetv, timeptr, sizeof(savetv)); - gettimeofday(&starttv, NULL); + if (timeptr) { + memcpy(&savetv, timeptr, sizeof(savetv)); + gettimeofday(&starttv, NULL); + } /* If we have carry-over return it right away */ FD_ZERO(&carryfds); @@ -649,9 +701,11 @@ int _WS_select(int mode, int nfds, fd_set *readfds, } do { - TRACE(" _WS_select(%d, %d, _, _, _, _) tv/ts: %ld:%ld\n", mode, nfds, - ((struct timeval *) timeptr)->tv_sec, - ((struct timeval *) timeptr)->tv_usec); + if (timeptr) { + TRACE(" _WS_select tv/ts: %ld:%ld\n", + ((struct timeval *) timeptr)->tv_sec, + ((struct timeval *) timeptr)->tv_usec); + } if (mode == 0) { ret = (int) func0(nfds, readfds, writefds, exceptfds, timeptr); @@ -689,6 +743,10 @@ int _WS_select(int mode, int nfds, fd_set *readfds, * them were really ready (empty frames) then we select again. But * first restore original values less passage of time. */ + if (! timeptr) { + /* No timeout, spin forever */ + continue; + } memcpy(readfds, &savefds, sizeof(savefds)); gettimeofday(&nowtv, NULL); /* Amount of time that has passed */ @@ -871,7 +929,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) _WS_listen_fd = sockfd; - TRACE("<< bind, interposing on port: %d (fd %d)\n", envport, sockfd); + TRACE("<< bind, listening for WebSockets connections on port: %d (fd %d)\n", envport, sockfd); return ret; } @@ -902,21 +960,13 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) if (_WS_nfds >= WS_MAX_FDS) { RET_ERROR(ENOMEM, "Too many interposer fds\n"); } - if (! (_WS_connections[fd] = malloc(sizeof(_WS_connection)))) { - RET_ERROR(ENOMEM, "Could not allocate interposer memory\n"); + if (_WS_alloc(fd) < 0) { + return -1; } - _WS_connections[fd]->rcarry_cnt = 0; - _WS_connections[fd]->rcarry[0] = '\0'; - _WS_connections[fd]->newframe = 1; - - /* Add to search list for select/pselect */ - _WS_fds[_WS_nfds] = fd; - _WS_nfds++; ret = _WS_handshake(fd); if (ret < 0) { - free(_WS_connections[fd]); - _WS_connections[fd] = NULL; + _WS_free(fd); errno = EPROTO; TRACE("<< accept(%d, _, _): ret %d\n", sockfd, ret); return ret; @@ -929,61 +979,45 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) int close(int fd) { - int i; static void * (*func)(); if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "close"); - if (_WS_connections[fd]) { - TRACE(">> close(%d)\n", fd); - free(_WS_connections[fd]); - _WS_connections[fd] = NULL; + TRACE("close(%d) called\n", fd); - /* Remove from the search list for select/pselect */ - for (i = 0; i < _WS_nfds; i++) { - if (_WS_fds[i] == fd) { - break; - } - } - if (_WS_nfds - i - 1 > 0) { - memmove(_WS_fds + i, _WS_fds + i + 1, _WS_nfds - i - 1); - } - _WS_nfds--; + _WS_free(fd); - MSG("finished interposing on fd %d (freed memory)\n", fd); - TRACE("<< close(%d)\n", fd); - } return (int) func(fd); } ssize_t read(int fd, void *buf, size_t count) { - //TRACE("read(%d, _, %d) called\n", fd, count); + TRACE("read(%d, _, %d) called\n", fd, count); return (ssize_t) _WS_recv(0, fd, buf, count, 0); } ssize_t write(int fd, const void *buf, size_t count) { - //TRACE("write(%d, _, %d) called\n", fd, count); + TRACE("write(%d, _, %d) called\n", fd, count); return (ssize_t) _WS_send(0, fd, buf, count, 0); } ssize_t recv(int sockfd, void *buf, size_t len, int flags) { - //TRACE("recv(%d, _, %d, %d) called\n", sockfd, len, flags); + TRACE("recv(%d, _, %d, %d) called\n", sockfd, len, flags); return (ssize_t) _WS_recv(1, sockfd, buf, len, flags); } ssize_t send(int sockfd, const void *buf, size_t len, int flags) { - //TRACE("send(%d, _, %d, %d) called\n", sockfd, len, flags); + TRACE("send(%d, _, %d, %d) called\n", sockfd, len, flags); return (ssize_t) _WS_send(1, sockfd, buf, len, flags); } int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { - //TRACE("select(%d, _, _, _, _) called\n", nfds); + TRACE("select(%d, _, _, _, _) called\n", nfds); return _WS_select(0, nfds, readfds, writefds, exceptfds, (void *) timeout, NULL); } @@ -1007,5 +1041,43 @@ int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) { TRACE("ppoll(_, %ld, _, _) called\n", nfds); - return _WS_poll(0, fds, nfds, 0, timeout, sigmask); + return _WS_poll(0, fds, nfds, 0, (struct timespec *)timeout, + (sigset_t *)sigmask); +} + +int dup2(int oldfd, int newfd) { + int ret; + static void * (*func)(); + if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "dup2"); + + TRACE("dup2(%d, %d) called\n", oldfd, newfd); + + ret = (int) func(oldfd, newfd); + if (! _WS_connections[oldfd]) { + return ret; + } + + if (ret < 0) { + return ret; + } + if (oldfd == newfd) { + return newfd; + } + + /* dup2 behavior is to close newfd if it's open */ + if (_WS_connections[newfd]) { + _WS_free(newfd); + } + + /* oldfd and newfd are now descriptors for the same socket, + * re-use the same context memory area */ + _WS_connections[newfd] = _WS_connections[oldfd]; + _WS_connections[newfd]->refcnt++; + + /* Add to search list for select/pselect */ + _WS_fds[_WS_nfds] = newfd; + _WS_nfds++; + + return ret; + } diff --git a/utils/wswrapper.h b/utils/wswrapper.h index afe9375b..b69e9cf1 100644 --- a/utils/wswrapper.h +++ b/utils/wswrapper.h @@ -61,6 +61,7 @@ typedef struct { int rcarry_cnt; char rcarry[3]; int newframe; + int refcnt; } _WS_connection;