Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/bitcoin.cpp
| #include <algorithm> | #include "bitcoin.h" | ||||
| #include "db.h" | #include "db.h" | ||||
| #include "netbase.h" | #include "netbase.h" | ||||
| #include "protocol.h" | |||||
| #include "serialize.h" | #include "serialize.h" | ||||
| #include "uint256.h" | #include "uint256.h" | ||||
| #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL | #include <algorithm> | ||||
| using namespace std; | #define BITCOIN_SEED_NONCE 0x0539a019ca550825ULL | ||||
| class CNode { | class CNode { | ||||
| SOCKET sock; | SOCKET sock; | ||||
| CDataStream vSend; | CDataStream vSend; | ||||
| CDataStream vRecv; | CDataStream vRecv; | ||||
| unsigned int nHeaderStart; | unsigned int nHeaderStart; | ||||
| unsigned int nMessageStart; | unsigned int nMessageStart; | ||||
| int nVersion; | int nVersion; | ||||
| string strSubVer; | std::string strSubVer; | ||||
| int nStartingHeight; | int nStartingHeight; | ||||
| vector<CAddress> *vAddr; | std::vector<CAddress> *vAddr; | ||||
| int ban; | int ban; | ||||
| int64 doneAfter; | int64 doneAfter; | ||||
| CAddress you; | CAddress you; | ||||
| int GetTimeout() { | int GetTimeout() { return you.IsTor() ? 120 : 30; } | ||||
| if (you.IsTor()) | |||||
| return 120; | |||||
| else | |||||
| return 30; | |||||
| } | |||||
| void BeginMessage(const char *pszCommand) { | void BeginMessage(const char *pszCommand) { | ||||
| if (nHeaderStart != -1) AbortMessage(); | if (nHeaderStart != -1) AbortMessage(); | ||||
| nHeaderStart = vSend.size(); | nHeaderStart = vSend.size(); | ||||
| vSend << CMessageHeader(pszCommand, 0); | vSend << CMessageHeader(pszCommand, 0); | ||||
| nMessageStart = vSend.size(); | nMessageStart = vSend.size(); | ||||
| // printf("%s: SEND %s\n", ToString(you).c_str(), pszCommand); | // printf("%s: SEND %s\n", ToString(you).c_str(), pszCommand); | ||||
| } | } | ||||
| Show All 33 Lines | void Send() { | ||||
| vSend.erase(vSend.begin(), vSend.begin() + nBytes); | vSend.erase(vSend.begin(), vSend.begin() + nBytes); | ||||
| } else { | } else { | ||||
| close(sock); | close(sock); | ||||
| sock = INVALID_SOCKET; | sock = INVALID_SOCKET; | ||||
| } | } | ||||
| } | } | ||||
| void PushVersion() { | void PushVersion() { | ||||
| int64 nTime = time(NULL); | int64 nTime = time(nullptr); | ||||
| uint64 nLocalNonce = BITCOIN_SEED_NONCE; | uint64 nLocalNonce = BITCOIN_SEED_NONCE; | ||||
| int64 nLocalServices = 0; | int64 nLocalServices = 0; | ||||
| CAddress me(CService("0.0.0.0")); | CAddress me(CService("0.0.0.0")); | ||||
| BeginMessage("version"); | BeginMessage("version"); | ||||
| int nBestHeight = GetRequireHeight(); | int nBestHeight = GetRequireHeight(); | ||||
| string ver = "/bitcoin-seeder:0.01/"; | std::string ver = "/bitcoin-seeder:0.01/"; | ||||
| vSend << PROTOCOL_VERSION << nLocalServices << nTime << you << me | vSend << PROTOCOL_VERSION << nLocalServices << nTime << you << me | ||||
| << nLocalNonce << ver << nBestHeight; | << nLocalNonce << ver << nBestHeight; | ||||
| EndMessage(); | EndMessage(); | ||||
| } | } | ||||
| void GotVersion() { | void GotVersion() { | ||||
| // printf("\n%s: version %i\n", ToString(you).c_str(), nVersion); | // printf("\n%s: version %i\n", ToString(you).c_str(), nVersion); | ||||
| if (vAddr) { | if (vAddr) { | ||||
| BeginMessage("getaddr"); | BeginMessage("getaddr"); | ||||
| EndMessage(); | EndMessage(); | ||||
| doneAfter = time(NULL) + GetTimeout(); | doneAfter = time(nullptr) + GetTimeout(); | ||||
| } else { | } else { | ||||
| doneAfter = time(NULL) + 1; | doneAfter = time(nullptr) + 1; | ||||
| } | } | ||||
| } | } | ||||
| bool ProcessMessage(string strCommand, CDataStream &vRecv) { | bool ProcessMessage(std::string strCommand, CDataStream &vRecv) { | ||||
| // printf("%s: RECV %s\n", ToString(you).c_str(), | // printf("%s: RECV %s\n", ToString(you).c_str(), | ||||
| // strCommand.c_str()); | // strCommand.c_str()); | ||||
| if (strCommand == "version") { | if (strCommand == "version") { | ||||
| int64 nTime; | int64 nTime; | ||||
| CAddress addrMe; | CAddress addrMe; | ||||
| CAddress addrFrom; | CAddress addrFrom; | ||||
| uint64 nNonce = 1; | uint64 nNonce = 1; | ||||
| vRecv >> nVersion >> you.nServices >> nTime >> addrMe; | vRecv >> nVersion >> you.nServices >> nTime >> addrMe; | ||||
| if (nVersion == 10300) nVersion = 300; | if (nVersion == 10300) nVersion = 300; | ||||
| if (nVersion >= 106 && !vRecv.empty()) vRecv >> addrFrom >> nNonce; | if (nVersion >= 106 && !vRecv.empty()) vRecv >> addrFrom >> nNonce; | ||||
| if (nVersion >= 106 && !vRecv.empty()) vRecv >> strSubVer; | if (nVersion >= 106 && !vRecv.empty()) vRecv >> strSubVer; | ||||
| if (nVersion >= 209 && !vRecv.empty()) vRecv >> nStartingHeight; | if (nVersion >= 209 && !vRecv.empty()) vRecv >> nStartingHeight; | ||||
| if (nVersion >= 209) { | if (nVersion >= 209) { | ||||
| BeginMessage("verack"); | BeginMessage("verack"); | ||||
| EndMessage(); | EndMessage(); | ||||
| } | } | ||||
| vSend.SetVersion(min(nVersion, PROTOCOL_VERSION)); | vSend.SetVersion(std::min(nVersion, PROTOCOL_VERSION)); | ||||
| if (nVersion < 209) { | if (nVersion < 209) { | ||||
| this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION)); | this->vRecv.SetVersion(std::min(nVersion, PROTOCOL_VERSION)); | ||||
| GotVersion(); | GotVersion(); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (strCommand == "verack") { | if (strCommand == "verack") { | ||||
| this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION)); | this->vRecv.SetVersion(std::min(nVersion, PROTOCOL_VERSION)); | ||||
| GotVersion(); | GotVersion(); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (strCommand == "addr" && vAddr) { | if (strCommand == "addr" && vAddr) { | ||||
| vector<CAddress> vAddrNew; | std::vector<CAddress> vAddrNew; | ||||
| vRecv >> vAddrNew; | vRecv >> vAddrNew; | ||||
| // printf("%s: got %i addresses\n", ToString(you).c_str(), | // printf("%s: got %i addresses\n", ToString(you).c_str(), | ||||
| // (int)vAddrNew.size()); | // (int)vAddrNew.size()); | ||||
| int64 now = time(NULL); | int64 now = time(nullptr); | ||||
| vector<CAddress>::iterator it = vAddrNew.begin(); | std::vector<CAddress>::iterator it = vAddrNew.begin(); | ||||
| if (vAddrNew.size() > 1) { | if (vAddrNew.size() > 1) { | ||||
| if (doneAfter == 0 || doneAfter > now + 1) doneAfter = now + 1; | if (doneAfter == 0 || doneAfter > now + 1) doneAfter = now + 1; | ||||
| } | } | ||||
| while (it != vAddrNew.end()) { | while (it != vAddrNew.end()) { | ||||
| CAddress &addr = *it; | CAddress &addr = *it; | ||||
| // printf("%s: got address %s\n", ToString(you).c_str(), | // printf("%s: got address %s\n", ToString(you).c_str(), | ||||
| // addr.ToString().c_str(), (int)(vAddr->size())); | // addr.ToString().c_str(), (int)(vAddr->size())); | ||||
| it++; | it++; | ||||
| Show All 23 Lines | bool ProcessMessages() { | ||||
| int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader()); | int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader()); | ||||
| if (vRecv.end() - pstart < nHeaderSize) { | if (vRecv.end() - pstart < nHeaderSize) { | ||||
| if (vRecv.size() > nHeaderSize) { | if (vRecv.size() > nHeaderSize) { | ||||
| vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize); | vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| vRecv.erase(vRecv.begin(), pstart); | vRecv.erase(vRecv.begin(), pstart); | ||||
| vector<char> vHeaderSave(vRecv.begin(), | std::vector<char> vHeaderSave(vRecv.begin(), | ||||
| vRecv.begin() + nHeaderSize); | vRecv.begin() + nHeaderSize); | ||||
| CMessageHeader hdr; | CMessageHeader hdr; | ||||
| vRecv >> hdr; | vRecv >> hdr; | ||||
| if (!hdr.IsValid()) { | if (!hdr.IsValid()) { | ||||
| // printf("%s: BAD (invalid header)\n", ToString(you).c_str()); | // printf("%s: BAD (invalid header)\n", ToString(you).c_str()); | ||||
| ban = 100000; | ban = 100000; | ||||
| return true; | return true; | ||||
| } | } | ||||
| string strCommand = hdr.GetCommand(); | std::string strCommand = hdr.GetCommand(); | ||||
| unsigned int nMessageSize = hdr.nMessageSize; | unsigned int nMessageSize = hdr.nMessageSize; | ||||
| if (nMessageSize > MAX_SIZE) { | if (nMessageSize > MAX_SIZE) { | ||||
| // printf("%s: BAD (message too large)\n", | // printf("%s: BAD (message too large)\n", | ||||
| // ToString(you).c_str()); | // ToString(you).c_str()); | ||||
| ban = 100000; | ban = 100000; | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (nMessageSize > vRecv.size()) { | if (nMessageSize > vRecv.size()) { | ||||
| Show All 14 Lines | bool ProcessMessages() { | ||||
| if (ProcessMessage(strCommand, vMsg)) return true; | if (ProcessMessage(strCommand, vMsg)) return true; | ||||
| // printf("%s: done processing %s\n", ToString(you).c_str(), | // printf("%s: done processing %s\n", ToString(you).c_str(), | ||||
| // strCommand.c_str()); | // strCommand.c_str()); | ||||
| } while (1); | } while (1); | ||||
| return false; | return false; | ||||
| } | } | ||||
| public: | public: | ||||
| CNode(const CService &ip, vector<CAddress> *vAddrIn) | CNode(const CService &ip, std::vector<CAddress> *vAddrIn) | ||||
| : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(vAddrIn), ban(0), | : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(vAddrIn), ban(0), | ||||
| doneAfter(0), nVersion(0) { | doneAfter(0), nVersion(0) { | ||||
| vSend.SetType(SER_NETWORK); | vSend.SetType(SER_NETWORK); | ||||
| vSend.SetVersion(0); | vSend.SetVersion(0); | ||||
| vRecv.SetType(SER_NETWORK); | vRecv.SetType(SER_NETWORK); | ||||
| vRecv.SetVersion(0); | vRecv.SetVersion(0); | ||||
| if (time(NULL) > 1329696000) { | if (time(nullptr) > 1329696000) { | ||||
| vSend.SetVersion(209); | vSend.SetVersion(209); | ||||
| vRecv.SetVersion(209); | vRecv.SetVersion(209); | ||||
| } | } | ||||
| } | } | ||||
| bool Run() { | bool Run() { | ||||
| bool res = true; | bool res = true; | ||||
| if (!ConnectSocket(you, sock)) return false; | if (!ConnectSocket(you, sock)) return false; | ||||
| PushVersion(); | PushVersion(); | ||||
| Send(); | Send(); | ||||
| int64 now; | int64 now; | ||||
| while (now = time(NULL), ban == 0 && | while (now = time(nullptr), ban == 0 && | ||||
| (doneAfter == 0 || doneAfter > now) && | (doneAfter == 0 || doneAfter > now) && | ||||
| sock != INVALID_SOCKET) { | sock != INVALID_SOCKET) { | ||||
| char pchBuf[0x10000]; | char pchBuf[0x10000]; | ||||
| fd_set set; | fd_set set; | ||||
| FD_ZERO(&set); | FD_ZERO(&set); | ||||
| FD_SET(sock, &set); | FD_SET(sock, &set); | ||||
| struct timeval wa; | struct timeval wa; | ||||
| if (doneAfter) { | if (doneAfter) { | ||||
| wa.tv_sec = doneAfter - now; | wa.tv_sec = doneAfter - now; | ||||
| wa.tv_usec = 0; | wa.tv_usec = 0; | ||||
| } else { | } else { | ||||
| wa.tv_sec = GetTimeout(); | wa.tv_sec = GetTimeout(); | ||||
| wa.tv_usec = 0; | wa.tv_usec = 0; | ||||
| } | } | ||||
| int ret = select(sock + 1, &set, NULL, &set, &wa); | int ret = select(sock + 1, &set, nullptr, &set, &wa); | ||||
| if (ret != 1) { | if (ret != 1) { | ||||
| if (!doneAfter) res = false; | if (!doneAfter) res = false; | ||||
| break; | break; | ||||
| } | } | ||||
| int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0); | int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0); | ||||
| int nPos = vRecv.size(); | int nPos = vRecv.size(); | ||||
| if (nBytes > 0) { | if (nBytes > 0) { | ||||
| vRecv.resize(nPos + nBytes); | vRecv.resize(nPos + nBytes); | ||||
| Show All 23 Lines | public: | ||||
| int GetClientVersion() { return nVersion; } | int GetClientVersion() { return nVersion; } | ||||
| std::string GetClientSubVersion() { return strSubVer; } | std::string GetClientSubVersion() { return strSubVer; } | ||||
| int GetStartingHeight() { return nStartingHeight; } | int GetStartingHeight() { return nStartingHeight; } | ||||
| }; | }; | ||||
| bool TestNode(const CService &cip, int &ban, int &clientV, | bool TestNode(const CService &cip, int &ban, int &clientV, | ||||
| std::string &clientSV, int &blocks, vector<CAddress> *vAddr) { | std::string &clientSV, int &blocks, | ||||
| std::vector<CAddress> *vAddr) { | |||||
| try { | try { | ||||
| CNode node(cip, vAddr); | CNode node(cip, vAddr); | ||||
| bool ret = node.Run(); | bool ret = node.Run(); | ||||
| if (!ret) { | if (!ret) { | ||||
| ban = node.GetBan(); | ban = node.GetBan(); | ||||
| } else { | } else { | ||||
| ban = 0; | ban = 0; | ||||
| } | } | ||||
| clientV = node.GetClientVersion(); | clientV = node.GetClientVersion(); | ||||
| clientSV = node.GetClientSubVersion(); | clientSV = node.GetClientSubVersion(); | ||||
| blocks = node.GetStartingHeight(); | blocks = node.GetStartingHeight(); | ||||
| // printf("%s: %s!!!\n", cip.ToString().c_str(), ret ? "GOOD" : "BAD"); | // printf("%s: %s!!!\n", cip.ToString().c_str(), ret ? "GOOD" : "BAD"); | ||||
| return ret; | return ret; | ||||
| } catch (std::ios_base::failure &e) { | } catch (std::ios_base::failure &e) { | ||||
| ban = 0; | ban = 0; | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| /* | /* | ||||
| int main(void) { | int main(void) { | ||||
| CService ip("bitcoin.sipa.be", 8333, true); | CService ip("bitcoin.sipa.be", 8333, true); | ||||
| vector<CAddress> vAddr; | std::vector<CAddress> vAddr; | ||||
| vAddr.clear(); | vAddr.clear(); | ||||
| int ban = 0; | int ban = 0; | ||||
| bool ret = TestNode(ip, ban, vAddr); | bool ret = TestNode(ip, ban, vAddr); | ||||
| printf("ret=%s ban=%i vAddr.size()=%i\n", ret ? "good" : "bad", ban, | printf("ret=%s ban=%i vAddr.size()=%i\n", ret ? "good" : "bad", ban, | ||||
| (int)vAddr.size()); | (int)vAddr.size()); | ||||
| } | } | ||||
| */ | */ | ||||