Streams the body of an upload request to `tmpPath`, tracking progress and honouring a receive cancel. `leftover` is the body bytes already read while parsing the header. Returns true when the full body was written.
| 187 | // honouring a receive cancel. `leftover` is the body bytes already read while |
| 188 | // parsing the header. Returns true when the full body was written. |
| 189 | bool streamBodyToFile(s32 clientSocket, const std::string& tmpPath, size_t contentLength, const char* leftover, size_t leftoverLen) |
| 190 | { |
| 191 | FILE* out = fopen(tmpPath.c_str(), "wb"); |
| 192 | if (out == nullptr) { |
| 193 | Logging::error("Failed to open upload temp file {} with errno {}.", tmpPath, errno); |
| 194 | return false; |
| 195 | } |
| 196 | |
| 197 | TransferStatus::beginNetwork(i18n::t("transfer.downloading"), contentLength); |
| 198 | |
| 199 | size_t written = 0; |
| 200 | if (leftoverLen > 0) { |
| 201 | size_t toWrite = leftoverLen > contentLength ? contentLength : leftoverLen; |
| 202 | fwrite(leftover, 1, toWrite, out); |
| 203 | written += toWrite; |
| 204 | TransferStatus::setBytesDone(written); |
| 205 | } |
| 206 | |
| 207 | constexpr size_t RECV_CHUNK = 64 * 1024; |
| 208 | std::vector<char> buffer(RECV_CHUNK); |
| 209 | int idleMs = 0; |
| 210 | bool ok = true; |
| 211 | while (written < contentLength) { |
| 212 | ssize_t received = pollRecv(clientSocket, buffer.data(), buffer.size(), idleMs, true); |
| 213 | if (received <= 0) { |
| 214 | ok = false; // clean close, idle timeout, or cancel: incomplete body |
| 215 | break; |
| 216 | } |
| 217 | size_t toWrite = (size_t)received; |
| 218 | if (written + toWrite > contentLength) { |
| 219 | toWrite = contentLength - written; |
| 220 | } |
| 221 | fwrite(buffer.data(), 1, toWrite, out); |
| 222 | written += toWrite; |
| 223 | TransferStatus::setBytesDone(written); |
| 224 | } |
| 225 | |
| 226 | fclose(out); |
| 227 | return ok && written == contentLength; |
| 228 | } |
| 229 | |
| 230 | void handleHttpRequest(s32 clientSocket) |
| 231 | { |
no test coverage detected