| 982 | } |
| 983 | |
| 984 | void HTTPServer::MaybeDispatchRequestsFromClient(const std::shared_ptr<HTTPRemoteClient>& client) const |
| 985 | { |
| 986 | // Try reading (potentially multiple) HTTP requests from the buffer |
| 987 | while (!client->m_recv_buffer.empty()) { |
| 988 | // Create a new request object and try to fill it with data from the receive buffer |
| 989 | auto req = std::make_unique<HTTPRequest>(client); |
| 990 | try { |
| 991 | // Stop reading if we need more data from the client to parse a complete request |
| 992 | if (!client->ReadRequest(*req)) break; |
| 993 | } catch (const ContentTooLargeError& e) { |
| 994 | LogDebug( |
| 995 | BCLog::HTTP, |
| 996 | "HTTP request body too large from client %s (id=%llu): %s", |
| 997 | client->m_origin, |
| 998 | client->m_id, |
| 999 | e.what()); |
| 1000 | |
| 1001 | req->WriteReply(HTTP_CONTENT_TOO_LARGE); |
| 1002 | client->m_disconnect = true; |
| 1003 | return; |
| 1004 | } catch (const std::runtime_error& e) { |
| 1005 | LogDebug( |
| 1006 | BCLog::HTTP, |
| 1007 | "Error reading HTTP request from client %s (id=%llu): %s", |
| 1008 | client->m_origin, |
| 1009 | client->m_id, |
| 1010 | e.what()); |
| 1011 | |
| 1012 | // We failed to read a complete request from the buffer |
| 1013 | req->WriteReply(HTTP_BAD_REQUEST); |
| 1014 | client->m_disconnect = true; |
| 1015 | return; |
| 1016 | } |
| 1017 | |
| 1018 | // We read a complete request from the buffer into the queue |
| 1019 | LogDebug( |
| 1020 | BCLog::HTTP, |
| 1021 | "Received a %s request for %s from %s (id=%llu)", |
| 1022 | RequestMethodString(req->m_method), |
| 1023 | req->m_target, |
| 1024 | client->m_origin, |
| 1025 | client->m_id); |
| 1026 | |
| 1027 | // add request to client queue |
| 1028 | client->m_req_queue.push_back(std::move(req)); |
| 1029 | } |
| 1030 | |
| 1031 | // If we are already handling a request from |
| 1032 | // this client, do nothing. We'll check again on the next I/O |
| 1033 | // loop iteration. |
| 1034 | if (client->m_req_busy) return; |
| 1035 | |
| 1036 | // Otherwise, if there is a pending request in the queue, handle it. |
| 1037 | if (!client->m_req_queue.empty()) { |
| 1038 | LOCK(m_request_dispatcher_mutex); |
| 1039 | client->m_req_busy = true; |
| 1040 | m_request_dispatcher(std::move(client->m_req_queue.front())); |
| 1041 | client->m_req_queue.pop_front(); |
nothing calls this directly
no test coverage detected