#ifdef _WIN32 #include #undef min #undef max #else #include #include #endif #include #include #ifndef MSG_NOSIGNAL // Default value to 0x00 (do nothing) in systems where it's not supported. #define MSG_NOSIGNAL 0x00 #endif #include "Common/File/FileDescriptor.h" #include "Common/Log.h" #include "Common/Net/NetBuffer.h" #include "Common/TimeUtil.h" namespace net { bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) { static constexpr float CANCEL_INTERVAL = 0.25f; for (size_t pos = 0, end = data_.size(); pos < end; ) { bool ready = false; double leftTimeout = timeout; while (!ready && (leftTimeout >= 0 || cancelled)) { if (cancelled && *cancelled) return false; ready = fd_util::WaitUntilReady(sock, CANCEL_INTERVAL, true); if (!ready && leftTimeout >= 0.0) { leftTimeout -= CANCEL_INTERVAL; if (leftTimeout < 0) { ERROR_LOG(IO, "FlushSocket timed out"); return false; } } } int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL); if (sent < 0) { ERROR_LOG(IO, "FlushSocket failed"); return false; } pos += sent; // Buffer full, don't spin. if (sent == 0 && timeout < 0.0) { sleep_ms(1); } } data_.resize(0); return true; } bool Buffer::ReadAll(int fd, int hintSize) { std::vector buf; if (hintSize >= 65536 * 16) { buf.resize(65536); } else if (hintSize >= 1024 * 16) { buf.resize(hintSize / 16); } else { buf.resize(4096); } while (true) { int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); if (retval == 0) { break; } else if (retval < 0) { ERROR_LOG(IO, "Error reading from buffer: %i", retval); return false; } char *p = Append((size_t)retval); memcpy(p, &buf[0], retval); } return true; } bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled) { static constexpr float CANCEL_INTERVAL = 0.25f; std::vector buf; if (knownSize >= 65536 * 16) { buf.resize(65536); } else if (knownSize >= 1024 * 16) { buf.resize(knownSize / 16); } else { buf.resize(1024); } int total = 0; while (true) { bool ready = false; while (!ready && cancelled) { if (*cancelled) return false; ready = fd_util::WaitUntilReady(fd, CANCEL_INTERVAL, false); } int retval = recv(fd, &buf[0], (int)buf.size(), MSG_NOSIGNAL); if (retval == 0) { return true; } else if (retval < 0) { ERROR_LOG(IO, "Error reading from buffer: %i", retval); return false; } char *p = Append((size_t)retval); memcpy(p, &buf[0], retval); total += retval; if (progress) *progress = (float)total / (float)knownSize; } return true; } int Buffer::Read(int fd, size_t sz) { char buf[1024]; int retval; size_t received = 0; while ((retval = recv(fd, buf, (int)std::min(sz, sizeof(buf)), MSG_NOSIGNAL)) > 0) { if (retval < 0) { return retval; } char *p = Append((size_t)retval); memcpy(p, buf, retval); sz -= retval; received += retval; if (sz == 0) return 0; } return (int)received; } }