diff options
Diffstat (limited to 'libvncserver/sockets.c')
-rw-r--r-- | libvncserver/sockets.c | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 188a8fd..415f712 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -62,6 +62,10 @@ #include <unistd.h> #endif +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +#include "rfbssl.h" +#endif + #if defined(__linux__) && defined(NEED_TIMEVAL) struct timeval { @@ -392,6 +396,11 @@ rfbCloseClient(rfbClientPtr cl) while(cl->screen->maxFd>0 && !FD_ISSET(cl->screen->maxFd,&(cl->screen->allFds))) cl->screen->maxFd--; +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->sslctx) + rfbssl_destroy(cl); + free(cl->wspath); +#endif #ifndef __MINGW32__ shutdown(cl->sock,SHUT_RDWR); #endif @@ -457,7 +466,17 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) struct timeval tv; while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->wsctx) { + n = webSocketsDecode(cl, buf, len); + } else if (cl->sslctx) { + n = rfbssl_read(cl, buf, len); + } else { + n = read(sock, buf, len); + } +#else n = read(sock, buf, len); +#endif if (n > 0) { @@ -482,6 +501,12 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) return n; } +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->sslctx) { + if (rfbssl_pending(cl)) + continue; + } +#endif FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = timeout / 1000; @@ -492,6 +517,7 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) return n; } if (n == 0) { + rfbErr("ReadExact: select timeout\n"); errno = ETIMEDOUT; return -1; } @@ -518,6 +544,82 @@ int rfbReadExact(rfbClientPtr cl,char* buf,int len) } /* + * PeekExact peeks at an exact number of bytes from a client. Returns 1 if + * those bytes have been read, 0 if the other end has closed, or -1 if an + * error occurred (errno is set to ETIMEDOUT if it timed out). + */ + +int +rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) +{ + int sock = cl->sock; + int n; + fd_set fds; + struct timeval tv; + + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->sslctx) + n = rfbssl_peek(cl, buf, len); + else +#endif + n = recv(sock, buf, len, MSG_PEEK); + + if (n == len) { + + break; + + } else if (n == 0) { + + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + if (errno != ENOENT) +#endif + if (errno != EWOULDBLOCK && errno != EAGAIN) { + return n; + } + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->sslctx) { + if (rfbssl_pending(cl)) + continue; + } +#endif + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + n = select(sock+1, &fds, NULL, &fds, &tv); + if (n < 0) { + rfbLogPerror("PeekExact: select"); + return n; + } + if (n == 0) { + errno = ETIMEDOUT; + return -1; + } + } + } +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + rfbLog("PeekExact %d bytes\n",len); + for(n=0;n<len;n++) + fprintf(stderr,"%02x ",(unsigned char)buf[n]); + fprintf(stderr,"\n"); +#endif + + return 1; +} + +/* * WriteExact writes an exact number of bytes to a client. Returns 1 if * those bytes have been written, or -1 if an error occurred (errno is set to * ETIMEDOUT if it timed out). @@ -543,9 +645,25 @@ rfbWriteExact(rfbClientPtr cl, fprintf(stderr,"\n"); #endif +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->wsctx) { + char *tmp = NULL; + if ((len = webSocketsEncode(cl, buf, len, &tmp)) < 0) { + rfbErr("WriteExact: WebSockets encode error\n"); + return -1; + } + buf = tmp; + } +#endif + LOCK(cl->outputMutex); while (len > 0) { - n = write(sock, buf, len); +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->sslctx) + n = rfbssl_write(cl, buf, len); + else +#endif + n = write(sock, buf, len); if (n > 0) { |