| 1605 | } |
| 1606 | |
| 1607 | std::pair<size_t, bool> CConnman::SocketSendData(CNode& node) const |
| 1608 | { |
| 1609 | auto it = node.vSendMsg.begin(); |
| 1610 | size_t nSentSize = 0; |
| 1611 | bool data_left{false}; //!< second return value (whether unsent data remains) |
| 1612 | std::optional<bool> expected_more; |
| 1613 | |
| 1614 | while (true) { |
| 1615 | if (it != node.vSendMsg.end()) { |
| 1616 | // If possible, move one message from the send queue to the transport. This fails when |
| 1617 | // there is an existing message still being sent, or (for v2 transports) when the |
| 1618 | // handshake has not yet completed. |
| 1619 | size_t memusage = it->GetMemoryUsage(); |
| 1620 | if (node.m_transport->SetMessageToSend(*it)) { |
| 1621 | // Update memory usage of send buffer (as *it will be deleted). |
| 1622 | node.m_send_memusage -= memusage; |
| 1623 | ++it; |
| 1624 | } |
| 1625 | } |
| 1626 | const auto& [data, more, msg_type] = node.m_transport->GetBytesToSend(it != node.vSendMsg.end()); |
| 1627 | // We rely on the 'more' value returned by GetBytesToSend to correctly predict whether more |
| 1628 | // bytes are still to be sent, to correctly set the MSG_MORE flag. As a sanity check, |
| 1629 | // verify that the previously returned 'more' was correct. |
| 1630 | if (expected_more.has_value()) Assume(!data.empty() == *expected_more); |
| 1631 | expected_more = more; |
| 1632 | data_left = !data.empty(); // will be overwritten on next loop if all of data gets sent |
| 1633 | int nBytes = 0; |
| 1634 | if (!data.empty()) { |
| 1635 | LOCK(node.m_sock_mutex); |
| 1636 | // There is no socket in case we've already disconnected, or in test cases without |
| 1637 | // real connections. In these cases, we bail out immediately and just leave things |
| 1638 | // in the send queue and transport. |
| 1639 | if (!node.m_sock) { |
| 1640 | break; |
| 1641 | } |
| 1642 | int flags = MSG_NOSIGNAL | MSG_DONTWAIT; |
| 1643 | #ifdef MSG_MORE |
| 1644 | if (more) { |
| 1645 | flags |= MSG_MORE; |
| 1646 | } |
| 1647 | #endif |
| 1648 | nBytes = node.m_sock->Send(data.data(), data.size(), flags); |
| 1649 | } |
| 1650 | if (nBytes > 0) { |
| 1651 | node.m_last_send = NodeClock::now(); |
| 1652 | node.nSendBytes += nBytes; |
| 1653 | // Notify transport that bytes have been processed. |
| 1654 | node.m_transport->MarkBytesSent(nBytes); |
| 1655 | // Update statistics per message type. |
| 1656 | if (!msg_type.empty()) { // don't report v2 handshake bytes for now |
| 1657 | node.AccountForSentBytes(msg_type, nBytes); |
| 1658 | } |
| 1659 | nSentSize += nBytes; |
| 1660 | if ((size_t)nBytes != data.size()) { |
| 1661 | // could not send full message; stop sending more |
| 1662 | break; |
| 1663 | } |
| 1664 | } else { |
nothing calls this directly
no test coverage detected