raw
experimental-genesis    1 //  /****************************\
experimental-genesis 2 // * EXPERIMENTAL BRANCH. *
experimental-genesis 3 // * FOR LABORATORY USE ONLY. *
experimental-genesis 4 // ********************************
experimental-genesis 5 // ************
experimental-genesis 6 // **************
experimental-genesis 7 // ****************
experimental-genesis 8 // **** **** ****
experimental-genesis 9 // *** *** ***
experimental-genesis 10 // *** *** ***
experimental-genesis 11 // *** * * **
experimental-genesis 12 // ******** ********
experimental-genesis 13 // ******* ******
experimental-genesis 14 // *** **
experimental-genesis 15 // * ******* **
experimental-genesis 16 // ** * * * * *
experimental-genesis 17 // ** * * ***
experimental-genesis 18 // **** * * * * ****
experimental-genesis 19 // **** *** * * ** ***
experimental-genesis 20 // **** ********* ******
experimental-genesis 21 // ******* ***** *******
experimental-genesis 22 // ********* ****** **
experimental-genesis 23 // ** ****** ******
experimental-genesis 24 // ** ******* **
experimental-genesis 25 // ** ******* ***
experimental-genesis 26 // **** ******** ************
experimental-genesis 27 // ************ ************
experimental-genesis 28 // ******** *******
experimental-genesis 29 // ****** ****
experimental-genesis 30 // *** ***
experimental-genesis 31 // ********************************
experimental-genesis 32 // Copyright (c) 2009-2010 Satoshi Nakamoto
experimental-genesis 33 // Copyright (c) 2009-2012 The Bitcoin developers
experimental-genesis 34 // Distributed under the MIT/X11 software license, see the accompanying
experimental-genesis 35 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
experimental-genesis 36
experimental-genesis 37 #include "headers.h"
experimental-genesis 38 #include "irc.h"
experimental-genesis 39 #include "net.h"
experimental-genesis 40 #include "strlcpy.h"
experimental-genesis 41
experimental-genesis 42 using namespace std;
experimental-genesis 43 using namespace boost;
experimental-genesis 44
experimental-genesis 45 int nGotIRCAddresses = 0;
experimental-genesis 46 bool fGotExternalIP = false;
experimental-genesis 47
experimental-genesis 48 void ThreadIRCSeed2(void* parg);
experimental-genesis 49
experimental-genesis 50
experimental-genesis 51
experimental-genesis 52
experimental-genesis 53 #pragma pack(push, 1)
experimental-genesis 54 struct ircaddr
experimental-genesis 55 {
experimental-genesis 56 int ip;
experimental-genesis 57 short port;
experimental-genesis 58 };
experimental-genesis 59 #pragma pack(pop)
experimental-genesis 60
experimental-genesis 61 string EncodeAddress(const CAddress& addr)
experimental-genesis 62 {
experimental-genesis 63 struct ircaddr tmp;
experimental-genesis 64 tmp.ip = addr.ip;
experimental-genesis 65 tmp.port = addr.port;
experimental-genesis 66
experimental-genesis 67 vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
experimental-genesis 68 return string("u") + EncodeBase58Check(vch);
experimental-genesis 69 }
experimental-genesis 70
experimental-genesis 71 bool DecodeAddress(string str, CAddress& addr)
experimental-genesis 72 {
experimental-genesis 73 vector<unsigned char> vch;
experimental-genesis 74 if (!DecodeBase58Check(str.substr(1), vch))
experimental-genesis 75 return false;
experimental-genesis 76
experimental-genesis 77 struct ircaddr tmp;
experimental-genesis 78 if (vch.size() != sizeof(tmp))
experimental-genesis 79 return false;
experimental-genesis 80 memcpy(&tmp, &vch[0], sizeof(tmp));
experimental-genesis 81
experimental-genesis 82 addr = CAddress(tmp.ip, ntohs(tmp.port), NODE_NETWORK);
experimental-genesis 83 return true;
experimental-genesis 84 }
experimental-genesis 85
experimental-genesis 86
experimental-genesis 87
experimental-genesis 88
experimental-genesis 89
experimental-genesis 90
experimental-genesis 91 static bool Send(SOCKET hSocket, const char* pszSend)
experimental-genesis 92 {
experimental-genesis 93 if (strstr(pszSend, "PONG") != pszSend)
experimental-genesis 94 printf("IRC SENDING: %s\n", pszSend);
experimental-genesis 95 const char* psz = pszSend;
experimental-genesis 96 const char* pszEnd = psz + strlen(psz);
experimental-genesis 97 while (psz < pszEnd)
experimental-genesis 98 {
experimental-genesis 99 int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL);
experimental-genesis 100 if (ret < 0)
experimental-genesis 101 return false;
experimental-genesis 102 psz += ret;
experimental-genesis 103 }
experimental-genesis 104 return true;
experimental-genesis 105 }
experimental-genesis 106
experimental-genesis 107 bool RecvLine(SOCKET hSocket, string& strLine)
experimental-genesis 108 {
experimental-genesis 109 strLine = "";
experimental-genesis 110 loop
experimental-genesis 111 {
experimental-genesis 112 char c;
experimental-genesis 113 int nBytes = recv(hSocket, &c, 1, 0);
experimental-genesis 114 if (nBytes > 0)
experimental-genesis 115 {
experimental-genesis 116 if (c == '\n')
experimental-genesis 117 continue;
experimental-genesis 118 if (c == '\r')
experimental-genesis 119 return true;
experimental-genesis 120 strLine += c;
experimental-genesis 121 if (strLine.size() >= 9000)
experimental-genesis 122 return true;
experimental-genesis 123 }
experimental-genesis 124 else if (nBytes <= 0)
experimental-genesis 125 {
experimental-genesis 126 if (fShutdown)
experimental-genesis 127 return false;
experimental-genesis 128 if (nBytes < 0)
experimental-genesis 129 {
experimental-genesis 130 int nErr = WSAGetLastError();
experimental-genesis 131 if (nErr == WSAEMSGSIZE)
experimental-genesis 132 continue;
experimental-genesis 133 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
experimental-genesis 134 {
experimental-genesis 135 Sleep(10);
experimental-genesis 136 continue;
experimental-genesis 137 }
experimental-genesis 138 }
experimental-genesis 139 if (!strLine.empty())
experimental-genesis 140 return true;
experimental-genesis 141 if (nBytes == 0)
experimental-genesis 142 {
experimental-genesis 143 // socket closed
experimental-genesis 144 printf("socket closed\n");
experimental-genesis 145 return false;
experimental-genesis 146 }
experimental-genesis 147 else
experimental-genesis 148 {
experimental-genesis 149 // socket error
experimental-genesis 150 int nErr = WSAGetLastError();
experimental-genesis 151 printf("recv failed: %d\n", nErr);
experimental-genesis 152 return false;
experimental-genesis 153 }
experimental-genesis 154 }
experimental-genesis 155 }
experimental-genesis 156 }
experimental-genesis 157
experimental-genesis 158 bool RecvLineIRC(SOCKET hSocket, string& strLine)
experimental-genesis 159 {
experimental-genesis 160 loop
experimental-genesis 161 {
experimental-genesis 162 bool fRet = RecvLine(hSocket, strLine);
experimental-genesis 163 if (fRet)
experimental-genesis 164 {
experimental-genesis 165 if (fShutdown)
experimental-genesis 166 return false;
experimental-genesis 167 vector<string> vWords;
experimental-genesis 168 ParseString(strLine, ' ', vWords);
experimental-genesis 169 if (vWords.size() >= 1 && vWords[0] == "PING")
experimental-genesis 170 {
experimental-genesis 171 strLine[1] = 'O';
experimental-genesis 172 strLine += '\r';
experimental-genesis 173 Send(hSocket, strLine.c_str());
experimental-genesis 174 continue;
experimental-genesis 175 }
experimental-genesis 176 }
experimental-genesis 177 return fRet;
experimental-genesis 178 }
experimental-genesis 179 }
experimental-genesis 180
experimental-genesis 181 int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL)
experimental-genesis 182 {
experimental-genesis 183 loop
experimental-genesis 184 {
experimental-genesis 185 string strLine;
experimental-genesis 186 strLine.reserve(10000);
experimental-genesis 187 if (!RecvLineIRC(hSocket, strLine))
experimental-genesis 188 return 0;
experimental-genesis 189 printf("IRC %s\n", strLine.c_str());
experimental-genesis 190 if (psz1 && strLine.find(psz1) != -1)
experimental-genesis 191 return 1;
experimental-genesis 192 if (psz2 && strLine.find(psz2) != -1)
experimental-genesis 193 return 2;
experimental-genesis 194 if (psz3 && strLine.find(psz3) != -1)
experimental-genesis 195 return 3;
experimental-genesis 196 if (psz4 && strLine.find(psz4) != -1)
experimental-genesis 197 return 4;
experimental-genesis 198 }
experimental-genesis 199 }
experimental-genesis 200
experimental-genesis 201 bool Wait(int nSeconds)
experimental-genesis 202 {
experimental-genesis 203 if (fShutdown)
experimental-genesis 204 return false;
experimental-genesis 205 printf("IRC waiting %d seconds to reconnect\n", nSeconds);
experimental-genesis 206 for (int i = 0; i < nSeconds; i++)
experimental-genesis 207 {
experimental-genesis 208 if (fShutdown)
experimental-genesis 209 return false;
experimental-genesis 210 Sleep(1000);
experimental-genesis 211 }
experimental-genesis 212 return true;
experimental-genesis 213 }
experimental-genesis 214
experimental-genesis 215 bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet)
experimental-genesis 216 {
experimental-genesis 217 strRet.clear();
experimental-genesis 218 loop
experimental-genesis 219 {
experimental-genesis 220 string strLine;
experimental-genesis 221 if (!RecvLineIRC(hSocket, strLine))
experimental-genesis 222 return false;
experimental-genesis 223
experimental-genesis 224 vector<string> vWords;
experimental-genesis 225 ParseString(strLine, ' ', vWords);
experimental-genesis 226 if (vWords.size() < 2)
experimental-genesis 227 continue;
experimental-genesis 228
experimental-genesis 229 if (vWords[1] == psz1)
experimental-genesis 230 {
experimental-genesis 231 printf("IRC %s\n", strLine.c_str());
experimental-genesis 232 strRet = strLine;
experimental-genesis 233 return true;
experimental-genesis 234 }
experimental-genesis 235 }
experimental-genesis 236 }
experimental-genesis 237
experimental-genesis 238 bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet)
experimental-genesis 239 {
experimental-genesis 240 Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str());
experimental-genesis 241
experimental-genesis 242 string strLine;
experimental-genesis 243 if (!RecvCodeLine(hSocket, "302", strLine))
experimental-genesis 244 return false;
experimental-genesis 245
experimental-genesis 246 vector<string> vWords;
experimental-genesis 247 ParseString(strLine, ' ', vWords);
experimental-genesis 248 if (vWords.size() < 4)
experimental-genesis 249 return false;
experimental-genesis 250
experimental-genesis 251 string str = vWords[3];
experimental-genesis 252 if (str.rfind("@") == string::npos)
experimental-genesis 253 return false;
experimental-genesis 254 string strHost = str.substr(str.rfind("@")+1);
experimental-genesis 255
experimental-genesis 256 // Hybrid IRC used by lfnet always returns IP when you userhost yourself,
experimental-genesis 257 // but in case another IRC is ever used this should work.
experimental-genesis 258 printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
experimental-genesis 259 if (fUseProxy)
experimental-genesis 260 return false;
experimental-genesis 261 CAddress addr(strHost, 0, true);
experimental-genesis 262 if (!addr.IsValid())
experimental-genesis 263 return false;
experimental-genesis 264 ipRet = addr.ip;
experimental-genesis 265
experimental-genesis 266 return true;
experimental-genesis 267 }
experimental-genesis 268
experimental-genesis 269
experimental-genesis 270
experimental-genesis 271 void ThreadIRCSeed(void* parg)
experimental-genesis 272 {
experimental-genesis 273 IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg));
experimental-genesis 274 try
experimental-genesis 275 {
experimental-genesis 276 ThreadIRCSeed2(parg);
experimental-genesis 277 }
experimental-genesis 278 catch (std::exception& e) {
experimental-genesis 279 PrintExceptionContinue(&e, "ThreadIRCSeed()");
experimental-genesis 280 } catch (...) {
experimental-genesis 281 PrintExceptionContinue(NULL, "ThreadIRCSeed()");
experimental-genesis 282 }
experimental-genesis 283 printf("ThreadIRCSeed exiting\n");
experimental-genesis 284 }
experimental-genesis 285
experimental-genesis 286 void ThreadIRCSeed2(void* parg)
experimental-genesis 287 {
experimental-genesis 288 /* Dont advertise on IRC if we don't allow incoming connections */
experimental-genesis 289 if (mapArgs.count("-connect") || fNoListen)
experimental-genesis 290 return;
experimental-genesis 291
experimental-genesis 292 if (GetBoolArg("-noirc"))
experimental-genesis 293 return;
experimental-genesis 294 printf("ThreadIRCSeed started\n");
experimental-genesis 295 int nErrorWait = 10;
experimental-genesis 296 int nRetryWait = 10;
experimental-genesis 297 bool fNameInUse = false;
experimental-genesis 298
experimental-genesis 299 while (!fShutdown)
experimental-genesis 300 {
experimental-genesis 301 CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org
experimental-genesis 302
experimental-genesis 303 CAddress addrIRC("irc.lfnet.org", 6667, true);
experimental-genesis 304 if (addrIRC.IsValid())
experimental-genesis 305 addrConnect = addrIRC;
experimental-genesis 306
experimental-genesis 307 SOCKET hSocket;
experimental-genesis 308 if (!ConnectSocket(addrConnect, hSocket))
experimental-genesis 309 {
experimental-genesis 310 printf("IRC connect failed\n");
experimental-genesis 311 nErrorWait = nErrorWait * 11 / 10;
experimental-genesis 312 if (Wait(nErrorWait += 60))
experimental-genesis 313 continue;
experimental-genesis 314 else
experimental-genesis 315 return;
experimental-genesis 316 }
experimental-genesis 317
experimental-genesis 318 if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname"))
experimental-genesis 319 {
experimental-genesis 320 closesocket(hSocket);
experimental-genesis 321 hSocket = INVALID_SOCKET;
experimental-genesis 322 nErrorWait = nErrorWait * 11 / 10;
experimental-genesis 323 if (Wait(nErrorWait += 60))
experimental-genesis 324 continue;
experimental-genesis 325 else
experimental-genesis 326 return;
experimental-genesis 327 }
experimental-genesis 328
experimental-genesis 329 string strMyName;
experimental-genesis 330 if (addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse)
experimental-genesis 331 strMyName = EncodeAddress(addrLocalHost);
experimental-genesis 332 else
experimental-genesis 333 strMyName = strprintf("x%u", GetRand(1000000000));
experimental-genesis 334
experimental-genesis 335 Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
experimental-genesis 336 Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());
experimental-genesis 337
experimental-genesis 338 int nRet = RecvUntil(hSocket, " 004 ", " 433 ");
experimental-genesis 339 if (nRet != 1)
experimental-genesis 340 {
experimental-genesis 341 closesocket(hSocket);
experimental-genesis 342 hSocket = INVALID_SOCKET;
experimental-genesis 343 if (nRet == 2)
experimental-genesis 344 {
experimental-genesis 345 printf("IRC name already in use\n");
experimental-genesis 346 fNameInUse = true;
experimental-genesis 347 Wait(10);
experimental-genesis 348 continue;
experimental-genesis 349 }
experimental-genesis 350 nErrorWait = nErrorWait * 11 / 10;
experimental-genesis 351 if (Wait(nErrorWait += 60))
experimental-genesis 352 continue;
experimental-genesis 353 else
experimental-genesis 354 return;
experimental-genesis 355 }
experimental-genesis 356 Sleep(500);
experimental-genesis 357
experimental-genesis 358 // Get our external IP from the IRC server and re-nick before joining the channel
experimental-genesis 359 CAddress addrFromIRC;
experimental-genesis 360 if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip))
experimental-genesis 361 {
experimental-genesis 362 printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str());
experimental-genesis 363 if (!fUseProxy && addrFromIRC.IsRoutable())
experimental-genesis 364 {
experimental-genesis 365 // IRC lets you to re-nick
experimental-genesis 366 fGotExternalIP = true;
experimental-genesis 367 addrLocalHost.ip = addrFromIRC.ip;
experimental-genesis 368 strMyName = EncodeAddress(addrLocalHost);
experimental-genesis 369 Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
experimental-genesis 370 }
experimental-genesis 371 }
experimental-genesis 372
experimental-genesis 373 if (fTestNet) {
experimental-genesis 374 Send(hSocket, "JOIN #bitcoinTEST\r");
experimental-genesis 375 Send(hSocket, "WHO #bitcoinTEST\r");
experimental-genesis 376 } else {
experimental-genesis 377 // randomly join #bitcoin00-#bitcoin99
experimental-genesis 378 int channel_number = GetRandInt(100);
experimental-genesis 379 Send(hSocket, strprintf("JOIN #bitcoin%02d\r", channel_number).c_str());
experimental-genesis 380 Send(hSocket, strprintf("WHO #bitcoin%02d\r", channel_number).c_str());
experimental-genesis 381 }
experimental-genesis 382
experimental-genesis 383 int64 nStart = GetTime();
experimental-genesis 384 string strLine;
experimental-genesis 385 strLine.reserve(10000);
experimental-genesis 386 while (!fShutdown && RecvLineIRC(hSocket, strLine))
experimental-genesis 387 {
experimental-genesis 388 if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
experimental-genesis 389 continue;
experimental-genesis 390
experimental-genesis 391 vector<string> vWords;
experimental-genesis 392 ParseString(strLine, ' ', vWords);
experimental-genesis 393 if (vWords.size() < 2)
experimental-genesis 394 continue;
experimental-genesis 395
experimental-genesis 396 char pszName[10000];
experimental-genesis 397 pszName[0] = '\0';
experimental-genesis 398
experimental-genesis 399 if (vWords[1] == "352" && vWords.size() >= 8)
experimental-genesis 400 {
experimental-genesis 401 // index 7 is limited to 16 characters
experimental-genesis 402 // could get full length name at index 10, but would be different from join messages
experimental-genesis 403 strlcpy(pszName, vWords[7].c_str(), sizeof(pszName));
experimental-genesis 404 printf("IRC got who\n");
experimental-genesis 405 }
experimental-genesis 406
experimental-genesis 407 if (vWords[1] == "JOIN" && vWords[0].size() > 1)
experimental-genesis 408 {
experimental-genesis 409 // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname
experimental-genesis 410 strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
experimental-genesis 411 if (strchr(pszName, '!'))
experimental-genesis 412 *strchr(pszName, '!') = '\0';
experimental-genesis 413 printf("IRC got join\n");
experimental-genesis 414 }
experimental-genesis 415
experimental-genesis 416 if (pszName[0] == 'u')
experimental-genesis 417 {
experimental-genesis 418 CAddress addr;
experimental-genesis 419 if (DecodeAddress(pszName, addr))
experimental-genesis 420 {
experimental-genesis 421 addr.nTime = GetAdjustedTime();
experimental-genesis 422 if (AddAddress(addr, 51 * 60))
experimental-genesis 423 printf("IRC got new address: %s\n", addr.ToString().c_str());
experimental-genesis 424 nGotIRCAddresses++;
experimental-genesis 425 }
experimental-genesis 426 else
experimental-genesis 427 {
experimental-genesis 428 printf("IRC decode failed\n");
experimental-genesis 429 }
experimental-genesis 430 }
experimental-genesis 431 }
experimental-genesis 432 closesocket(hSocket);
experimental-genesis 433 hSocket = INVALID_SOCKET;
experimental-genesis 434
experimental-genesis 435 if (GetTime() - nStart > 20 * 60)
experimental-genesis 436 {
experimental-genesis 437 nErrorWait /= 3;
experimental-genesis 438 nRetryWait /= 3;
experimental-genesis 439 }
experimental-genesis 440
experimental-genesis 441 nRetryWait = nRetryWait * 11 / 10;
experimental-genesis 442 if (!Wait(nRetryWait += 60))
experimental-genesis 443 return;
experimental-genesis 444 }
experimental-genesis 445 }
experimental-genesis 446
experimental-genesis 447
experimental-genesis 448
experimental-genesis 449
experimental-genesis 450
experimental-genesis 451
experimental-genesis 452
experimental-genesis 453
experimental-genesis 454
experimental-genesis 455
experimental-genesis 456 #ifdef TEST
experimental-genesis 457 int main(int argc, char *argv[])
experimental-genesis 458 {
experimental-genesis 459 WSADATA wsadata;
experimental-genesis 460 if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR)
experimental-genesis 461 {
experimental-genesis 462 printf("Error at WSAStartup()\n");
experimental-genesis 463 return false;
experimental-genesis 464 }
experimental-genesis 465
experimental-genesis 466 ThreadIRCSeed(NULL);
experimental-genesis 467
experimental-genesis 468 WSACleanup();
experimental-genesis 469 return 0;
experimental-genesis 470 }
experimental-genesis 471 #endif