2
0
Эх сурвалжийг харах

Testnet work... getting there!

Adam Ierymenko 10 жил өмнө
parent
commit
4fbb098daa

+ 0 - 18
control/NodeControlService.cpp

@@ -120,7 +120,6 @@ void NodeControlService::_doCommand(IpcConnection *ipcc,const char *commandLine)
 		ipcc->printf("200 help leave <network ID>"ZT_EOL_S);
 		ipcc->printf("200 help terminate [<reason>]"ZT_EOL_S);
 		ipcc->printf("200 help updatecheck"ZT_EOL_S);
-		//ipcc->printf("200 help inject <network ID> <from MAC> <to MAC> <ethertype(hex)> <string>");
 	} else if (cmd[0] == "auth") {
 		if ((cmd.size() > 1)&&(_authToken.length() > 0)&&(_authToken == cmd[1])) {
 			Mutex::Lock _l(_connections_m);
@@ -240,23 +239,6 @@ void NodeControlService::_doCommand(IpcConnection *ipcc,const char *commandLine)
 			} else {
 				ipcc->printf("200 OK"ZT_EOL_S);
 			}
-		} else if (cmd[0] == "inject") {
-			if (cmd.size() >= 6) {
-				MAC from,to;
-				unsigned char from2[6];
-				unsigned char to2[6];
-				from.fromString(cmd[2].c_str());
-				to.fromString(cmd[3].c_str());
-				from.copyTo(from2,6);
-				to.copyTo(to2,6);
-				if (_node->injectPacketFromHost(Utils::hexStrToU64(cmd[1].c_str()),from2,to2,Utils::hexStrToUInt(cmd[4].c_str()),cmd[5].c_str(),(unsigned int)cmd[5].length()+1)) {
-					ipcc->printf("200 OK"ZT_EOL_S);
-				} else {
-					ipcc->printf("500 inject failed or not supported by this tap device"ZT_EOL_S);
-				}
-			} else {
-				ipcc->printf("400 missing required arguments"ZT_EOL_S);
-			}
 		} else {
 			ipcc->printf("404 %s No such command. Use 'help' for help."ZT_EOL_S,cmd[0].c_str());
 		}

+ 7 - 2
make-mac.mk

@@ -39,6 +39,7 @@ CXXFLAGS=$(CFLAGS) -fno-rtti
 
 include objects.mk
 OBJS+=osnet/BSDRoutingTable.o osnet/OSXEthernetTap.o osnet/OSXEthernetTapFactory.o
+TESTNET_OBJS=testnet/SimNet.o testnet/SimNetSocketManager.o testnet/TestEthernetTap.o testnet/TestEthernetTapFactory.o testnet/TestRoutingTable.o
 
 all: one
 
@@ -48,10 +49,14 @@ one:	$(OBJS) main.o
 	ln -sf zerotier-one zerotier-cli
 	ln -sf zerotier-one zerotier-idtool
 
-selftest: $(OBJS) selftest.o
+selftest: $(OBJS) sefltest.o
 	$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
 	$(STRIP) zerotier-selftest
 
+testnet: $(OBJS) $(TESTNET_OBJS) testnet.o
+	$(CXX) $(CXXFLAGS) -o zerotier-testnet testnet.o $(OBJS) $(TESTNET_OBJS) $(LIBS)
+	$(STRIP) zerotier-testnet
+
 # Requires that ../Qt be symlinked to the Qt root to use for UI build
 mac-ui: FORCE
 	mkdir -p build-ZeroTierUI-release
@@ -62,7 +67,7 @@ mac-ui: FORCE
 	$(CODESIGN) -vvv "build-ZeroTierUI-release/ZeroTier One.app"
 
 clean:
-	rm -rf *.dSYM main.o selftest.o build-* $(OBJS) zerotier-* ZeroTierOneInstaller-* "ZeroTier One.zip" "ZeroTier One.dmg"
+	rm -rf *.dSYM testnet.o selftest.o build-* $(OBJS) $(TEST_OBJS) zerotier-* ZeroTierOneInstaller-* "ZeroTier One.zip" "ZeroTier One.dmg"
 
 debug:	FORCE
 	make -j 4 ZT_DEBUG=1

+ 0 - 16
node/Node.cpp

@@ -1018,22 +1018,6 @@ bool Node::updateCheck()
 	return false;
 }
 
