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 if (vSend.GetVersion() >= 209) {
56 uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
57 unsigned int nChecksum = 0;
58 memcpy(&nChecksum, &hash, sizeof(nChecksum));
59 assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
60 memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
67 if (sock == INVALID_SOCKET) return;
68 if (vSend.empty()) return;
69 int nBytes = send(sock, &vSend[0], vSend.size(), 0);
71 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
74 sock = INVALID_SOCKET;
79 int64 nTime = time(NULL);
80 uint64 nLocalNonce = BITCOIN_SEED_NONCE;
81 int64 nLocalServices = 0;
82 CAddress me(CService("0.0.0.0"));
83 BeginMessage("version");
84 int nBestHeight = REQUIRE_HEIGHT;
85 string ver = "/novacoin-seeder:0.01/";
86 vSend << PROTOCOL_VERSION << nLocalServices << nTime << you << me << nLocalNonce << ver << nBestHeight;
91 // printf("\n%s: version %i\n", ToString(you).c_str(), nVersion);
92 BeginMessage("getaddr");
94 doneAfter = time(NULL) + GetTimeout();
97 bool ProcessMessage(string strCommand, CDataStream& vRecv) {
98 //printf("%s: RECV %s\n", ToString(you).c_str(), strCommand.c_str());
99 if (strCommand == "version") {
104 vRecv >> nVersion >> you.nServices >> nTime >> addrMe;
105 if (nVersion == 10300) nVersion = 300;
106 if (nVersion >= 106 && !vRecv.empty())
107 vRecv >> addrFrom >> nNonce;
108 if (nVersion >= 106 && !vRecv.empty())
110 if (nVersion >= 209 && !vRecv.empty())
111 vRecv >> nStartingHeight;
113 if (nVersion >= 209) {
114 BeginMessage("verack");
117 vSend.SetVersion(min(nVersion, PROTOCOL_VERSION));
118 if (nVersion < 209) {
119 this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION));
125 if (strCommand == "verack") {
126 this->vRecv.SetVersion(min(nVersion, PROTOCOL_VERSION));
131 if (strCommand == "addr") {
132 vector<CAddress> vAddrNew;
134 // printf("%s: got %i addresses\n", ToString(you).c_str(), (int)vAddrNew.size());
135 int64 now = time(NULL);
136 vector<CAddress>::iterator it = vAddrNew.begin();
137 if (doneAfter == 0 || doneAfter > now + 1) doneAfter = now + 1;
138 while (it != vAddrNew.end()) {
139 CAddress &addr = *it;
140 // printf("%s: got address %s\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
142 if (addr.nTime <= 100000000 || addr.nTime > now + 600)
143 addr.nTime = now - 5 * 86400;
144 if (addr.nTime > now - 604800)
145 vAddr->push_back(addr);
146 // printf("%s: added address %s (#%i)\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
147 if (vAddr->size() > 1000) {doneAfter = 1; return true; }
155 bool ProcessMessages() {
156 if (vRecv.empty()) return false;
158 CDataStream::iterator pstart = search(vRecv.begin(), vRecv.end(), BEGIN(pchMessageStart), END(pchMessageStart));
159 int nHeaderSize = vRecv.GetSerializeSize(CMessageHeader());
160 if (vRecv.end() - pstart < nHeaderSize) {
161 if (vRecv.size() > nHeaderSize) {
162 vRecv.erase(vRecv.begin(), vRecv.end() - nHeaderSize);
166 vRecv.erase(vRecv.begin(), pstart);
167 vector<char> vHeaderSave(vRecv.begin(), vRecv.begin() + nHeaderSize);
170 if (!hdr.IsValid()) {
171 // printf("%s: BAD (invalid header)\n", ToString(you).c_str());
172 ban = 100000; return true;
174 string strCommand = hdr.GetCommand();
175 unsigned int nMessageSize = hdr.nMessageSize;
176 if (nMessageSize > MAX_SIZE) {
177 // printf("%s: BAD (message too large)\n", ToString(you).c_str());
181 if (nMessageSize > vRecv.size()) {
182 vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
185 if (vRecv.GetVersion() >= 209) {
186 uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
187 unsigned int nChecksum = 0;
188 memcpy(&nChecksum, &hash, sizeof(nChecksum));
189 if (nChecksum != hdr.nChecksum) continue;
191 CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
192 vRecv.ignore(nMessageSize);
193 if (ProcessMessage(strCommand, vMsg))
195 // printf("%s: done processing %s\n", ToString(you).c_str(), strCommand.c_str());
201 CNode(const CService& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) {
202 vSend.SetType(SER_NETWORK);
204 vRecv.SetType(SER_NETWORK);
206 if (time(NULL) > 1329696000) {
207 vSend.SetVersion(209);
208 vRecv.SetVersion(209);
213 if (!ConnectSocket(you, sock)) return false;
217 while (now = time(NULL), ban == 0 && (doneAfter == 0 || doneAfter > now) && sock != INVALID_SOCKET) {
218 char pchBuf[0x10000];
224 wa.tv_sec = doneAfter - now;
227 wa.tv_sec = GetTimeout();
230 int ret = select(sock+1, &set, NULL, &set, &wa);
232 if (!doneAfter) res = false;
235 int nBytes = recv(sock, pchBuf, sizeof(pchBuf), 0);
236 int nPos = vRecv.size();
238 vRecv.resize(nPos + nBytes);
239 memcpy(&vRecv[nPos], pchBuf, nBytes);
240 } else if (nBytes == 0) {
241 // printf("%s: BAD (connection closed prematurely)\n", ToString(you).c_str());
245 // printf("%s: BAD (connection error)\n", ToString(you).c_str());
252 if (sock == INVALID_SOCKET) res = false;
254 sock = INVALID_SOCKET;
255 return (ban == 0) && res;
262 int GetClientVersion() {
266 std::string GetClientSubVersion() {
270 int GetStartingHeight() {
271 return nStartingHeight;
275 bool TestNode(const CService &cip, int &ban, int &clientV, std::string &clientSV, int &blocks, vector<CAddress>& vAddr) {
277 CNode node(cip, vAddr);
278 bool ret = node.Run();
284 clientV = node.GetClientVersion();
285 clientSV = node.GetClientSubVersion();
286 blocks = node.GetStartingHeight();
287 // printf("%s: %s!!!\n", cip.ToString().c_str(), ret ? "GOOD" : "BAD");
289 } catch(std::ios_base::failure& e) {
297 CService ip("bitcoin.sipa.be", 8333, true);
298 vector<CAddress> vAddr;
301 bool ret = TestNode(ip, ban, vAddr);
302 printf("ret=%s ban=%i vAddr.size()=%i\n", ret ? "good" : "bad", ban, (int)vAddr.size());