Skip to content

Commit 362d3d1

Browse files
committed
Move CNetMessage and Transport headers to common
This avoids a circular dependency between bitcoin-sv2 and bitcoin-node.
1 parent 9ba1a18 commit 362d3d1

File tree

4 files changed

+188
-173
lines changed

4 files changed

+188
-173
lines changed

src/common/transport.h

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// Copyright (c) 2024 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_COMMON_TRANSPORT_H
6+
#define BITCOIN_COMMON_TRANSPORT_H
7+
8+
#include <chrono>
9+
#include <span.h>
10+
#include <stdint.h>
11+
#include <streams.h>
12+
#include <string>
13+
#include <uint256.h>
14+
15+
/** Transport layer version */
16+
enum class TransportProtocolType : uint8_t {
17+
DETECTING, //!< Peer could be v1 or v2
18+
V1, //!< Unencrypted, plaintext protocol
19+
V2, //!< BIP324 protocol
20+
};
21+
22+
/** Convert TransportProtocolType enum to a string value */
23+
std::string TransportTypeAsString(TransportProtocolType transport_type);
24+
25+
/** Transport protocol agnostic message container.
26+
* Ideally it should only contain receive time, payload,
27+
* type and size.
28+
*/
29+
class CNetMessage
30+
{
31+
public:
32+
DataStream m_recv; //!< received message data
33+
std::chrono::microseconds m_time{0}; //!< time of message receipt
34+
uint32_t m_message_size{0}; //!< size of the payload
35+
uint32_t m_raw_message_size{0}; //!< used wire size of the message (including header/checksum)
36+
std::string m_type;
37+
38+
explicit CNetMessage(DataStream&& recv_in) : m_recv(std::move(recv_in)) {}
39+
// Only one CNetMessage object will exist for the same message on either
40+
// the receive or processing queue. For performance reasons we therefore
41+
// delete the copy constructor and assignment operator to avoid the
42+
// possibility of copying CNetMessage objects.
43+
CNetMessage(CNetMessage&&) = default;
44+
CNetMessage(const CNetMessage&) = delete;
45+
CNetMessage& operator=(CNetMessage&&) = default;
46+
CNetMessage& operator=(const CNetMessage&) = delete;
47+
};
48+
49+
struct CSerializedNetMsg {
50+
CSerializedNetMsg() = default;
51+
CSerializedNetMsg(CSerializedNetMsg&&) = default;
52+
CSerializedNetMsg& operator=(CSerializedNetMsg&&) = default;
53+
// No implicit copying, only moves.
54+
CSerializedNetMsg(const CSerializedNetMsg& msg) = delete;
55+
CSerializedNetMsg& operator=(const CSerializedNetMsg&) = delete;
56+
57+
CSerializedNetMsg Copy() const
58+
{
59+
CSerializedNetMsg copy;
60+
copy.data = data;
61+
copy.m_type = m_type;
62+
return copy;
63+
}
64+
65+
std::vector<unsigned char> data;
66+
std::string m_type;
67+
68+
/** Compute total memory usage of this object (own memory + any dynamic memory). */
69+
size_t GetMemoryUsage() const noexcept;
70+
};
71+
72+
/** The Transport converts one connection's sent messages to wire bytes, and received bytes back. */
73+
class Transport {
74+
public:
75+
virtual ~Transport() = default;
76+
77+
struct Info
78+
{
79+
TransportProtocolType transport_type;
80+
std::optional<uint256> session_id;
81+
};
82+
83+
/** Retrieve information about this transport. */
84+
virtual Info GetInfo() const noexcept = 0;
85+
86+
// 1. Receiver side functions, for decoding bytes received on the wire into transport protocol
87+
// agnostic CNetMessage (message type & payload) objects.
88+
89+
/** Returns true if the current message is complete (so GetReceivedMessage can be called). */
90+
virtual bool ReceivedMessageComplete() const = 0;
91+
92+
/** Feed wire bytes to the transport.
93+
*
94+
* @return false if some bytes were invalid, in which case the transport can't be used anymore.
95+
*
96+
* Consumed bytes are chopped off the front of msg_bytes.
97+
*/
98+
virtual bool ReceivedBytes(Span<const uint8_t>& msg_bytes) = 0;
99+
100+
/** Retrieve a completed message from transport.
101+
*
102+
* This can only be called when ReceivedMessageComplete() is true.
103+
*
104+
* If reject_message=true is returned the message itself is invalid, but (other than false
105+
* returned by ReceivedBytes) the transport is not in an inconsistent state.
106+
*/
107+
virtual CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool& reject_message) = 0;
108+
109+
// 2. Sending side functions, for converting messages into bytes to be sent over the wire.
110+
111+
/** Set the next message to send.
112+
*
113+
* If no message can currently be set (perhaps because the previous one is not yet done being
114+
* sent), returns false, and msg will be unmodified. Otherwise msg is enqueued (and
115+
* possibly moved-from) and true is returned.
116+
*/
117+
virtual bool SetMessageToSend(CSerializedNetMsg& msg) noexcept = 0;
118+
119+
/** Return type for GetBytesToSend, consisting of:
120+
* - Span<const uint8_t> to_send: span of bytes to be sent over the wire (possibly empty).
121+
* - bool more: whether there will be more bytes to be sent after the ones in to_send are
122+
* all sent (as signaled by MarkBytesSent()).
123+
* - const std::string& m_type: message type on behalf of which this is being sent
124+
* ("" for bytes that are not on behalf of any message).
125+
*/
126+
using BytesToSend = std::tuple<
127+
Span<const uint8_t> /*to_send*/,
128+
bool /*more*/,
129+
const std::string& /*m_type*/
130+
>;
131+
132+
/** Get bytes to send on the wire, if any, along with other information about it.
133+
*
134+
* As a const function, it does not modify the transport's observable state, and is thus safe
135+
* to be called multiple times.
136+
*
137+
* @param[in] have_next_message If true, the "more" return value reports whether more will
138+
* be sendable after a SetMessageToSend call. It is set by the caller when they know
139+
* they have another message ready to send, and only care about what happens
140+
* after that. The have_next_message argument only affects this "more" return value
141+
* and nothing else.
142+
*
143+
* Effectively, there are three possible outcomes about whether there are more bytes
144+
* to send:
145+
* - Yes: the transport itself has more bytes to send later. For example, for
146+
* V1Transport this happens during the sending of the header of a
147+
* message, when there is a non-empty payload that follows.
148+
* - No: the transport itself has no more bytes to send, but will have bytes to
149+
* send if handed a message through SetMessageToSend. In V1Transport this
150+
* happens when sending the payload of a message.
151+
* - Blocked: the transport itself has no more bytes to send, and is also incapable
152+
* of sending anything more at all now, if it were handed another
153+
* message to send. This occurs in V2Transport before the handshake is
154+
* complete, as the encryption ciphers are not set up for sending
155+
* messages before that point.
156+
*
157+
* The boolean 'more' is true for Yes, false for Blocked, and have_next_message
158+
* controls what is returned for No.
159+
*
160+
* @return a BytesToSend object. The to_send member returned acts as a stream which is only
161+
* ever appended to. This means that with the exception of MarkBytesSent (which pops
162+
* bytes off the front of later to_sends), operations on the transport can only append
163+
* to what is being returned. Also note that m_type and to_send refer to data that is
164+
* internal to the transport, and calling any non-const function on this object may
165+
* invalidate them.
166+
*/
167+
virtual BytesToSend GetBytesToSend(bool have_next_message) const noexcept = 0;
168+
169+
/** Report how many bytes returned by the last GetBytesToSend() have been sent.
170+
*
171+
* bytes_sent cannot exceed to_send.size() of the last GetBytesToSend() result.
172+
*
173+
* If bytes_sent=0, this call has no effect.
174+
*/
175+
virtual void MarkBytesSent(size_t bytes_sent) noexcept = 0;
176+
177+
/** Return the memory usage of this transport attributable to buffered data to send. */
178+
virtual size_t GetSendMemoryUsage() const noexcept = 0;
179+
180+
// 3. Miscellaneous functions.
181+
182+
/** Whether upon disconnections, a reconnect with V1 is warranted. */
183+
virtual bool ShouldReconnectV1() const noexcept = 0;
184+
};
185+
186+
#endif // BITCOIN_COMMON_TRANSPORT_H

