VBool VSocket::SendExact(const char *buff, const VCard bufflen) { struct fd_set write_fds; struct timeval tm; int count; // Put the data into the queue SendQueued(buff, bufflen); while (out_queue) { // Wait until some data can be sent do { FD_ZERO(&write_fds); FD_SET((unsigned int)sock, &write_fds); tm.tv_sec = 1; tm.tv_usec = 0; count = select(sock + 1, NULL, &write_fds, NULL, &tm); } while (count == 0); if (count < 0 || count > 1) { vnclog.Print(LL_SOCKERR, VNCLOG("socket error in select()\n")); return VFalse; } // Actually send some data if (FD_ISSET((unsigned int)sock, &write_fds)) { if (!SendFromQueue()) return VFalse; } } return VTrue; }
VBool VSocket::ReadExact(char *buff, const VCard bufflen) { int bytes; VCard currlen = bufflen; struct fd_set read_fds, write_fds; struct timeval tm; int count; while (currlen > 0) { // Wait until some data can be read or sent do { FD_ZERO(&read_fds); FD_SET((unsigned int)sock, &read_fds); FD_ZERO(&write_fds); if (out_queue) FD_SET((unsigned int)sock, &write_fds); tm.tv_sec = 0; tm.tv_usec = 50; count = select(sock + 1, &read_fds, &write_fds, NULL, &tm); } while (count == 0); if (count < 0 || count > 2) { vnclog.Print(LL_SOCKERR, VNCLOG("socket error in select()\n")); return VFalse; } if (FD_ISSET((unsigned int)sock, &write_fds)) { // Try to send some data if (!SendFromQueue()) return VFalse; } if (FD_ISSET((unsigned int)sock, &read_fds)) { // Try to read some data in bytes = Read(buff, currlen); if (bytes > 0) { // Adjust the buffer position and size buff += bytes; currlen -= bytes; } else if (bytes < 0 && errno != EWOULDBLOCK) { vnclog.Print(LL_SOCKERR, VNCLOG("socket error\n")); return VFalse; } else if (bytes == 0) { vnclog.Print(LL_SOCKERR, VNCLOG("zero bytes read\n")); return VFalse; } } } return VTrue; }
VBool CurlSocket::SendExact(const char *buff, const VCard bufflen) { // Put the data into the queue SendQueued(buff, bufflen); while (!out_queue.empty()) { // Actually send some data if (!SendFromQueue()) { return VFalse; } } return VTrue; }
VBool CurlSocket::ReadExact(char *buff, const VCard bufflen) { // Reads exactly bufflen amount of data. // We don't have poll support yet. So just flush the queue and // simulate appropriate read. if (!m_bIsConnected) return VFalse; TimeStampGenerator tip; tip.reset(); while (!out_queue.empty()) { if (!SendFromQueue()) return VFalse; } if (tip.getTimeStamp() < 20) ::WaitForSingleObject(m_eTimer, m_transactionWaitTime); return VTrue; }