Streams the body of an upload request to `tmpPath`, tracking progress and honouring a receive cancel. `leftover` is the body already read while parsing the header. Returns true when the full body was written.
| 159 | // honouring a receive cancel. `leftover` is the body already read while |
| 160 | // parsing the header. Returns true when the full body was written. |
| 161 | static bool streamBodyToFile(s32 clientSocket, const std::u16string& tmpPath, size_t contentLength, const char* leftover, size_t leftoverLen) |
| 162 | { |
| 163 | FSStream out(Archive::sdmc(), tmpPath, FS_OPEN_WRITE, (u32)contentLength); |
| 164 | if (!out.good()) { |
| 165 | Logging::error("Failed to open upload temp file (0x{:08X}).", (u32)out.result()); |
| 166 | return false; |
| 167 | } |
| 168 | |
| 169 | TransferStatus::beginNetwork(i18n::t("transfer.downloading"), contentLength); |
| 170 | |
| 171 | size_t written = 0; |
| 172 | if (leftoverLen > 0) { |
| 173 | size_t toWrite = leftoverLen > contentLength ? contentLength : leftoverLen; |
| 174 | out.write(leftover, (u32)toWrite); |
| 175 | written += toWrite; |
| 176 | TransferStatus::setBytesDone(written); |
| 177 | } |
| 178 | |
| 179 | constexpr size_t RECV_CHUNK = 32 * 1024; |
| 180 | std::unique_ptr<char[]> buffer(new char[RECV_CHUNK]); |
| 181 | int idleMs = 0; |
| 182 | bool ok = true; |
| 183 | while (written < contentLength) { |
| 184 | ssize_t received = pollRecv(clientSocket, buffer.get(), RECV_CHUNK, idleMs, true); |
| 185 | if (received <= 0) { |
| 186 | ok = false; // clean close, idle timeout, or cancel: incomplete body |
| 187 | break; |
| 188 | } |
| 189 | size_t toWrite = (size_t)received; |
| 190 | if (written + toWrite > contentLength) { |
| 191 | toWrite = contentLength - written; |
| 192 | } |
| 193 | out.write(buffer.get(), (u32)toWrite); |
| 194 | written += toWrite; |
| 195 | TransferStatus::setBytesDone(written); |
| 196 | } |
| 197 | out.close(); |
| 198 | return ok && written == contentLength; |
| 199 | } |
| 200 | |
| 201 | static void handleHttpRequest(s32 clientSocket) |
| 202 | { |
no test coverage detected