-bool Node::injectPacketFromHost(uint64_t nwid,const unsigned char *from,const unsigned char *to,unsigned int etherType,const void *data,unsigned int len)
-{
-	if (!running())
-		return false;
-	if ((!from)||(!to))
-		return false;
-
-	_NodeImpl *impl = (_NodeImpl *)_impl;
-	RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv);
-
-	SharedPtr<Network> network(RR->nc->network(nwid));
-	if (network)
-		return network->tapInjectPacketFromHost(MAC(from,6),MAC(to,6),etherType,data,len);
-	return false;
-}
-
 class _VersionStringMaker
 {
 public:

+ 0 - 17
node/Node.hpp

@@ -226,23 +226,6 @@ public:
 	bool updateCheck()
 		throw();
 
-	/**
-	 * Inject a packet into a network's tap as if it came from the host
-	 *
-	 * This is primarily for debugging, and at the moment is only supported on
-	 * the test/dummy Ethernet tap implementation. Attempting to use it for real
-	 * devices will fail and return 'false.'
-	 *
-	 * @param nwid Network ID
-	 * @param from Source MAC address (must be 6 bytes in length)
-	 * @param to Destination MAC address (must be 6 bytes in length)
-	 * @param etherType Ethernet frame type
-	 * @param data Frame data
-	 * @param len Length of frame in bytes
-	 * @return True on success; false if not a member of network, injection not supported, or data too large
-	 */
-	bool injectPacketFromHost(uint64_t nwid,const unsigned char *from,const unsigned char *to,unsigned int etherType,const void *data,unsigned int len);
-
 	static const char *versionString() throw();
 	static unsigned int versionMajor() throw();
 	static unsigned int versionMinor() throw();

+ 362 - 0
testnet.cpp

@@ -0,0 +1,362 @@
+/*
+ * ZeroTier One - Global Peer to Peer Ethernet
+ * Copyright (C) 2011-2014  ZeroTier Networks LLC
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "node/Constants.hpp"
+#include "node/Node.hpp"
+#include "node/Utils.hpp"
+#include "node/Address.hpp"
+#include "node/Identity.hpp"
+#include "node/Thread.hpp"
+#include "node/CMWC4096.hpp"
+
+#include "testnet/SimNet.hpp"
+#include "testnet/SimNetSocketManager.hpp"
+#include "testnet/TestEthernetTap.hpp"
+#include "testnet/TestEthernetTapFactory.hpp"
+#include "testnet/TestRoutingTable.hpp"
+
+#ifdef __WINDOWS__
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+
+using namespace ZeroTier;
+
+class SimNode
+{
+public:
+	SimNode(SimNet &net,const std::string &hp,const char *rootTopology,bool issn,const InetAddress &addr) :
+		home(hp),
+		tapFactory(),
+		routingTable(),
+		socketManager(net.newEndpoint(addr)),
+		node(home.c_str(),&tapFactory,&routingTable,socketManager,false,rootTopology),
+		reasonForTermination(Node::NODE_RUNNING),
+		supernode(issn)
+	{
+		thread = Thread::start(this);
+	}
+
+	~SimNode()
+	{
+		node.terminate(Node::NODE_NORMAL_TERMINATION,"SimNode shutdown");
+		Thread::join(thread);
+	}
+
+	void threadMain()
+		throw()
+	{
+		reasonForTermination = node.run();
+	}
+
+	std::string home;
+	TestEthernetTapFactory tapFactory;
+	TestRoutingTable routingTable;
+	SimNetSocketManager *socketManager;
+	Node node;
+	Node::ReasonForTermination reasonForTermination;
+	bool supernode;
+	Thread thread;
+};
+
+static std::string basePath;
+static SimNet net;
+static std::map< Address,SimNode * > nodes;
+static std::map< InetAddress,Address > usedIps;
+static CMWC4096 prng;
+static std::string rootTopology;
+
+// Converts an address into a fake IP not already claimed.
+// Be sure to call only once, as this claims the IP before returning it.
+static InetAddress inetAddressFromZeroTierAddress(const Address &addr)
+{
+	uint32_t ip = (uint32_t)(addr.toInt() & 0xffffffff);
+	for(;;) {
+		if (((ip >> 24) & 0xff) >= 240) {
+			ip &= 0x00ffffff;
+			ip |= (((ip >> 24) & 0xff) % 240) << 24;
+		}
+		if (((ip >> 24) & 0xff) == 0)
+			ip |= 0x01000000;
+		if (((ip & 0xff) == 0)||((ip & 0xff) == 255))
+			ip ^= 0x00000001;
+		InetAddress inaddr(Utils::hton(ip),9993);
+		if (usedIps.find(inaddr) == usedIps.end()) {
+			usedIps[inaddr] = addr;
+			return inaddr;
+		}
+		++ip; // keep looking sequentially for an unclaimed IP
+	}
+}
+
+static Identity makeNodeHome(bool super)
+{
+	Identity id;
+	id.generate();
+
+	std::string path(basePath + ZT_PATH_SEPARATOR_S + (super ? "S" : "N") + id.address().toString());
+
+#ifdef __WINDOWS__
+	CreateDirectoryA(path.c_str(),NULL);
+#else
+	mkdir(path.c_str(),0700);
+#endif
+
+	if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.secret"),id.toString(true)))
+		return Identity();
+	if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.public"),id.toString(false)))
+		return Identity();
+
+	return id;
+}
+
+// Instantiates supernodes by scanning for S########## subdirectories
+static std::vector<Address> initSupernodes()
+{
+	Dictionary supernodes;
+	std::vector< std::pair<Identity,InetAddress> > snids;
+	std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
+
+	for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
+		if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'S')) {
+			std::string idbuf;
+			if (Utils::readFile((basePath + ZT_PATH_SEPARATOR_S + d->first + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),idbuf)) {
+				Identity id(idbuf);
+				if (id) {
+					InetAddress inaddr(inetAddressFromZeroTierAddress(id.address()));
+					snids.push_back(std::pair<Identity,InetAddress>(id,inaddr));
+
+					Dictionary snd;
+					snd["id"] = id.toString(false);
+					snd["udp"] = inaddr.toString();
+					snd["desc"] = id.address().toString();
+					snd["dns"] = inaddr.toIpString();
+					supernodes[id.address().toString()] = snd.toString();
+				}
+			}
+		}
+	}
+
+	Dictionary rtd;
+	rtd["supernodes"] = supernodes.toString();
+	rtd["noupdate"] = "1";
+	rootTopology = rtd.toString();
+
+	std::vector<Address> newNodes;
+
+	for(std::vector< std::pair<Identity,InetAddress> >::iterator i(snids.begin());i!=snids.end();++i) {
+		SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + "S" + i->first.address().toString()),rootTopology.c_str(),true,i->second);
+		nodes[id.address()] = n;
+		newNodes.push_back(id.address());
+	}
+
+	return newNodes;
+}
+
+// Instantiates any not-already-instantiated regular nodes
+static std::vector<Address> scanForNewNodes()
+{
+	std::vector<Address> newNodes;
+	std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
+
+	for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
+		if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'N')) {
+			Address na(d->first.c_str() + 1);
+			if (nodes.find(na) == nodes.end()) {
+				InetAddress inaddr(inetAddressFromZeroTierAddress(na));
+
+				SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + d->first),rootTopology.c_str(),false,inaddr);
+				nodes[na] = n;
+
+				newNodes.push_back(na);
+			}
+		}
+	}
+
+	return newNodes;
+}
+
+static void doHelp(const std::vector<std::string> &cmd)
+{
+	printf("---------- help"ZT_EOL_S);
+	printf("---------- mksn <number of supernodes>"ZT_EOL_S);
+	printf("---------- mkn <number of normal nodes>"ZT_EOL_S);
+	printf("---------- list"ZT_EOL_S);
+	printf("---------- join <address/*> <network ID>"ZT_EOL_S);
+	printf("---------- leave <address/*> <network ID>"ZT_EOL_S);
+	printf("---------- listnetworks <address/*>"ZT_EOL_S);
+	printf("---------- listpeers <address/*>"ZT_EOL_S);
+	printf("---------- alltoall"ZT_EOL_S);
+	printf("---------- quit"ZT_EOL_S)
+}
+
+static void doMKSN(const std::vector<std::string> &cmd)
+{
+	if (cmd.size() < 2) {
+		doHelp(cmd);
+		return;
+	}
+	if (nodes.size() > 0) {
+		printf("---------- mksn error: mksn can only be called once (network already exists)"ZT_EOL_S,(unsigned int)nodes.size());
+		return;
+	}
+
+	int count = Utils::strToInt(cmd[1].c_str());
+	for(int i=0;i<count;++i) {
+		Identity id(makeNodeHome(true));
+		printf("%s identity created"ZT_EOL_S,id.address().toString().c_str());
+	}
+
+	std::vector<Address> nodes(initSupernodes());
+	for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
+		printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
+
+	printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
+}
+
+static void doMKN(const std::vector<std::string> &cmd)
+{
+	if (cmd.size() < 2) {
+		doHelp(cmd);
+		return;
+	}
+	if (nodes.size() == 0) {
+		printf("---------- mkn error: use mksn to create supernodes first."ZT_EOL_S);
+		return;
+	}
+}
+
+static void doList(const std::vector<std::string> &cmd)
+{
+}
+
+static void doJoin(const std::vector<std::string> &cmd)
+{
+}
+
+static void doLeave(const std::vector<std::string> &cmd)
+{
+}
+
+static void doListNetworks(const std::vector<std::string> &cmd)
+{
+}
+
+static void doListPeers(const std::vector<std::string> &cmd)
+{
+}
+
+static void doAllToAll(const std::vector<std::string> &cmd)
+{
+}
+
+int main(int argc,char **argv)
+{
+	char linebuf[1024];
+
+	if (argc <= 1) {
+		fprintf(stderr,"Usage: %s <base path for temporary node home directories>"ZT_EOL_S,argv[0]);
+		return 1;
+	}
+
+	basePath = argv[1];
+#ifdef __WINDOWS__
+	CreateDirectoryA(basePath.c_str(),NULL);
+#else
+	mkdir(basePath.c_str(),0700);
+#endif
+
+	printf("*** ZeroTier One Version %s -- Headless Network Simulator ***"ZT_EOL_S,Node::versionString());
+	printf(ZT_EOL_S);
+
+	{
+		printf("---------- scanning '%s' for existing network..."ZT_EOL_S);
+		std::vector<Address> snodes(initSupernodes());
+		if (snodes.empty()) {
+			printf("---------- no existing network found; use 'mksn' to create one."ZT_EOL_S);
+		} else {
+			for(std::vector<Address>::iterator a(snodes.begin());a!=snodes.end();++a)
+				printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
+			printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
+			std::vector<Address> nodes(scanForNewNodes());
+			for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
+				printf("%s started (normal peer)"ZT_EOL_S,a->toString().c_str());
+			printf("---------- %u peers and %u supernodes loaded!"ZT_EOL_S,(unsigned int)nodes.size(),(unsigned int)snodes.size());
+		}
+	}
+	printf(ZT_EOL_S);
+
+	printf("Type 'help' for help."ZT_EOL_S);
+	printf(ZT_EOL_S);
+
+	for(;;) {
+		printf(">> ");
+		fflush(stdout);
+		if (!fgets(linebuf,sizeof(linebuf),stdin))
+			break;
+		std::vector<std::string> cmd(Utils::split(linebuf," \r\n\t","\\","\""));
+		if (cmd.size() == 0)
+			continue;
+
+		if (cmd[0] == "quit")
+			break;
+		else if (cmd[0] == "help")
+			doHelp(cmd);
+		else if (cmd[0] == "mksn")
+			doMKSN(cmd);
+		else if (cmd[0] == "mkn")
+			doMKN(cmd);
+		else if (cmd[0] == "join")
+			doJoin(cmd);
+		else if (cmd[0] == "leave")
+			doLeave(cmd);
+		else if (cmd[0] == "listnetworks")
+			doListNetworks(cmd);
+		else if (cmd[0] == "listpeers")
+			doListPeers(cmd);
+		else if (cmd[0] == "alltoall")
+			doAllToAll(cmd);
+		else doHelp(cmd);
+	}
+
+	for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
+		printf("%s shutting down..."ZT_EOL_S,n->first.toString().c_str());
+		delete n->second;
+	}
+
+	return 0;
+}

+ 11 - 32
testnet/SimNet.cpp

@@ -40,50 +40,29 @@ SimNet::~SimNet()
 {
 }
 
-SimNetSocketManager *newEndpoint()
+SimNetSocketManager *SimNet::newEndpoint(const InetAddress &addr)
 {
 	Mutex::Lock _l(_lock);
 
 	if (_endpoints.size() >= ZT_SIMNET_MAX_TESTNET_SIZE)
 		return (SimNetSocketManager *)0;
+	if (_endpoints.find(addr) != _endpoints.end())
+		return (SimNetSocketManager *)0;
 
-	InetAddress fake;
-	uint32_t ip = _prng.next32();
-	for(;;) {
-		++ip;
-		ip &= 0x00ffffff;
-		ip |= 0x0a000000; // 10.x.x.x
-		if (((ip >> 16) & 0xff) == 0xff) ip ^= 0x00010000;
-		if (((ip >> 8) & 0xff) == 0xff) ip ^= 0x00000100;
-		if ((ip & 0xff) == 0xff) --ip;
-		if ((ip & 0xff) == 0x00) ++ip;
-		uint32_t ipn = Utils::hton(ip);
-		fake.set(&ipn,4,8); // 10.x.x.x/8
-		if (_endpoints.find(fake) == _endpoints.end()) {
-			SimNetSocketManager *sm = &(_endpoints[fake]);
-			sm->_sn = this;
-			sm->_address = fake;
-			return sm;
-		}
-	}
+	SimNetSocketManager *sm = new SimNetSocketManager();
+	sm->_sn = this;
+	sm->_address = addr;
+	_endpoints[addr] = sm;
+	return sm;
 }
 
-SimNetSocketManager *get(const InetAddress &addr)
+SimNetSocketManager *SimNet::get(const InetAddress &addr)
 {
 	Mutex::Lock _l(_lock);
-	std::map< InetAddress,SimNetSocketManager >::iterator ep(_endpoints.find(addr));
+	std::map< InetAddress,SimNetSocketManager * >::iterator ep(_endpoints.find(addr));
 	if (ep == _endpoints.end())
 		return (SimNetSocketManager *)0;
-	return &(ep->second);
-}
-
-std::vector<SimNetSocketManager *> SimNet::all()
-{
-	std::vector<SimNetSocketManager *> a;
-	Mutex::Lock _l(_lock);
-	for (std::map< InetAddress,SimNetSocketManager >::iterator ep(_endpoints.begin());ep!=_endpoints.end();++ep)
-		a.push_back(&(ep->second));
-	return a;
+	return ep->second;
 }
 
 } // namespace ZeroTier

+ 4 - 11
testnet/SimNet.hpp

@@ -34,13 +34,12 @@
 #include "../node/Constants.hpp"
 #include "../node/InetAddress.hpp"
 #include "../node/Mutex.hpp"
-#include "../node/CMWC4096.hpp"
 
 #include "SimNetSocketManager.hpp"
 
 #define ZT_SIMNET_MAX_TESTNET_SIZE 1048576
 
-namespcae ZeroTier {
+namespace ZeroTier {
 
 /**
  * A simulated headless IP network for testing
@@ -52,9 +51,9 @@ public:
 	~SimNet();
 
 	/**
-	 * @return New endpoint with random IP address
+	 * @return New endpoint or NULL on failure
 	 */
-	SimNetSocketManager *newEndpoint();
+	SimNetSocketManager *newEndpoint(const InetAddress &addr);
 
 	/**
 	 * @param addr Address to look up
@@ -62,14 +61,8 @@ public:
 	 */
 	SimNetSocketManager *get(const InetAddress &addr);
 
-	/**
-	 * @return All socket managers (pointers remain safe while SimNet is running-- these aren't cleaned)
-	 */
-	std::vector<SimNetSocketManager *> all();
-
 private:
-	std::map< InetAddress,SimNetSocketManager > _endpoints;
-	CMWC4096 _prng;
+	std::map< InetAddress,SimNetSocketManager * > _endpoints;
 	Mutex _lock;
 };
 

