Post
Topic
Board Beginners & Help
Re: Can't get bitcoind to accept RPC connections from other machines
by
tim_s_uk
on 06/06/2013, 14:56:25 UTC
I've had a look at the code in bitcoinrpc.cpp, specifically the function StartRPCThreads().

The code attempts to open an IPv6 socket and then set the 'v6_only' option to false if the 'rpcallowip' option is used. This should cause the socket to listen for IPv4 connections, but on my system netstat doesn't show a listening IPv4 socket (see my original post).

If the socket failed to open, or the 'rpcallowip' option is not used, the code opens a separate IPv4 socket. This means that when 'rpcallowip' is not used, separate IPv4 and IPv6 sockets are always used.

When I modify the code (by setting fListening to false), so that it tries to open the IPv4 socket after opening the IPv4/IPv6 socket, I get the error:
Error: An error occurred while setting up the RPC port 8332 for listening on IPv4: Address already in use
which indicates that the combined IPv4/IPv6 socket is listening, although netstat doesn't show this.

When I modify the code (by forcing set_option(v6_only(true)) and removing the if( !fListening... ) line), so that it always opens separate IPv4 and IPv6 sockets, things work as I expect them to:
Code:
user@server:~$ netstat -lp | grep bitcoind
tcp        0      0 *:8332                  *:*                     LISTEN      3063/bitcoind
tcp        0      0 *:8333                  *:*                     LISTEN      3063/bitcoind
tcp6       0      0 [::]:8332               [::]:*                  LISTEN      3063/bitcoind
tcp6       0      0 [::]:8333               [::]:*                  LISTEN      3063/bitcoind

I assume that the IPv4/IPv6 socket just works on most systems. Unfortunately I can't see a work-around for systems like mine without recompiling bitcoind.

Here are the changes I made:
Code:
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index c99b74f..ba7f462 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -791,8 +791,8 @@ void StartRPCThreads()
         acceptor->open(endpoint.protocol());
         acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));

-        // Try making the socket dual IPv6/IPv4 (if listening on the "any" address)
-        acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error);
+        // This is an IPv6 only socket
+        acceptor->set_option(boost::asio::ip::v6_only(true), v6_only_error);

         acceptor->bind(endpoint);
         acceptor->listen(socket_base::max_connections);
@@ -807,8 +807,7 @@ void StartRPCThreads()
     }

     try {
-        // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately
-        if (!fListening || loopback || v6_only_error)
+        // This is an IPv4 socket
         {
             bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any();
             endpoint.address(bindAddress);