Skip to content

Commit d0b928b

Browse files
committed
Merge bitcoin/bitcoin#26312: Remove Sock::Get() and Sock::Sock()
7df4508 test: improve sock_tests/move_assignment (Vasil Dimov) 5086a99 net: remove Sock default constructor, it's not necessary (Vasil Dimov) 7829272 net: remove now unnecessary Sock::Get() (Vasil Dimov) 944b21b net: don't check if the socket is valid in ConnectSocketDirectly() (Vasil Dimov) aeac68d net: don't check if the socket is valid in GetBindAddress() (Vasil Dimov) 5ac1a51 i2p: avoid using Sock::Get() for checking for a valid socket (Vasil Dimov) Pull request description: _This is a piece of #21878, chopped off to ease review._ Peeking at the underlying socket file descriptor of `Sock` and checkig if it is `INVALID_SOCKET` is bad encapsulation and stands in the way of testing/mocking/fuzzing. Instead use an empty `unique_ptr` to denote that there is no valid socket where appropriate or outright remove such checks where they are not necessary. The default constructor `Sock::Sock()` is unnecessary now after recent changes, thus remove it. ACKs for top commit: ajtowns: ACK 7df4508 jonatack: ACK 7df4508 Tree-SHA512: 9742aeeeabe8690530bf74caa6ba296787028c52f4a3342afd193b05dbbb1f6645935c33ba0a5230199a09af01c666bd3c7fb16b48692a0d185356ea59a8ddbf
2 parents 88e5a02 + 7df4508 commit d0b928b

File tree

9 files changed

+62
-55
lines changed

9 files changed

+62
-55
lines changed

src/i2p.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,13 @@ Session::Session(const fs::path& private_key_file,
119119
: m_private_key_file{private_key_file},
120120
m_control_host{control_host},
121121
m_interrupt{interrupt},
122-
m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
123122
m_transient{false}
124123
{
125124
}
126125

127126
Session::Session(const CService& control_host, CThreadInterrupt* interrupt)
128127
: m_control_host{control_host},
129128
m_interrupt{interrupt},
130-
m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
131129
m_transient{true}
132130
{
133131
}
@@ -315,7 +313,7 @@ void Session::CheckControlSock()
315313
LOCK(m_mutex);
316314

317315
std::string errmsg;
318-
if (!m_control_sock->IsConnected(errmsg)) {
316+
if (m_control_sock && !m_control_sock->IsConnected(errmsg)) {
319317
Log("Control socket error: %s", errmsg);
320318
Disconnect();
321319
}
@@ -364,7 +362,7 @@ Binary Session::MyDestination() const
364362
void Session::CreateIfNotCreatedAlready()
365363
{
366364
std::string errmsg;
367-
if (m_control_sock->IsConnected(errmsg)) {
365+
if (m_control_sock && m_control_sock->IsConnected(errmsg)) {
368366
return;
369367
}
370368

@@ -437,14 +435,14 @@ std::unique_ptr<Sock> Session::StreamAccept()
437435

438436
void Session::Disconnect()
439437
{
440-
if (m_control_sock->Get() != INVALID_SOCKET) {
438+
if (m_control_sock) {
441439
if (m_session_id.empty()) {
442440
Log("Destroying incomplete SAM session");
443441
} else {
444442
Log("Destroying SAM session %s", m_session_id);
445443
}
444+
m_control_sock.reset();
446445
}
447-
m_control_sock = std::make_unique<Sock>(INVALID_SOCKET);
448446
m_session_id.clear();
449447
}
450448
} // namespace sam

src/i2p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ class Session
261261
* ("SESSION CREATE"). With the established session id we later open
262262
* other connections to the SAM service to accept incoming I2P
263263
* connections and make outgoing ones.
264+
* If not connected then this unique_ptr will be empty.
264265
* See https://geti2p.net/en/docs/api/samv3
265266
*/
266267
std::unique_ptr<Sock> m_control_sock GUARDED_BY(m_mutex);

src/net.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,12 +429,10 @@ static CAddress GetBindAddress(const Sock& sock)
429429
CAddress addr_bind;
430430
struct sockaddr_storage sockaddr_bind;
431431
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
432-
if (sock.Get() != INVALID_SOCKET) {
433-
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
434-
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
435-
} else {
436-
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
437-
}
432+
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
433+
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
434+
} else {
435+
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
438436
}
439437
return addr_bind;
440438
}

src/netbase.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
514514
// Create a sockaddr from the specified service.
515515
struct sockaddr_storage sockaddr;
516516
socklen_t len = sizeof(sockaddr);
517-
if (sock.Get() == INVALID_SOCKET) {
518-
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToStringAddrPort());
519-
return false;
520-
}
521517
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
522518
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToStringAddrPort());
523519
return false;

