| 141 | } |
| 142 | |
| 143 | int HttpStreamServer::recvData(fl::span<u8> buffer) { |
| 144 | if (!isConnected()) { |
| 145 | return -1; |
| 146 | } |
| 147 | |
| 148 | // Get list of all client IDs |
| 149 | fl::vector<u32> clientIds = mNativeServer->getClientIds(); |
| 150 | if (clientIds.empty()) { |
| 151 | return 0; // No clients connected |
| 152 | } |
| 153 | |
| 154 | // Round-robin through clients to avoid starvation |
| 155 | // Start from the last processed client + 1 |
| 156 | size_t startIdx = 0; |
| 157 | for (size_t i = 0; i < clientIds.size(); i++) { |
| 158 | if (clientIds[i] == mLastProcessedClientId) { |
| 159 | startIdx = (i + 1) % clientIds.size(); |
| 160 | break; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | // Try each client starting from startIdx |
| 165 | for (size_t offset = 0; offset < clientIds.size(); offset++) { |
| 166 | size_t idx = (startIdx + offset) % clientIds.size(); |
| 167 | u32 clientId = clientIds[idx]; |
| 168 | |
| 169 | ClientState* state = getOrCreateClientState(clientId); |
| 170 | if (!state || !state->httpHeaderReceived || !state->httpHeaderSent) { |
| 171 | continue; // Skip clients that haven't completed HTTP handshake |
| 172 | } |
| 173 | |
| 174 | // Try to receive data from this client |
| 175 | int received = mNativeServer->recv(clientId, buffer); |
| 176 | if (received > 0) { |
| 177 | mLastProcessedClientId = clientId; |
| 178 | return received; |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | return 0; // No data available from any client |
| 183 | } |
| 184 | |
| 185 | void HttpStreamServer::triggerReconnect() { |
| 186 | // For server: disconnect all clients and restart |
nothing calls this directly
no test coverage detected