Update License in File Headers
[novacoin.git] / src / netbase.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "netbase.h"
7 #include "util.h"
8
9 #ifndef WIN32
10 #include <sys/fcntl.h>
11 #endif
12
13 #include "strlcpy.h"
14
15 using namespace std;
16
17 // Settings
18 int fUseProxy = false;
19 CService addrProxy("127.0.0.1",9050);
20 int nConnectTimeout = 5000;
21
22
23 static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
24
25 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
26 {
27     vIP.clear();
28     struct addrinfo aiHint;
29     memset(&aiHint, 0, sizeof(struct addrinfo));
30
31     aiHint.ai_socktype = SOCK_STREAM;
32     aiHint.ai_protocol = IPPROTO_TCP;
33 #ifdef WIN32
34 #  ifdef USE_IPV6
35     aiHint.ai_family = AF_UNSPEC;
36     aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
37 #  else
38     aiHint.ai_family = AF_INET;
39     aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
40 #  endif
41 #else
42 #  ifdef USE_IPV6
43     aiHint.ai_family = AF_UNSPEC;
44     aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
45 #  else
46     aiHint.ai_family = AF_INET;
47     aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
48 #  endif
49 #endif
50     struct addrinfo *aiRes = NULL;
51     int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
52     if (nErr)
53         return false;
54
55     struct addrinfo *aiTrav = aiRes;
56     while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
57     {
58         if (aiTrav->ai_family == AF_INET)
59         {
60             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
61             vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
62         }
63
64 #ifdef USE_IPV6
65         if (aiTrav->ai_family == AF_INET6)
66         {
67             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
68             vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
69         }
70 #endif
71
72         aiTrav = aiTrav->ai_next;
73     }
74
75     freeaddrinfo(aiRes);
76
77     return (vIP.size() > 0);
78 }
79
80 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
81 {
82     if (pszName[0] == 0)
83         return false;
84     char psz[256];
85     char *pszHost = psz;
86     strlcpy(psz, pszName, sizeof(psz));
87     if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
88     {
89         pszHost = psz+1;
90         psz[strlen(psz)-1] = 0;
91     }
92
93     return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
94 }
95
96 bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions)
97 {
98     return LookupHost(pszName, vIP, nMaxSolutions, false);
99 }
100
101 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
102 {
103     if (pszName[0] == 0)
104         return false;
105     int port = portDefault;
106     char psz[256];
107     char *pszHost = psz;
108     strlcpy(psz, pszName, sizeof(psz));
109     char* pszColon = strrchr(psz+1,':');
110     char *pszPortEnd = NULL;
111     int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
112     if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
113     {
114         if (psz[0] == '[' && pszColon[-1] == ']')
115         {
116             pszHost = psz+1;
117             pszColon[-1] = 0;
118         }
119         else
120             pszColon[0] = 0;
121         if (port >= 0 && port <= USHRT_MAX)
122             port = portParsed;
123     }
124     else
125     {
126         if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
127         {
128             pszHost = psz+1;
129             psz[strlen(psz)-1] = 0;
130         }
131
132     }
133
134     std::vector<CNetAddr> vIP;
135     bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
136     if (!fRet)
137         return false;
138     vAddr.resize(vIP.size());
139     for (unsigned int i = 0; i < vIP.size(); i++)
140         vAddr[i] = CService(vIP[i], port);
141     return true;
142 }
143
144 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
145 {
146     std::vector<CService> vService;
147     bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
148     if (!fRet)
149         return false;
150     addr = vService[0];
151     return true;
152 }
153
154 bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
155 {
156     return Lookup(pszName, addr, portDefault, false);
157 }
158
159 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
160 {
161     hSocketRet = INVALID_SOCKET;
162
163     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
164     if (hSocket == INVALID_SOCKET)
165         return false;
166 #ifdef SO_NOSIGPIPE
167     int set = 1;
168     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
169 #endif
170
171     bool fProxy = (fUseProxy && addrDest.IsRoutable());
172     struct sockaddr_in sockaddr;
173     if (fProxy)
174         addrProxy.GetSockAddr(&sockaddr);
175     else
176         addrDest.GetSockAddr(&sockaddr);
177
178 #ifdef WIN32
179     u_long fNonblock = 1;
180     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
181 #else
182     int fFlags = fcntl(hSocket, F_GETFL, 0);
183     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
184 #endif
185     {
186         closesocket(hSocket);
187         return false;
188     }
189
190
191     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
192     {
193         // WSAEINVAL is here because some legacy version of winsock uses it
194         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
195         {
196             struct timeval timeout;
197             timeout.tv_sec  = nTimeout / 1000;
198             timeout.tv_usec = (nTimeout % 1000) * 1000;
199
200             fd_set fdset;
201             FD_ZERO(&fdset);
202             FD_SET(hSocket, &fdset);
203             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
204             if (nRet == 0)
205             {
206                 printf("connection timeout\n");
207                 closesocket(hSocket);
208                 return false;
209             }
210             if (nRet == SOCKET_ERROR)
211             {
212                 printf("select() for connection failed: %i\n",WSAGetLastError());
213                 closesocket(hSocket);
214                 return false;
215             }
216             socklen_t nRetSize = sizeof(nRet);
217 #ifdef WIN32
218             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
219 #else
220             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
221 #endif
222             {
223                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
224                 closesocket(hSocket);
225                 return false;
226             }
227             if (nRet != 0)
228             {
229                 printf("connect() failed after select(): %s\n",strerror(nRet));
230                 closesocket(hSocket);
231                 return false;
232             }
233         }
234 #ifdef WIN32
235         else if (WSAGetLastError() != WSAEISCONN)
236 #else
237         else
238 #endif
239         {
240             printf("connect() failed: %i\n",WSAGetLastError());
241             closesocket(hSocket);
242             return false;
243         }
244     }
245
246     // this isn't even strictly necessary
247     // CNode::ConnectNode immediately turns the socket back to non-blocking
248     // but we'll turn it back to blocking just in case
249 #ifdef WIN32
250     fNonblock = 0;
251     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
252 #else
253     fFlags = fcntl(hSocket, F_GETFL, 0);
254     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
255 #endif
256     {
257         closesocket(hSocket);
258         return false;
259     }
260
261     if (fProxy)
262     {
263         printf("proxy connecting %s\n", addrDest.ToString().c_str());
264         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
265         struct sockaddr_in addr;
266         addrDest.GetSockAddr(&addr);
267         memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
268         memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
269         char* pszSocks4 = pszSocks4IP;
270         int nSize = sizeof(pszSocks4IP);
271
272         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
273         if (ret != nSize)
274         {
275             closesocket(hSocket);
276             return error("Error sending to proxy");
277         }
278         char pchRet[8];
279         if (recv(hSocket, pchRet, 8, 0) != 8)
280         {
281             closesocket(hSocket);
282             return error("Error reading proxy response");
283         }
284         if (pchRet[1] != 0x5a)
285         {
286             closesocket(hSocket);
287             if (pchRet[1] != 0x5b)
288                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
289             return false;
290         }
291         printf("proxy connected %s\n", addrDest.ToString().c_str());
292     }
293
294     hSocketRet = hSocket;
295     return true;
296 }
297
298 void CNetAddr::Init()
299 {
300     memset(ip, 0, 16);
301 }
302
303 void CNetAddr::SetIP(const CNetAddr& ipIn)
304 {
305     memcpy(ip, ipIn.ip, sizeof(ip));
306 }
307
308 CNetAddr::CNetAddr()
309 {
310     Init();
311 }
312
313 CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
314 {
315     memcpy(ip,    pchIPv4, 12);
316     memcpy(ip+12, &ipv4Addr, 4);
317 }
318
319 #ifdef USE_IPV6
320 CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
321 {
322     memcpy(ip, &ipv6Addr, 16);
323 }
324 #endif
325
326 CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
327 {
328     Init();
329     std::vector<CNetAddr> vIP;
330     if (LookupHost(pszIp, vIP, 1, fAllowLookup))
331         *this = vIP[0];
332 }
333
334 CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
335 {
336     Init();
337     std::vector<CNetAddr> vIP;
338     if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
339         *this = vIP[0];
340 }
341
342 int CNetAddr::GetByte(int n) const
343 {
344     return ip[15-n];
345 }
346
347 bool CNetAddr::IsIPv4() const
348 {
349     return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
350 }
351
352 bool CNetAddr::IsRFC1918() const
353 {
354     return IsIPv4() && (
355         GetByte(3) == 10 || 
356         (GetByte(3) == 192 && GetByte(2) == 168) || 
357         (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
358 }
359
360 bool CNetAddr::IsRFC3927() const
361 {
362     return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
363 }
364
365 bool CNetAddr::IsRFC3849() const
366 {
367     return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
368 }
369
370 bool CNetAddr::IsRFC3964() const
371 {
372     return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
373 }
374
375 bool CNetAddr::IsRFC6052() const
376 {
377     static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
378     return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
379 }
380
381 bool CNetAddr::IsRFC4380() const
382 {
383     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
384 }
385
386 bool CNetAddr::IsRFC4862() const
387 {
388     static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
389     return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
390 }
391
392 bool CNetAddr::IsRFC4193() const
393 {
394     return ((GetByte(15) & 0xFE) == 0xFC);
395 }
396
397 bool CNetAddr::IsRFC6145() const
398 {
399     static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
400     return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
401 }
402
403 bool CNetAddr::IsRFC4843() const
404 {
405     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
406 }
407
408 bool CNetAddr::IsLocal() const
409 {
410     // IPv4 loopback
411    if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
412        return true;
413
414    // IPv6 loopback (::1/128)
415    static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
416    if (memcmp(ip, pchLocal, 16) == 0)
417        return true;
418
419    return false;
420 }
421
422 bool CNetAddr::IsMulticast() const
423 {
424     return    (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
425            || (GetByte(15) == 0xFF);
426 }
427
428 bool CNetAddr::IsValid() const
429 {
430     // Clean up 3-byte shifted addresses caused by garbage in size field
431     // of addr messages from versions before 0.2.9 checksum.
432     // Two consecutive addr messages look like this:
433     // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
434     // so if the first length field is garbled, it reads the second batch
435     // of addr misaligned by 3 bytes.
436     if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
437         return false;
438
439     // unspecified IPv6 address (::/128)
440     unsigned char ipNone[16] = {};
441     if (memcmp(ip, ipNone, 16) == 0)
442         return false;
443
444     // documentation IPv6 address
445     if (IsRFC3849())
446         return false;
447
448     if (IsIPv4())
449     {
450         // INADDR_NONE
451         uint32_t ipNone = INADDR_NONE;
452         if (memcmp(ip+12, &ipNone, 4) == 0)
453             return false;
454
455         // 0
456         ipNone = 0;
457         if (memcmp(ip+12, &ipNone, 4) == 0)
458             return false;
459     }
460
461     return true;
462 }
463
464 bool CNetAddr::IsRoutable() const
465 {
466     return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || IsRFC4193() || IsRFC4843() || IsLocal());
467 }
468
469 std::string CNetAddr::ToStringIP() const
470 {
471     if (IsIPv4())
472         return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
473     else
474         return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
475                          GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
476                          GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
477                          GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
478                          GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
479 }
480
481 std::string CNetAddr::ToString() const
482 {
483     return ToStringIP();
484 }
485
486 bool operator==(const CNetAddr& a, const CNetAddr& b)
487 {
488     return (memcmp(a.ip, b.ip, 16) == 0);
489 }
490
491 bool operator!=(const CNetAddr& a, const CNetAddr& b)
492 {
493     return (memcmp(a.ip, b.ip, 16) != 0);
494 }
495
496 bool operator<(const CNetAddr& a, const CNetAddr& b)
497 {
498     return (memcmp(a.ip, b.ip, 16) < 0);
499 }
500
501 bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
502 {
503     if (!IsIPv4())
504         return false;
505     memcpy(pipv4Addr, ip+12, 4);
506     return true;
507 }
508
509 #ifdef USE_IPV6
510 bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
511 {
512     memcpy(pipv6Addr, ip, 16);
513     return true;
514 }
515 #endif
516
517 // get canonical identifier of an address' group
518 // no two connections will be attempted to addresses with the same group
519 std::vector<unsigned char> CNetAddr::GetGroup() const
520 {
521     std::vector<unsigned char> vchRet;
522     int nClass = 0; // 0=IPv6, 1=IPv4, 254=local, 255=unroutable
523     int nStartByte = 0;
524     int nBits = 16;
525
526     // all local addresses belong to the same group
527     if (IsLocal())
528     {
529         nClass = 254;
530         nBits = 0;
531     }
532
533     // all unroutable addresses belong to the same group
534     if (!IsRoutable())
535     {
536         nClass = 255;
537         nBits = 0;
538     }
539     // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
540     // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
541     else if (IsIPv4() || IsRFC6145() || IsRFC6052())
542     {
543         nClass = 1;
544         nStartByte = 12;
545     }
546     // for 6to4 tunneled addresses, use the encapsulated IPv4 address
547     else if (IsRFC3964())
548     {
549         nClass = 1;
550         nStartByte = 2;
551     }
552     // for Teredo-tunneled IPv6 addresses, use the encapsulated IPv4 address
553     else if (IsRFC4380())
554     {
555         vchRet.push_back(1);
556         vchRet.push_back(GetByte(3) ^ 0xFF);
557         vchRet.push_back(GetByte(2) ^ 0xFF);
558         return vchRet;
559     }
560     // for he.net, use /36 groups
561     else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
562         nBits = 36;
563     // for the rest of the IPv6 network, use /32 groups
564     else
565         nBits = 32;
566
567     vchRet.push_back(nClass);
568     while (nBits >= 8)
569     {
570         vchRet.push_back(GetByte(15 - nStartByte));
571         nStartByte++;
572         nBits -= 8;
573     }
574     if (nBits > 0)
575         vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1));
576
577     return vchRet;
578 }
579
580 int64 CNetAddr::GetHash() const
581 {
582     uint256 hash = Hash(&ip[0], &ip[16]);
583     int64 nRet;
584     memcpy(&nRet, &hash, sizeof(nRet));
585     return nRet;
586 }
587
588 void CNetAddr::print() const
589 {
590     printf("CNetAddr(%s)\n", ToString().c_str());
591 }
592
593 void CService::Init()
594 {
595     port = 0;
596 }
597
598 CService::CService()
599 {
600     Init();
601 }
602
603 CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
604 {
605 }
606
607 CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
608 {
609 }
610
611 #ifdef USE_IPV6
612 CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
613 {
614 }
615 #endif
616
617 CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
618 {
619     assert(addr.sin_family == AF_INET);
620 }
621
622 #ifdef USE_IPV6
623 CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
624 {
625    assert(addr.sin6_family == AF_INET6);
626 }
627 #endif
628
629 CService::CService(const char *pszIpPort, bool fAllowLookup)
630 {
631     Init();
632     CService ip;
633     if (Lookup(pszIpPort, ip, 0, fAllowLookup))
634         *this = ip;
635 }
636
637 CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
638 {
639     Init();
640     CService ip;
641     if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
642         *this = ip;
643 }
644
645 CService::CService(const std::string &strIpPort, bool fAllowLookup)
646 {
647     Init();
648     CService ip;
649     if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
650         *this = ip;
651 }
652
653 CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
654 {
655     Init();
656     CService ip;
657     if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
658         *this = ip;
659 }
660
661 unsigned short CService::GetPort() const
662 {
663     return port;
664 }
665
666 bool operator==(const CService& a, const CService& b)
667 {
668     return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
669 }
670
671 bool operator!=(const CService& a, const CService& b)
672 {
673     return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
674 }
675
676 bool operator<(const CService& a, const CService& b)
677 {
678     return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
679 }
680
681 bool CService::GetSockAddr(struct sockaddr_in* paddr) const
682 {
683     if (!IsIPv4())
684         return false;
685     memset(paddr, 0, sizeof(struct sockaddr_in));
686     if (!GetInAddr(&paddr->sin_addr))
687         return false;
688     paddr->sin_family = AF_INET;
689     paddr->sin_port = htons(port);
690     return true;
691 }
692
693 #ifdef USE_IPV6
694 bool CService::GetSockAddr6(struct sockaddr_in6* paddr) const
695 {
696     memset(paddr, 0, sizeof(struct sockaddr_in6));
697     if (!GetIn6Addr(&paddr->sin6_addr))
698         return false;
699     paddr->sin6_family = AF_INET6;
700     paddr->sin6_port = htons(port);
701     return true;
702 }
703 #endif
704
705 std::vector<unsigned char> CService::GetKey() const
706 {
707      std::vector<unsigned char> vKey;
708      vKey.resize(18);
709      memcpy(&vKey[0], ip, 16);
710      vKey[16] = port / 0x100;
711      vKey[17] = port & 0x0FF;
712      return vKey;
713 }
714
715 std::string CService::ToStringPort() const
716 {
717     return strprintf(":%i", port);
718 }
719
720 std::string CService::ToStringIPPort() const
721 {
722     return ToStringIP() + ToStringPort();
723 }
724
725 std::string CService::ToString() const
726 {
727     return ToStringIPPort();
728 }
729
730 void CService::print() const
731 {
732     printf("CService(%s)\n", ToString().c_str());
733 }
734
735 void CService::SetPort(unsigned short portIn)
736 {
737     port = portIn;
738 }