X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Firc.cpp;h=a29874ebfbdafd3111b3bc407013f75986ee322f;hp=cde934e80c4a20792e6a53d8f4d46a2050ce732d;hb=1c1980bccd1bcccdb03c69ebbe03ad51e08f343a;hpb=0eeb4f5d5b4c6b634dea4a5ec5b2e6c322c9230e diff --git a/src/irc.cpp b/src/irc.cpp index cde934e..a29874e 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -1,17 +1,15 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "headers.h" #include "irc.h" +#include "base58.h" #include "net.h" -#include "strlcpy.h" using namespace std; -using namespace boost; int nGotIRCAddresses = 0; -bool fGotExternalIP = false; void ThreadIRCSeed2(void* parg); @@ -21,22 +19,25 @@ void ThreadIRCSeed2(void* parg); #pragma pack(push, 1) struct ircaddr { - int ip; - short port; + struct in_addr ip; + unsigned short port; }; #pragma pack(pop) -string EncodeAddress(const CAddress& addr) +string EncodeAddress(const CService& addr) { struct ircaddr tmp; - tmp.ip = addr.ip; - tmp.port = addr.port; + if (addr.GetInAddr(&tmp.ip)) + { + tmp.port = htons(addr.GetPort()); - vector vch(UBEGIN(tmp), UEND(tmp)); - return string("u") + EncodeBase58Check(vch); + vector vch(UBEGIN(tmp), UEND(tmp)); + return string("u") + EncodeBase58Check(vch); + } + return ""; } -bool DecodeAddress(string str, CAddress& addr) +bool DecodeAddress(string str, CService& addr) { vector vch; if (!DecodeBase58Check(str.substr(1), vch)) @@ -47,7 +48,7 @@ bool DecodeAddress(string str, CAddress& addr) return false; memcpy(&tmp, &vch[0], sizeof(tmp)); - addr = CAddress(tmp.ip, ntohs(tmp.port), NODE_NETWORK); + addr = CService(tmp.ip, ntohs(tmp.port)); return true; } @@ -72,60 +73,9 @@ static bool Send(SOCKET hSocket, const char* pszSend) return true; } -bool RecvLine(SOCKET hSocket, string& strLine) -{ - strLine = ""; - loop - { - char c; - int nBytes = recv(hSocket, &c, 1, 0); - if (nBytes > 0) - { - if (c == '\n') - continue; - if (c == '\r') - return true; - strLine += c; - if (strLine.size() >= 9000) - return true; - } - else if (nBytes <= 0) - { - if (fShutdown) - return false; - if (nBytes < 0) - { - int nErr = WSAGetLastError(); - if (nErr == WSAEMSGSIZE) - continue; - if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) - { - Sleep(10); - continue; - } - } - if (!strLine.empty()) - return true; - if (nBytes == 0) - { - // socket closed - printf("IRC socket closed\n"); - return false; - } - else - { - // socket error - int nErr = WSAGetLastError(); - printf("IRC recv failed: %d\n", nErr); - return false; - } - } - } -} - bool RecvLineIRC(SOCKET hSocket, string& strLine) { - loop + for ( ; ; ) { bool fRet = RecvLine(hSocket, strLine); if (fRet) @@ -148,20 +98,20 @@ bool RecvLineIRC(SOCKET hSocket, string& strLine) int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL) { - loop + for ( ; ; ) { string strLine; strLine.reserve(10000); if (!RecvLineIRC(hSocket, strLine)) return 0; printf("IRC %s\n", strLine.c_str()); - if (psz1 && strLine.find(psz1) != -1) + if (psz1 && strLine.find(psz1) != string::npos) return 1; - if (psz2 && strLine.find(psz2) != -1) + if (psz2 && strLine.find(psz2) != string::npos) return 2; - if (psz3 && strLine.find(psz3) != -1) + if (psz3 && strLine.find(psz3) != string::npos) return 3; - if (psz4 && strLine.find(psz4) != -1) + if (psz4 && strLine.find(psz4) != string::npos) return 4; } } @@ -183,7 +133,7 @@ bool Wait(int nSeconds) bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet) { strRet.clear(); - loop + for ( ; ; ) { string strLine; if (!RecvLineIRC(hSocket, strLine)) @@ -203,7 +153,7 @@ bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet) } } -bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) +bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet) { Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str()); @@ -224,12 +174,10 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) // Hybrid IRC used by lfnet always returns IP when you userhost yourself, // but in case another IRC is ever used this should work. printf("GetIPFromIRC() got userhost %s\n", strHost.c_str()); - if (fUseProxy) - return false; - CAddress addr(strHost, 0, true); + CNetAddr addr(strHost, true); if (!addr.IsValid()) return false; - ipRet = addr.ip; + ipRet = addr; return true; } @@ -238,7 +186,11 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) void ThreadIRCSeed(void* parg) { - IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg)); + // Make this thread recognisable as the IRC seeding thread + RenameThread("novacoin-ircseed"); + + printf("ThreadIRCSeed started\n"); + try { ThreadIRCSeed2(parg); @@ -248,34 +200,37 @@ void ThreadIRCSeed(void* parg) } catch (...) { PrintExceptionContinue(NULL, "ThreadIRCSeed()"); } - printf("ThreadIRCSeed exiting\n"); + printf("ThreadIRCSeed exited\n"); } void ThreadIRCSeed2(void* parg) { - /* Dont advertise on IRC if we don't allow incoming connections */ - if (mapArgs.count("-connect") || fNoListen) + // Don't connect to IRC if we won't use IPv4 connections. + if (IsLimited(NET_IPV4)) return; - if (GetBoolArg("-noirc")) + // ... or if we won't make outbound connections and won't accept inbound ones. + if (mapArgs.count("-connect") && fNoListen) return; - printf("ThreadIRCSeed started\n"); + + // ... or if IRC is not enabled. + if (!GetBoolArg("-irc", true)) + return; + + printf("ThreadIRCSeed trying to connect...\n"); + int nErrorWait = 10; int nRetryWait = 10; - bool fNameInUse = false; - bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); + int nNameRetry = 0; while (!fShutdown) { - //CAddress addrConnect("216.155.130.130:6667"); // chat.freenode.net - CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org - if (!fTOR) - { - //struct hostent* phostent = gethostbyname("chat.freenode.net"); - CAddress addrIRC("irc.lfnet.org", 6667, true); - if (addrIRC.IsValid()) - addrConnect = addrIRC; - } + const uint16_t nIrcPort = 6667; + CService addrConnect("92.243.23.21", nIrcPort); // irc.lfnet.org + + CService addrIRC("irc.lfnet.org", nIrcPort, true); + if (addrIRC.IsValid()) + addrConnect = addrIRC; SOCKET hSocket; if (!ConnectSocket(addrConnect, hSocket)) @@ -290,8 +245,7 @@ void ThreadIRCSeed2(void* parg) if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname")) { - closesocket(hSocket); - hSocket = INVALID_SOCKET; + CloseSocket(hSocket); nErrorWait = nErrorWait * 11 / 10; if (Wait(nErrorWait += 60)) continue; @@ -299,11 +253,15 @@ void ThreadIRCSeed2(void* parg) return; } + CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses + CService addrLocal; string strMyName; - if (addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse) - strMyName = EncodeAddress(addrLocalHost); - else - strMyName = strprintf("x%u", GetRand(1000000000)); + // Don't use our IP as our nick if we're not listening + // or if it keeps failing because the nick is already in use. + if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3) + strMyName = EncodeAddress(GetLocalAddress(&addrConnect)); + if (strMyName.empty()) + strMyName = strprintf("x%" PRIu64 "", GetRand(1000000000)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str()); @@ -311,12 +269,11 @@ void ThreadIRCSeed2(void* parg) int nRet = RecvUntil(hSocket, " 004 ", " 433 "); if (nRet != 1) { - closesocket(hSocket); - hSocket = INVALID_SOCKET; + CloseSocket(hSocket); if (nRet == 2) { printf("IRC name already in use\n"); - fNameInUse = true; + nNameRetry++; Wait(10); continue; } @@ -326,34 +283,38 @@ void ThreadIRCSeed2(void* parg) else return; } + nNameRetry = 0; Sleep(500); // Get our external IP from the IRC server and re-nick before joining the channel - CAddress addrFromIRC; - if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip)) + CNetAddr addrFromIRC; + if (GetIPFromIRC(hSocket, strMyName, addrFromIRC)) { - printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str()); - if (!fUseProxy && addrFromIRC.IsRoutable()) + printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str()); + // Don't use our IP as our nick if we're not listening + if (!fNoListen && addrFromIRC.IsRoutable()) { // IRC lets you to re-nick - fGotExternalIP = true; - addrLocalHost.ip = addrFromIRC.ip; - strMyName = EncodeAddress(addrLocalHost); + AddLocal(addrFromIRC, LOCAL_IRC); + strMyName = EncodeAddress(GetLocalAddress(&addrConnect)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); } } - + if (fTestNet) { - Send(hSocket, "JOIN #bitcoinTEST\r"); - Send(hSocket, "WHO #bitcoinTEST\r"); + Send(hSocket, "JOIN #novacoinTEST2\r"); + Send(hSocket, "WHO #novacoinTEST2\r"); } else { - // randomly join #bitcoin00-#bitcoin99 - int channel_number = GetRandInt(100); - Send(hSocket, strprintf("JOIN #bitcoin%02d\r", channel_number).c_str()); - Send(hSocket, strprintf("WHO #bitcoin%02d\r", channel_number).c_str()); + // randomly join #novacoin00-#novacoin05 + // int channel_number = GetRandInt(5); + + // Channel number is always 0 for initial release + int channel_number = 0; + Send(hSocket, strprintf("JOIN #novacoin%02d\r", channel_number).c_str()); + Send(hSocket, strprintf("WHO #novacoin%02d\r", channel_number).c_str()); } - int64 nStart = GetTime(); + int64_t nStart = GetTime(); string strLine; strLine.reserve(10000); while (!fShutdown && RecvLineIRC(hSocket, strLine)) @@ -366,33 +327,30 @@ void ThreadIRCSeed2(void* parg) if (vWords.size() < 2) continue; - char pszName[10000]; - pszName[0] = '\0'; + std::string strName; if (vWords[1] == "352" && vWords.size() >= 8) { // index 7 is limited to 16 characters // could get full length name at index 10, but would be different from join messages - strlcpy(pszName, vWords[7].c_str(), sizeof(pszName)); + strName = vWords[7]; printf("IRC got who\n"); } if (vWords[1] == "JOIN" && vWords[0].size() > 1) { // :username!username@50000007.F000000B.90000002.IP JOIN :#channelname - strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName)); - if (strchr(pszName, '!')) - *strchr(pszName, '!') = '\0'; + strName = vWords[0].substr(1, vWords[0].find('!', 1) - 1); printf("IRC got join\n"); } - if (pszName[0] == 'u') + if (strName.compare(0,1, "u") == 0) { CAddress addr; - if (DecodeAddress(pszName, addr)) + if (DecodeAddress(strName, addr)) { addr.nTime = GetAdjustedTime(); - if (AddAddress(addr, 51 * 60)) + if (addrman.Add(addr, addrConnect, 51 * 60)) printf("IRC got new address: %s\n", addr.ToString().c_str()); nGotIRCAddresses++; } @@ -402,12 +360,7 @@ void ThreadIRCSeed2(void* parg) } } } - closesocket(hSocket); - hSocket = INVALID_SOCKET; - - // IRC usually blocks TOR, so only try once - if (fTOR) - return; + CloseSocket(hSocket); if (GetTime() - nStart > 20 * 60) {