| 835 | } |
| 836 | |
| 837 | void HTTPServer::SocketHandlerConnected(const IOReadiness& io_readiness) const |
| 838 | { |
| 839 | for (const auto& [sock, events] : io_readiness.events_per_sock) { |
| 840 | if (m_interrupt_net) { |
| 841 | return; |
| 842 | } |
| 843 | |
| 844 | auto it{io_readiness.httpclients_per_sock.find(sock)}; |
| 845 | if (it == io_readiness.httpclients_per_sock.end()) { |
| 846 | continue; |
| 847 | } |
| 848 | const std::shared_ptr<HTTPRemoteClient>& client{it->second}; |
| 849 | |
| 850 | bool send_ready = events.occurred & Sock::SendEvent; |
| 851 | bool recv_ready = events.occurred & Sock::RecvEvent; |
| 852 | bool err_ready = events.occurred & Sock::ErrorEvent; |
| 853 | |
| 854 | if (send_ready) { |
| 855 | // Try to send as much data as is ready for this client. |
| 856 | // If there's an error we can skip the receive phase for this client |
| 857 | // because we need to disconnect. |
| 858 | if (!client->MaybeSendBytesFromBuffer()) { |
| 859 | recv_ready = false; |
| 860 | } |
| 861 | } |
| 862 | |
| 863 | if (recv_ready || err_ready) { |
| 864 | std::byte buf[0x10000]; // typical socket buffer is 8K-64K |
| 865 | |
| 866 | const ssize_t nrecv{WITH_LOCK( |
| 867 | client->m_sock_mutex, |
| 868 | return client->m_sock->Recv(buf, sizeof(buf), MSG_DONTWAIT);)}; |
| 869 | |
| 870 | if (nrecv < 0) { |
| 871 | const int err = WSAGetLastError(); |
| 872 | if (IOErrorIsPermanent(err)) { |
| 873 | LogDebug( |
| 874 | BCLog::HTTP, |
| 875 | "Permanent read error from %s (id=%llu): %s", |
| 876 | client->m_origin, |
| 877 | client->m_id, |
| 878 | NetworkErrorString(err)); |
| 879 | client->m_disconnect = true; |
| 880 | } |
| 881 | } else if (nrecv == 0) { |
| 882 | LogDebug( |
| 883 | BCLog::HTTP, |
| 884 | "Received EOF from %s (id=%llu)", |
| 885 | client->m_origin, |
| 886 | client->m_id); |
| 887 | client->m_disconnect = true; |
| 888 | } else { |
| 889 | // Reset idle timeout |
| 890 | client->m_idle_since = Now<SteadySeconds>(); |
| 891 | |
| 892 | // Prevent disconnect until all requests are completely handled. |
| 893 | client->m_connection_busy = true; |
| 894 |
nothing calls this directly
no test coverage detected