aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorAndrew Chow <github@achow101.com>2023-11-07 14:11:46 -0500
committerAndrew Chow <github@achow101.com>2023-11-07 14:11:58 -0500
commit0528cfd3071380e4d8a8877761f3ef9564757f30 (patch)
treec88eab625537fe9f1e2a84c3a598d781f3ca6325 /src/util
parent3da69c464f16841a5c8d9fcc9c63238ab807d5ff (diff)
parentaf0fca530e4d8311bcb24a14c416e5ad7c30ff78 (diff)
downloadbitcoin-0528cfd3071380e4d8a8877761f3ef9564757f30.tar.xz
Merge bitcoin/bitcoin#28649: Do the SOCKS5 handshake reliably
af0fca530e4d8311bcb24a14c416e5ad7c30ff78 netbase: use reliable send() during SOCKS5 handshake (Vasil Dimov) 1b19d1117ca5373a15313227b547ef4392022dbd sock: change Sock::SendComplete() to take Span (Vasil Dimov) Pull request description: The `Socks5()` function which does the SOCKS5 handshake with the SOCKS5 proxy sends bytes to the socket without retrying partial writes. `send(2)` may write only part of the provided data and return. In this case the caller is responsible for retrying the operation with the remaining data. Change `Socks5()` to do that. There is already a method `Sock::SendComplete()` which does exactly that, so use it in `Socks5()`. A minor complication for this PR is that `Sock::SendComplete()` takes `std::string` argument whereas `Socks5()` has `std::vector<uint8_t>`. Thus the necessity for the first commit. It is possible to do also in other ways - convert the data in `Socks5()` to `std::string` or have just one `Sock::SendComplete()` that takes `void*` and change the callers to pass `str.data(), str.size()` or `vec.data(), vec.size()`. This came up while testing https://github.com/bitcoin/bitcoin/pull/27375. ACKs for top commit: achow101: ACK af0fca530e4d8311bcb24a14c416e5ad7c30ff78 jonatack: ACK af0fca530e4d8311bcb24a14c416e5ad7c30ff78 pinheadmz: ACK af0fca530e4d8311bcb24a14c416e5ad7c30ff78 Tree-SHA512: 1d4a53d0628f7607378038ac56dc3b8624ce9322b034c9547a0c3ce052eafb4b18213f258aa3b57bcb4d990a5e0548a37ec70af2bd55f6e8e6399936f1ce047a
Diffstat (limited to 'src/util')
-rw-r--r--src/util/sock.cpp9
-rw-r--r--src/util/sock.h9
2 files changed, 16 insertions, 2 deletions
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index d16dc56aa3..e896b87160 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -242,7 +242,7 @@ bool Sock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per
#endif /* USE_POLL */
}
-void Sock::SendComplete(const std::string& data,
+void Sock::SendComplete(Span<const unsigned char> data,
std::chrono::milliseconds timeout,
CThreadInterrupt& interrupt) const
{
@@ -283,6 +283,13 @@ void Sock::SendComplete(const std::string& data,
}
}
+void Sock::SendComplete(Span<const char> data,
+ std::chrono::milliseconds timeout,
+ CThreadInterrupt& interrupt) const
+{
+ SendComplete(MakeUCharSpan(data), timeout, interrupt);
+}
+
std::string Sock::RecvUntilTerminator(uint8_t terminator,
std::chrono::milliseconds timeout,
CThreadInterrupt& interrupt,
diff --git a/src/util/sock.h b/src/util/sock.h
index d78e01929b..65e7ffc165 100644
--- a/src/util/sock.h
+++ b/src/util/sock.h
@@ -228,7 +228,14 @@ public:
* @throws std::runtime_error if the operation cannot be completed. In this case only some of
* the data will be written to the socket.
*/
- virtual void SendComplete(const std::string& data,
+ virtual void SendComplete(Span<const unsigned char> data,
+ std::chrono::milliseconds timeout,
+ CThreadInterrupt& interrupt) const;
+
+ /**
+ * Convenience method, equivalent to `SendComplete(MakeUCharSpan(data), timeout, interrupt)`.
+ */
+ virtual void SendComplete(Span<const char> data,
std::chrono::milliseconds timeout,
CThreadInterrupt& interrupt) const;