* @brief Handles incoming data from worker thread. */
| 1175 | * @brief Handles incoming data from worker thread. |
| 1176 | */ |
| 1177 | void API::Server::onDataReceived(QTcpSocket* socket, const QByteArray& data) |
| 1178 | { |
| 1179 | Q_ASSERT(socket); |
| 1180 | Q_ASSERT(!data.isEmpty()); |
| 1181 | |
| 1182 | if (!enabled() || data.isEmpty() || !socket) |
| 1183 | return; |
| 1184 | |
| 1185 | if (!m_connections.contains(socket)) |
| 1186 | return; |
| 1187 | |
| 1188 | auto& state = m_connections[socket]; |
| 1189 | |
| 1190 | if (!validateRateLimits(socket, state, data)) |
| 1191 | return; |
| 1192 | |
| 1193 | if (!state.authenticated) { |
| 1194 | handleAuthHandshake(socket, state, data); |
| 1195 | return; |
| 1196 | } |
| 1197 | |
| 1198 | state.buffer.append(data); |
| 1199 | auto& buffer = state.buffer; |
| 1200 | |
| 1201 | constexpr int kMaxBufferIterations = 10000; |
| 1202 | int bufferIterations = 0; |
| 1203 | while (!buffer.isEmpty() && bufferIterations < kMaxBufferIterations) { |
| 1204 | ++bufferIterations; |
| 1205 | |
| 1206 | const int newlineIndex = buffer.indexOf('\n'); |
| 1207 | |
| 1208 | if (newlineIndex < 0) { |
| 1209 | processNoNewlineBuffer(socket, state); |
| 1210 | return; |
| 1211 | } |
| 1212 | |
| 1213 | int bodyLen = newlineIndex; |
| 1214 | if (bodyLen > 0 && buffer.at(bodyLen - 1) == '\r') |
| 1215 | --bodyLen; |
| 1216 | |
| 1217 | const QByteArray line = buffer.left(bodyLen); |
| 1218 | buffer.remove(0, newlineIndex + 1); |
| 1219 | |
| 1220 | const auto trimmedLine = line.trimmed(); |
| 1221 | if (trimmedLine.isEmpty()) |
| 1222 | continue; |
| 1223 | |
| 1224 | if (trimmedLine.at(0) == '{' || trimmedLine.at(0) == '[') |
| 1225 | processJsonLine(socket, state, trimmedLine); |
| 1226 | else |
| 1227 | processRawLine(socket, state, line); |
| 1228 | } |
| 1229 | |
| 1230 | if (bufferIterations >= kMaxBufferIterations && !buffer.isEmpty()) [[unlikely]] { |
| 1231 | qWarning() << "[API] Buffer processing iteration limit reached:" << state.peerAddress << ":" |
| 1232 | << state.peerPort << "- Disconnecting client"; |
| 1233 | |
| 1234 | disconnectClient( |