commit
1684f98b27
21 changed files with 1042 additions and 547 deletions
|
@ -97,6 +97,7 @@ HEADERS += src/qt/bitcoingui.h \
|
|||
src/base58.h \
|
||||
src/bignum.h \
|
||||
src/checkpoints.h \
|
||||
src/compat.h \
|
||||
src/util.h \
|
||||
src/uint256.h \
|
||||
src/serialize.h \
|
||||
|
@ -156,6 +157,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
|||
src/qt/editaddressdialog.cpp \
|
||||
src/qt/bitcoinaddressvalidator.cpp \
|
||||
src/util.cpp \
|
||||
src/netbase.cpp \
|
||||
src/key.cpp \
|
||||
src/script.cpp \
|
||||
src/main.cpp \
|
||||
|
|
42
src/compat.h
Normal file
42
src/compat.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 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.
|
||||
#ifndef _BITCOIN_COMPAT_H
|
||||
#define _BITCOIN_COMPAT_H 1
|
||||
|
||||
typedef u_int SOCKET;
|
||||
#ifdef WIN32
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define MSG_DONTWAIT 0
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include "errno.h"
|
||||
#define WSAGetLastError() errno
|
||||
#define WSAEINVAL EINVAL
|
||||
#define WSAEALREADY EALREADY
|
||||
#define WSAEWOULDBLOCK EWOULDBLOCK
|
||||
#define WSAEMSGSIZE EMSGSIZE
|
||||
#define WSAEINTR EINTR
|
||||
#define WSAEINPROGRESS EINPROGRESS
|
||||
#define WSAEADDRINUSE EADDRINUSE
|
||||
#define WSAENOTSOCK EBADF
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
inline int myclosesocket(SOCKET& hSocket)
|
||||
{
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return WSAENOTSOCK;
|
||||
#ifdef WIN32
|
||||
int ret = closesocket(hSocket);
|
||||
#else
|
||||
int ret = close(hSocket);
|
||||
#endif
|
||||
hSocket = INVALID_SOCKET;
|
||||
return ret;
|
||||
}
|
||||
#define closesocket(s) myclosesocket(s)
|
||||
|
||||
#endif
|
|
@ -12,7 +12,7 @@
|
|||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#ifdef _WIN32_IE
|
||||
#undef _WIN32_IE
|
||||
#endif
|
||||
|
|
|
@ -470,7 +470,7 @@ bool AppInit2(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
bool fTor = (fUseProxy && addrProxy.port == htons(9050));
|
||||
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050);
|
||||
if (fTor)
|
||||
{
|
||||
// Use SoftSetArg here so user can override any of these if they wish.
|
||||
|
|
33
src/irc.cpp
33
src/irc.cpp
|
@ -22,22 +22,25 @@ void ThreadIRCSeed2(void* parg);
|
|||
#pragma pack(push, 1)
|
||||
struct ircaddr
|
||||
{
|
||||
int ip;
|
||||
struct in_addr ip;
|
||||
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<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
|
||||
return string("u") + EncodeBase58Check(vch);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool DecodeAddress(string str, CAddress& addr)
|
||||
bool DecodeAddress(string str, CService& addr)
|
||||
{
|
||||
vector<unsigned char> vch;
|
||||
if (!DecodeBase58Check(str.substr(1), vch))
|
||||
|
@ -48,7 +51,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;
|
||||
}
|
||||
|
||||
|
@ -204,7 +207,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());
|
||||
|
||||
|
@ -227,10 +230,10 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet)
|
|||
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;
|
||||
}
|
||||
|
@ -267,9 +270,9 @@ void ThreadIRCSeed2(void* parg)
|
|||
|
||||
while (!fShutdown)
|
||||
{
|
||||
CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org
|
||||
CService addrConnect("92.243.23.21", 6667); // irc.lfnet.org
|
||||
|
||||
CAddress addrIRC("irc.lfnet.org", 6667, true);
|
||||
CService addrIRC("irc.lfnet.org", 6667, true);
|
||||
if (addrIRC.IsValid())
|
||||
addrConnect = addrIRC;
|
||||
|
||||
|
@ -325,15 +328,15 @@ void ThreadIRCSeed2(void* parg)
|
|||
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());
|
||||
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
|
||||
if (!fUseProxy && addrFromIRC.IsRoutable())
|
||||
{
|
||||
// IRC lets you to re-nick
|
||||
fGotExternalIP = true;
|
||||
addrLocalHost.ip = addrFromIRC.ip;
|
||||
addrLocalHost.SetIP(addrFromIRC);
|
||||
strMyName = EncodeAddress(addrLocalHost);
|
||||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
|
||||
}
|
||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -1931,7 +1931,7 @@ unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
|
|||
|
||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
{
|
||||
static map<unsigned int, vector<unsigned char> > mapReuseKey;
|
||||
static map<CService, vector<unsigned char> > mapReuseKey;
|
||||
RandAddSeedPerfmon();
|
||||
if (fDebug) {
|
||||
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
|
||||
|
@ -1987,7 +1987,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
|
||||
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
|
||||
|
||||
AddTimeData(pfrom->addr.ip, nTime);
|
||||
AddTimeData(pfrom->addr, nTime);
|
||||
|
||||
// Change version
|
||||
if (pfrom->nVersion >= 209)
|
||||
|
@ -2093,7 +2093,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
static uint256 hashSalt;
|
||||
if (hashSalt == 0)
|
||||
RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
|
||||
uint256 hashRand = hashSalt ^ (((int64)addr.ip)<<32) ^ ((GetTime()+addr.ip)/(24*60*60));
|
||||
int64 hashAddr = addr.GetHash();
|
||||
uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60));
|
||||
hashRand = Hash(BEGIN(hashRand), END(hashRand));
|
||||
multimap<uint256, CNode*> mapMix;
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
|
@ -2392,12 +2393,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
/// we have a chance to check the order here
|
||||
|
||||
// Keep giving the same key to the same ip until they use it
|
||||
if (!mapReuseKey.count(pfrom->addr.ip))
|
||||
pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr.ip], true);
|
||||
if (!mapReuseKey.count(pfrom->addr))
|
||||
pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr], true);
|
||||
|
||||
// Send back approval of order and pubkey to use
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey << mapReuseKey[pfrom->addr.ip] << OP_CHECKSIG;
|
||||
scriptPubKey << mapReuseKey[pfrom->addr] << OP_CHECKSIG;
|
||||
pfrom->PushMessage("reply", hashReply, (int)0, scriptPubKey);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ HEADERS = \
|
|||
base58.h \
|
||||
bignum.h \
|
||||
checkpoints.h \
|
||||
compat.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
|
@ -63,6 +64,7 @@ LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l w
|
|||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
|
|
|
@ -30,6 +30,7 @@ HEADERS = \
|
|||
base58.h \
|
||||
bignum.h \
|
||||
checkpoints.h \
|
||||
compat.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
|
@ -60,6 +61,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell
|
|||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
|
|
|
@ -51,6 +51,7 @@ HEADERS = \
|
|||
base58.h \
|
||||
bignum.h \
|
||||
checkpoints.h \
|
||||
compat.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
|
@ -72,6 +73,7 @@ HEADERS = \
|
|||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
|
|
|
@ -88,6 +88,7 @@ HEADERS = \
|
|||
base58.h \
|
||||
bignum.h \
|
||||
checkpoints.h \
|
||||
compat.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
|
@ -109,6 +110,7 @@ HEADERS = \
|
|||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
|
|
308
src/net.cpp
308
src/net.cpp
|
@ -45,7 +45,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
|
|||
bool fClient = false;
|
||||
bool fAllowDNS = false;
|
||||
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
|
||||
CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
|
||||
CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
|
||||
static CNode* pnodeLocalHost = NULL;
|
||||
uint64 nLocalHostNonce = 0;
|
||||
array<int, 10> vnThreadsRunning;
|
||||
|
@ -60,10 +60,6 @@ deque<pair<int64, CInv> > vRelayExpiration;
|
|||
CCriticalSection cs_mapRelay;
|
||||
map<CInv, int64> mapAlreadyAskedFor;
|
||||
|
||||
// Settings
|
||||
int fUseProxy = false;
|
||||
int nConnectTimeout = 5000;
|
||||
CAddress addrProxy("127.0.0.1",9050);
|
||||
|
||||
|
||||
|
||||
|
@ -88,213 +84,7 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
|
|||
|
||||
|
||||
|
||||
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
hSocketRet = INVALID_SOCKET;
|
||||
|
||||
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return false;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int set = 1;
|
||||
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
|
||||
#endif
|
||||
|
||||
bool fProxy = (fUseProxy && addrConnect.IsRoutable());
|
||||
struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
|
||||
|
||||
#ifdef WIN32
|
||||
u_long fNonblock = 1;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
#else
|
||||
int fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
{
|
||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = nTimeout / 1000;
|
||||
timeout.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(hSocket, &fdset);
|
||||
int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
|
||||
if (nRet == 0)
|
||||
{
|
||||
printf("connection timeout\n");
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
printf("select() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
socklen_t nRetSize = sizeof(nRet);
|
||||
#ifdef WIN32
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
|
||||
#else
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet != 0)
|
||||
{
|
||||
printf("connect() failed after select(): %s\n",strerror(nRet));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
else if (WSAGetLastError() != WSAEISCONN)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
printf("connect() failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this isn't even strictly necessary
|
||||
CNode::ConnectNode immediately turns the socket back to non-blocking
|
||||
but we'll turn it back to blocking just in case
|
||||
*/
|
||||
#ifdef WIN32
|
||||
fNonblock = 0;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
#else
|
||||
fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fProxy)
|
||||
{
|
||||
printf("proxy connecting %s\n", addrConnect.ToString().c_str());
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
return false;
|
||||
}
|
||||
printf("proxy connected %s\n", addrConnect.ToString().c_str());
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
// portDefault is in host order
|
||||
bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
|
||||
{
|
||||
vaddr.clear();
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
int port = portDefault;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
if (fAllowPort)
|
||||
{
|
||||
char* pszColon = strrchr(psz+1,':');
|
||||
char *pszPortEnd = NULL;
|
||||
int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
|
||||
if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
|
||||
{
|
||||
if (psz[0] == '[' && pszColon[-1] == ']')
|
||||
{
|
||||
// Future: enable IPv6 colon-notation inside []
|
||||
pszHost = psz+1;
|
||||
pszColon[-1] = 0;
|
||||
}
|
||||
else
|
||||
pszColon[0] = 0;
|
||||
port = portParsed;
|
||||
if (port < 0 || port > std::numeric_limits<unsigned short>::max())
|
||||
port = std::numeric_limits<unsigned short>::max();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int addrIP = inet_addr(pszHost);
|
||||
if (addrIP != INADDR_NONE)
|
||||
{
|
||||
// valid IP address passed
|
||||
vaddr.push_back(CAddress(addrIP, port, nServices));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!fAllowLookup)
|
||||
return false;
|
||||
|
||||
struct hostent* phostent = gethostbyname(pszHost);
|
||||
if (!phostent)
|
||||
return false;
|
||||
|
||||
if (phostent->h_addrtype != AF_INET)
|
||||
return false;
|
||||
|
||||
char** ppAddr = phostent->h_addr_list;
|
||||
while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
|
||||
{
|
||||
CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
|
||||
if (addr.IsValid())
|
||||
vaddr.push_back(addr);
|
||||
ppAddr++;
|
||||
}
|
||||
|
||||
return (vaddr.size() > 0);
|
||||
}
|
||||
|
||||
// portDefault is in host order
|
||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
|
||||
{
|
||||
vector<CAddress> vaddr;
|
||||
bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
|
||||
if (fRet)
|
||||
addr = vaddr[0];
|
||||
return fRet;
|
||||
}
|
||||
|
||||
bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
|
||||
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
|
||||
{
|
||||
SOCKET hSocket;
|
||||
if (!ConnectSocket(addrConnect, hSocket))
|
||||
|
@ -328,11 +118,11 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
|
|||
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
|
||||
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
|
||||
strLine.resize(strLine.size()-1);
|
||||
CAddress addr(strLine,0,true);
|
||||
CService addr(strLine,0,true);
|
||||
printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
|
||||
if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
|
||||
if (!addr.IsValid() || !addr.IsRoutable())
|
||||
return false;
|
||||
ipRet = addr.ip;
|
||||
ipRet.SetIP(addr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +131,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
|
|||
}
|
||||
|
||||
// We now get our external IP from the IRC server first and only use this as a backup
|
||||
bool GetMyExternalIP(unsigned int& ipRet)
|
||||
bool GetMyExternalIP(CNetAddr& ipRet)
|
||||
{
|
||||
CAddress addrConnect;
|
||||
const char* pszGet;
|
||||
|
@ -363,7 +153,7 @@ bool GetMyExternalIP(unsigned int& ipRet)
|
|||
|
||||
if (nLookup == 1)
|
||||
{
|
||||
CAddress addrIP("checkip.dyndns.org", 80, true);
|
||||
CService addrIP("checkip.dyndns.org", 80, true);
|
||||
if (addrIP.IsValid())
|
||||
addrConnect = addrIP;
|
||||
}
|
||||
|
@ -382,7 +172,7 @@ bool GetMyExternalIP(unsigned int& ipRet)
|
|||
|
||||
if (nLookup == 1)
|
||||
{
|
||||
CAddress addrIP("www.showmyip.com", 80, true);
|
||||
CService addrIP("www.showmyip.com", 80, true);
|
||||
if (addrIP.IsValid())
|
||||
addrConnect = addrIP;
|
||||
}
|
||||
|
@ -417,7 +207,7 @@ void ThreadGetMyExternalIP(void* parg)
|
|||
}
|
||||
|
||||
// Fallback in case IRC fails to get it
|
||||
if (GetMyExternalIP(addrLocalHost.ip))
|
||||
if (GetMyExternalIP(addrLocalHost))
|
||||
{
|
||||
printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
|
||||
if (addrLocalHost.IsRoutable())
|
||||
|
@ -441,7 +231,7 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
|
|||
{
|
||||
if (!addr.IsRoutable())
|
||||
return false;
|
||||
if (addr.ip == addrLocalHost.ip)
|
||||
if ((CService)addr == (CService)addrLocalHost)
|
||||
return false;
|
||||
addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
|
||||
bool fUpdated = false;
|
||||
|
@ -494,7 +284,7 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
|
|||
return fNew;
|
||||
}
|
||||
|
||||
void AddressCurrentlyConnected(const CAddress& addr)
|
||||
void AddressCurrentlyConnected(const CService& addr)
|
||||
{
|
||||
CAddress *paddrFound = NULL;
|
||||
|
||||
|
@ -624,23 +414,23 @@ void CNode::CancelSubscribe(unsigned int nChannel)
|
|||
|
||||
|
||||
|
||||
CNode* FindNode(unsigned int ip)
|
||||
CNode* FindNode(const CNetAddr& ip)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->addr.ip == ip)
|
||||
if ((CNetAddr)pnode->addr == ip)
|
||||
return (pnode);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CNode* FindNode(CAddress addr)
|
||||
CNode* FindNode(const CService& addr)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->addr == addr)
|
||||
if ((CService)pnode->addr == addr)
|
||||
return (pnode);
|
||||
}
|
||||
return NULL;
|
||||
|
@ -648,11 +438,11 @@ CNode* FindNode(CAddress addr)
|
|||
|
||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
|
||||
{
|
||||
if (addrConnect.ip == addrLocalHost.ip)
|
||||
if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost)
|
||||
return NULL;
|
||||
|
||||
// Look for an existing connection
|
||||
CNode* pnode = FindNode(addrConnect.ip);
|
||||
CNode* pnode = FindNode((CService)addrConnect);
|
||||
if (pnode)
|
||||
{
|
||||
if (nTimeout != 0)
|
||||
|
@ -746,7 +536,7 @@ void CNode::PushVersion()
|
|||
|
||||
|
||||
|
||||
std::map<unsigned int, int64> CNode::setBanned;
|
||||
std::map<CNetAddr, int64> CNode::setBanned;
|
||||
CCriticalSection CNode::cs_setBanned;
|
||||
|
||||
void CNode::ClearBanned()
|
||||
|
@ -754,12 +544,12 @@ void CNode::ClearBanned()
|
|||
setBanned.clear();
|
||||
}
|
||||
|
||||
bool CNode::IsBanned(unsigned int ip)
|
||||
bool CNode::IsBanned(CNetAddr ip)
|
||||
{
|
||||
bool fResult = false;
|
||||
CRITICAL_BLOCK(cs_setBanned)
|
||||
{
|
||||
std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
|
||||
std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
|
||||
if (i != setBanned.end())
|
||||
{
|
||||
int64 t = (*i).second;
|
||||
|
@ -783,8 +573,8 @@ bool CNode::Misbehaving(int howmuch)
|
|||
{
|
||||
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
|
||||
CRITICAL_BLOCK(cs_setBanned)
|
||||
if (setBanned[addr.ip] < banTime)
|
||||
setBanned[addr.ip] = banTime;
|
||||
if (setBanned[addr] < banTime)
|
||||
setBanned[addr] = banTime;
|
||||
CloseSocketDisconnect();
|
||||
printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
|
||||
return true;
|
||||
|
@ -962,7 +752,7 @@ void ThreadSocketHandler2(void* parg)
|
|||
{
|
||||
closesocket(hSocket);
|
||||
}
|
||||
else if (CNode::IsBanned(addr.ip))
|
||||
else if (CNode::IsBanned(addr))
|
||||
{
|
||||
printf("connetion from %s dropped (banned)\n", addr.ToString().c_str());
|
||||
closesocket(hSocket);
|
||||
|
@ -1277,15 +1067,16 @@ void ThreadDNSAddressSeed2(void* parg)
|
|||
printf("Loading addresses from DNS seeds (could take a while)\n");
|
||||
|
||||
for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
|
||||
vector<CAddress> vaddr;
|
||||
if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
|
||||
vector<CNetAddr> vaddr;
|
||||
if (LookupHost(strDNSSeed[seed_idx], vaddr))
|
||||
{
|
||||
CAddrDB addrDB;
|
||||
addrDB.TxnBegin();
|
||||
BOOST_FOREACH (CAddress& addr, vaddr)
|
||||
BOOST_FOREACH (CNetAddr& ip, vaddr)
|
||||
{
|
||||
if (addr.GetByte(3) != 127)
|
||||
if (ip.IsRoutable())
|
||||
{
|
||||
CAddress addr(CService(ip, GetDefaultPort()), NODE_NETWORK);
|
||||
addr.nTime = 0;
|
||||
AddAddress(addr, 0, &addrDB);
|
||||
found++;
|
||||
|
@ -1470,8 +1261,8 @@ void ThreadOpenConnections2(void* parg)
|
|||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
{
|
||||
// Add seed nodes if IRC isn't working
|
||||
bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
|
||||
if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
|
||||
bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
|
||||
if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
|
||||
fAddSeeds = true;
|
||||
}
|
||||
|
||||
|
@ -1484,8 +1275,9 @@ void ThreadOpenConnections2(void* parg)
|
|||
// Seed nodes are given a random 'last seen time' of between one and two
|
||||
// weeks ago.
|
||||
const int64 nOneWeek = 7*24*60*60;
|
||||
CAddress addr;
|
||||
addr.ip = pnSeed[i];
|
||||
struct in_addr ip;
|
||||
memcpy(&ip, &pnSeed[i], sizeof(ip));
|
||||
CAddress addr(CService(ip, GetDefaultPort()));
|
||||
addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
|
||||
AddAddress(addr);
|
||||
}
|
||||
|
@ -1499,10 +1291,10 @@ void ThreadOpenConnections2(void* parg)
|
|||
|
||||
// Only connect to one address per a.b.?.? range.
|
||||
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
||||
set<unsigned int> setConnected;
|
||||
set<vector<unsigned char> > setConnected;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
setConnected.insert(pnode->addr.ip & 0x0000ffff);
|
||||
setConnected.insert(pnode->addr.GetGroup());
|
||||
|
||||
int64 nANow = GetAdjustedTime();
|
||||
|
||||
|
@ -1511,14 +1303,14 @@ void ThreadOpenConnections2(void* parg)
|
|||
BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
|
||||
{
|
||||
const CAddress& addr = item.second;
|
||||
if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
|
||||
if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()))
|
||||
continue;
|
||||
int64 nSinceLastSeen = nANow - addr.nTime;
|
||||
int64 nSinceLastTry = nANow - addr.nLastTry;
|
||||
|
||||
// Randomize the order in a deterministic way, putting the standard port first
|
||||
int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
|
||||
if (addr.port != htons(GetDefaultPort()))
|
||||
int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.GetHash()) % (2 * 60 * 60);
|
||||
if (addr.GetPort() != GetDefaultPort())
|
||||
nRandomizer += 2 * 60 * 60;
|
||||
|
||||
// Last seen Base retry frequency
|
||||
|
@ -1573,8 +1365,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
|
|||
//
|
||||
if (fShutdown)
|
||||
return false;
|
||||
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
|
||||
FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
|
||||
if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
|
||||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
|
||||
return false;
|
||||
|
||||
vnThreadsRunning[1]--;
|
||||
|
@ -1676,7 +1468,7 @@ bool BindListenPort(string& strError)
|
|||
{
|
||||
strError = "";
|
||||
int nOne = 1;
|
||||
addrLocalHost.port = htons(GetListenPort());
|
||||
addrLocalHost.SetPort(GetListenPort());
|
||||
|
||||
#ifdef WIN32
|
||||
// Initialize Windows Sockets
|
||||
|
@ -1755,19 +1547,19 @@ bool BindListenPort(string& strError)
|
|||
void StartNode(void* parg)
|
||||
{
|
||||
if (pnodeLocalHost == NULL)
|
||||
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
|
||||
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
|
||||
|
||||
#ifdef WIN32
|
||||
// Get local host ip
|
||||
char pszHostName[1000] = "";
|
||||
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
|
||||
{
|
||||
vector<CAddress> vaddr;
|
||||
if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
|
||||
BOOST_FOREACH (const CAddress &addr, vaddr)
|
||||
if (addr.GetByte(3) != 127)
|
||||
vector<CNetAddr> vaddr;
|
||||
if (LookupHost(pszHostName, vaddr))
|
||||
BOOST_FOREACH (const CNetAddr &addr, vaddr)
|
||||
if (!addr.IsLocal())
|
||||
{
|
||||
addrLocalHost = addr;
|
||||
addrLocalHost.SetIP(addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1790,8 +1582,8 @@ void StartNode(void* parg)
|
|||
printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
|
||||
|
||||
// Take the first IP that isn't loopback 127.x.x.x
|
||||
CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
|
||||
if (addr.IsValid() && addr.GetByte(3) != 127)
|
||||
CAddress addr(CService(s4->sin_addr, GetListenPort()), nLocalServices);
|
||||
if (addr.IsValid() && !addr.IsLocal())
|
||||
{
|
||||
addrLocalHost = addr;
|
||||
break;
|
||||
|
@ -1812,7 +1604,7 @@ void StartNode(void* parg)
|
|||
if (fUseProxy || mapArgs.count("-connect") || fNoListen)
|
||||
{
|
||||
// Proxies can't take incoming connections
|
||||
addrLocalHost.ip = CAddress("0.0.0.0").ip;
|
||||
addrLocalHost.SetIP(CNetAddr("0.0.0.0"));
|
||||
printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
|
||||
}
|
||||
else
|
||||
|
|
20
src/net.h
20
src/net.h
|
@ -14,6 +14,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
|
||||
class CAddrDB;
|
||||
|
@ -21,7 +22,6 @@ class CRequestTracker;
|
|||
class CNode;
|
||||
class CBlockIndex;
|
||||
extern int nBestHeight;
|
||||
extern int nConnectTimeout;
|
||||
|
||||
|
||||
|
||||
|
@ -29,13 +29,11 @@ inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer"
|
|||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
|
||||
static const unsigned int PUBLISH_HOPS = 5;
|
||||
|
||||
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
|
||||
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool GetMyExternalIP(unsigned int& ipRet);
|
||||
bool GetMyExternalIP(CNetAddr& ipRet);
|
||||
bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
|
||||
void AddressCurrentlyConnected(const CAddress& addr);
|
||||
CNode* FindNode(unsigned int ip);
|
||||
void AddressCurrentlyConnected(const CService& addr);
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
CNode* FindNode(const CService& ip);
|
||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
||||
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
|
||||
bool AnySubscribed(unsigned int nChannel);
|
||||
|
@ -88,9 +86,6 @@ extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
|
|||
extern CCriticalSection cs_mapRelay;
|
||||
extern std::map<CInv, int64> mapAlreadyAskedFor;
|
||||
|
||||
// Settings
|
||||
extern int fUseProxy;
|
||||
extern CAddress addrProxy;
|
||||
|
||||
|
||||
|
||||
|
@ -126,7 +121,7 @@ protected:
|
|||
|
||||
// Denial-of-service detection/prevention
|
||||
// Key is ip address, value is banned-until-time
|
||||
static std::map<unsigned int, int64> setBanned;
|
||||
static std::map<CNetAddr, int64> setBanned;
|
||||
static CCriticalSection cs_setBanned;
|
||||
int nMisbehavior;
|
||||
|
||||
|
@ -355,7 +350,6 @@ public:
|
|||
|
||||
|
||||
|
||||
|
||||
void PushVersion();
|
||||
|
||||
|
||||
|
@ -581,7 +575,7 @@ public:
|
|||
// between nodes running old code and nodes running
|
||||
// new code.
|
||||
static void ClearBanned(); // needed for unit testing
|
||||
static bool IsBanned(unsigned int ip);
|
||||
static bool IsBanned(CNetAddr ip);
|
||||
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
|
||||
};
|
||||
|
||||
|
|
715
src/netbase.cpp
Normal file
715
src/netbase.cpp
Normal file
|
@ -0,0 +1,715 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 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.
|
||||
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "strlcpy.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Settings
|
||||
int fUseProxy = false;
|
||||
CService addrProxy("127.0.0.1",9050);
|
||||
int nConnectTimeout = 5000;
|
||||
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
vIP.clear();
|
||||
struct addrinfo aiHint = {};
|
||||
aiHint.ai_socktype = SOCK_STREAM;
|
||||
aiHint.ai_protocol = IPPROTO_TCP;
|
||||
#ifdef WIN32
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# endif
|
||||
#else
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# endif
|
||||
#endif
|
||||
struct addrinfo *aiRes = NULL;
|
||||
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
|
||||
if (nErr)
|
||||
return false;
|
||||
|
||||
struct addrinfo *aiTrav = aiRes;
|
||||
while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
|
||||
{
|
||||
if (aiTrav->ai_family == AF_INET)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
|
||||
vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if (aiTrav->ai_family == AF_INET6)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
|
||||
vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
aiTrav = aiTrav->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(aiRes);
|
||||
|
||||
return (vIP.size() > 0);
|
||||
}
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
psz[strlen(psz)-1] = 0;
|
||||
}
|
||||
|
||||
return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
}
|
||||
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions)
|
||||
{
|
||||
return LookupHost(pszName, vIP, nMaxSolutions, false);
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
int port = portDefault;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
char* pszColon = strrchr(psz+1,':');
|
||||
char *pszPortEnd = NULL;
|
||||
int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
|
||||
if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
|
||||
{
|
||||
if (psz[0] == '[' && pszColon[-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
pszColon[-1] = 0;
|
||||
}
|
||||
else
|
||||
pszColon[0] = 0;
|
||||
if (port >= 0 && port <= USHRT_MAX)
|
||||
port = portParsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
psz[strlen(psz)-1] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<CNetAddr> vIP;
|
||||
bool fRet = LookupIntern(pszHost, vIP, 1, fAllowLookup);
|
||||
if (!fRet)
|
||||
return false;
|
||||
addr = CService(vIP[0], port);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
||||
{
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
hSocketRet = INVALID_SOCKET;
|
||||
|
||||
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return false;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int set = 1;
|
||||
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
|
||||
#endif
|
||||
|
||||
bool fProxy = (fUseProxy && addrDest.IsRoutable());
|
||||
struct sockaddr_in sockaddr;
|
||||
if (fProxy)
|
||||
addrProxy.GetSockAddr(&sockaddr);
|
||||
else
|
||||
addrDest.GetSockAddr(&sockaddr);
|
||||
|
||||
#ifdef WIN32
|
||||
u_long fNonblock = 1;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
#else
|
||||
int fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
{
|
||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = nTimeout / 1000;
|
||||
timeout.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(hSocket, &fdset);
|
||||
int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
|
||||
if (nRet == 0)
|
||||
{
|
||||
printf("connection timeout\n");
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
printf("select() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
socklen_t nRetSize = sizeof(nRet);
|
||||
#ifdef WIN32
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
|
||||
#else
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet != 0)
|
||||
{
|
||||
printf("connect() failed after select(): %s\n",strerror(nRet));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
else if (WSAGetLastError() != WSAEISCONN)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
printf("connect() failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// this isn't even strictly necessary
|
||||
// CNode::ConnectNode immediately turns the socket back to non-blocking
|
||||
// but we'll turn it back to blocking just in case
|
||||
#ifdef WIN32
|
||||
fNonblock = 0;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
#else
|
||||
fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fProxy)
|
||||
{
|
||||
printf("proxy connecting %s\n", addrDest.ToString().c_str());
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
addrDest.GetSockAddr(&addr);
|
||||
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
return false;
|
||||
}
|
||||
printf("proxy connected %s\n", addrDest.ToString().c_str());
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetAddr::Init()
|
||||
{
|
||||
memset(ip, 0, 16);
|
||||
}
|
||||
|
||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
{
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, &ipv4Addr, 4);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
|
||||
{
|
||||
memcpy(ip, &ipv6Addr, 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(pszIp, vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
int CNetAddr::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3849() const
|
||||
{
|
||||
return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3964() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6052() const
|
||||
{
|
||||
static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4380() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4862() const
|
||||
{
|
||||
static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4193() const
|
||||
{
|
||||
return ((GetByte(15) & 0xFE) == 0xFC);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6145() const
|
||||
{
|
||||
static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
|
||||
return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4843() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && GetByte(12) & 0xF0 == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsLocal() const
|
||||
{
|
||||
// IPv4 loopback
|
||||
if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
|
||||
return true;
|
||||
|
||||
// IPv6 loopback (::1/128)
|
||||
static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
|
||||
if (memcmp(ip, pchLocal, 16) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsMulticast() const
|
||||
{
|
||||
return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
|
||||
|| (GetByte(15) == 0xFF);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsValid() const
|
||||
{
|
||||
// Clean up 3-byte shifted addresses caused by garbage in size field
|
||||
// of addr messages from versions before 0.2.9 checksum.
|
||||
// Two consecutive addr messages look like this:
|
||||
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
// unspecified IPv6 address (::/128)
|
||||
unsigned char ipNone[16] = {};
|
||||
if (memcmp(ip, ipNone, 16) == 0)
|
||||
return false;
|
||||
|
||||
// documentation IPv6 address
|
||||
if (IsRFC3849())
|
||||
return false;
|
||||
|
||||
if (IsIPv4())
|
||||
{
|
||||
// INADDR_NONE
|
||||
uint32_t ipNone = INADDR_NONE;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
|
||||
// 0
|
||||
ipNone = 0;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || IsRFC4193() || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsIPv4())
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
else
|
||||
return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
|
||||
GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
|
||||
GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
|
||||
GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToString() const
|
||||
{
|
||||
return ToStringIP();
|
||||
}
|
||||
|
||||
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) != 0);
|
||||
}
|
||||
|
||||
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) < 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memcpy(pipv4Addr, ip+12, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
{
|
||||
memcpy(pipv6Addr, ip, 16);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// get canonical identifier of an address' group
|
||||
// no two connections will be attempted to addresses with the same group
|
||||
std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
{
|
||||
std::vector<unsigned char> vchRet;
|
||||
int nClass = 0; // 0=IPv6, 1=IPv4, 255=unroutable
|
||||
int nStartByte = 0;
|
||||
int nBits = 16;
|
||||
|
||||
// for unroutable addresses, each address is considered different
|
||||
if (!IsRoutable())
|
||||
{
|
||||
nClass = 255;
|
||||
nBits = 128;
|
||||
}
|
||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
|
||||
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
|
||||
else if (IsIPv4() || IsRFC6145() || IsRFC6052())
|
||||
{
|
||||
nClass = 1;
|
||||
nStartByte = 12;
|
||||
}
|
||||
// for 6to4 tunneled addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC3964())
|
||||
{
|
||||
nClass = 1;
|
||||
nStartByte = 2;
|
||||
}
|
||||
// for Teredo-tunneled IPv6 addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC4380())
|
||||
{
|
||||
vchRet.push_back(1);
|
||||
vchRet.push_back(GetByte(3) ^ 0xFF);
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
// for the rest of the IPv6 network, use /32 groups
|
||||
else
|
||||
nBits = 32;
|
||||
|
||||
vchRet.push_back(nClass);
|
||||
while (nBits >= 8)
|
||||
{
|
||||
vchRet.push_back(GetByte(15 - nStartByte));
|
||||
nStartByte++;
|
||||
nBits -= 8;
|
||||
}
|
||||
if (nBits > 0)
|
||||
vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1));
|
||||
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
int64 CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
int64 nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
|
||||
void CNetAddr::print() const
|
||||
{
|
||||
printf("CNetAddr(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
{
|
||||
port = 0;
|
||||
}
|
||||
|
||||
CService::CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
|
||||
{
|
||||
assert(addr.sin_family == AF_INET);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
|
||||
{
|
||||
assert(addr.sin6_family == AF_INET6);
|
||||
}
|
||||
#endif
|
||||
|
||||
CService::CService(const char *pszIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(pszIpPort, ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const char *pszIp, int portIn, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CNetAddr> ip;
|
||||
if (LookupHost(pszIp, ip, 1, fAllowLookup))
|
||||
*this = CService(ip[0], portIn);
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIp, int portIn, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CNetAddr> ip;
|
||||
if (LookupHost(strIp.c_str(), ip, 1, fAllowLookup))
|
||||
*this = CService(ip[0], portIn);
|
||||
}
|
||||
|
||||
unsigned short CService::GetPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
bool operator==(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
|
||||
}
|
||||
|
||||
bool operator!=(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
|
||||
}
|
||||
|
||||
bool operator<(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
|
||||
}
|
||||
|
||||
bool CService::GetSockAddr(struct sockaddr_in* paddr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memset(paddr, 0, sizeof(struct sockaddr_in));
|
||||
if (!GetInAddr(&paddr->sin_addr))
|
||||
return false;
|
||||
paddr->sin_family = AF_INET;
|
||||
paddr->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
bool CService::GetSockAddr6(struct sockaddr_in6* paddr) const
|
||||
{
|
||||
memset(paddr, 0, sizeof(struct sockaddr_in6));
|
||||
if (!GetIn6Addr(&paddr->sin6_addr))
|
||||
return false;
|
||||
paddr->sin6_family = AF_INET6;
|
||||
paddr->sin6_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<unsigned char> CService::GetKey() const
|
||||
{
|
||||
std::vector<unsigned char> vKey;
|
||||
vKey.resize(18);
|
||||
memcpy(&vKey[0], ip, 16);
|
||||
vKey[16] = port / 0x100;
|
||||
vKey[17] = port & 0x0FF;
|
||||
return vKey;
|
||||
}
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf(":%i", port);
|
||||
}
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
return ToStringIP() + ToStringPort();
|
||||
}
|
||||
|
||||
std::string CService::ToString() const
|
||||
{
|
||||
return ToStringIPPort();
|
||||
}
|
||||
|
||||
void CService::print() const
|
||||
{
|
||||
printf("CService(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CService::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
138
src/netbase.h
Normal file
138
src/netbase.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) 2011 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.
|
||||
#ifndef BITCOIN_NETBASE_H
|
||||
#define BITCOIN_NETBASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef BSD
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "serialize.h"
|
||||
#include "compat.h"
|
||||
|
||||
extern int nConnectTimeout;
|
||||
|
||||
|
||||
// IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
|
||||
class CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned char ip[16]; // in network byte order
|
||||
|
||||
public:
|
||||
CNetAddr();
|
||||
CNetAddr(const struct in_addr& ipv4Addr);
|
||||
CNetAddr(const char *pszIp, bool fAllowLookup = false);
|
||||
CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||
bool IsRFC3964() const; // IPv6 6to4 tunneling (2002::/16)
|
||||
bool IsRFC4193() const; // IPv6 unique local (FC00::/15)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunneling (2001::/32)
|
||||
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
|
||||
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
|
||||
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
||||
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
bool IsMulticast() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
int GetByte(int n) const;
|
||||
int64 GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
void print() const;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CNetAddr(const struct in6_addr& pipv6Addr);
|
||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||
#endif
|
||||
|
||||
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(FLATDATA(ip));
|
||||
)
|
||||
};
|
||||
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
|
||||
public:
|
||||
CService();
|
||||
CService(const CNetAddr& ip, unsigned short port);
|
||||
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in& addr);
|
||||
CService(const char *pszIp, int port, bool fAllowLookup = false);
|
||||
CService(const char *pszIpPort, bool fAllowLookup = false);
|
||||
CService(const std::string& strIp, int port, bool fAllowLookup = false);
|
||||
CService(const std::string& strIpPort, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetPort(unsigned short portIn);
|
||||
unsigned short GetPort() const;
|
||||
bool GetSockAddr(struct sockaddr_in* paddr) const;
|
||||
friend bool operator==(const CService& a, const CService& b);
|
||||
friend bool operator!=(const CService& a, const CService& b);
|
||||
friend bool operator<(const CService& a, const CService& b);
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToStringIPPort() const;
|
||||
void print() const;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
bool GetSockAddr6(struct sockaddr_in6* paddr) const;
|
||||
CService(const struct sockaddr_in6& addr);
|
||||
#endif
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CService* pthis = const_cast<CService*>(this);
|
||||
READWRITE(FLATDATA(ip));
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(portN);
|
||||
if (fRead)
|
||||
pthis->port = ntohs(portN);
|
||||
)
|
||||
};
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
|
||||
|
||||
// Settings
|
||||
extern int fUseProxy;
|
||||
extern CService addrProxy;
|
||||
|
||||
#endif
|
174
src/protocol.cpp
174
src/protocol.cpp
|
@ -5,16 +5,12 @@
|
|||
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "netbase.h"
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
// Prototypes from net.h, but that header (currently) stinks, can't #include it without breaking things
|
||||
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
static const char* ppszTypeName[] =
|
||||
{
|
||||
"ERROR",
|
||||
|
@ -77,185 +73,26 @@ bool CMessageHeader::IsValid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
CAddress::CAddress()
|
||||
|
||||
|
||||
CAddress::CAddress() : CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddress::CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn)
|
||||
CAddress::CAddress(CService ipIn, uint64 nServicesIn) : CService(ipIn)
|
||||
{
|
||||
Init();
|
||||
ip = ipIn;
|
||||
port = htons(portIn == 0 ? GetDefaultPort() : portIn);
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
CAddress::CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
ip = sockaddr.sin_addr.s_addr;
|
||||
port = sockaddr.sin_port;
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
CAddress::CAddress(const char* pszIn, int portIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(pszIn, *this, nServicesIn, fNameLookup, portIn);
|
||||
}
|
||||
|
||||
CAddress::CAddress(const char* pszIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(pszIn, *this, nServicesIn, fNameLookup, 0, true);
|
||||
}
|
||||
|
||||
CAddress::CAddress(std::string strIn, int portIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, portIn);
|
||||
}
|
||||
|
||||
CAddress::CAddress(std::string strIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, 0, true);
|
||||
}
|
||||
|
||||
void CAddress::Init()
|
||||
{
|
||||
nServices = NODE_NETWORK;
|
||||
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
|
||||
ip = INADDR_NONE;
|
||||
port = htons(GetDefaultPort());
|
||||
nTime = 100000000;
|
||||
nLastTry = 0;
|
||||
}
|
||||
|
||||
bool operator==(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
|
||||
a.ip == b.ip &&
|
||||
a.port == b.port);
|
||||
}
|
||||
|
||||
bool operator!=(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
bool operator<(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
|
||||
if (ret < 0)
|
||||
return true;
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (ntohl(a.ip) < ntohl(b.ip))
|
||||
return true;
|
||||
else if (a.ip == b.ip)
|
||||
return ntohs(a.port) < ntohs(b.port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CAddress::GetKey() const
|
||||
{
|
||||
CDataStream ss;
|
||||
ss.reserve(18);
|
||||
ss << FLATDATA(pchReserved) << ip << port;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
return std::vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
|
||||
#else
|
||||
return std::vector<unsigned char>(ss.begin(), ss.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr_in CAddress::GetSockAddr() const
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_addr.s_addr = ip;
|
||||
sockaddr.sin_port = port;
|
||||
return sockaddr;
|
||||
}
|
||||
|
||||
bool CAddress::IsIPv4() const
|
||||
{
|
||||
return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CAddress::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 &&
|
||||
(GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CAddress::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CAddress::IsLocal() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 127 ||
|
||||
GetByte(3) == 0);
|
||||
}
|
||||
|
||||
bool CAddress::IsRoutable() const
|
||||
{
|
||||
return IsValid() &&
|
||||
!(IsRFC1918() || IsRFC3927() || IsLocal());
|
||||
}
|
||||
|
||||
bool CAddress::IsValid() const
|
||||
{
|
||||
// Clean up 3-byte shifted addresses caused by garbage in size field
|
||||
// of addr messages from versions before 0.2.9 checksum.
|
||||
// Two consecutive addr messages look like this:
|
||||
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
return (ip != 0 && ip != INADDR_NONE && port != htons(std::numeric_limits<unsigned short>::max()));
|
||||
}
|
||||
|
||||
unsigned char CAddress::GetByte(int n) const
|
||||
{
|
||||
return ((unsigned char*)&ip)[3-n];
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringIPPort() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringIP() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringPort() const
|
||||
{
|
||||
return strprintf("%u", ntohs(port));
|
||||
}
|
||||
|
||||
std::string CAddress::ToString() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
|
||||
}
|
||||
|
||||
void CAddress::print() const
|
||||
{
|
||||
printf("CAddress(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
CInv::CInv()
|
||||
{
|
||||
type = 0;
|
||||
|
@ -310,3 +147,4 @@ void CInv::print() const
|
|||
{
|
||||
printf("CInv(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#define __INCLUDED_PROTOCOL_H__
|
||||
|
||||
#include "serialize.h"
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
#include <string>
|
||||
#include "uint256.h"
|
||||
|
||||
|
@ -61,58 +63,33 @@ enum
|
|||
NODE_NETWORK = (1 << 0),
|
||||
};
|
||||
|
||||
class CAddress
|
||||
class CAddress : public CService
|
||||
{
|
||||
public:
|
||||
CAddress();
|
||||
CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const char* pszIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const char* pszIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(std::string strIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(std::string strIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
CAddress(CService ipIn, uint64 nServicesIn=NODE_NETWORK);
|
||||
|
||||
void Init();
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CAddress* pthis = const_cast<CAddress*>(this);
|
||||
CService* pip = (CService*)pthis;
|
||||
if (fRead)
|
||||
const_cast<CAddress*>(this)->Init();
|
||||
pthis->Init();
|
||||
if (nType & SER_DISK)
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
READWRITE(nServices);
|
||||
READWRITE(FLATDATA(pchReserved)); // for IPv6
|
||||
READWRITE(ip);
|
||||
READWRITE(port);
|
||||
READWRITE(*pip);
|
||||
)
|
||||
|
||||
friend bool operator==(const CAddress& a, const CAddress& b);
|
||||
friend bool operator!=(const CAddress& a, const CAddress& b);
|
||||
friend bool operator<(const CAddress& a, const CAddress& b);
|
||||
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
struct sockaddr_in GetSockAddr() const;
|
||||
bool IsIPv4() const;
|
||||
bool IsRFC1918() const;
|
||||
bool IsRFC3927() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
unsigned char GetByte(int n) const;
|
||||
std::string ToStringIPPort() const;
|
||||
std::string ToStringIP() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
uint64 nServices;
|
||||
unsigned char pchReserved[12];
|
||||
unsigned int ip;
|
||||
unsigned short port;
|
||||
|
||||
// disk and network only
|
||||
unsigned int nTime;
|
||||
|
|
|
@ -88,9 +88,9 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
|
|||
{
|
||||
// Use CAddress to parse and check IP
|
||||
CAddress addr(value.toString().toStdString() + ":1");
|
||||
if (addr.ip != INADDR_NONE)
|
||||
if (addr.IsValid())
|
||||
{
|
||||
addrProxy.ip = addr.ip;
|
||||
addrProxy.SetIP(addr);
|
||||
walletdb.WriteSetting("addrProxy", addrProxy);
|
||||
}
|
||||
else
|
||||
|
@ -104,7 +104,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
|
|||
int nPort = atoi(value.toString().toAscii().data());
|
||||
if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max())
|
||||
{
|
||||
addrProxy.port = htons(nPort);
|
||||
addrProxy.SetPort(nPort);
|
||||
walletdb.WriteSetting("addrProxy", addrProxy);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -10,40 +10,47 @@
|
|||
#include "net.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace std;
|
||||
#include <stdint.h>
|
||||
|
||||
CService ip(uint32_t i)
|
||||
{
|
||||
struct in_addr s;
|
||||
s.s_addr = i;
|
||||
return CService(CNetAddr(s), GetDefaultPort());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(DoS_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DoS_banning)
|
||||
{
|
||||
CNode::ClearBanned();
|
||||
CAddress addr1(0xa0b0c001);
|
||||
CAddress addr1(ip(0xa0b0c001));
|
||||
CNode dummyNode1(INVALID_SOCKET, addr1, true);
|
||||
dummyNode1.Misbehaving(100); // Should get banned
|
||||
BOOST_CHECK(CNode::IsBanned(addr1.ip));
|
||||
BOOST_CHECK(!CNode::IsBanned(addr1.ip|0x0000ff00)); // Different ip, not banned
|
||||
BOOST_CHECK(CNode::IsBanned(addr1));
|
||||
BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different ip, not banned
|
||||
|
||||
CAddress addr2(0xa0b0c002);
|
||||
CAddress addr2(ip(0xa0b0c002));
|
||||
CNode dummyNode2(INVALID_SOCKET, addr2, true);
|
||||
dummyNode2.Misbehaving(50);
|
||||
BOOST_CHECK(!CNode::IsBanned(addr2.ip)); // 2 not banned yet...
|
||||
BOOST_CHECK(CNode::IsBanned(addr1.ip)); // ... but 1 still should be
|
||||
BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet...
|
||||
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be
|
||||
dummyNode2.Misbehaving(50);
|
||||
BOOST_CHECK(CNode::IsBanned(addr2.ip));
|
||||
BOOST_CHECK(CNode::IsBanned(addr2));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DoS_banscore)
|
||||
{
|
||||
CNode::ClearBanned();
|
||||
mapArgs["-banscore"] = "111"; // because 11 is my favorite number
|
||||
CAddress addr1(0xa0b0c001);
|
||||
CAddress addr1(ip(0xa0b0c001));
|
||||
CNode dummyNode1(INVALID_SOCKET, addr1, true);
|
||||
dummyNode1.Misbehaving(100);
|
||||
BOOST_CHECK(!CNode::IsBanned(addr1.ip));
|
||||
BOOST_CHECK(!CNode::IsBanned(addr1));
|
||||
dummyNode1.Misbehaving(10);
|
||||
BOOST_CHECK(!CNode::IsBanned(addr1.ip));
|
||||
BOOST_CHECK(!CNode::IsBanned(addr1));
|
||||
dummyNode1.Misbehaving(1);
|
||||
BOOST_CHECK(CNode::IsBanned(addr1.ip));
|
||||
BOOST_CHECK(CNode::IsBanned(addr1));
|
||||
mapArgs["-banscore"] = "100";
|
||||
}
|
||||
|
||||
|
@ -53,20 +60,20 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
|
|||
int64 nStartTime = GetTime();
|
||||
SetMockTime(nStartTime); // Overrides future calls to GetTime()
|
||||
|
||||
CAddress addr(0xa0b0c001);
|
||||
CAddress addr(ip(0xa0b0c001));
|
||||
CNode dummyNode(INVALID_SOCKET, addr, true);
|
||||
|
||||
dummyNode.Misbehaving(100);
|
||||
BOOST_CHECK(CNode::IsBanned(addr.ip));
|
||||
BOOST_CHECK(CNode::IsBanned(addr));
|
||||
|
||||
SetMockTime(nStartTime+60*60);
|
||||
BOOST_CHECK(CNode::IsBanned(addr.ip));
|
||||
BOOST_CHECK(CNode::IsBanned(addr));
|
||||
|
||||
SetMockTime(nStartTime+60*60*24+1);
|
||||
BOOST_CHECK(!CNode::IsBanned(addr.ip));
|
||||
BOOST_CHECK(!CNode::IsBanned(addr));
|
||||
}
|
||||
|
||||
static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)
|
||||
static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)\
|
||||
{
|
||||
if (time1 > time2)
|
||||
return CheckNBits(nbits2, time2, nbits1, time1);
|
||||
|
|
|
@ -623,7 +623,7 @@ inline const uint256 operator-(const uint256& a, const uint256& b) { return
|
|||
|
||||
|
||||
|
||||
|
||||
#ifdef TEST_UINT256
|
||||
|
||||
inline int Testuint256AdHoc(std::vector<std::string> vArg)
|
||||
{
|
||||
|
@ -756,3 +756,5 @@ inline int Testuint256AdHoc(std::vector<std::string> vArg)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -948,12 +948,12 @@ int64 GetAdjustedTime()
|
|||
return GetTime() + nTimeOffset;
|
||||
}
|
||||
|
||||
void AddTimeData(unsigned int ip, int64 nTime)
|
||||
void AddTimeData(const CNetAddr& ip, int64 nTime)
|
||||
{
|
||||
int64 nOffsetSample = nTime - GetTime();
|
||||
|
||||
// Ignore duplicates
|
||||
static set<unsigned int> setKnown;
|
||||
static set<CNetAddr> setKnown;
|
||||
if (!setKnown.insert(ip).second)
|
||||
return;
|
||||
|
||||
|
@ -1008,7 +1008,6 @@ void AddTimeData(unsigned int ip, int64 nTime)
|
|||
|
||||
|
||||
|
||||
|
||||
string FormatVersion(int nVersion)
|
||||
{
|
||||
if (nVersion%100 == 0)
|
||||
|
@ -1178,3 +1177,4 @@ bool CCriticalSection::TryEnter(const char*, const char*, int)
|
|||
}
|
||||
|
||||
#endif /* DEBUG_LOCKORDER */
|
||||
|
||||
|
|
30
src/util.h
30
src/util.h
|
@ -24,6 +24,7 @@
|
|||
#include <openssl/sha.h>
|
||||
#include <openssl/ripemd.h>
|
||||
|
||||
#include "netbase.h"
|
||||
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
|
@ -79,20 +80,7 @@ T* alignup(T* p)
|
|||
#define S_IWUSR 0200
|
||||
#endif
|
||||
#define unlink _unlink
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#define WSAGetLastError() errno
|
||||
#define WSAEINVAL EINVAL
|
||||
#define WSAEALREADY EALREADY
|
||||
#define WSAEWOULDBLOCK EWOULDBLOCK
|
||||
#define WSAEMSGSIZE EMSGSIZE
|
||||
#define WSAEINTR EINTR
|
||||
#define WSAEINPROGRESS EINPROGRESS
|
||||
#define WSAEADDRINUSE EADDRINUSE
|
||||
#define WSAENOTSOCK EBADF
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR -1
|
||||
typedef u_int SOCKET;
|
||||
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
|
||||
#define strlwr(psz) to_lower(psz)
|
||||
#define _strlwr(psz) to_lower(psz)
|
||||
|
@ -104,19 +92,6 @@ inline void Sleep(int64 n)
|
|||
}
|
||||
#endif
|
||||
|
||||
inline int myclosesocket(SOCKET& hSocket)
|
||||
{
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return WSAENOTSOCK;
|
||||
#ifdef WIN32
|
||||
int ret = closesocket(hSocket);
|
||||
#else
|
||||
int ret = close(hSocket);
|
||||
#endif
|
||||
hSocket = INVALID_SOCKET;
|
||||
return ret;
|
||||
}
|
||||
#define closesocket(s) myclosesocket(s)
|
||||
#if !defined(QT_GUI)
|
||||
inline const char* _(const char* psz)
|
||||
{
|
||||
|
@ -187,9 +162,9 @@ uint64 GetRand(uint64 nMax);
|
|||
int64 GetTime();
|
||||
void SetMockTime(int64 nMockTimeIn);
|
||||
int64 GetAdjustedTime();
|
||||
void AddTimeData(unsigned int ip, int64 nTime);
|
||||
std::string FormatFullVersion();
|
||||
std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
|
||||
void AddTimeData(const CNetAddr& ip, int64 nTime);
|
||||
|
||||
|
||||
|
||||
|
@ -745,3 +720,4 @@ inline uint32_t ByteReverse(uint32_t value)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue