@@ -52,7 +52,7 @@ static bool vfLimited[NET_MAX] = {};
52
52
static CNode* pnodeLocalHost = NULL ;
53
53
uint64 nLocalHostNonce = 0 ;
54
54
array<int , THREAD_MAX> vnThreadsRunning;
55
- static SOCKET hListenSocket = INVALID_SOCKET ;
55
+ static std::vector< SOCKET> vhListenSocket ;
56
56
CAddrMan addrman;
57
57
58
58
vector<CNode*> vNodes;
@@ -719,9 +719,10 @@ void ThreadSocketHandler2(void* parg)
719
719
FD_ZERO (&fdsetError);
720
720
SOCKET hSocketMax = 0 ;
721
721
722
- if ( hListenSocket != INVALID_SOCKET)
722
+ BOOST_FOREACH (SOCKET hListenSocket, vhListenSocket) {
723
723
FD_SET (hListenSocket, &fdsetRecv);
724
- hSocketMax = max (hSocketMax, hListenSocket);
724
+ hSocketMax = max (hSocketMax, hListenSocket);
725
+ }
725
726
{
726
727
LOCK (cs_vNodes);
727
728
BOOST_FOREACH (CNode* pnode, vNodes)
@@ -762,20 +763,22 @@ void ThreadSocketHandler2(void* parg)
762
763
//
763
764
// Accept new connections
764
765
//
766
+ BOOST_FOREACH (SOCKET hListenSocket, vhListenSocket)
765
767
if (hListenSocket != INVALID_SOCKET && FD_ISSET (hListenSocket, &fdsetRecv))
766
768
{
767
769
#ifdef USE_IPV6
768
- struct sockaddr_in6 sockaddr;
770
+ struct sockaddr_storage sockaddr;
769
771
#else
770
- struct sockaddr_in sockaddr;
772
+ struct sockaddr sockaddr;
771
773
#endif
772
774
socklen_t len = sizeof (sockaddr);
773
775
SOCKET hSocket = accept (hListenSocket, (struct sockaddr *)&sockaddr, &len);
774
776
CAddress addr;
775
777
int nInbound = 0 ;
776
778
777
779
if (hSocket != INVALID_SOCKET)
778
- addr = CAddress (sockaddr);
780
+ if (!addr.SetSockAddr ((const struct sockaddr *)&sockaddr))
781
+ printf (" warning: unknown socket family\n " );
779
782
780
783
{
781
784
LOCK (cs_vNodes);
@@ -1656,9 +1659,8 @@ void ThreadMessageHandler2(void* parg)
1656
1659
1657
1660
1658
1661
1659
- bool BindListenPort (string& strError)
1662
+ bool BindListenPort (const CService &addrBind, string& strError)
1660
1663
{
1661
- unsigned short nPort = GetListenPort ();
1662
1664
strError = " " ;
1663
1665
int nOne = 1 ;
1664
1666
@@ -1676,11 +1678,19 @@ bool BindListenPort(string& strError)
1676
1678
1677
1679
// Create socket for listening for incoming connections
1678
1680
#ifdef USE_IPV6
1679
- int nFamily = AF_INET6 ;
1681
+ struct sockaddr_storage sockaddr ;
1680
1682
#else
1681
- int nFamily = AF_INET ;
1683
+ struct sockaddr sockaddr ;
1682
1684
#endif
1683
- hListenSocket = socket (nFamily, SOCK_STREAM, IPPROTO_TCP);
1685
+ socklen_t len = sizeof (sockaddr);
1686
+ if (!addrBind.GetSockAddr ((struct sockaddr *)&sockaddr, &len))
1687
+ {
1688
+ strError = strprintf (" Error: bind address family for %s not supported" , addrBind.ToString ().c_str ());
1689
+ printf (" %s\n " , strError.c_str ());
1690
+ return false ;
1691
+ }
1692
+
1693
+ SOCKET hListenSocket = socket (((struct sockaddr *)&sockaddr)->sa_family , SOCK_STREAM, IPPROTO_TCP);
1684
1694
if (hListenSocket == INVALID_SOCKET)
1685
1695
{
1686
1696
strError = strprintf (" Error: Couldn't open socket for incoming connections (socket returned error %d)" , WSAGetLastError ());
@@ -1699,6 +1709,7 @@ bool BindListenPort(string& strError)
1699
1709
setsockopt (hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&nOne, sizeof (int ));
1700
1710
#endif
1701
1711
1712
+
1702
1713
#ifdef WIN32
1703
1714
// Set to nonblocking, incoming connections will also inherit this
1704
1715
if (ioctlsocket (hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
@@ -1711,38 +1722,33 @@ bool BindListenPort(string& strError)
1711
1722
return false ;
1712
1723
}
1713
1724
1714
- // The sockaddr_in structure specifies the address family,
1715
- // IP address, and port for the socket that is being bound
1716
1725
#ifdef USE_IPV6
1717
- struct sockaddr_in6 sockaddr = sockaddr_in6 ();
1718
- memset (&sockaddr, 0 , sizeof (sockaddr));
1719
- sockaddr.sin6_family = AF_INET6;
1720
- sockaddr.sin6_addr = in6addr_any; // bind to all IPs on this computer
1721
- sockaddr.sin6_port = htons (nPort);
1722
- # ifdef WIN32
1723
- int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */ ;
1724
- int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */ ;
1725
- // this call is allowed to fail
1726
- setsockopt (hListenSocket, IPPROTO_IPV6, nParameterId, (const char *)&nProtLevel, sizeof (int ));
1727
- # endif
1728
- #else
1729
- struct sockaddr_in sockaddr = sockaddr_in ();
1730
- memset (&sockaddr, 0 , sizeof (sockaddr));
1731
- sockaddr.sin_family = AF_INET;
1732
- sockaddr.sin_addr .s_addr = INADDR_ANY; // bind to all IPs on this computer
1733
- sockaddr.sin_port = htons (nPort);
1726
+ // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1727
+ // and enable it by default or not. Try to enable it, if possible.
1728
+ if (addrBind.IsIPv6 ()) {
1729
+ #ifdef IPV6_V6ONLY
1730
+ setsockopt (hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&nOne, sizeof (int ));
1734
1731
#endif
1735
- if (::bind (hListenSocket, (struct sockaddr *)&sockaddr, sizeof (sockaddr)) == SOCKET_ERROR)
1732
+ #ifdef WIN32
1733
+ int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */ ;
1734
+ int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */ ;
1735
+ // this call is allowed to fail
1736
+ setsockopt (hListenSocket, IPPROTO_IPV6, nParameterId, (const char *)&nProtLevel, sizeof (int ));
1737
+ #endif
1738
+ }
1739
+ #endif
1740
+
1741
+ if (::bind (hListenSocket, (struct sockaddr *)&sockaddr, len) == SOCKET_ERROR)
1736
1742
{
1737
1743
int nErr = WSAGetLastError ();
1738
1744
if (nErr == WSAEADDRINUSE)
1739
- strError = strprintf (_ (" Unable to bind to port %d on this computer. Bitcoin is probably already running." ), nPort );
1745
+ strError = strprintf (_ (" Unable to bind to %s on this computer. Bitcoin is probably already running." ), addrBind. ToString (). c_str () );
1740
1746
else
1741
- strError = strprintf (" Error: Unable to bind to port %d on this computer (bind returned error %d, %s)" , nPort , nErr, strerror (nErr));
1747
+ strError = strprintf (_ ( " Unable to bind to %s on this computer (bind returned error %d, %s)" ), addrBind. ToString (). c_str () , nErr, strerror (nErr));
1742
1748
printf (" %s\n " , strError.c_str ());
1743
1749
return false ;
1744
1750
}
1745
- printf (" Bound to port %d \n " , ( int )nPort );
1751
+ printf (" Bound to %s \n " , addrBind. ToString (). c_str () );
1746
1752
1747
1753
// Listen for incoming connections
1748
1754
if (listen (hListenSocket, SOMAXCONN) == SOCKET_ERROR)
@@ -1752,6 +1758,11 @@ bool BindListenPort(string& strError)
1752
1758
return false ;
1753
1759
}
1754
1760
1761
+ vhListenSocket.push_back (hListenSocket);
1762
+
1763
+ if (addrBind.IsRoutable () && GetBoolArg (" -discover" , true ))
1764
+ AddLocal (addrBind, LOCAL_BIND);
1765
+
1755
1766
return true ;
1756
1767
}
1757
1768
@@ -1915,9 +1926,10 @@ class CNetCleanup
1915
1926
BOOST_FOREACH (CNode* pnode, vNodes)
1916
1927
if (pnode->hSocket != INVALID_SOCKET)
1917
1928
closesocket (pnode->hSocket );
1918
- if (hListenSocket != INVALID_SOCKET)
1919
- if (closesocket (hListenSocket) == SOCKET_ERROR)
1920
- printf (" closesocket(hListenSocket) failed with error %d\n " , WSAGetLastError ());
1929
+ BOOST_FOREACH (SOCKET hListenSocket, vhListenSocket)
1930
+ if (hListenSocket != INVALID_SOCKET)
1931
+ if (closesocket (hListenSocket) == SOCKET_ERROR)
1932
+ printf (" closesocket(hListenSocket) failed with error %d\n " , WSAGetLastError ());
1921
1933
1922
1934
#ifdef WIN32
1923
1935
// Shutdown Windows Sockets
0 commit comments