Skip to content

Commit 6b340ca

Browse files
committed
sv2: extract send loop helper
Factor the EventReadyToSend send loop into a shared helper so the logic can be reused without altering behavior. Reviewer hint: git show --color-moved=dimmed-zebra Assisted-by: GitHub Copilot Assisted-by: OpenAI GPT-5-Codex
1 parent d433599 commit 6b340ca

File tree

2 files changed

+31
-21
lines changed

2 files changed

+31
-21
lines changed

src/sv2/connman.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -113,36 +113,27 @@ bool Sv2Connman::EventNewConnectionAccepted(NodeId node_id,
113113
return true;
114114
}
115115

116-
void Sv2Connman::EventReadyToSend(NodeId node_id, bool& cancel_recv)
116+
std::pair<size_t, bool> Sv2Connman::SendMessagesAsBytes(Sv2Client& client)
117117
{
118-
AssertLockNotHeld(m_clients_mutex);
119-
120-
auto client{WITH_LOCK(m_clients_mutex, return GetClientById(node_id);)};
121-
if (client == nullptr) {
122-
cancel_recv = true;
123-
return;
124-
}
125-
126-
LOCK(client->cs_send);
127-
auto it = client->m_send_messages.begin();
118+
auto it = client.m_send_messages.begin();
128119
std::optional<bool> expected_more;
129120
size_t total_sent = 0;
130121

131122
while (true) {
132-
if (it != client->m_send_messages.end()) {
123+
if (it != client.m_send_messages.end()) {
133124
// If possible, move one message from the send queue to the transport.
134125
// This fails when there is an existing message still being sent,
135126
// or when the handshake has not yet completed.
136127
//
137128
// Wrap Sv2NetMsg inside CSerializedNetMsg for transport
138129
CSerializedNetMsg net_msg{*it};
139-
if (client->m_transport->SetMessageToSend(net_msg)) {
130+
if (client.m_transport->SetMessageToSend(net_msg)) {
140131
++it;
141132
}
142133
}
143134

144135
const auto& [data, more, _m_message_type] =
145-
client->m_transport->GetBytesToSend(/*have_next_message=*/it != client->m_send_messages.end());
136+
client.m_transport->GetBytesToSend(/*have_next_message=*/it != client.m_send_messages.end());
146137

147138
// We rely on the 'more' value returned by GetBytesToSend to correctly predict whether more
148139
// bytes are still to be sent, to correctly set the MSG_MORE flag. As a sanity check,
@@ -155,13 +146,13 @@ void Sv2Connman::EventReadyToSend(NodeId node_id, bool& cancel_recv)
155146

156147
if (!data.empty()) {
157148
LogPrintLevel(BCLog::SV2, BCLog::Level::Trace,
158-
"Send %d bytes to client id=%zu\n", data.size(), client->m_id);
149+
"Send %d bytes to client id=%zu\n", data.size(), client.m_id);
159150

160-
sent = SendBytes(client->m_id, data, more, errmsg);
151+
sent = SendBytes(client.m_id, data, more, errmsg);
161152
}
162153

163154
if (sent > 0) {
164-
client->m_transport->MarkBytesSent(sent);
155+
client.m_transport->MarkBytesSent(sent);
165156
total_sent += sent;
166157
if (static_cast<size_t>(sent) != data.size()) {
167158
// could not send full message; stop sending more
@@ -170,17 +161,31 @@ void Sv2Connman::EventReadyToSend(NodeId node_id, bool& cancel_recv)
170161
} else {
171162
if (sent < 0) {
172163
LogDebug(BCLog::NET, "socket send error for peer=%d: %s\n",
173-
client->m_id, errmsg);
174-
CloseConnection(client->m_id);
164+
client.m_id, errmsg);
165+
CloseConnection(client.m_id);
175166
}
176167
break;
177168
}
178169
}
179170

180171
// Clear messages that have been handed to transport from the queue
181-
client->m_send_messages.erase(client->m_send_messages.begin(), it);
172+
client.m_send_messages.erase(client.m_send_messages.begin(), it);
173+
174+
return {total_sent, expected_more.value_or(false)};
175+
}
182176

183-
const bool more_pending = expected_more.value_or(false);
177+
void Sv2Connman::EventReadyToSend(NodeId node_id, bool& cancel_recv)
178+
{
179+
AssertLockNotHeld(m_clients_mutex);
180+
181+
auto client{WITH_LOCK(m_clients_mutex, return GetClientById(node_id);)};
182+
if (client == nullptr) {
183+
cancel_recv = true;
184+
return;
185+
}
186+
187+
LOCK(client->cs_send);
188+
const auto [total_sent, more_pending] = SendMessagesAsBytes(*client);
184189

185190
// If both receiving and (non-optimistic) sending were possible, we first attempt
186191
// sending. If that succeeds, but does not fully drain the send queue, do not

src/sv2/connman.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <sv2/transport.h>
1111
#include <pubkey.h>
1212

13+
#include <utility>
14+
1315
namespace {
1416
/*
1517
* Supported Stratum v2 subprotocols
@@ -144,6 +146,9 @@ class Sv2Connman : SockMan
144146

145147
void DisconnectFlagged() EXCLUSIVE_LOCKS_REQUIRED(m_clients_mutex);
146148

149+
std::pair<size_t, bool> SendMessagesAsBytes(Sv2Client& client)
150+
EXCLUSIVE_LOCKS_REQUIRED(client.cs_send);
151+
147152
/**
148153
* Create a `Sv2Client` object and add it to the `m_sv2_clients` member.
149154
* @param[in] node_id Id of the newly accepted connection.

0 commit comments

Comments
 (0)