net: deserialize the entire version message locally

This avoids having some vars set if the version negotiation fails.

Also copy it all into CNode at the same site. nVersion and
fSuccessfullyConnected are set last, as they are the gates for the other vars.
Make them atomic for that reason.
This commit is contained in:
Cory Fields 2017-01-18 18:15:00 -05:00
parent 80ff0344ae
commit 2046617b5e
2 changed files with 36 additions and 29 deletions

View file

@ -627,7 +627,7 @@ public:
const CAddress addr; const CAddress addr;
std::string addrName; std::string addrName;
CService addrLocal; CService addrLocal;
int nVersion; std::atomic<int> nVersion;
// strSubVer is whatever byte array we read from the wire. However, this field is intended // strSubVer is whatever byte array we read from the wire. However, this field is intended
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and // to be printed out, displayed to humans in various forms and so on. So we sanitize it and
// store the sanitized version in cleanSubVer. The original should be used when dealing with // store the sanitized version in cleanSubVer. The original should be used when dealing with
@ -639,7 +639,7 @@ public:
bool fAddnode; bool fAddnode;
bool fClient; bool fClient;
const bool fInbound; const bool fInbound;
bool fSuccessfullyConnected; std::atomic_bool fSuccessfullyConnected;
std::atomic_bool fDisconnect; std::atomic_bool fDisconnect;
// We use fRelayTxes for two purposes - // We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message // a) it allows us to not relay tx invs before receiving the peer's version message

View file

@ -1199,16 +1199,23 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
CAddress addrFrom; CAddress addrFrom;
uint64_t nNonce = 1; uint64_t nNonce = 1;
uint64_t nServiceInt; uint64_t nServiceInt;
ServiceFlags nServices;
int nVersion; int nVersion;
int nSendVersion;
std::string strSubVer;
int nStartingHeight = -1;
bool fRelay = true;
vRecv >> nVersion >> nServiceInt >> nTime >> addrMe; vRecv >> nVersion >> nServiceInt >> nTime >> addrMe;
pfrom->nServices = ServiceFlags(nServiceInt); nSendVersion = std::min(nVersion, PROTOCOL_VERSION);
nServices = ServiceFlags(nServiceInt);
if (!pfrom->fInbound) if (!pfrom->fInbound)
{ {
connman.SetServices(pfrom->addr, pfrom->nServices); connman.SetServices(pfrom->addr, nServices);
} }
if (pfrom->nServicesExpected & ~pfrom->nServices) if (pfrom->nServicesExpected & ~nServices)
{ {
LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected); LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected);
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
strprintf("Expected to offer services %08x", pfrom->nServicesExpected))); strprintf("Expected to offer services %08x", pfrom->nServicesExpected)));
pfrom->fDisconnect = true; pfrom->fDisconnect = true;
@ -1230,20 +1237,13 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
if (!vRecv.empty()) if (!vRecv.empty())
vRecv >> addrFrom >> nNonce; vRecv >> addrFrom >> nNonce;
if (!vRecv.empty()) { if (!vRecv.empty()) {
vRecv >> LIMITED_STRING(pfrom->strSubVer, MAX_SUBVERSION_LENGTH); vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
} }
if (!vRecv.empty()) { if (!vRecv.empty()) {
vRecv >> pfrom->nStartingHeight; vRecv >> nStartingHeight;
} }
{ if (!vRecv.empty())
LOCK(pfrom->cs_filter); vRecv >> fRelay;
if (!vRecv.empty())
vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message
else
pfrom->fRelayTxes = true;
}
// Disconnect if we connected to ourself // Disconnect if we connected to ourself
if (pfrom->fInbound && !connman.CheckIncomingNonce(nNonce)) if (pfrom->fInbound && !connman.CheckIncomingNonce(nNonce))
{ {
@ -1252,7 +1252,6 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
return true; return true;
} }
pfrom->addrLocal = addrMe;
if (pfrom->fInbound && addrMe.IsRoutable()) if (pfrom->fInbound && addrMe.IsRoutable())
{ {
SeenLocal(addrMe); SeenLocal(addrMe);
@ -1262,9 +1261,25 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
if (pfrom->fInbound) if (pfrom->fInbound)
PushNodeVersion(pfrom, connman, GetAdjustedTime()); PushNodeVersion(pfrom, connman, GetAdjustedTime());
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
if((pfrom->nServices & NODE_WITNESS)) pfrom->nServices = nServices;
pfrom->addrLocal = addrMe;
pfrom->strSubVer = strSubVer;
pfrom->cleanSubVer = SanitizeString(strSubVer);
pfrom->nStartingHeight = nStartingHeight;
pfrom->fClient = !(nServices & NODE_NETWORK);
{
LOCK(pfrom->cs_filter);
pfrom->fRelayTxes = fRelay; // set to true after we get the first filter* message
}
// Change version
pfrom->SetSendVersion(nSendVersion);
pfrom->nVersion = nVersion;
pfrom->fSuccessfullyConnected = true;
if((nServices & NODE_WITNESS))
{ {
LOCK(cs_main); LOCK(cs_main);
State(pfrom->GetId())->fHaveWitness = true; State(pfrom->GetId())->fHaveWitness = true;
@ -1276,12 +1291,6 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
UpdatePreferredDownload(pfrom, State(pfrom->GetId())); UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
} }
// Change version
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
int nSendVersion = std::min(nVersion, PROTOCOL_VERSION);
pfrom->nVersion = nVersion;
pfrom->SetSendVersion(nSendVersion);
if (!pfrom->fInbound) if (!pfrom->fInbound)
{ {
// Advertise our address // Advertise our address
@ -1309,8 +1318,6 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
connman.MarkAddressGood(pfrom->addr); connman.MarkAddressGood(pfrom->addr);
} }
pfrom->fSuccessfullyConnected = true;
std::string remoteAddr; std::string remoteAddr;
if (fLogIPs) if (fLogIPs)
remoteAddr = ", peeraddr=" + pfrom->addr.ToString(); remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
@ -1352,7 +1359,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
if (strCommand == NetMsgType::VERACK) if (strCommand == NetMsgType::VERACK)
{ {
pfrom->SetRecvVersion(std::min(pfrom->nVersion, PROTOCOL_VERSION)); pfrom->SetRecvVersion(std::min(pfrom->nVersion.load(), PROTOCOL_VERSION));
if (!pfrom->fInbound) { if (!pfrom->fInbound) {
// Mark this node as currently connected, so we update its timestamp later. // Mark this node as currently connected, so we update its timestamp later.