New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: Split socket create/connect #11363
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not yet familiar with P2P code to ACK. In any case see my comment below.
src/netbase.cpp
Outdated
@@ -554,8 +567,6 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int | |||
if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) | |||
return false; | |||
} | |||
|
|||
hSocketRet = hSocket; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If socks negotiation fail then hSocket
will not be INVALID_SOCKET
which is a different behavior than before. This also indicates that there is a leak in master because hSocket
is not freed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice Catch! Force-pushed the missing CloseSocket()s.
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 18763d2..4b72826 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -561,11 +561,15 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int
ProxyCredentials random_auth;
static std::atomic_int counter(0);
random_auth.username = random_auth.password = strprintf("%i", counter++);
- if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
+ if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
+ CloseSocket(hSocket);
return false;
+ }
} else {
- if (!Socks5(strDest, (unsigned short)port, 0, hSocket))
+ if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
+ CloseSocket(hSocket);
return false;
+ }
}
return true;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CloseSocket
sets hSocket
to INVALID_SOCKET
so this LGTM. I wonder if you could just return CloseSocket(hSocket)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CloseSocket's return value indicates whether the close succeeded or not, which would be true in this case. Not what we want :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh yeah... now I win the most stupid comment award.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hah, no worries. We'll call it even for pointing out my mistake here
d555b09
to
ced8190
Compare
ced8190
to
29e0a16
Compare
Rebased after #10663. Also, changed from the last version: Rather than passing in a socket reference and returning a bool, CreateSocket() now returns a socket (which may be invalid) instead. That's much more straightforward, IMO, and matches the usage of socket(). |
@@ -452,10 +452,8 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials | |||
return true; | |||
} | |||
|
|||
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) | |||
SOCKET CreateSocket(const CService &addrConnect) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to change the return values values of all the "return false"s in here - INVALID_SOCKET is (currently) ~0, so we will pretend the socket creation succeeded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, don't know how I missed those.
src/netbase.cpp
Outdated
} | ||
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { | ||
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); | ||
CloseSocket(hSocket); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the risk of making you redo a bunch of work, is it possible to const-ify the socket here and make the caller do the CloseSocket instead? Shits currently a maze and it'd be nice to clean it up sooner rather than try to follow it through the libevent changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that makes sense. Now that we don't have chained connect functions, it's much more clear what "the caller" means. The maze was only there because we had to close at all levels to be safe.
Will do.
29e0a16
to
0606eb5
Compare
17b2a71
to
f766175
Compare
Rebased and fixed the check against the connect() return value, which was already wrong, but doesn't really matter because it's always detected on first use anyway. |
utACK f766175ebe4400561f60b75b0ede4015003bad8c |
This gives me a new warning:
|
#ifndef WIN32 | ||
#ifdef SO_NOSIGPIPE | ||
// Different way of disabling SIGPIPE on BSD | ||
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOSIGPIPE handling moved to CreateSocket(addrBind)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think part of the goal is to get random socket flag-fiddling things out of net and into netbase, its kinda split between both right now. @theuni ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. If it's something we require for all sockets, imo it makes sense to do it in CreateSocket.
#else | ||
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int)); | ||
setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nOne, sizeof(int)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did this move? The only remaining reference to TCP_NODELAY I see is in SetSocketNoDelay
, which is called on accepted sockets only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its also called in netbase.cpp in CreateSocket, so should be set for outbound and inbound connection sockets, though not the listen socket, but that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's set on the listen socket as well (which should pass it down to accepted sockets anyway), since BindListenPort now uses CreateSocket().
Also, check for the correct error during socket creation
We use select in ConnectSocketDirectly, so this check needs to happen before that. IsSelectableSocket will not be relevant after upcoming changes to remove select.
…nections This allows const references to be passed around, making it clear where the socket may and may not be invalidated.
f766175
to
3830b6e
Compare
@laanwj Yes, thanks. Due to our SOCKET wrappers, we need to compare against INVALID_SOCKET rather than SOCKET_ERROR. Pushed the squashed change as it was very simple (it's actually just reverting a change from this PR, it was already correct in master). Diff from before: git diff f766175ebe44..3830b6e diff --git a/src/netbase.cpp b/src/netbase.cpp
index ba2c988..74ea6b1 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -446,7 +446,7 @@ SOCKET CreateSocket(const CService &addrConnect)
}
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
- if (hSocket == SOCKET_ERROR)
+ if (hSocket == INVALID_SOCKET)
return INVALID_SOCKET;
if (!IsSelectableSocket(hSocket)) { |
utACK 3830b6e |
3830b6e net: use CreateSocket for binds (Cory Fields) df3bcf8 net: pass socket closing responsibility up to caller for outgoing connections (Cory Fields) 9e3b2f5 net: Move IsSelectableSocket check into socket creation (Cory Fields) 1729c29 net: split socket creation out of connection (Cory Fields) Pull request description: Requirement for #11227. We'll need to create sockets and perform the actual connect in separate steps, so break them up. #11227 adds an RAII wrapper around connection attempts, as a belt-and-suspenders in case a CloseSocket is missed. Tree-SHA512: de675bb718cc56d68893c303b8057ca062c7431eaa17ae7c4829caed119fa3f15b404d8f52aca22a6bca6e73a26fb79e898b335d090ab015bf6456cf417fc694
3830b6e net: use CreateSocket for binds (Cory Fields) df3bcf8 net: pass socket closing responsibility up to caller for outgoing connections (Cory Fields) 9e3b2f5 net: Move IsSelectableSocket check into socket creation (Cory Fields) 1729c29 net: split socket creation out of connection (Cory Fields) Pull request description: Requirement for bitcoin#11227. We'll need to create sockets and perform the actual connect in separate steps, so break them up. bitcoin#11227 adds an RAII wrapper around connection attempts, as a belt-and-suspenders in case a CloseSocket is missed. Tree-SHA512: de675bb718cc56d68893c303b8057ca062c7431eaa17ae7c4829caed119fa3f15b404d8f52aca22a6bca6e73a26fb79e898b335d090ab015bf6456cf417fc694
3830b6e net: use CreateSocket for binds (Cory Fields) df3bcf8 net: pass socket closing responsibility up to caller for outgoing connections (Cory Fields) 9e3b2f5 net: Move IsSelectableSocket check into socket creation (Cory Fields) 1729c29 net: split socket creation out of connection (Cory Fields) Pull request description: Requirement for bitcoin#11227. We'll need to create sockets and perform the actual connect in separate steps, so break them up. bitcoin#11227 adds an RAII wrapper around connection attempts, as a belt-and-suspenders in case a CloseSocket is missed. Tree-SHA512: de675bb718cc56d68893c303b8057ca062c7431eaa17ae7c4829caed119fa3f15b404d8f52aca22a6bca6e73a26fb79e898b335d090ab015bf6456cf417fc694
Requirement for #11227.
We'll need to create sockets and perform the actual connect in separate steps, so break them up.
#11227 adds an RAII wrapper around connection attempts, as a belt-and-suspenders in case a CloseSocket is missed.