src/test/fuzz/util/net.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ template CNetAddr::SerParams ConsumeDeserializationParams(FuzzedDataProvider&) n
7777
template CAddress::SerParams ConsumeDeserializationParams(FuzzedDataProvider&) noexcept;
7878

7979
FuzzedSock::FuzzedSock(FuzzedDataProvider& fuzzed_data_provider)
80-
: m_fuzzed_data_provider{fuzzed_data_provider}, m_selectable{fuzzed_data_provider.ConsumeBool()}
80+
: Sock{fuzzed_data_provider.ConsumeIntegralInRange<SOCKET>(INVALID_SOCKET - 1, INVALID_SOCKET)},
81+
m_fuzzed_data_provider{fuzzed_data_provider},
82+
m_selectable{fuzzed_data_provider.ConsumeBool()}
8183
{
82-
m_socket = fuzzed_data_provider.ConsumeIntegralInRange<SOCKET>(INVALID_SOCKET - 1, INVALID_SOCKET);
8384
}
8485

8586
FuzzedSock::~FuzzedSock()

src/test/sock_tests.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(constructor_and_destructor)
3838
{
3939
const SOCKET s = CreateSocket();
4040
Sock* sock = new Sock(s);
41-
BOOST_CHECK_EQUAL(sock->Get(), s);
41+
BOOST_CHECK(*sock == s);
4242
BOOST_CHECK(!SocketIsClosed(s));
4343
delete sock;
4444
BOOST_CHECK(SocketIsClosed(s));
@@ -51,22 +51,34 @@ BOOST_AUTO_TEST_CASE(move_constructor)
5151
Sock* sock2 = new Sock(std::move(*sock1));
5252
delete sock1;
5353
BOOST_CHECK(!SocketIsClosed(s));
54-
BOOST_CHECK_EQUAL(sock2->Get(), s);
54+
BOOST_CHECK(*sock2 == s);
5555
delete sock2;
5656
BOOST_CHECK(SocketIsClosed(s));
5757
}
5858

5959
BOOST_AUTO_TEST_CASE(move_assignment)
6060
{
61-
const SOCKET s = CreateSocket();
62-
Sock* sock1 = new Sock(s);
63-
Sock* sock2 = new Sock();
61+
const SOCKET s1 = CreateSocket();
62+
const SOCKET s2 = CreateSocket();
63+
Sock* sock1 = new Sock(s1);
64+
Sock* sock2 = new Sock(s2);
65+
66+
BOOST_CHECK(!SocketIsClosed(s1));
67+
BOOST_CHECK(!SocketIsClosed(s2));
68+
6469
*sock2 = std::move(*sock1);
70+
BOOST_CHECK(!SocketIsClosed(s1));
71+
BOOST_CHECK(SocketIsClosed(s2));
72+
BOOST_CHECK(*sock2 == s1);
73+
6574
delete sock1;
66-
BOOST_CHECK(!SocketIsClosed(s));
67-
BOOST_CHECK_EQUAL(sock2->Get(), s);
75+
BOOST_CHECK(!SocketIsClosed(s1));
76+
BOOST_CHECK(SocketIsClosed(s2));
77+
BOOST_CHECK(*sock2 == s1);
78+
6879
delete sock2;
69-
BOOST_CHECK(SocketIsClosed(s));
80+
BOOST_CHECK(SocketIsClosed(s1));
81+
BOOST_CHECK(SocketIsClosed(s2));
7082
}
7183

