9 #define BITCOIN_SEED_NONCE 0x0539a019ca550825
10 #define REQUIRE_HEIGHT 0
11 #define MIN_VERSION 40000
19 unsigned int nHeaderStart;
20 unsigned int nMessageStart;
24 vector<CAddress> *vAddr;
36 void BeginMessage(const char *pszCommand) {
37 if (nHeaderStart != -1) AbortMessage();
38 nHeaderStart = vSend.size();
39 vSend << CMessageHeader(pszCommand, 0);
40 nMessageStart = vSend.size();
41 // printf("%s: SEND %s\n", ToString(you).c_str(), pszCommand);
45 if (nHeaderStart == -1) return;
46 vSend.resize(nHeaderStart);
52 if (nHeaderStart == -1) return;
53 unsigned int nSize = vSend.size() - nMessageStart;
54 memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
55 uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
56 unsigned int nChecksum = 0;
57 memcpy(&nChecksum, &hash, sizeof(nChecksum));
58 assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
59 memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
65 if (sock == INVALID_SOCKET) return;
66 if (vSend.empty()) return;
67 int nBytes = send(sock, &vSend[0], vSend.size(), 0);
69 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
72 sock = INVALID_SOCKET;
77 int64 nTime = time(NULL);
78 uint64 nLocalNonce = BITCOIN_SEED_NONCE;
79 int64 nLocalServices = 0;
80 CAddress me(CService("0.0.0.0"));
81 BeginMessage("version");
82 int nBestHeight = REQUIRE_HEIGHT;
83 string ver = "/novacoin-seeder:0.01/";
84 vSend << PROTOCOL_VERSION << nLocalServices << nTime << you << me << nLocalNonce << ver << nBestHeight;
89 // printf("\n%s: version %i\n", ToString(you).c_str(), nVersion);
90 BeginMessage("getaddr");
92 doneAfter = time(NULL) + GetTimeout();
95 bool ProcessMessage(string strCommand, CDataStream& vRecv) {
96 //printf("%s: RECV %s\n", ToString(you).c_str(), strCommand.c_str());
97 if (strCommand == "version") {
102 vRecv >> nVersion >> you.nServices >> nTime >> addrMe;
103 if (nVersion == 10300) nVersion = 300;
104 if (nVersion >= 106 && !vRecv.empty())
105 vRecv >> addrFrom >> nNonce;
106 if (nVersion >= 106 && !vRecv.empty())
108 if (nVersion >= 209 && !vRecv.empty())
109 vRecv >> nStartingHeight;
111 if (nVersion >= 209) {
112 BeginMessage("verack");
115 vSend.SetVersion(min(nVersion, PROTOCOL_VERSION));
116 if (nVersion < 209) {
117 this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION));
123 if (strCommand == "verack") {
124 this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION));
129 if (strCommand == "addr") {
130 vector<CAddress> vAddrNew;
132 // printf("%s: got %i addresses\n", ToString(you).c_str(), (int)vAddrNew.size());
133 int64 now = time(NULL);
134 vector<CAddress>::iterator it = vAddrNew.begin();
135 if (doneAfter == 0 || doneAfter > now + 1) doneAfter = now + 1;
136 while (it != vAddrNew.end()) {
137 CAddress &addr = *it;
138 // printf("%s: got address %s\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
140 if (addr.nTime <= 100000000 || addr.nTime > now + 600)
141 addr.nTime = now - 5 * 86400;
142 if (addr.nTime > now - 604800)
143 vAddr->push_back(addr);
144 // printf("%s: added address %s (#%i)\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
145 if (vAddr->size() > 1000) {doneAfter = 1; return true; }
153 bool ProcessMessages() {
154 if (vRecv.empty()) return false;
156 CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
157 int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
158 if (vRecv.end() - pstart < nHeaderSize) {
159 if (vRecv.size() > nHeaderSize) {
160 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
164 vRecv.erase(vRecv.begin(), pstart);
165 vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
168 if (!hdr.IsValid()) {
169 // printf("%s: BAD (invalid header)\n", ToString(you).c_str());
170 ban = 100000; return true;
172 string strCommand = hdr.GetCommand();
173 unsigned int nMessageSize = hdr.nMessageSize;
174 if (nMessageSize > MAX_SIZE) {
175 // printf("%s: BAD (message too large)\n", ToString(you).c_str());
179 if (nMessageSize > vRecv.size()) {
180 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
183 uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
184 unsigned int nChecksum = 0;
185 memcpy(&nChecksum, &hash, sizeof(nChecksum));
186 if (nChecksum != hdr.nChecksum) continue;
187 CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
188 vRecv.ignore(nMessageSize);
189 if (ProcessMessage(strCommand, vMsg))
191 // printf("%s: done processing %s\n", ToString(you).c_str(), strCommand.c_str());
197 CNode(const CService& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) {
198 vSend.SetType(SER_NETWORK);
200 vRecv.SetType(SER_NETWORK);
202 if (time(NULL) > 1329696000) {
203 vSend.SetVersion(209);
204 vRecv.SetVersion(209);
209 if (!ConnectSocket(you, sock)) return false;
213 while (now = time(NULL), ban == 0 && (doneAfter == 0 || doneAfter > now) && sock != INVALID_SOCKET) {
214 char pchBuf[0x10000];
220 wa.tv_sec = doneAfter - now;
223 wa.tv_sec = GetTimeout();
226 int ret = select(sock+1, &set, NULL, &set, &wa);
228 if (!doneAfter) res = false;
231 int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0);
232 int nPos = vRecv.size();
234 vRecv.resize(nPos + nBytes);
235 memcpy(&vRecv[nPos], pchBuf, nBytes);
236 } else if (nBytes == 0) {
237 // printf("%s: BAD (connection closed prematurely)\n", ToString(you).c_str());
241 // printf("%s: BAD (connection error)\n", ToString(you).c_str());
248 if (sock == INVALID_SOCKET) res = false;
250 sock = INVALID_SOCKET;
251 return (ban == 0) && res;
258 int GetClientVersion() {
262 std::string GetClientSubVersion() {
266 int GetStartingHeight() {
267 return nStartingHeight;
271 bool TestNode(const CService &cip, int &ban, int &clientV, std::string &clientSV, int &blocks, vector<CAddress>& vAddr) {
273 CNode node(cip, vAddr);
274 bool ret = node.Run();
280 clientV = node.GetClientVersion();
281 clientSV = node.GetClientSubVersion();
282 blocks = node.GetStartingHeight();
283 // printf("%s: %s!!!\n", cip.ToString().c_str(), ret ? "GOOD" : "BAD");
285 } catch(std::ios_base::failure& e) {
293 CService ip("bitcoin.sipa.be", 8333, true);
294 vector<CAddress> vAddr;
297 bool ret = TestNode(ip, ban, vAddr);
298 printf("ret=%s ban=%i vAddr.size()=%i\n", ret ? "good" : "bad", ban, (int)vAddr.size());