diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index 187f3dfad..b4c06279b 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 b27a93e28..be8e4a96f 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);
+}