summaryrefslogtreecommitdiff
path: root/attic/testnet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/testnet.cpp')
-rw-r--r--attic/testnet.cpp765
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;
-}