netbase and protocol from satoshi bitcoin
This commit is contained in:
parent
e93ffbf4df
commit
aeec0156a2
8 changed files with 3367 additions and 31 deletions
123
dns.c
123
dns.c
|
@ -6,9 +6,18 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define BUFLEN 512
|
||||
|
||||
int port = 53;
|
||||
int datattl = 60;
|
||||
int nsttl = 30583;
|
||||
char *host = "seedtest.bitcoin.sipa.be";
|
||||
char *ns = "vps.sipa.be";
|
||||
char *mbox = "sipa.ulyssis.org";
|
||||
|
||||
typedef enum {
|
||||
CLASS_IN = 1,
|
||||
QCLASS_ANY = 255
|
||||
|
@ -25,15 +34,11 @@ typedef enum {
|
|||
QTYPE_ANY = 255
|
||||
} dns_type;
|
||||
|
||||
int port = 53;
|
||||
int datattl = 60;
|
||||
char *host = "seedtest.bitcoin.sipa.be";
|
||||
char *ns = "vps.sipa.be";
|
||||
|
||||
// 0: ok
|
||||
// -1: premature end of input, forward reference, component > 63 char
|
||||
// -1: premature end of input, forward reference, component > 63 char, invalid character
|
||||
// -2: insufficient space in output
|
||||
int parse_name(const unsigned char **inpos, const unsigned char *inend, const unsigned char *inbuf, char *buf, size_t bufsize) {
|
||||
int static parse_name(const unsigned char **inpos, const unsigned char *inend, const unsigned char *inbuf, char *buf, size_t bufsize) {
|
||||
size_t bufused = 0;
|
||||
int init = 1;
|
||||
do {
|
||||
|
@ -62,14 +67,17 @@ int parse_name(const unsigned char **inpos, const unsigned char *inend, const un
|
|||
return parse_name(&newbuf, *inpos, inbuf, buf+bufused, bufsize-bufused);
|
||||
}
|
||||
if (octet > 63) return -1;
|
||||
// copy data
|
||||
// copy label
|
||||
while (octet) {
|
||||
if (*inpos == inend)
|
||||
return -1;
|
||||
if (bufused == bufsize-1)
|
||||
return -2;
|
||||
int c = *((*inpos)++);
|
||||
if (c == '.')
|
||||
return -1;
|
||||
octet--;
|
||||
buf[bufused++] = *((*inpos)++);
|
||||
buf[bufused++] = c;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
|
@ -78,7 +86,7 @@ int parse_name(const unsigned char **inpos, const unsigned char *inend, const un
|
|||
// -1: component > 63 characters
|
||||
// -2: insufficent space in output
|
||||
// -3: two subsequent dots
|
||||
int write_name(unsigned char** outpos, unsigned char *outend, char *name, int offset) {
|
||||
int static write_name(unsigned char** outpos, unsigned char *outend, char *name, int offset) {
|
||||
while (*name != 0) {
|
||||
char *dot = strchr(name, '.');
|
||||
char *fin = dot;
|
||||
|
@ -104,7 +112,7 @@ int write_name(unsigned char** outpos, unsigned char *outend, char *name, int of
|
|||
return 0;
|
||||
}
|
||||
|
||||
int write_record(unsigned char** outpos, unsigned char *outend, char *name, int offset, int typ, int cls, int ttl) {
|
||||
int static write_record(unsigned char** outpos, unsigned char *outend, char *name, int offset, dns_type typ, dns_class cls, int ttl) {
|
||||
unsigned char *oldpos = *outpos;
|
||||
int error = 0;
|
||||
// name
|
||||
|
@ -124,7 +132,7 @@ error:
|
|||
}
|
||||
|
||||
|
||||
int write_record_a(unsigned char** outpos, unsigned char *outend, char *name, int offset, int cls, int ttl, uint32_t ip) {
|
||||
int static write_record_a(unsigned char** outpos, unsigned char *outend, char *name, int offset, dns_class cls, int ttl, const struct in_addr *ip) {
|
||||
unsigned char *oldpos = *outpos;
|
||||
int error = 0;
|
||||
int ret = write_record(outpos, outend, name, offset, TYPE_A, cls, ttl);
|
||||
|
@ -133,14 +141,34 @@ int write_record_a(unsigned char** outpos, unsigned char *outend, char *name, in
|
|||
// rdlength
|
||||
*((*outpos)++) = 0; *((*outpos)++) = 4;
|
||||
// rdata
|
||||
*((*outpos)++) = (ip >> 24) & 0xFF; *((*outpos)++) = (ip >> 16) & 0xFF; *((*outpos)++) = (ip >> 8) & 0xFF; *((*outpos)++) = ttl & 0xFF;
|
||||
const unsigned char *pd = (const unsigned char*)ip;
|
||||
for (int i=0; i<4; i++)
|
||||
*((*outpos)++) = pd[i];
|
||||
return 0;
|
||||
error:
|
||||
*outpos = oldpos;
|
||||
return error;
|
||||
}
|
||||
|
||||
int write_record_ns(unsigned char** outpos, unsigned char *outend, char *name, int offset, int cls, int ttl, char *ns) {
|
||||
int static write_record_aaaa(unsigned char** outpos, unsigned char *outend, char *name, int offset, dns_class cls, int ttl, const struct in6_addr *ip) {
|
||||
unsigned char *oldpos = *outpos;
|
||||
int error = 0;
|
||||
int ret = write_record(outpos, outend, name, offset, TYPE_AAAA, cls, ttl);
|
||||
if (ret) return ret;
|
||||
if (outend - *outpos < 6) { error = -5; goto error; }
|
||||
// rdlength
|
||||
*((*outpos)++) = 0; *((*outpos)++) = 16;
|
||||
// rdata
|
||||
const unsigned char *pd = (const unsigned char*)ip;
|
||||
for (int i=0; i<16; i++)
|
||||
*((*outpos)++) = pd[i];
|
||||
return 0;
|
||||
error:
|
||||
*outpos = oldpos;
|
||||
return error;
|
||||
}
|
||||
|
||||
int static write_record_ns(unsigned char** outpos, unsigned char *outend, char *name, int offset, dns_class cls, int ttl, char *ns) {
|
||||
unsigned char *oldpos = *outpos;
|
||||
int ret = write_record(outpos, outend, name, offset, TYPE_NS, cls, ttl);
|
||||
if (ret) return ret;
|
||||
|
@ -158,7 +186,34 @@ error:
|
|||
return error;
|
||||
}
|
||||
|
||||
ssize_t dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outbuf) {
|
||||
int static write_record_soa(unsigned char** outpos, unsigned char *outend, char *name, int offset, dns_class cls, int ttl, char* mname, char *rname,
|
||||
uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) {
|
||||
unsigned char *oldpos = *outpos;
|
||||
int ret = write_record(outpos, outend, name, offset, TYPE_SOA, cls, ttl);
|
||||
if (ret) return ret;
|
||||
int error = 0;
|
||||
if (outend - *outpos < 2) { error = -5; goto error; }
|
||||
(*outpos) += 2;
|
||||
unsigned char *curpos = *outpos;
|
||||
ret = write_name(outpos, outend, mname, -1);
|
||||
if (ret) { error = ret; goto error; }
|
||||
ret = write_name(outpos, outend, rname, -1);
|
||||
if (ret) { error = ret; goto error; }
|
||||
if (outend - *outpos < 20) { error = -5; goto error; }
|
||||
*((*outpos)++) = (serial >> 24) & 0xFF; *((*outpos)++) = (serial >> 16) & 0xFF; *((*outpos)++) = (serial >> 8) & 0xFF; *((*outpos)++) = serial & 0xFF;
|
||||
*((*outpos)++) = (refresh >> 24) & 0xFF; *((*outpos)++) = (refresh >> 16) & 0xFF; *((*outpos)++) = (refresh >> 8) & 0xFF; *((*outpos)++) = refresh & 0xFF;
|
||||
*((*outpos)++) = (retry >> 24) & 0xFF; *((*outpos)++) = (retry >> 16) & 0xFF; *((*outpos)++) = (retry >> 8) & 0xFF; *((*outpos)++) = retry & 0xFF;
|
||||
*((*outpos)++) = (expire >> 24) & 0xFF; *((*outpos)++) = (expire >> 16) & 0xFF; *((*outpos)++) = (expire >> 8) & 0xFF; *((*outpos)++) = expire & 0xFF;
|
||||
*((*outpos)++) = (minimum >> 24) & 0xFF; *((*outpos)++) = (minimum >> 16) & 0xFF; *((*outpos)++) = (minimum >> 8) & 0xFF; *((*outpos)++) = minimum & 0xFF;
|
||||
curpos[-2] = (*outpos - curpos) >> 8;
|
||||
curpos[-1] = (*outpos - curpos) & 0xFF;
|
||||
return 0;
|
||||
error:
|
||||
*outpos = oldpos;
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t static dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outbuf) {
|
||||
int error = 0;
|
||||
if (insize < 12) // DNS header
|
||||
return -1;
|
||||
|
@ -171,25 +226,24 @@ ssize_t dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outb
|
|||
// clear error
|
||||
outbuf[3] &= ~15;
|
||||
// check qr
|
||||
if (inbuf[2] & 128) { printf("Got response?\n"); error = 1; goto error; }
|
||||
if (inbuf[2] & 128) { /* printf("Got response?\n"); */ error = 1; goto error; }
|
||||
// check opcode
|
||||
if (((inbuf[2] & 120) >> 3) != 0) { printf("Opcode nonzero?\n"); error = 4; goto error; }
|
||||
if (((inbuf[2] & 120) >> 3) != 0) { /* printf("Opcode nonzero?\n"); */ error = 4; goto error; }
|
||||
// check Z
|
||||
if (((inbuf[3] & 112) >> 4) != 0) { printf("Z nonzero?\n"); error = 1; goto error; }
|
||||
if (((inbuf[3] & 112) >> 4) != 0) { /* printf("Z nonzero?\n"); */ error = 1; goto error; }
|
||||
// unset TC
|
||||
outbuf[2] &= ~2;
|
||||
// unset RA
|
||||
outbuf[3] &= ~128;
|
||||
// check questions
|
||||
int nquestion = (inbuf[4] << 8) + inbuf[5];
|
||||
if (nquestion == 0) { printf("No questions?\n"); error = 0; goto error; }
|
||||
if (nquestion > 1) { printf("Multiple questions %i?\n", nquestion); error = 4; goto error; }
|
||||
if (nquestion == 0) { /* printf("No questions?\n"); */ error = 0; goto error; }
|
||||
if (nquestion > 1) { /* printf("Multiple questions %i?\n", nquestion); */ error = 4; goto error; }
|
||||
const unsigned char *inpos = inbuf + 12;
|
||||
const unsigned char *inend = inbuf + insize;
|
||||
char name[256];
|
||||
int offset = inpos - inbuf;
|
||||
int ret = parse_name(&inpos, inend, inbuf, name, 256);
|
||||
printf("got request for host='%s'\n", name);
|
||||
if (ret == -1) { error = 1; goto error; }
|
||||
if (ret == -2) { error = 5; goto error; }
|
||||
int namel = strlen(name), hostl = strlen(host);
|
||||
|
@ -212,7 +266,7 @@ ssize_t dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outb
|
|||
unsigned char *outpos = outbuf+(inpos-inbuf);
|
||||
unsigned char *outend = outbuf + BUFLEN;
|
||||
|
||||
printf("type=%i class=%i\n", typ, cls);
|
||||
printf("Request host='%s' type=%i class=%i\n", name, typ, cls);
|
||||
|
||||
// calculate size of authority section
|
||||
|
||||
|
@ -223,25 +277,33 @@ ssize_t dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outb
|
|||
unsigned char *oldpos = outpos;
|
||||
write_record_ns(&oldpos, outend, "", offset, CLASS_IN, 0, ns);
|
||||
auth_size = oldpos - outpos;
|
||||
printf("Authority section will claim %i bytes\n", auth_size);
|
||||
// printf("Authority section will claim %i bytes\n", auth_size);
|
||||
}
|
||||
|
||||
// Answer section
|
||||
|
||||
int have_ns = 0;
|
||||
|
||||
// NS records
|
||||
if ((typ == TYPE_NS || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
|
||||
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, 30583, ns);
|
||||
printf("wrote NS record: %i\n", ret2);
|
||||
int ret2 = write_record_ns(&outpos, outend - auth_size, "", offset, CLASS_IN, nsttl, ns);
|
||||
// printf("wrote NS record: %i\n", ret2);
|
||||
if (!ret2) { outbuf[7]++; have_ns++; }
|
||||
}
|
||||
|
||||
// SOA records
|
||||
if ((typ == TYPE_SOA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
|
||||
int ret2 = write_record_soa(&outpos, outend - auth_size, "", offset, CLASS_IN, nsttl, ns, mbox, time(NULL), 604800, 86400, 2592000, 604800);
|
||||
// printf("wrote SOA record: %i\n", ret2);
|
||||
if (!ret2) { outbuf[7]++; }
|
||||
}
|
||||
|
||||
// A records
|
||||
if ((typ == TYPE_A || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
|
||||
uint32_t ip = 0x01101102;
|
||||
do {
|
||||
int ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, datattl, ip);
|
||||
printf("wrote A record: %i\n", ret);
|
||||
int ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, datattl, (const struct in_addr*)(&ip));
|
||||
// printf("wrote A record: %i\n", ret);
|
||||
if (!ret) {
|
||||
ip += 0x01101102;
|
||||
outbuf[7]++;
|
||||
|
@ -252,8 +314,8 @@ ssize_t dnshandle(const unsigned char *inbuf, size_t insize, unsigned char* outb
|
|||
|
||||
// Authority section
|
||||
if (!have_ns) {
|
||||
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, 30583, ns);
|
||||
printf("wrote NS record: %i\n", ret2);
|
||||
int ret2 = write_record_ns(&outpos, outend, "", offset, CLASS_IN, nsttl, ns);
|
||||
// printf("wrote NS record: %i\n", ret2);
|
||||
if (!ret2) {
|
||||
outbuf[9]++;
|
||||
}
|
||||
|
@ -276,7 +338,7 @@ error:
|
|||
|
||||
int dnsserver(void) {
|
||||
struct sockaddr_in si_me, si_other;
|
||||
socklen_t s, i, slen=sizeof(si_other);
|
||||
socklen_t s, slen=sizeof(si_other);
|
||||
unsigned char inbuf[BUFLEN], outbuf[BUFLEN];
|
||||
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
|
||||
return -1;
|
||||
|
@ -288,7 +350,8 @@ int dnsserver(void) {
|
|||
return -2;
|
||||
do {
|
||||
ssize_t insize = recvfrom(s, inbuf, BUFLEN, 0, (struct sockaddr*)&si_other, &slen);
|
||||
printf("Got %i-byte request\n", insize);
|
||||
unsigned char *addr = (unsigned char*)&si_other.sin_addr.s_addr;
|
||||
printf("Request from %i.%i.%i.%i:%i of %i bytes\n", addr[0], addr[1], addr[2], addr[3], ntohs(si_other.sin_port), (int)insize);
|
||||
if (insize > 0) {
|
||||
ssize_t ret = dnshandle(inbuf, insize, outbuf);
|
||||
if (ret > 0)
|
||||
|
|
740
netbase.cpp
Normal file
740
netbase.cpp
Normal file
|
@ -0,0 +1,740 @@
|
|||
// 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.
|
||||
|
||||
#define BSD_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
string strprintf(const std::string &format, ...)
|
||||
{
|
||||
char buffer[50000];
|
||||
char* p = buffer;
|
||||
int limit = sizeof(buffer);
|
||||
int ret;
|
||||
loop
|
||||
{
|
||||
va_list arg_ptr;
|
||||
va_start(arg_ptr, format);
|
||||
ret = vsnprintf(p, limit, format.c_str(), arg_ptr);
|
||||
va_end(arg_ptr);
|
||||
if (ret >= 0 && ret < limit)
|
||||
break;
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
limit *= 2;
|
||||
p = new char[limit];
|
||||
if (p == NULL)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
string str(p, p+ret);
|
||||
if (p != buffer)
|
||||
delete[] p;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
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<CIP>& 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(CIP(((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(CIP(((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<CIP>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strncpy(psz, pszName, sizeof(psz)-1);
|
||||
psz[255] = 0;
|
||||
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<CIP>& vIP, int nMaxSolutions)
|
||||
{
|
||||
return LookupHost(pszName, vIP, nMaxSolutions, false);
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, CIPPort& addr, int portDefault, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
int port = portDefault;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strncpy(psz, pszName, sizeof(psz)-1);
|
||||
psz[255] = 0;
|
||||
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<CIP> vIP;
|
||||
bool fRet = LookupIntern(pszHost, vIP, 1, fAllowLookup);
|
||||
if (!fRet)
|
||||
return false;
|
||||
addr = CIPPort(vIP[0], port);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LookupNumeric(const char *pszName, CIPPort& addr, int portDefault)
|
||||
{
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool CIPPort::ConnectSocket(SOCKET& hSocketRet, int nTimeout) const
|
||||
{
|
||||
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 && IsRoutable());
|
||||
struct sockaddr_in sockaddr;
|
||||
if (fProxy)
|
||||
addrProxy.GetSockAddr(&sockaddr);
|
||||
else
|
||||
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", ToString().c_str());
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
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 false;
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
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", ToString().c_str());
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CIP::Init()
|
||||
{
|
||||
memset(ip, 0, 16);
|
||||
}
|
||||
|
||||
void CIP::SetIP(const CIP& ipIn)
|
||||
{
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
CIP::CIP()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CIP::CIP(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, &ipv4Addr, 4);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CIP::CIP(const struct in6_addr& ipv6Addr)
|
||||
{
|
||||
memcpy(ip, &ipv6Addr, 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
CIP::CIP(const char *pszIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CIP> vIP;
|
||||
if (LookupHost(pszIp, vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
CIP::CIP(const std::string &strIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CIP> vIP;
|
||||
if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
int CIP::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CIP::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CIP::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CIP::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CIP::IsRFC3849() const
|
||||
{
|
||||
return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
|
||||
}
|
||||
|
||||
bool CIP::IsRFC3964() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
|
||||
}
|
||||
|
||||
bool CIP::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 CIP::IsRFC4380() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
|
||||
}
|
||||
|
||||
bool CIP::IsRFC4862() const
|
||||
{
|
||||
static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
|
||||
}
|
||||
|
||||
bool CIP::IsRFC4193() const
|
||||
{
|
||||
return ((GetByte(15) & 0xFE) == 0xFC);
|
||||
}
|
||||
|
||||
bool CIP::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 CIP::IsRFC4843() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && GetByte(12) & 0xF0 == 0x10);
|
||||
}
|
||||
|
||||
bool CIP::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 CIP::IsMulticast() const
|
||||
{
|
||||
return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
|
||||
|| (GetByte(15) == 0xFF);
|
||||
}
|
||||
|
||||
bool CIP::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 CIP::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || IsRFC4193() || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
std::string CIP::ToString() 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));
|
||||
}
|
||||
|
||||
bool operator==(const CIP& a, const CIP& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const CIP& a, const CIP& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator<(const CIP& a, const CIP& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) <= 0);
|
||||
}
|
||||
|
||||
bool CIP::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memcpy(pipv4Addr, ip+12, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
bool CIP::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> CIP::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 CIP::GetHash() const
|
||||
{
|
||||
if (IsIPv4())
|
||||
{
|
||||
// reconstruct ip in reversed-byte order
|
||||
// (the original definition of the randomizer used network-order integers on little endian architecture)
|
||||
int64 ip = GetByte(0) << 24 + GetByte(1) << 16 + GetByte(2) << 8 + GetByte(3);
|
||||
return ip * 7789;
|
||||
}
|
||||
|
||||
// for IPv6 addresses, use separate multipliers for each byte
|
||||
// these numbers are from the hexadecimal expansion of 3/Pi:
|
||||
static const int64 nByteMult[16] =
|
||||
{0xF4764525, 0x75661FBE, 0xFA3B03BA, 0xEFCF4CA1, 0x4913E065, 0xDA655862, 0xFD7A1581, 0xCE19A812,
|
||||
0x92B6A557, 0x6374BC50, 0x096DC65F, 0x0EBA5B2B, 0x7D2CE0AB, 0x09BE7ADE, 0x5CC350EF, 0xC618E6C7};
|
||||
int64 nRet = 0;
|
||||
for (int n=0; n<16; n++)
|
||||
nRet += nByteMult[n]*GetByte(n);
|
||||
return nRet;
|
||||
}
|
||||
|
||||
void CIP::print() const
|
||||
{
|
||||
printf("CIP(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CIPPort::Init()
|
||||
{
|
||||
port = 0;
|
||||
}
|
||||
|
||||
CIPPort::CIPPort()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CIPPort::CIPPort(const CIP& cip, unsigned short portIn) : CIP(cip), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CIPPort::CIPPort(const struct in_addr& ipv4Addr, unsigned short portIn) : CIP(ipv4Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CIPPort::CIPPort(const struct in6_addr& ipv6Addr, unsigned short portIn) : CIP(ipv6Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
CIPPort::CIPPort(const struct sockaddr_in& addr) : CIP(addr.sin_addr), port(ntohs(addr.sin_port))
|
||||
{
|
||||
assert(addr.sin_family == AF_INET);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CIPPort::CIPPort(const struct sockaddr_in6 &addr) : CIP(addr.sin6_addr), port(ntohs(addr.sin6_port))
|
||||
{
|
||||
assert(addr.sin6_family == AF_INET6);
|
||||
}
|
||||
#endif
|
||||
|
||||
CIPPort::CIPPort(const char *pszIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CIPPort ip;
|
||||
if (Lookup(pszIpPort, ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CIPPort::CIPPort(const char *pszIp, int portIn, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CIP> ip;
|
||||
if (LookupHost(pszIp, ip, 1, fAllowLookup))
|
||||
*this = CIPPort(ip[0], portIn);
|
||||
}
|
||||
|
||||
CIPPort::CIPPort(const std::string &strIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CIPPort ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CIPPort::CIPPort(const std::string &strIp, int portIn, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CIP> ip;
|
||||
if (LookupHost(strIp.c_str(), ip, 1, fAllowLookup))
|
||||
*this = CIPPort(ip[0], portIn);
|
||||
}
|
||||
|
||||
unsigned short CIPPort::GetPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
bool operator==(const CIPPort& a, const CIPPort& b)
|
||||
{
|
||||
return (operator==((CIP)a, (CIP)b) && a.port == b.port);
|
||||
}
|
||||
|
||||
bool operator!=(const CIPPort& a, const CIPPort& b)
|
||||
{
|
||||
return (operator!=((CIP)a, (CIP)b) || a.port != b.port);
|
||||
}
|
||||
|
||||
bool operator<(const CIPPort& a, const CIPPort& b)
|
||||
{
|
||||
return (operator<((CIP)a, (CIP)b) || a.port < b.port);
|
||||
}
|
||||
|
||||
bool CIPPort::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);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
bool CIPPort::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);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<unsigned char> CIPPort::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 CIPPort::ToString() const
|
||||
{
|
||||
return CIP::ToString() + strprintf(":%i", port);
|
||||
}
|
||||
|
||||
void CIPPort::print() const
|
||||
{
|
||||
printf("CIPPort(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CIPPort::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
135
netbase.h
Normal file
135
netbase.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
// 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
|
||||
#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"
|
||||
|
||||
typedef int SOCKET;
|
||||
|
||||
extern int nConnectTimeout;
|
||||
|
||||
// IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
|
||||
class CIP
|
||||
{
|
||||
protected:
|
||||
unsigned char ip[16]; // in network byte order
|
||||
|
||||
public:
|
||||
CIP();
|
||||
CIP(const struct in_addr& ipv4Addr);
|
||||
CIP(const char *pszIp, bool fAllowLookup = false);
|
||||
CIP(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CIP& 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;
|
||||
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
|
||||
CIP(const struct in6_addr& pipv6Addr);
|
||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||
#endif
|
||||
|
||||
friend bool operator==(const CIP& a, const CIP& b);
|
||||
friend bool operator!=(const CIP& a, const CIP& b);
|
||||
friend bool operator<(const CIP& a, const CIP& b);
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(FLATDATA(ip));
|
||||
)
|
||||
};
|
||||
|
||||
class CIPPort : public CIP
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
|
||||
public:
|
||||
CIPPort();
|
||||
CIPPort(const CIP& ip, unsigned short port);
|
||||
CIPPort(const struct in_addr& ipv4Addr, unsigned short port);
|
||||
CIPPort(const struct sockaddr_in& addr);
|
||||
CIPPort(const char *pszIp, int port, bool fAllowLookup = false);
|
||||
CIPPort(const char *pszIpPort, bool fAllowLookup = false);
|
||||
CIPPort(const std::string& strIp, int port, bool fAllowLookup = false);
|
||||
CIPPort(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;
|
||||
bool ConnectSocket(SOCKET& hSocketRet, int nTimeout = nConnectTimeout) const;
|
||||
friend bool operator==(const CIPPort& a, const CIPPort& b);
|
||||
friend bool operator!=(const CIPPort& a, const CIPPort& b);
|
||||
friend bool operator<(const CIPPort& a, const CIPPort& b);
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CIPPort(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
bool GetSockAddr6(struct sockaddr_in6* paddr) const;
|
||||
CIPPort(const struct sockaddr_in6& addr);
|
||||
#endif
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CIPPort* pthis = const_cast<CIPPort*>(this);
|
||||
READWRITE(FLATDATA(ip));
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(portN);
|
||||
if (fRead)
|
||||
pthis->port = ntohs(portN);
|
||||
)
|
||||
};
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, CIPPort& addr, int portDefault = 0, bool fAllowLookup = true);
|
||||
bool LookupNumeric(const char *pszName, CIPPort& addr, int portDefault = 0);
|
||||
|
||||
// Settings
|
||||
extern int fUseProxy;
|
||||
extern CIPPort addrProxy;
|
||||
|
||||
#endif
|
158
protocol.cpp
Normal file
158
protocol.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
// 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 <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "netbase.h"
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
static const char* ppszTypeName[] =
|
||||
{
|
||||
"ERROR",
|
||||
"tx",
|
||||
"block",
|
||||
};
|
||||
|
||||
CMessageHeader::CMessageHeader()
|
||||
{
|
||||
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
|
||||
memset(pchCommand, 0, sizeof(pchCommand));
|
||||
pchCommand[1] = 1;
|
||||
nMessageSize = -1;
|
||||
nChecksum = 0;
|
||||
}
|
||||
|
||||
CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
|
||||
{
|
||||
memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
|
||||
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
|
||||
nMessageSize = nMessageSizeIn;
|
||||
nChecksum = 0;
|
||||
}
|
||||
|
||||
std::string CMessageHeader::GetCommand() const
|
||||
{
|
||||
if (pchCommand[COMMAND_SIZE-1] == 0)
|
||||
return std::string(pchCommand, pchCommand + strlen(pchCommand));
|
||||
else
|
||||
return std::string(pchCommand, pchCommand + COMMAND_SIZE);
|
||||
}
|
||||
|
||||
bool CMessageHeader::IsValid() const
|
||||
{
|
||||
// Check start string
|
||||
if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
|
||||
return false;
|
||||
|
||||
// Check the command string for errors
|
||||
for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
|
||||
{
|
||||
if (*p1 == 0)
|
||||
{
|
||||
// Must be all zeros after the first zero
|
||||
for (; p1 < pchCommand + COMMAND_SIZE; p1++)
|
||||
if (*p1 != 0)
|
||||
return false;
|
||||
}
|
||||
else if (*p1 < ' ' || *p1 > 0x7E)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Message size
|
||||
if (nMessageSize > MAX_SIZE)
|
||||
{
|
||||
printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CAddress::CAddress() : CIPPort()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddress::CAddress(CIPPort &ipIn, uint64 nServicesIn) : CIPPort(ipIn)
|
||||
{
|
||||
Init();
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
void CAddress::Init()
|
||||
{
|
||||
nServices = NODE_NETWORK;
|
||||
nTime = 100000000;
|
||||
nLastTry = 0;
|
||||
}
|
||||
|
||||
void CAddress::print() const
|
||||
{
|
||||
printf("CAddress(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
CInv::CInv()
|
||||
{
|
||||
type = 0;
|
||||
hash = 0;
|
||||
}
|
||||
|
||||
CInv::CInv(int typeIn, const uint256& hashIn)
|
||||
{
|
||||
type = typeIn;
|
||||
hash = hashIn;
|
||||
}
|
||||
|
||||
CInv::CInv(const std::string& strType, const uint256& hashIn)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
|
||||
{
|
||||
if (strType == ppszTypeName[i])
|
||||
{
|
||||
type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAYLEN(ppszTypeName))
|
||||
throw std::out_of_range("CInv::CInv(string, uint256) : unknown type");
|
||||
hash = hashIn;
|
||||
}
|
||||
|
||||
bool operator<(const CInv& a, const CInv& b)
|
||||
{
|
||||
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
|
||||
}
|
||||
|
||||
bool CInv::IsKnownType() const
|
||||
{
|
||||
return (type >= 1 && type < ARRAYLEN(ppszTypeName));
|
||||
}
|
||||
|
||||
const char* CInv::GetCommand() const
|
||||
{
|
||||
if (!IsKnownType())
|
||||
throw std::out_of_range("CInv::GetCommand() : unknown type");
|
||||
return ppszTypeName[type];
|
||||
}
|
||||
|
||||
std::string CInv::ToString() const
|
||||
{
|
||||
return "CInv()";
|
||||
}
|
||||
|
||||
void CInv::print() const
|
||||
{
|
||||
printf("CInv\n");
|
||||
}
|
123
protocol.h
Normal file
123
protocol.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
// 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 __cplusplus
|
||||
# error This header can only be compiled as C++.
|
||||
#endif
|
||||
|
||||
#ifndef __INCLUDED_PROTOCOL_H__
|
||||
#define __INCLUDED_PROTOCOL_H__
|
||||
|
||||
#include "netbase.h"
|
||||
#include "serialize.h"
|
||||
#include <string>
|
||||
#include "uint256.h"
|
||||
|
||||
extern bool fTestNet;
|
||||
static inline unsigned short GetDefaultPort(const bool testnet = fTestNet)
|
||||
{
|
||||
return testnet ? 18333 : 8333;
|
||||
}
|
||||
|
||||
//
|
||||
// Message header
|
||||
// (4) message start
|
||||
// (12) command
|
||||
// (4) size
|
||||
// (4) checksum
|
||||
|
||||
extern unsigned char pchMessageStart[4];
|
||||
|
||||
class CMessageHeader
|
||||
{
|
||||
public:
|
||||
CMessageHeader();
|
||||
CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn);
|
||||
|
||||
std::string GetCommand() const;
|
||||
bool IsValid() const;
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(FLATDATA(pchMessageStart));
|
||||
READWRITE(FLATDATA(pchCommand));
|
||||
READWRITE(nMessageSize);
|
||||
if (nVersion >= 209)
|
||||
READWRITE(nChecksum);
|
||||
)
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
enum { COMMAND_SIZE=12 };
|
||||
char pchMessageStart[sizeof(::pchMessageStart)];
|
||||
char pchCommand[COMMAND_SIZE];
|
||||
unsigned int nMessageSize;
|
||||
unsigned int nChecksum;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NODE_NETWORK = (1 << 0),
|
||||
};
|
||||
|
||||
class CAddress : public CIPPort
|
||||
{
|
||||
public:
|
||||
CAddress();
|
||||
CAddress(CIPPort& ipIn, uint64 nServicesIn=NODE_NETWORK);
|
||||
|
||||
void Init();
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CAddress* pthis = const_cast<CAddress*>(this);
|
||||
CIPPort* pip = (CIPPort*)pthis;
|
||||
if (fRead)
|
||||
pthis->Init();
|
||||
if (nType & SER_DISK)
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
READWRITE(nServices);
|
||||
READWRITE(*pip);
|
||||
)
|
||||
|
||||
void print() const;
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
uint64 nServices;
|
||||
|
||||
// disk and network only
|
||||
unsigned int nTime;
|
||||
};
|
||||
|
||||
class CInv
|
||||
{
|
||||
public:
|
||||
CInv();
|
||||
CInv(int typeIn, const uint256& hashIn);
|
||||
CInv(const std::string& strType, const uint256& hashIn);
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(type);
|
||||
READWRITE(hash);
|
||||
)
|
||||
|
||||
friend bool operator<(const CInv& a, const CInv& b);
|
||||
|
||||
bool IsKnownType() const;
|
||||
const char* GetCommand() const;
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
int type;
|
||||
uint256 hash;
|
||||
};
|
||||
|
||||
#endif // __INCLUDED_PROTOCOL_H__
|
1314
serialize.h
Normal file
1314
serialize.h
Normal file
File diff suppressed because it is too large
Load diff
766
uint256.h
Normal file
766
uint256.h
Normal file
|
@ -0,0 +1,766 @@
|
|||
// 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_UINT256_H
|
||||
#define BITCOIN_UINT256_H
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define for if (false) ; else for
|
||||
#endif
|
||||
|
||||
|
||||
inline int Testuint256AdHoc(std::vector<std::string> vArg);
|
||||
|
||||
|
||||
|
||||
// We have to keep a separate base class without constructors
|
||||
// so the compiler will let us use it in a union
|
||||
template<unsigned int BITS>
|
||||
class base_uint
|
||||
{
|
||||
protected:
|
||||
enum { WIDTH=BITS/32 };
|
||||
unsigned int pn[WIDTH];
|
||||
public:
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
if (pn[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const base_uint operator~() const
|
||||
{
|
||||
base_uint ret;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
ret.pn[i] = ~pn[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
const base_uint operator-() const
|
||||
{
|
||||
base_uint ret;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
ret.pn[i] = ~pn[i];
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
base_uint& operator=(uint64 b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator^=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] ^= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator&=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] &= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator|=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] |= b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator^=(uint64 b)
|
||||
{
|
||||
pn[0] ^= (unsigned int)b;
|
||||
pn[1] ^= (unsigned int)(b >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator&=(uint64 b)
|
||||
{
|
||||
pn[0] &= (unsigned int)b;
|
||||
pn[1] &= (unsigned int)(b >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator|=(uint64 b)
|
||||
{
|
||||
pn[0] |= (unsigned int)b;
|
||||
pn[1] |= (unsigned int)(b >> 32);
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator<<=(unsigned int shift)
|
||||
{
|
||||
base_uint a(*this);
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
int k = shift / 32;
|
||||
shift = shift % 32;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (i+k+1 < WIDTH && shift != 0)
|
||||
pn[i+k+1] |= (a.pn[i] >> (32-shift));
|
||||
if (i+k < WIDTH)
|
||||
pn[i+k] |= (a.pn[i] << shift);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator>>=(unsigned int shift)
|
||||
{
|
||||
base_uint a(*this);
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
int k = shift / 32;
|
||||
shift = shift % 32;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (i-k-1 >= 0 && shift != 0)
|
||||
pn[i-k-1] |= (a.pn[i] << (32-shift));
|
||||
if (i-k >= 0)
|
||||
pn[i-k] |= (a.pn[i] >> shift);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator+=(const base_uint& b)
|
||||
{
|
||||
uint64 carry = 0;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
uint64 n = carry + pn[i] + b.pn[i];
|
||||
pn[i] = n & 0xffffffff;
|
||||
carry = n >> 32;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator-=(const base_uint& b)
|
||||
{
|
||||
*this += -b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator+=(uint64 b64)
|
||||
{
|
||||
base_uint b;
|
||||
b = b64;
|
||||
*this += b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator-=(uint64 b64)
|
||||
{
|
||||
base_uint b;
|
||||
b = b64;
|
||||
*this += -b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
base_uint& operator++()
|
||||
{
|
||||
// prefix operator
|
||||
int i = 0;
|
||||
while (++pn[i] == 0 && i < WIDTH-1)
|
||||
i++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
++(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
base_uint& operator--()
|
||||
{
|
||||
// prefix operator
|
||||
int i = 0;
|
||||
while (--pn[i] == -1 && i < WIDTH-1)
|
||||
i++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
--(*this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
friend inline bool operator<(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] < b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] > b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
friend inline bool operator<=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] < b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] > b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator>(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] > b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] < b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
friend inline bool operator>=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] > b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] < b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator==(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < base_uint::WIDTH; i++)
|
||||
if (a.pn[i] != b.pn[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator==(const base_uint& a, uint64 b)
|
||||
{
|
||||
if (a.pn[0] != (unsigned int)b)
|
||||
return false;
|
||||
if (a.pn[1] != (unsigned int)(b >> 32))
|
||||
return false;
|
||||
for (int i = 2; i < base_uint::WIDTH; i++)
|
||||
if (a.pn[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator!=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
friend inline bool operator!=(const base_uint& a, uint64 b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string GetHex() const
|
||||
{
|
||||
char psz[sizeof(pn)*2 + 1];
|
||||
for (int i = 0; i < sizeof(pn); i++)
|
||||
sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
|
||||
return std::string(psz, psz + sizeof(pn)*2);
|
||||
}
|
||||
|
||||
void SetHex(const char* psz)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
|
||||
// skip leading spaces
|
||||
while (isspace(*psz))
|
||||
psz++;
|
||||
|
||||
// skip 0x
|
||||
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
||||
psz += 2;
|
||||
|
||||
// hex string to uint
|
||||
static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
const char* pbegin = psz;
|
||||
while (phexdigit[*psz] || *psz == '0')
|
||||
psz++;
|
||||
psz--;
|
||||
unsigned char* p1 = (unsigned char*)pn;
|
||||
unsigned char* pend = p1 + WIDTH * 4;
|
||||
while (psz >= pbegin && p1 < pend)
|
||||
{
|
||||
*p1 = phexdigit[(unsigned char)*psz--];
|
||||
if (psz >= pbegin)
|
||||
{
|
||||
*p1 |= (phexdigit[(unsigned char)*psz--] << 4);
|
||||
p1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetHex(const std::string& str)
|
||||
{
|
||||
SetHex(str.c_str());
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return (GetHex());
|
||||
}
|
||||
|
||||
unsigned char* begin()
|
||||
{
|
||||
return (unsigned char*)&pn[0];
|
||||
}
|
||||
|
||||
unsigned char* end()
|
||||
{
|
||||
return (unsigned char*)&pn[WIDTH];
|
||||
}
|
||||
|
||||
unsigned int size()
|
||||
{
|
||||
return sizeof(pn);
|
||||
}
|
||||
|
||||
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
return sizeof(pn);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
|
||||
{
|
||||
s.write((char*)pn, sizeof(pn));
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
|
||||
{
|
||||
s.read((char*)pn, sizeof(pn));
|
||||
}
|
||||
|
||||
|
||||
friend class uint160;
|
||||
friend class uint256;
|
||||
friend inline int Testuint256AdHoc(std::vector<std::string> vArg);
|
||||
};
|
||||
|
||||
typedef base_uint<160> base_uint160;
|
||||
typedef base_uint<256> base_uint256;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// uint160 and uint256 could be implemented as templates, but to keep
|
||||
// compile errors and debugging cleaner, they're copy and pasted.
|
||||
//
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint160
|
||||
//
|
||||
|
||||
class uint160 : public base_uint160
|
||||
{
|
||||
public:
|
||||
typedef base_uint160 basetype;
|
||||
|
||||
uint160()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint160(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
uint160& operator=(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint160(uint64 b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint160& operator=(uint64 b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit uint160(const std::string& str)
|
||||
{
|
||||
SetHex(str);
|
||||
}
|
||||
|
||||
explicit uint160(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() == sizeof(pn))
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
else
|
||||
*this = 0;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const uint160& a, uint64 b) { return (base_uint160)a == b; }
|
||||
inline bool operator!=(const uint160& a, uint64 b) { return (base_uint160)a != b; }
|
||||
inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
|
||||
inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
|
||||
inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
|
||||
inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
|
||||
|
||||
inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; }
|
||||
inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; }
|
||||
inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; }
|
||||
inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; }
|
||||
inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; }
|
||||
|
||||
inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint256
|
||||
//
|
||||
|
||||
class uint256 : public base_uint256
|
||||
{
|
||||
public:
|
||||
typedef base_uint256 basetype;
|
||||
|
||||
uint256()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint256(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
uint256& operator=(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint256(uint64 b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint256& operator=(uint64 b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit uint256(const std::string& str)
|
||||
{
|
||||
SetHex(str);
|
||||
}
|
||||
|
||||
explicit uint256(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() == sizeof(pn))
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
else
|
||||
*this = 0;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const uint256& a, uint64 b) { return (base_uint256)a == b; }
|
||||
inline bool operator!=(const uint256& a, uint64 b) { return (base_uint256)a != b; }
|
||||
inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
||||
inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
|
||||
inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
||||
inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
|
||||
|
||||
inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; }
|
||||
inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; }
|
||||
inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; }
|
||||
inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; }
|
||||
inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; }
|
||||
|
||||
inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline int Testuint256AdHoc(std::vector<std::string> vArg)
|
||||
{
|
||||
uint256 g(0);
|
||||
|
||||
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g--; printf("g--\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g--; printf("g--\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g++; printf("g++\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g++; printf("g++\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g++; printf("g++\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
g++; printf("g++\n");
|
||||
printf("%s\n", g.ToString().c_str());
|
||||
|
||||
|
||||
|
||||
uint256 a(7);
|
||||
printf("a=7\n");
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
|
||||
uint256 b;
|
||||
printf("b undefined\n");
|
||||
printf("%s\n", b.ToString().c_str());
|
||||
int c = 3;
|
||||
|
||||
a = c;
|
||||
a.pn[3] = 15;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
uint256 k(c);
|
||||
|
||||
a = 5;
|
||||
a.pn[3] = 15;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
b = 1;
|
||||
b <<= 52;
|
||||
|
||||
a |= b;
|
||||
|
||||
a ^= 0x500;
|
||||
|
||||
printf("a %s\n", a.ToString().c_str());
|
||||
|
||||
a = a | b | (uint256)0x1000;
|
||||
|
||||
|
||||
printf("a %s\n", a.ToString().c_str());
|
||||
printf("b %s\n", b.ToString().c_str());
|
||||
|
||||
a = 0xfffffffe;
|
||||
a.pn[4] = 9;
|
||||
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a++;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a++;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a++;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a++;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
|
||||
a--;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a--;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a--;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
uint256 d = a--;
|
||||
printf("%s\n", d.ToString().c_str());
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a--;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
a--;
|
||||
printf("%s\n", a.ToString().c_str());
|
||||
|
||||
d = a;
|
||||
|
||||
printf("%s\n", d.ToString().c_str());
|
||||
for (int i = uint256::WIDTH-1; i >= 0; i--) printf("%08x", d.pn[i]); printf("\n");
|
||||
|
||||
uint256 neg = d;
|
||||
neg = ~neg;
|
||||
printf("%s\n", neg.ToString().c_str());
|
||||
|
||||
|
||||
uint256 e = uint256("0xABCDEF123abcdef12345678909832180000011111111");
|
||||
printf("\n");
|
||||
printf("%s\n", e.ToString().c_str());
|
||||
|
||||
|
||||
printf("\n");
|
||||
uint256 x1 = uint256("0xABCDEF123abcdef12345678909832180000011111111");
|
||||
uint256 x2;
|
||||
printf("%s\n", x1.ToString().c_str());
|
||||
for (int i = 0; i < 270; i += 4)
|
||||
{
|
||||
x2 = x1 << i;
|
||||
printf("%s\n", x2.ToString().c_str());
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("%s\n", x1.ToString().c_str());
|
||||
for (int i = 0; i < 270; i += 4)
|
||||
{
|
||||
x2 = x1;
|
||||
x2 >>= i;
|
||||
printf("%s\n", x2.ToString().c_str());
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
uint256 k = (~uint256(0) >> i);
|
||||
printf("%s\n", k.ToString().c_str());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
uint256 k = (~uint256(0) << i);
|
||||
printf("%s\n", k.ToString().c_str());
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
37
util.h
Normal file
37
util.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_ 1
|
||||
|
||||
#define loop for (;;)
|
||||
#define BEGIN(a) ((char*)&(a))
|
||||
#define END(a) ((char*)&((&(a))[1]))
|
||||
#define UBEGIN(a) ((unsigned char*)&(a))
|
||||
#define UEND(a) ((unsigned char*)&((&(a))[1]))
|
||||
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
#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
|
||||
|
||||
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
|
Loading…
Reference in a new issue