From 3791926e97227ef32143e1f8cc0cea120608e957 Mon Sep 17 00:00:00 2001 From: Marko Simovic Date: Tue, 8 Apr 2014 01:32:00 -0400 Subject: [PATCH] Updated to allow listening+UPnP on system-assigned port --- libethereum/Client.cpp | 3 ++- libethereum/PeerServer.cpp | 19 ++++++++++++++ libethereum/PeerServer.h | 3 +++ test/network.cpp | 51 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 test/network.cpp diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 9c50e7e83..eea3edf76 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -99,7 +99,8 @@ void Client::startNetwork(unsigned short _listenPort, std::string const& _seedHo catch (std::exception const&) { // Probably already have the port open. - m_net.reset(new PeerServer(m_clientVersion, m_bc, 0, _mode)); + cwarn << "Could not initialize with specified/default port. Trying system-assigned port"; + m_net.reset(new PeerServer(m_clientVersion, m_bc, 0, _mode, _publicIP, _upnp)); } m_net->setIdealPeerCount(_peers); diff --git a/libethereum/PeerServer.cpp b/libethereum/PeerServer.cpp index e16bae671..b4ff3890e 100644 --- a/libethereum/PeerServer.cpp +++ b/libethereum/PeerServer.cpp @@ -71,6 +71,25 @@ PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full"); } +PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m, string const& _publicAddress, bool _upnp): + m_clientVersion(_clientVersion), + m_mode(_m), + m_listenPort(0), + m_chain(&_ch), + m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)), + m_socket(m_ioService), + m_key(KeyPair::create()), + m_networkId(_networkId) +{ + m_listenPort = m_acceptor.local_endpoint().port(); + + // populate addresses. + populateAddresses(); + determinePublic(_publicAddress, _upnp); + ensureAccepting(); + clog(NetNote) << "Id:" << toHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (m_mode == NodeMode::PeerServer ? "PeerServer" : "Full"); +} + PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m): m_clientVersion(_clientVersion), m_mode(_m), diff --git a/libethereum/PeerServer.h b/libethereum/PeerServer.h index cc877300e..425f262a9 100644 --- a/libethereum/PeerServer.h +++ b/libethereum/PeerServer.h @@ -42,8 +42,11 @@ class PeerServer public: /// Start server, listening for connections on the given port. PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, unsigned short _port, NodeMode _m = NodeMode::Full, std::string const& _publicAddress = std::string(), bool _upnp = true); + /// Start server, listening for connections on a system-assigned port. + PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m = NodeMode::Full, std::string const& _publicAddress = std::string(), bool _upnp = true); /// Start server, but don't listen. PeerServer(std::string const& _clientVersion, BlockChain const& _ch, unsigned int _networkId, NodeMode _m = NodeMode::Full); + ~PeerServer(); static unsigned protocolVersion(); diff --git a/test/network.cpp b/test/network.cpp new file mode 100644 index 000000000..3e27ac6b9 --- /dev/null +++ b/test/network.cpp @@ -0,0 +1,51 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file network.cpp + * @author Marko Simovic + * @date 2014 + * Basic networking tests + */ + +#include +#include +#include +#include +#include +#include "TestHelper.h" +using namespace std; +using namespace eth; + +BOOST_AUTO_TEST_CASE(listen_port_busy) +{ + short port = 20000; + + //make use of the port ahead of our client + ba::io_service ioService; + bi::tcp::endpoint endPoint(bi::tcp::v4(), port); + bi::tcp::acceptor acceptor(ioService, endPoint); + acceptor.listen(10); + + //prepare client and try to listen on same, used, port + Client c1("TestClient1", KeyPair::create().address(), + (boost::filesystem::temp_directory_path() / boost::filesystem::unique_path()).string()); + + c1.startNetwork(port); + + BOOST_REQUIRE(c1.haveNetwork()); + BOOST_REQUIRE(c1.peerServer()->listenPort() != 0); + BOOST_REQUIRE(c1.peerServer()->listenPort() != port); +}