| 133 | } |
| 134 | |
| 135 | bool HttpStreamClient::readHttpResponseHeader() { |
| 136 | // Read HTTP response header |
| 137 | // Expected format: |
| 138 | // HTTP/1.1 200 OK |
| 139 | // Content-Type: application/json |
| 140 | // Transfer-Encoding: chunked |
| 141 | // Connection: keep-alive |
| 142 | // \r\n |
| 143 | |
| 144 | // Read until we find \r\n\r\n (end of headers) |
| 145 | fl::string headerBuffer; |
| 146 | u8 buffer[256]; // Read in chunks instead of byte-by-byte |
| 147 | |
| 148 | // Maximum header size: 4KB, max retries when no data (yield to server thread) |
| 149 | const size_t MAX_HEADER_SIZE = 4096; |
| 150 | const int MAX_READ_ATTEMPTS = 500; // 500 yields before giving up |
| 151 | int readAttempts = 0; |
| 152 | |
| 153 | while (headerBuffer.size() < MAX_HEADER_SIZE) { |
| 154 | int received = mNativeClient->recv(buffer); |
| 155 | |
| 156 | if (received < 0) { |
| 157 | return false; |
| 158 | } |
| 159 | |
| 160 | if (received == 0) { |
| 161 | // No data yet - server may still be processing the request |
| 162 | // Yield to allow other threads (e.g. server thread) to run |
| 163 | readAttempts++; |
| 164 | if (readAttempts >= MAX_READ_ATTEMPTS) { |
| 165 | return false; |
| 166 | } |
| 167 | // Sleep briefly to allow server thread to run. |
| 168 | // The server thread sleeps 10ms between iterations, so we need |
| 169 | // a real sleep (not just yield) to give it time to process. |
| 170 | fl::this_thread::sleep_for(fl::chrono::milliseconds(10)); // ok sleep for |
| 171 | continue; |
| 172 | } |
| 173 | |
| 174 | headerBuffer.append(reinterpret_cast<const char*>(buffer), received); // ok reinterpret cast |
| 175 | |
| 176 | // Check for \r\n\r\n pattern |
| 177 | if (headerBuffer.size() >= 4) { |
| 178 | size_t pos = headerBuffer.find("\r\n\r\n"); |
| 179 | if (pos != fl::string::npos) { |
| 180 | break; |
| 181 | } |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | // Validate response |
| 186 | // Must start with "HTTP/1.1 200" |
| 187 | if (headerBuffer.size() < 12) { |
| 188 | return false; |
| 189 | } |
| 190 | |
| 191 | if (headerBuffer.substr(0, 12) != "HTTP/1.1 200") { |
| 192 | return false; |