+ 9 - 8
testnet/SimNetSocketManager.cpp

@@ -26,6 +26,7 @@
  */
 
 #include "SimNetSocketManager.hpp"
+#include "SimNet.hpp"
 
 #include "../node/Constants.hpp"
 #include "../node/Socket.hpp"
@@ -73,20 +74,20 @@ bool SimNetSocketManager::send(const InetAddress &to,bool tcp,bool autoConnectTc
 void SimNetSocketManager::poll(unsigned long timeout,void (*handler)(const SharedPtr<Socket> &,void *,const InetAddress &,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &),void *arg)
 {
 	{
-		Mutex::Lock _l(_lock);
-		while (!_queue.empty()) {
-			handler(_mySocket,arg,_queue.front().first,_queue.front().second);
-			_queue.pop();
+		Mutex::Lock _l(_inbox_m);
+		while (!_inbox.empty()) {
+			handler(_mySocket,arg,_inbox.front().first,_inbox.front().second);
+			_inbox.pop();
 		}
 	}
 	if (timeout)
 		_waitCond.wait(timeout);
 	else _waitCond.wait();
 	{
-		Mutex::Lock _l(_lock);
-		while (!_queue.empty()) {
-			handler(_mySocket,arg,_queue.front().first,_queue.front().second);
-			_queue.pop();
+		Mutex::Lock _l(_inbox_m);
+		while (!_inbox.empty()) {
+			handler(_mySocket,arg,_inbox.front().first,_inbox.front().second);
+			_inbox.pop();
 		}
 	}
 }

+ 5 - 2
testnet/SimNetSocketManager.hpp

@@ -32,7 +32,7 @@
 #include <utility>
 #include <queue>
 
-#include "Constants.hpp"
+#include "../node/Constants.hpp"
 #include "../node/SocketManager.hpp"
 #include "../node/Mutex.hpp"
 #include "../node/Condition.hpp"
@@ -76,7 +76,10 @@ public:
 	inline TransferStats stats(const InetAddress &peer) const
 	{
 		Mutex::Lock _l(_stats_m);
-		return _stats[peer];
+		std::map< InetAddress,TransferStats >::const_iterator s(_stats.find(peer));
+		if (s == _stats.end())
+			return TransferStats();
+		return s->second;
 	}
 
 	/**

+ 0 - 8
testnet/TestEthernetTapFactory.cpp

@@ -53,10 +53,6 @@ EthernetTap *TestEthernetTapFactory::open(
 		Mutex::Lock _l(_taps_m);
 		_taps.insert(tap);
 	}
-	{
-		Mutex::Lock _l(_tapsByDevice_m);
-		_tapsByDevice[tap->deviceName()] = tap;
-	}
 	{
 		Mutex::Lock _l(_tapsByMac_m);
 		_tapsByMac[mac] = tap;
@@ -73,10 +69,6 @@ void TestEthernetTapFactory::close(EthernetTap *tap,bool destroyPersistentDevice
 		Mutex::Lock _l(_taps_m);
 		_taps.erase(tapp);
 	}
-	{
-		Mutex::Lock _l(_tapsByDevice_m);
-		_tapsByDevice.erase(tapp->deviceName());
-	}
 	{
 		Mutex::Lock _l(_tapsByMac_m);
 		_tapsByMac.erase(tapp->mac());

+ 0 - 35
testnet/TestEthernetTapFactory.hpp

@@ -68,45 +68,10 @@ public:
 		return t->second;
 	}
 
-	inline SharedPtr<TestEthernetTap> getByDevice(const std::string &dev) const
-	{
-		Mutex::Lock _l(_tapsByDevice_m);
-		std::map< std::string,SharedPtr<TestEthernetTap> >::const_iterator t(_tapsByDevice.find(dev));
-		if (t == _tapsByDevice.end())
-			return SharedPtr<TestEthernetTap>();
-		return t->second;
-	}
-
-	inline SharedPtr<TestEthernetTap> getFirst() const
-	{
-		Mutex::Lock _l(_taps_m);
-		if (_taps.empty())
-			return SharedPtr<TestEthernetTap>();
-		return *(_taps.begin());
-	}
-
-	inline SharedPtr<TestEthernetTap> getRandom() const
-	{
-		Mutex::Lock _l(_taps_m);
-		Mutex::Lock _l2(_prng_m);
-		if (_taps.empty())
-			return SharedPtr<TestEthernetTap>();
-		unsigned int x = (const_cast<CMWC4096 *>(&_prng))->next32() % (unsigned int)_taps.size();
-		unsigned int i = 0;
-		for(std::set< SharedPtr<TestEthernetTap> >::const_iterator t(_taps.begin());t!=_taps.end();++t) {
-			if (i++ == x)
-				return *t;
-		}
-		return SharedPtr<TestEthernetTap>(); // never reached
-	}
-
 private:
 	std::set< SharedPtr<TestEthernetTap> > _taps;
 	Mutex _taps_m;
 
-	std::map<std::string,SharedPtr<TestEthernetTap> > _tapsByDevice;
-	Mutex _tapsByDevice_m;
-
 	std::map<MAC,SharedPtr<TestEthernetTap> > _tapsByMac;
 	Mutex _tapsByMac_m;