/** * Read bytes from socket. This will either read the full number of bytes requested * or return False on error or timeout. * This function can be interrupted by calling InterruptSocks5() * * @param data Buffer to receive into * @param len Length of data to receive * @param timeout Timeout in milliseconds for receive operation * * @note This function requires that hSocket is in non-blocking mode. */ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket) { int64_t curTime = GetTimeMillis(); int64_t endTime = curTime + timeout; // Maximum time to wait in one select call. It will take up until this time (in millis) // to break off in case of an interruption. const int64_t maxWait = 1000; while (len > 0 && curTime < endTime) { ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first if (ret > 0) { len -= ret; data += ret; } else if (ret == 0) { // Unexpected disconnection return false; } else { // Other error or blocking int nErr = WSAGetLastError(); if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { if (!IsSelectableSocket(hSocket)) { return false; } struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait)); fd_set fdset; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval); if (nRet == SOCKET_ERROR) { return false; } } else { return false; } } if (interruptSocks5Recv) return false; curTime = GetTimeMillis(); } return len == 0; }
void CActiveDeterministicMasternodeManager::Init() { LOCK(cs_main); if (!fMasternodeMode) return; if (!deterministicMNManager->IsDeterministicMNsSporkActive()) return; // Check that our local network configuration is correct if (!fListen) { // listen option is probably overwritten by smth else, no good state = MASTERNODE_ERROR; strError = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter."; LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s\n", strError); return; } if (!GetLocalAddress(activeMasternodeInfo.service)) { state = MASTERNODE_ERROR; return; } CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip(); CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(*activeMasternodeInfo.blsPubKeyOperator); if (!dmn) { // MN not appeared on the chain yet return; } if (!mnList.IsMNValid(dmn->proTxHash)) { if (mnList.IsMNPoSeBanned(dmn->proTxHash)) { state = MASTERNODE_POSE_BANNED; } else { state = MASTERNODE_REMOVED; } return; } mnListEntry = dmn; LogPrintf("CActiveDeterministicMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", mnListEntry->proTxHash.ToString(), mnListEntry->ToString()); if (activeMasternodeInfo.service != mnListEntry->pdmnState->addr) { state = MASTERNODE_ERROR; strError = "Local address does not match the address from ProTx"; LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s", strError); return; } if (Params().NetworkIDString() != CBaseChainParams::REGTEST) { // Check socket connectivity LogPrintf("CActiveDeterministicMasternodeManager::Init -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString()); SOCKET hSocket; bool fConnected = ConnectSocket(activeMasternodeInfo.service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket); CloseSocket(hSocket); if (!fConnected) { state = MASTERNODE_ERROR; strError = "Could not connect to " + activeMasternodeInfo.service.ToString(); LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s\n", strError); return; } } activeMasternodeInfo.proTxHash = mnListEntry->proTxHash; activeMasternodeInfo.outpoint = mnListEntry->collateralOutpoint; state = MASTERNODE_READY; }
void CActiveLegacyMasternodeManager::ManageStateInitial(CConnman& connman) { if (deterministicMNManager->IsDeterministicMNsSporkActive()) return; LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled); // Check that our local network configuration is correct if (!fListen) { // listen option is probably overwritten by smth else, no good nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter."; LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } // First try to find whatever local address is specified by externalip option bool fFoundLocal = GetLocal(activeMasternodeInfo.service) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service); if (!fFoundLocal) { bool empty = true; // If we have some peers, let's try to find our local address from one of them connman.ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty](CNode* pnode) { empty = false; if (pnode->addr.IsIPv4()) fFoundLocal = GetLocal(activeMasternodeInfo.service, &pnode->addr) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service); return !fFoundLocal; }); // nothing and no live connections, can't do anything for now if (empty) { nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available."; LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } } if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) { if (Lookup("127.0.0.1", activeMasternodeInfo.service, GetListenPort(), false)) { fFoundLocal = true; } } if (!fFoundLocal) { nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only."; LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort(); if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (activeMasternodeInfo.service.GetPort() != mainnetDefaultPort) { nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort); LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } } else if (activeMasternodeInfo.service.GetPort() == mainnetDefaultPort) { nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort); LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } if (Params().NetworkIDString() != CBaseChainParams::REGTEST) { // Check socket connectivity LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString()); SOCKET hSocket; bool fConnected = ConnectSocket(activeMasternodeInfo.service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket); CloseSocket(hSocket); if (!fConnected) { nState = ACTIVE_MASTERNODE_NOT_CAPABLE; strNotCapableReason = "Could not connect to " + activeMasternodeInfo.service.ToString(); LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason); return; } } // Default to REMOTE eType = MASTERNODE_REMOTE; LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled); }