diff options
Diffstat (limited to 'attic/testnet.cpp')
-rw-r--r-- | attic/testnet.cpp | 765 |
1 files changed, 0 insertions, 765 deletions
diff --git a/attic/testnet.cpp b/attic/testnet.cpp deleted file mode 100644 index 5b175728..00000000 --- a/attic/testnet.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/* - * ZeroTier One - Network Virtualization Everywhere - * Copyright (C) 2011-2015 ZeroTier, Inc. - * - * 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/ - */ - -/* SEE: testnet/README.md */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> - -#include <string> -#include <map> -#include <vector> -#include <set> - -#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 "node/Dictionary.hpp" - -#include "testnet/SimNet.hpp" -#include "testnet/SimNetSocketManager.hpp" -#include "testnet/TestEthernetTap.hpp" -#include "testnet/TestEthernetTapFactory.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(), - socketManager(net.newEndpoint(addr)), - node(home.c_str(),&tapFactory,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; - 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").c_str(),id.toString(true))) - return Identity(); - if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),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[i->first.address()] = n; - newNodes.push_back(i->first.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("---------- unicast <address/*/**> <address/*/**> <network ID> <frame length, min: 16> [<timeout (sec)>]"ZT_EOL_S); - printf("---------- multicast <address/*/**> <MAC/* for bcast> <network ID> <frame length, min: 16> [<timeout (sec)>]"ZT_EOL_S); - printf("---------- quit"ZT_EOL_S); - printf("---------- ( * means all regular nodes, ** means including supernodes )"ZT_EOL_S); - printf("---------- ( . runs previous command again )"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); - 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; - } - - int count = Utils::strToInt(cmd[1].c_str()); - for(int i=0;i<count;++i) { - Identity id(makeNodeHome(false)); - printf("%s identity created"ZT_EOL_S,id.address().toString().c_str()); - } - - std::vector<Address> nodes(scanForNewNodes()); - for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a) - printf("%s started (regular node)"ZT_EOL_S,a->toString().c_str()); -} - -static void doList(const std::vector<std::string> &cmd) -{ - unsigned int peers = 0,supernodes = 0; - ZT1_Node_Status status; - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - n->second->node.status(&status); - if (status.initialized) { - printf("%s %c %s (%u peers, %u direct links)"ZT_EOL_S, - n->first.toString().c_str(), - n->second->supernode ? 'S' : 'N', - (status.online ? "ONLINE" : "OFFLINE"), - status.knownPeers, - status.directlyConnectedPeers); - if (n->second->supernode) - ++supernodes; - else ++peers; - } else printf("%s ? INITIALIZING (0 peers, 0 direct links)"ZT_EOL_S,n->first.toString().c_str()); - } - printf("---------- %u regular peers, %u supernodes"ZT_EOL_S,peers,supernodes); -} - -static void doJoin(const std::vector<std::string> &cmd) -{ - if (cmd.size() < 3) { - doHelp(cmd); - return; - } - - std::vector<Address> addrs; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - addrs.push_back(n->first); - } - } else addrs.push_back(Address(cmd[1])); - - uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str()); - - for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) { - std::map< Address,SimNode * >::iterator n(nodes.find(*a)); - if (n != nodes.end()) { - n->second->node.join(nwid); - printf("%s join %.16llx"ZT_EOL_S,n->first.toString().c_str(),(unsigned long long)nwid); - } - } -} - -static void doLeave(const std::vector<std::string> &cmd) -{ - if (cmd.size() < 3) { - doHelp(cmd); - return; - } - - std::vector<Address> addrs; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - addrs.push_back(n->first); - } - } else addrs.push_back(Address(cmd[1])); - - uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str()); - - for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) { - std::map< Address,SimNode * >::iterator n(nodes.find(*a)); - if (n != nodes.end()) { - n->second->node.leave(nwid); - printf("%s leave %.16llx"ZT_EOL_S,n->first.toString().c_str(),(unsigned long long)nwid); - } - } -} - -static void doListNetworks(const std::vector<std::string> &cmd) -{ - if (cmd.size() < 2) { - doHelp(cmd); - return; - } - - std::vector<Address> addrs; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - addrs.push_back(n->first); - } - } else addrs.push_back(Address(cmd[1])); - - printf("---------- <nwid> <name> <mac> <status> <config age> <type> <dev> <ips>"ZT_EOL_S); - - for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) { - std::string astr(a->toString()); - std::map< Address,SimNode * >::iterator n(nodes.find(*a)); - if (n != nodes.end()) { - ZT1_Node_NetworkList *nl = n->second->node.listNetworks(); - if (nl) { - for(unsigned int i=0;i<nl->numNetworks;++i) { - printf("%s %s %s %s %s %ld %s %s ", - astr.c_str(), - nl->networks[i].nwidHex, - nl->networks[i].name, - nl->networks[i].macStr, - nl->networks[i].statusStr, - nl->networks[i].configAge, - (nl->networks[i].isPrivate ? "private" : "public"), - nl->networks[i].device); - if (nl->networks[i].numIps > 0) { - for(unsigned int j=0;j<nl->networks[i].numIps;++j) { - if (j > 0) - printf(","); - printf("%s/%d",nl->networks[i].ips[j].ascii,(int)nl->networks[i].ips[j].port); - } - } else printf("-"); - printf(ZT_EOL_S); - } - n->second->node.freeQueryResult(nl); - } - } - } -} - -static void doListPeers(const std::vector<std::string> &cmd) -{ - if (cmd.size() < 2) { - doHelp(cmd); - return; - } - - std::vector<Address> addrs; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - addrs.push_back(n->first); - } - } else addrs.push_back(Address(cmd[1])); - - printf("---------- <ztaddr> <paths> <latency> <version> <role>"ZT_EOL_S); - - for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) { - std::string astr(a->toString()); - std::map< Address,SimNode * >::iterator n(nodes.find(*a)); - if (n != nodes.end()) { - ZT1_Node_PeerList *pl = n->second->node.listPeers(); - if (pl) { - for(unsigned int i=0;i<pl->numPeers;++i) { - printf("%s %.10llx ",astr.c_str(),(unsigned long long)pl->peers[i].rawAddress); - if (pl->peers[i].numPaths == 0) - printf("-"); - else { - for(unsigned int j=0;j<pl->peers[i].numPaths;++j) { - if (j > 0) - printf(","); - switch(pl->peers[i].paths[j].type) { - default: - printf("unknown;"); - break; - case ZT1_Node_PhysicalPath_TYPE_UDP: - printf("udp;"); - break; - case ZT1_Node_PhysicalPath_TYPE_TCP_OUT: - printf("tcp_out;"); - break; - case ZT1_Node_PhysicalPath_TYPE_TCP_IN: - printf("tcp_in;"); - break; - case ZT1_Node_PhysicalPath_TYPE_ETHERNET: - printf("eth;"); - break; - } - printf("%s/%d;%ld;%ld;%ld;%s", - pl->peers[i].paths[j].address.ascii, - (int)pl->peers[i].paths[j].address.port, - pl->peers[i].paths[j].lastSend, - pl->peers[i].paths[j].lastReceive, - pl->peers[i].paths[j].lastPing, - (pl->peers[i].paths[j].fixed ? "fixed" : (pl->peers[i].paths[j].active ? "active" : "inactive"))); - } - } - const char *rolestr; - switch(pl->peers[i].role) { - case ZT1_Node_Peer_SUPERNODE: rolestr = "SUPERNODE"; break; - case ZT1_Node_Peer_HUB: rolestr = "HUB"; break; - case ZT1_Node_Peer_NODE: rolestr = "NODE"; break; - default: rolestr = "?"; break; - } - printf(" %u %s %s"ZT_EOL_S, - pl->peers[i].latency, - ((pl->peers[i].remoteVersion[0]) ? pl->peers[i].remoteVersion : "-"), - rolestr); - } - n->second->node.freeQueryResult(pl); - } - } - } -} - -static void doUnicast(const std::vector<std::string> &cmd) -{ - union { - uint64_t i[2]; - unsigned char data[2800]; - } pkt; - - if (cmd.size() < 5) { - doHelp(cmd); - return; - } - - uint64_t nwid = Utils::hexStrToU64(cmd[3].c_str()); - unsigned int frameLen = Utils::strToUInt(cmd[4].c_str()); - uint64_t tout = 2000; - if (cmd.size() >= 6) - tout = Utils::strToU64(cmd[5].c_str()) * 1000ULL; - - if (frameLen < 16) - frameLen = 16; - if (frameLen > 2800) - frameLen = 2800; - - std::vector<Address> senders; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - senders.push_back(n->first); - } - } else senders.push_back(Address(cmd[1])); - - std::vector<Address> receivers; - if ((cmd[2] == "*")||(cmd[2] == "**")) { - bool includeSuper = (cmd[2] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - receivers.push_back(n->first); - } - } else receivers.push_back(Address(cmd[2])); - - for(unsigned int i=0;i<frameLen;++i) - pkt.data[i] = (unsigned char)prng.next32(); - - std::set< std::pair<Address,Address> > sentPairs; - for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) { - for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) { - if (*s == *r) - continue; - - SimNode *sender = nodes[*s]; - SimNode *receiver = nodes[*r]; - TestEthernetTap *stap = sender->tapFactory.getByNwid(nwid); - TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid); - - if ((stap)&&(rtap)) { - pkt.i[0] = s->toInt(); - pkt.i[1] = Utils::now(); - stap->injectPacketFromHost(stap->mac(),rtap->mac(),0xdead,pkt.data,frameLen); - printf("%s -> %s etherType 0xdead network %.16llx length %u"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),(unsigned long long)nwid,frameLen); - sentPairs.insert(std::pair<Address,Address>(*s,*r)); - } else if (stap) { - printf("%s -> !%s (receiver not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),(unsigned long long)nwid); - } else if (rtap) { - printf("%s -> !%s (sender not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),(unsigned long long)nwid); - } else { - printf("%s -> !%s (neither party is a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),(unsigned long long)nwid); - } - } - } - - printf("---------- waiting up to %llu seconds..."ZT_EOL_S,tout / 1000ULL); - - std::set< std::pair<Address,Address> > receivedPairs; - TestEthernetTap::TestFrame frame; - uint64_t toutend = Utils::now() + tout; - do { - for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) { - SimNode *receiver = nodes[*r]; - TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid); - - if ((rtap)&&(rtap->getNextReceivedFrame(frame,5))) { - if ((frame.len == frameLen)&&(!memcmp(frame.data + 16,pkt.data + 16,frameLen - 16))) { - uint64_t ints[2]; - memcpy(ints,frame.data,16); - printf("%s <- %.10llx received test packet, length == %u, latency == %llums"ZT_EOL_S,r->toString().c_str(),(unsigned long long)ints[0],frame.len,(unsigned long long)(frame.timestamp - ints[1])); - receivedPairs.insert(std::pair<Address,Address>(Address(ints[0]),*r)); - } else { - printf("%s !! got spurious packet, length == %u, etherType == 0x%.4x"ZT_EOL_S,r->toString().c_str(),frame.len,frame.etherType); - } - } - } - - Thread::sleep(100); - } while ((receivedPairs.size() < sentPairs.size())&&(Utils::now() < toutend)); - - for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) { - for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) { - if (*s == *r) - continue; - if ((sentPairs.count(std::pair<Address,Address>(*s,*r)))&&(!receivedPairs.count(std::pair<Address,Address>(*s,*r)))) { - printf("%s <- %s was never received (timed out)"ZT_EOL_S,r->toString().c_str(),s->toString().c_str()); - } - } - } - - printf("---------- sent %u, received %u"ZT_EOL_S,(unsigned int)sentPairs.size(),(unsigned int)receivedPairs.size()); -} - -static void doMulticast(const std::vector<std::string> &cmd) -{ - union { - uint64_t i[2]; - unsigned char data[2800]; - } pkt; - - if (cmd.size() < 5) { - doHelp(cmd); - return; - } - - uint64_t nwid = Utils::hexStrToU64(cmd[3].c_str()); - unsigned int frameLen = Utils::strToUInt(cmd[4].c_str()); - uint64_t tout = 2000; - if (cmd.size() >= 6) - tout = Utils::strToU64(cmd[5].c_str()) * 1000ULL; - - if (frameLen < 16) - frameLen = 16; - if (frameLen > 2800) - frameLen = 2800; - - std::vector<Address> senders; - if ((cmd[1] == "*")||(cmd[1] == "**")) { - bool includeSuper = (cmd[1] == "**"); - for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { - if ((includeSuper)||(!n->second->supernode)) - senders.push_back(n->first); - } - } else senders.push_back(Address(cmd[1])); - - MAC mcaddr; - if (cmd[2] == "*") - mcaddr = MAC(0xff,0xff,0xff,0xff,0xff,0xff); - else mcaddr.fromString(cmd[2].c_str()); - - if (!mcaddr.isMulticast()) { - printf("---------- %s is not a multicast MAC address"ZT_EOL_S,mcaddr.toString().c_str()); - return; - } - - for(unsigned int i=0;i<frameLen;++i) - pkt.data[i] = (unsigned char)prng.next32(); - - for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) { - SimNode *sender = nodes[*s]; - TestEthernetTap *stap = sender->tapFactory.getByNwid(nwid); - - if (stap) { - pkt.i[0] = s->toInt(); - pkt.i[1] = Utils::now(); - stap->injectPacketFromHost(stap->mac(),mcaddr,0xdead,pkt.data,frameLen); - printf("%s -> %s etherType 0xdead network %.16llx length %u"ZT_EOL_S,s->toString().c_str(),mcaddr.toString().c_str(),(unsigned long long)nwid,frameLen); - } else { - printf("%s -> !%s (sender is not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),mcaddr.toString().c_str(),(unsigned long long)nwid); - } - } - - printf("---------- waiting %llu seconds..."ZT_EOL_S,tout / 1000ULL); - - unsigned int receiveCount = 0; - TestEthernetTap::TestFrame frame; - uint64_t toutend = Utils::now() + tout; - do { - for(std::map< Address,SimNode * >::iterator nn(nodes.begin());nn!=nodes.end();++nn) { - SimNode *receiver = nn->second; - TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid); - - if ((rtap)&&(rtap->getNextReceivedFrame(frame,5))) { - if ((frame.len == frameLen)&&(!memcmp(frame.data + 16,pkt.data + 16,frameLen - 16))) { - uint64_t ints[2]; - memcpy(ints,frame.data,16); - printf("%s <- %.10llx received test packet, length == %u, latency == %llums"ZT_EOL_S,nn->first.toString().c_str(),(unsigned long long)ints[0],frame.len,(unsigned long long)(frame.timestamp - ints[1])); - ++receiveCount; - } else { - printf("%s !! got spurious packet, length == %u, etherType == 0x%.4x"ZT_EOL_S,nn->first.toString().c_str(),frame.len,frame.etherType); - } - } - } - - Thread::sleep(100); - } while (Utils::now() < toutend); - - printf("---------- test multicast received by %u peers"ZT_EOL_S,receiveCount); -} - -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,basePath.c_str()); - 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); - - std::vector<std::string> cmd,prevCmd; - bool run = true; - while (run) { - printf(">> "); - fflush(stdout); - if (!fgets(linebuf,sizeof(linebuf),stdin)) - break; - - cmd = Utils::split(linebuf," \r\n\t","\\","\""); - - for(;;) { - if (cmd.size() == 0) - break; - else if (cmd[0] == "quit") - run = false; - 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] == "list") - doList(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] == "unicast") - doUnicast(cmd); - else if (cmd[0] == "multicast") - doMulticast(cmd); - else if ((cmd[0] == ".")&&(prevCmd.size() > 0)) { - cmd = prevCmd; - continue; - } else doHelp(cmd); - break; - } - - if ((cmd.size() > 0)&&(cmd[0] != ".")) - prevCmd = 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; -} |