int rfbWriteExact(rfbClientPtr cl, const char *buf, int len) { int sock = cl->sock; int n; fd_set fds; struct timeval tv; int totalTimeWaited = 0; const int timeout = (cl->screen && cl->screen->maxClientWait) ? cl->screen->maxClientWait : rfbMaxClientWait; #undef DEBUG_WRITE_EXACT #ifdef DEBUG_WRITE_EXACT rfbLog("WriteExact %d bytes\n",len); for(n=0;n<len;n++) fprintf(stderr,"%02x ",(unsigned char)buf[n]); 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) { #ifdef LIBVNCSERVER_WITH_WEBSOCKETS if (cl->sslctx) n = rfbssl_write(cl, buf, len); else #endif n = write(sock, buf, len); if (n > 0) { buf += n; len -= n; } else if (n == 0) { rfbErr("WriteExact: write returned 0?\n"); return 0; } else { #ifdef WIN32 errno = WSAGetLastError(); #endif if (errno == EINTR) continue; if (errno != EWOULDBLOCK && errno != EAGAIN) { UNLOCK(cl->outputMutex); return n; } /* Retry every 5 seconds until we exceed timeout. We need to do this because select doesn't necessarily return immediately when the other end has gone away */ FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = 5; tv.tv_usec = 0; n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv); if (n < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if(errno==EINTR) continue; rfbLogPerror("WriteExact: select"); UNLOCK(cl->outputMutex); return n; } if (n == 0) { totalTimeWaited += 5000; if (totalTimeWaited >= timeout) { errno = ETIMEDOUT; UNLOCK(cl->outputMutex); return -1; } } else { totalTimeWaited = 0; } } } UNLOCK(cl->outputMutex); return 1; }
int WriteExact(rfbClientPtr cl, char *buf, int len) { int n, bytesWritten = 0; fd_set fds; struct timeval tv; int totalTimeWaited = 0; int sock = cl->sock; while (len > 0) { do { #if USETLS if (cl->sslctx) n = rfbssl_write(cl, buf, len); else #endif n = write(sock, buf, len); } while (n < 0 && errno == EINTR); if (n > 0) { buf += n; len -= n; bytesWritten += n; sendBytes += n; } else if (n == 0) { rfbLog("WriteExact: write returned 0?\n"); exit(1); } else { if (errno != EWOULDBLOCK && errno != EAGAIN && errno != 0) { return n; } /* Retry every 5 seconds until we exceed rfbMaxClientWait. We need to do this because select doesn't necessarily return immediately when the other end has gone away */ FD_ZERO(&fds); FD_SET(sock, &fds); tv.tv_sec = 5; tv.tv_usec = 0; do { n = select(sock + 1, NULL, &fds, NULL, &tv); } while (n < 0 && errno == EINTR); if (n < 0) { rfbLogPerror("WriteExact: select"); return n; } if (n == 0) { totalTimeWaited += 5000; if (totalTimeWaited >= rfbMaxClientWait) { errno = ETIMEDOUT; return -1; } } else { totalTimeWaited = 0; } } } gettimeofday(&cl->lastWrite, NULL); cl->sockOffset += bytesWritten; return 1; }