src/net.h

Lines changed: 1 addition & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <bip324.h>
1010
#include <chainparams.h>
1111
#include <common/bloom.h>
12+
#include <common/transport.h>
1213
#include <compat/compat.h>
1314
#include <consensus/amount.h>
1415
#include <crypto/siphash.h>
@@ -111,29 +112,6 @@ struct AddedNodeInfo {
111112
class CNodeStats;
112113
class CClientUIInterface;
113114

114-
struct CSerializedNetMsg {
115-
CSerializedNetMsg() = default;
116-
CSerializedNetMsg(CSerializedNetMsg&&) = default;
117-
CSerializedNetMsg& operator=(CSerializedNetMsg&&) = default;
118-
// No implicit copying, only moves.
119-
CSerializedNetMsg(const CSerializedNetMsg& msg) = delete;
120-
CSerializedNetMsg& operator=(const CSerializedNetMsg&) = delete;
121-
122-
CSerializedNetMsg Copy() const
123-
{
124-
CSerializedNetMsg copy;
125-
copy.data = data;
126-
copy.m_type = m_type;
127-
return copy;
128-
}
129-
130-
std::vector<unsigned char> data;
131-
std::string m_type;
132-
133-
/** Compute total memory usage of this object (own memory + any dynamic memory). */
134-
size_t GetMemoryUsage() const noexcept;
135-
};
136-
137115
/**
138116
* Look up IP addresses from all interfaces on the machine and add them to the
139117
* list of local addresses to self-advertise.
@@ -222,145 +200,6 @@ class CNodeStats
222200
std::string m_session_id;
223201
};
224202

225-
226-
/** Transport protocol agnostic message container.
227-
* Ideally it should only contain receive time, payload,
228-
* type and size.
229-
*/
230-
class CNetMessage
231-
{
232-
public:
233-
DataStream m_recv; //!< received message data
234-
std::chrono::microseconds m_time{0}; //!< time of message receipt
235-
uint32_t m_message_size{0}; //!< size of the payload
236-
uint32_t m_raw_message_size{0}; //!< used wire size of the message (including header/checksum)
237-
std::string m_type;
238-
239-
explicit CNetMessage(DataStream&& recv_in) : m_recv(std::move(recv_in)) {}
240-
// Only one CNetMessage object will exist for the same message on either
241-
// the receive or processing queue. For performance reasons we therefore
242-
// delete the copy constructor and assignment operator to avoid the
243-
// possibility of copying CNetMessage objects.
244-
CNetMessage(CNetMessage&&) = default;
245-
CNetMessage(const CNetMessage&) = delete;
246-
CNetMessage& operator=(CNetMessage&&) = default;
247-
CNetMessage& operator=(const CNetMessage&) = delete;
248-
};
249-
250-
/** The Transport converts one connection's sent messages to wire bytes, and received bytes back. */
251-
class Transport {
252-
public:
253-
virtual ~Transport() = default;
254-
255-
struct Info
256-
{
257-
TransportProtocolType transport_type;
258-
std::optional<uint256> session_id;
259-
};
260-
261-
/** Retrieve information about this transport. */
262-
virtual Info GetInfo() const noexcept = 0;
263-
264-
// 1. Receiver side functions, for decoding bytes received on the wire into transport protocol
265-
// agnostic CNetMessage (message type & payload) objects.
266-
267-
/** Returns true if the current message is complete (so GetReceivedMessage can be called). */
268-
virtual bool ReceivedMessageComplete() const = 0;
269-
270-
/** Feed wire bytes to the transport.
271-
*
272-
* @return false if some bytes were invalid, in which case the transport can't be used anymore.
273-
*
274-
* Consumed bytes are chopped off the front of msg_bytes.
275-
*/
276-
virtual bool ReceivedBytes(Span<const uint8_t>& msg_bytes) = 0;
277-
278-
/** Retrieve a completed message from transport.
279-
*
280-
* This can only be called when ReceivedMessageComplete() is true.
281-
*
282-
* If reject_message=true is returned the message itself is invalid, but (other than false
283-
* returned by ReceivedBytes) the transport is not in an inconsistent state.
284-
*/
285-
virtual CNetMessage GetReceivedMessage(std::chrono::microseconds time, bool& reject_message) = 0;
286-
287-
// 2. Sending side functions, for converting messages into bytes to be sent over the wire.
288-
289-
/** Set the next message to send.
290-
*
291-
* If no message can currently be set (perhaps because the previous one is not yet done being
292-
* sent), returns false, and msg will be unmodified. Otherwise msg is enqueued (and
293-
* possibly moved-from) and true is returned.
294-
*/
295-
virtual bool SetMessageToSend(CSerializedNetMsg& msg) noexcept = 0;
296-
297-
/** Return type for GetBytesToSend, consisting of:
298-
* - Span<const uint8_t> to_send: span of bytes to be sent over the wire (possibly empty).
299-
* - bool more: whether there will be more bytes to be sent after the ones in to_send are
300-
* all sent (as signaled by MarkBytesSent()).
301-
* - const std::string& m_type: message type on behalf of which this is being sent
302-
* ("" for bytes that are not on behalf of any message).
303-
*/
304-
using BytesToSend = std::tuple<
305-
Span<const uint8_t> /*to_send*/,
306-
bool /*more*/,
307-
const std::string& /*m_type*/
308-
>;
309-
310-
/** Get bytes to send on the wire, if any, along with other information about it.
311-
*
312-
* As a const function, it does not modify the transport's observable state, and is thus safe
313-
* to be called multiple times.
314-
*
315-
* @param[in] have_next_message If true, the "more" return value reports whether more will
316-
* be sendable after a SetMessageToSend call. It is set by the caller when they know
317-
* they have another message ready to send, and only care about what happens
318-
* after that. The have_next_message argument only affects this "more" return value
319-
* and nothing else.
320-
*
321-
* Effectively, there are three possible outcomes about whether there are more bytes
322-
* to send:
323-
* - Yes: the transport itself has more bytes to send later. For example, for
324-
* V1Transport this happens during the sending of the header of a
325-
* message, when there is a non-empty payload that follows.
326-
* - No: the transport itself has no more bytes to send, but will have bytes to
327-
* send if handed a message through SetMessageToSend. In V1Transport this
328-
* happens when sending the payload of a message.
329-
* - Blocked: the transport itself has no more bytes to send, and is also incapable
330-
* of sending anything more at all now, if it were handed another
331-
* message to send. This occurs in V2Transport before the handshake is
332-
* complete, as the encryption ciphers are not set up for sending
333-
* messages before that point.
334-
*
335-
* The boolean 'more' is true for Yes, false for Blocked, and have_next_message
336-
* controls what is returned for No.
337-
*
338-
* @return a BytesToSend object. The to_send member returned acts as a stream which is only
339-
* ever appended to. This means that with the exception of MarkBytesSent (which pops
340-
* bytes off the front of later to_sends), operations on the transport can only append
341-
* to what is being returned. Also note that m_type and to_send refer to data that is
342-
* internal to the transport, and calling any non-const function on this object may
343-
* invalidate them.
344-
*/
345-
virtual BytesToSend GetBytesToSend(bool have_next_message) const noexcept = 0;
346-
347-
/** Report how many bytes returned by the last GetBytesToSend() have been sent.
348-
*
349-
* bytes_sent cannot exceed to_send.size() of the last GetBytesToSend() result.
350-
*
351-
* If bytes_sent=0, this call has no effect.
352-
*/
353-
virtual void MarkBytesSent(size_t bytes_sent) noexcept = 0;
354-
355-
/** Return the memory usage of this transport attributable to buffered data to send. */
356-
virtual size_t GetSendMemoryUsage() const noexcept = 0;
357-
358-
// 3. Miscellaneous functions.
359-
360-
/** Whether upon disconnections, a reconnect with V1 is warranted. */
361-
virtual bool ShouldReconnectV1() const noexcept = 0;
362-
};
363-
364203
class V1Transport final : public Transport
365204
{
366205
private:

src/node/connection_types.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <common/transport.h>
56
#include <node/connection_types.h>
67
#include <cassert>
78

0 commit comments

Comments
 (0)