7284
#ifndef WIN32 // Windows does not have socketpair(2).
@@ -98,7 +110,7 @@ BOOST_AUTO_TEST_CASE(send_and_receive)
98110
SendAndRecvMessage(*sock0, *sock1);
99111

100112
Sock* sock0moved = new Sock(std::move(*sock0));
101-
Sock* sock1moved = new Sock();
113+
Sock* sock1moved = new Sock(INVALID_SOCKET);
102114
*sock1moved = std::move(*sock1);
103115

104116
delete sock0;

src/test/util/net.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,10 @@ constexpr auto ALL_NETWORKS = std::array{
108108
class StaticContentsSock : public Sock
109109
{
110110
public:
111-
explicit StaticContentsSock(const std::string& contents) : m_contents{contents}
111+
explicit StaticContentsSock(const std::string& contents)
112+
: Sock{INVALID_SOCKET},
113+
m_contents{contents}
112114
{
113-
// Just a dummy number that is not INVALID_SOCKET.
114-
m_socket = INVALID_SOCKET - 1;
115115
}
116116

117117
~StaticContentsSock() override { m_socket = INVALID_SOCKET; }
@@ -194,6 +194,11 @@ class StaticContentsSock : public Sock
194194
return true;
195195
}
196196

197+
bool IsConnected(std::string&) const override
198+
{
199+
return true;
200+
}
201+
197202
private:
198203
const std::string m_contents;
199204
mutable size_t m_consumed{0};

src/util/sock.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ static inline bool IOErrorIsPermanent(int err)
2424
return err != WSAEAGAIN && err != WSAEINTR && err != WSAEWOULDBLOCK && err != WSAEINPROGRESS;
2525
}
2626

27-
Sock::Sock() : m_socket(INVALID_SOCKET) {}
28-
2927
Sock::Sock(SOCKET s) : m_socket(s) {}
3028

3129
Sock::Sock(Sock&& other)
@@ -44,8 +42,6 @@ Sock& Sock::operator=(Sock&& other)
4442
return *this;
4543
}
4644

47-
SOCKET Sock::Get() const { return m_socket; }
48-
4945
ssize_t Sock::Send(const void* data, size_t len, int flags) const
5046
{
5147
return send(m_socket, static_cast<const char*>(data), len, flags);
@@ -411,6 +407,11 @@ void Sock::Close()
411407
m_socket = INVALID_SOCKET;
412408
}
413409

