| 1125 | } |
| 1126 | |
| 1127 | bool HTTPRemoteClient::MaybeSendBytesFromBuffer() |
| 1128 | { |
| 1129 | // Send as much data from this client's buffer as we can |
| 1130 | LOCK(m_send_mutex); |
| 1131 | if (!m_send_buffer.empty()) { |
| 1132 | // Socket flags (See kernel docs for send(2) and tcp(7) for more details). |
| 1133 | // MSG_NOSIGNAL: If the remote end of the connection is closed, |
| 1134 | // fail with EPIPE (an error) as opposed to triggering |
| 1135 | // SIGPIPE which terminates the process. |
| 1136 | // MSG_DONTWAIT: Makes the send operation non-blocking regardless of socket blocking mode. |
| 1137 | // MSG_MORE: We do not set this flag here because http responses are usually |
| 1138 | // small and we want the kernel to send them right away. Setting MSG_MORE |
| 1139 | // would "cork" the socket to prevent sending out partial frames. |
| 1140 | int flags{MSG_NOSIGNAL | MSG_DONTWAIT}; |
| 1141 | |
| 1142 | // Try to send bytes through socket |
| 1143 | ssize_t bytes_sent; |
| 1144 | { |
| 1145 | LOCK(m_sock_mutex); |
| 1146 | bytes_sent = m_sock->Send(m_send_buffer.data(), |
| 1147 | m_send_buffer.size(), |
| 1148 | flags); |
| 1149 | } |
| 1150 | |
| 1151 | if (bytes_sent < 0) { |
| 1152 | // Something went wrong |
| 1153 | const int err{WSAGetLastError()}; |
| 1154 | if (!IOErrorIsPermanent(err)) { |
| 1155 | // The error can be safely ignored, try the send again on the next I/O loop. |
| 1156 | m_send_ready = true; |
| 1157 | m_connection_busy = true; |
| 1158 | return true; |
| 1159 | } else { |
| 1160 | // Unrecoverable error, log and disconnect client. |
| 1161 | LogDebug( |
| 1162 | BCLog::HTTP, |
| 1163 | "Error sending HTTP response data to client %s (id=%llu): %s", |
| 1164 | m_origin, |
| 1165 | m_id, |
| 1166 | NetworkErrorString(err)); |
| 1167 | m_send_ready = false; |
| 1168 | m_disconnect = true; |
| 1169 | |
| 1170 | // Do not attempt to read from this client. |
| 1171 | return false; |
| 1172 | } |
| 1173 | } |
| 1174 | |
| 1175 | // Successful send, remove sent bytes from our local buffer. |
| 1176 | Assume(static_cast<size_t>(bytes_sent) <= m_send_buffer.size()); |
| 1177 | m_send_buffer.erase(m_send_buffer.begin(), |
| 1178 | m_send_buffer.begin() + bytes_sent); |
| 1179 | |
| 1180 | LogDebug( |
| 1181 | BCLog::HTTP, |
| 1182 | "Sent %d bytes to client %s (id=%llu)", |
| 1183 | bytes_sent, |
| 1184 | m_origin, |
no test coverage detected