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