410+
bool Sock::operator==(SOCKET s) const
411+
{
412+
return m_socket == s;
413+
};
414+
414415
std::string NetworkErrorString(int err)
415416
{
416417
#if defined(WIN32)

src/util/sock.h

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,12 @@
2121
static constexpr auto MAX_WAIT_FOR_IO = 1s;
2222

2323
/**
24-
* RAII helper class that manages a socket. Mimics `std::unique_ptr`, but instead of a pointer it
25-
* contains a socket and closes it automatically when it goes out of scope.
24+
* RAII helper class that manages a socket and closes it automatically when it goes out of scope.
2625
*/
2726
class Sock
2827
{
2928
public:
30-
/**
31-
* Default constructor, creates an empty object that does nothing when destroyed.
32-
*/
33-
Sock();
29+
Sock() = delete;
3430

3531
/**
3632
* Take ownership of an existent socket.
@@ -63,43 +59,37 @@ class Sock
6359
virtual Sock& operator=(Sock&& other);
6460

6561
/**
66-
* Get the value of the contained socket.
67-
* @return socket or INVALID_SOCKET if empty
68-
*/
69-
[[nodiscard]] virtual SOCKET Get() const;
70-
71-
/**
72-
* send(2) wrapper. Equivalent to `send(this->Get(), data, len, flags);`. Code that uses this
62+
* send(2) wrapper. Equivalent to `send(m_socket, data, len, flags);`. Code that uses this
7363
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
7464
*/
7565
[[nodiscard]] virtual ssize_t Send(const void* data, size_t len, int flags) const;
7666

7767
/**
78-
* recv(2) wrapper. Equivalent to `recv(this->Get(), buf, len, flags);`. Code that uses this
68+
* recv(2) wrapper. Equivalent to `recv(m_socket, buf, len, flags);`. Code that uses this
7969
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
8070
*/
8171
[[nodiscard]] virtual ssize_t Recv(void* buf, size_t len, int flags) const;
8272

8373
/**
84-
* connect(2) wrapper. Equivalent to `connect(this->Get(), addr, addrlen)`. Code that uses this
74+
* connect(2) wrapper. Equivalent to `connect(m_socket, addr, addrlen)`. Code that uses this
8575
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
8676
*/
8777
[[nodiscard]] virtual int Connect(const sockaddr* addr, socklen_t addr_len) const;
8878

8979
/**
90-
* bind(2) wrapper. Equivalent to `bind(this->Get(), addr, addr_len)`. Code that uses this
80+
* bind(2) wrapper. Equivalent to `bind(m_socket, addr, addr_len)`. Code that uses this
9181
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
9282
*/
9383
[[nodiscard]] virtual int Bind(const sockaddr* addr, socklen_t addr_len) const;
9484

9585
/**
96-
* listen(2) wrapper. Equivalent to `listen(this->Get(), backlog)`. Code that uses this
86+
* listen(2) wrapper. Equivalent to `listen(m_socket, backlog)`. Code that uses this
9787
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
9888
*/
9989
[[nodiscard]] virtual int Listen(int backlog) const;
10090

10191
/**
102-
* accept(2) wrapper. Equivalent to `std::make_unique<Sock>(accept(this->Get(), addr, addr_len))`.
92+
* accept(2) wrapper. Equivalent to `std::make_unique<Sock>(accept(m_socket, addr, addr_len))`.
10393
* Code that uses this wrapper can be unit tested if this method is overridden by a mock Sock
10494
* implementation.
10595
* The returned unique_ptr is empty if `accept()` failed in which case errno will be set.
@@ -108,7 +98,7 @@ class Sock
10898

10999
/**
110100
* getsockopt(2) wrapper. Equivalent to
111-
* `getsockopt(this->Get(), level, opt_name, opt_val, opt_len)`. Code that uses this
101+
* `getsockopt(m_socket, level, opt_name, opt_val, opt_len)`. Code that uses this
112102
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
113103
*/
114104
[[nodiscard]] virtual int GetSockOpt(int level,
@@ -118,7 +108,7 @@ class Sock
118108

119109
/**
120110
* setsockopt(2) wrapper. Equivalent to
121-
* `setsockopt(this->Get(), level, opt_name, opt_val, opt_len)`. Code that uses this
111+
* `setsockopt(m_socket, level, opt_name, opt_val, opt_len)`. Code that uses this
122112
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
123113
*/
124114
[[nodiscard]] virtual int SetSockOpt(int level,
@@ -128,7 +118,7 @@ class Sock
128118

129119
/**
130120
* getsockname(2) wrapper. Equivalent to
131-
* `getsockname(this->Get(), name, name_len)`. Code that uses this
121+
* `getsockname(m_socket, name, name_len)`. Code that uses this
132122
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
133123
*/
134124
[[nodiscard]] virtual int GetSockName(sockaddr* name, socklen_t* name_len) const;
@@ -266,6 +256,11 @@ class Sock
266256
*/
267257
[[nodiscard]] virtual bool IsConnected(std::string& errmsg) const;
268258

259+
/**
260+
* Check if the internal socket is equal to `s`. Use only in tests.
261+
*/
262+
bool operator==(SOCKET s) const;
263+
269264
protected:
270265
/**
271266
* Contained socket. `INVALID_SOCKET` designates the object is empty.

0 commit comments

Comments
 (0)