testnet.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * ZeroTier One - Global Peer to Peer Ethernet
  3. * Copyright (C) 2011-2014 ZeroTier Networks LLC
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * ZeroTier may be used and distributed under the terms of the GPLv3, which
  21. * are available at: http://www.gnu.org/licenses/gpl-3.0.html
  22. *
  23. * If you would like to embed ZeroTier into a commercial application or
  24. * redistribute it in a modified binary form, please contact ZeroTier Networks
  25. * LLC. Start here: http://www.zerotier.com/
  26. */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <stdint.h>
  30. #include <string>
  31. #include <map>
  32. #include <vector>
  33. #include <set>
  34. #include "node/Constants.hpp"
  35. #include "node/Node.hpp"
  36. #include "node/Utils.hpp"
  37. #include "node/Address.hpp"
  38. #include "node/Identity.hpp"
  39. #include "node/Thread.hpp"
  40. #include "node/CMWC4096.hpp"
  41. #include "node/Dictionary.hpp"
  42. #include "testnet/SimNet.hpp"
  43. #include "testnet/SimNetSocketManager.hpp"
  44. #include "testnet/TestEthernetTap.hpp"
  45. #include "testnet/TestEthernetTapFactory.hpp"
  46. #include "testnet/TestRoutingTable.hpp"
  47. #ifdef __WINDOWS__
  48. #include <windows.h>
  49. #else
  50. #include <unistd.h>
  51. #include <sys/stat.h>
  52. #endif
  53. using namespace ZeroTier;
  54. class SimNode
  55. {
  56. public:
  57. SimNode(SimNet &net,const std::string &hp,const char *rootTopology,bool issn,const InetAddress &addr) :
  58. home(hp),
  59. tapFactory(),
  60. routingTable(),
  61. socketManager(net.newEndpoint(addr)),
  62. node(home.c_str(),&tapFactory,&routingTable,socketManager,false,rootTopology),
  63. reasonForTermination(Node::NODE_RUNNING),
  64. supernode(issn)
  65. {
  66. thread = Thread::start(this);
  67. }
  68. ~SimNode()
  69. {
  70. node.terminate(Node::NODE_NORMAL_TERMINATION,"SimNode shutdown");
  71. Thread::join(thread);
  72. }
  73. void threadMain()
  74. throw()
  75. {
  76. reasonForTermination = node.run();
  77. }
  78. std::string home;
  79. TestEthernetTapFactory tapFactory;
  80. TestRoutingTable routingTable;
  81. SimNetSocketManager *socketManager;
  82. Node node;
  83. Node::ReasonForTermination reasonForTermination;
  84. bool supernode;
  85. Thread thread;
  86. };
  87. static std::string basePath;
  88. static SimNet net;
  89. static std::map< Address,SimNode * > nodes;
  90. static std::map< InetAddress,Address > usedIps;
  91. static CMWC4096 prng;
  92. static std::string rootTopology;
  93. // Converts an address into a fake IP not already claimed.
  94. // Be sure to call only once, as this claims the IP before returning it.
  95. static InetAddress inetAddressFromZeroTierAddress(const Address &addr)
  96. {
  97. uint32_t ip = (uint32_t)(addr.toInt() & 0xffffffff);
  98. for(;;) {
  99. if (((ip >> 24) & 0xff) >= 240) {
  100. ip &= 0x00ffffff;
  101. ip |= (((ip >> 24) & 0xff) % 240) << 24;
  102. }
  103. if (((ip >> 24) & 0xff) == 0)
  104. ip |= 0x01000000;
  105. if (((ip & 0xff) == 0)||((ip & 0xff) == 255))
  106. ip ^= 0x00000001;
  107. InetAddress inaddr(Utils::hton(ip),9993);
  108. if (usedIps.find(inaddr) == usedIps.end()) {
  109. usedIps[inaddr] = addr;
  110. return inaddr;
  111. }
  112. ++ip; // keep looking sequentially for an unclaimed IP
  113. }
  114. }
  115. static Identity makeNodeHome(bool super)
  116. {
  117. Identity id;
  118. id.generate();
  119. std::string path(basePath + ZT_PATH_SEPARATOR_S + (super ? "S" : "N") + id.address().toString());
  120. #ifdef __WINDOWS__
  121. CreateDirectoryA(path.c_str(),NULL);
  122. #else
  123. mkdir(path.c_str(),0700);
  124. #endif
  125. if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),id.toString(true)))
  126. return Identity();
  127. if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),id.toString(false)))
  128. return Identity();
  129. return id;
  130. }
  131. // Instantiates supernodes by scanning for S########## subdirectories
  132. static std::vector<Address> initSupernodes()
  133. {
  134. Dictionary supernodes;
  135. std::vector< std::pair<Identity,InetAddress> > snids;
  136. std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
  137. for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
  138. if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'S')) {
  139. std::string idbuf;
  140. if (Utils::readFile((basePath + ZT_PATH_SEPARATOR_S + d->first + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),idbuf)) {
  141. Identity id(idbuf);
  142. if (id) {
  143. InetAddress inaddr(inetAddressFromZeroTierAddress(id.address()));
  144. snids.push_back(std::pair<Identity,InetAddress>(id,inaddr));
  145. Dictionary snd;
  146. snd["id"] = id.toString(false);
  147. snd["udp"] = inaddr.toString();
  148. snd["desc"] = id.address().toString();
  149. snd["dns"] = inaddr.toIpString();
  150. supernodes[id.address().toString()] = snd.toString();
  151. }
  152. }
  153. }
  154. }
  155. Dictionary rtd;
  156. rtd["supernodes"] = supernodes.toString();
  157. rtd["noupdate"] = "1";
  158. rootTopology = rtd.toString();
  159. std::vector<Address> newNodes;
  160. for(std::vector< std::pair<Identity,InetAddress> >::iterator i(snids.begin());i!=snids.end();++i) {
  161. SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + "S" + i->first.address().toString()),rootTopology.c_str(),true,i->second);
  162. nodes[i->first.address()] = n;
  163. newNodes.push_back(i->first.address());
  164. }
  165. return newNodes;
  166. }
  167. // Instantiates any not-already-instantiated regular nodes
  168. static std::vector<Address> scanForNewNodes()
  169. {
  170. std::vector<Address> newNodes;
  171. std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
  172. for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
  173. if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'N')) {
  174. Address na(d->first.c_str() + 1);
  175. if (nodes.find(na) == nodes.end()) {
  176. InetAddress inaddr(inetAddressFromZeroTierAddress(na));
  177. SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + d->first),rootTopology.c_str(),false,inaddr);
  178. nodes[na] = n;
  179. newNodes.push_back(na);
  180. }
  181. }
  182. }
  183. return newNodes;
  184. }
  185. static void doHelp(const std::vector<std::string> &cmd)
  186. {
  187. printf("---------- help"ZT_EOL_S);
  188. printf("---------- mksn <number of supernodes>"ZT_EOL_S);
  189. printf("---------- mkn <number of normal nodes>"ZT_EOL_S);
  190. printf("---------- list"ZT_EOL_S);
  191. printf("---------- join <address/*/**> <network ID>"ZT_EOL_S);
  192. printf("---------- leave <address/*/**> <network ID>"ZT_EOL_S);
  193. printf("---------- listnetworks <address/*/**>"ZT_EOL_S);
  194. printf("---------- listpeers <address/*/**>"ZT_EOL_S);
  195. printf("---------- unicast <address/*/**> <address/*/**> <network ID> <frame length, min: 8> [<timeout, default: 2>]"ZT_EOL_S);
  196. printf("---------- quit"ZT_EOL_S);
  197. }
  198. static void doMKSN(const std::vector<std::string> &cmd)
  199. {
  200. if (cmd.size() < 2) {
  201. doHelp(cmd);
  202. return;
  203. }
  204. if (nodes.size() > 0) {
  205. printf("---------- mksn error: mksn can only be called once (network already exists)"ZT_EOL_S);
  206. return;
  207. }
  208. int count = Utils::strToInt(cmd[1].c_str());
  209. for(int i=0;i<count;++i) {
  210. Identity id(makeNodeHome(true));
  211. printf("%s identity created"ZT_EOL_S,id.address().toString().c_str());
  212. }
  213. std::vector<Address> nodes(initSupernodes());
  214. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  215. printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
  216. printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
  217. }
  218. static void doMKN(const std::vector<std::string> &cmd)
  219. {
  220. if (cmd.size() < 2) {
  221. doHelp(cmd);
  222. return;
  223. }
  224. if (nodes.size() == 0) {
  225. printf("---------- mkn error: use mksn to create supernodes first."ZT_EOL_S);
  226. return;
  227. }
  228. int count = Utils::strToInt(cmd[1].c_str());
  229. for(int i=0;i<count;++i) {
  230. Identity id(makeNodeHome(false));
  231. printf("%s identity created"ZT_EOL_S,id.address().toString().c_str());
  232. }
  233. std::vector<Address> nodes(scanForNewNodes());
  234. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  235. printf("%s started (regular node)"ZT_EOL_S,a->toString().c_str());
  236. }
  237. static void doList(const std::vector<std::string> &cmd)
  238. {
  239. ZT1_Node_Status status;
  240. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  241. n->second->node.status(&status);
  242. printf("%s %c %s (%u peers, %u direct links)"ZT_EOL_S,
  243. n->first.toString().c_str(),
  244. n->second->supernode ? 'S' : 'N',
  245. (status.online ? "ONLINE" : "OFFLINE"),
  246. status.knownPeers,
  247. status.directlyConnectedPeers);
  248. }
  249. }
  250. static void doJoin(const std::vector<std::string> &cmd)
  251. {
  252. if (cmd.size() < 3) {
  253. doHelp(cmd);
  254. return;
  255. }
  256. std::vector<Address> addrs;
  257. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  258. bool includeSuper = (cmd[1] == "**");
  259. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  260. if ((includeSuper)||(!n->second->supernode))
  261. addrs.push_back(n->first);
  262. }
  263. } else addrs.push_back(Address(cmd[1]));
  264. uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str());
  265. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  266. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  267. if (n != nodes.end()) {
  268. n->second->node.join(nwid);
  269. printf("%s join %.16llx"ZT_EOL_S,n->first.toString().c_str(),nwid);
  270. }
  271. }
  272. }
  273. static void doLeave(const std::vector<std::string> &cmd)
  274. {
  275. if (cmd.size() < 3) {
  276. doHelp(cmd);
  277. return;
  278. }
  279. std::vector<Address> addrs;
  280. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  281. bool includeSuper = (cmd[1] == "**");
  282. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  283. if ((includeSuper)||(!n->second->supernode))
  284. addrs.push_back(n->first);
  285. }
  286. } else addrs.push_back(Address(cmd[1]));
  287. uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str());
  288. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  289. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  290. if (n != nodes.end()) {
  291. n->second->node.leave(nwid);
  292. printf("%s leave %.16llx"ZT_EOL_S,n->first.toString().c_str(),nwid);
  293. }
  294. }
  295. }
  296. static void doListNetworks(const std::vector<std::string> &cmd)
  297. {
  298. if (cmd.size() < 2) {
  299. doHelp(cmd);
  300. return;
  301. }
  302. std::vector<Address> addrs;
  303. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  304. bool includeSuper = (cmd[1] == "**");
  305. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  306. if ((includeSuper)||(!n->second->supernode))
  307. addrs.push_back(n->first);
  308. }
  309. } else addrs.push_back(Address(cmd[1]));
  310. printf("---------- <nwid> <name> <mac> <status> <config age> <type> <dev> <ips>"ZT_EOL_S);
  311. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  312. std::string astr(a->toString());
  313. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  314. if (n != nodes.end()) {
  315. ZT1_Node_NetworkList *nl = n->second->node.listNetworks();
  316. if (nl) {
  317. for(unsigned int i=0;i<nl->numNetworks;++i) {
  318. printf("%s %s %s %s %s %ld %s %s ",
  319. astr.c_str(),
  320. nl->networks[i].nwidHex,
  321. nl->networks[i].name,
  322. nl->networks[i].macStr,
  323. nl->networks[i].statusStr,
  324. nl->networks[i].configAge,
  325. (nl->networks[i].isPrivate ? "private" : "public"),
  326. nl->networks[i].device);
  327. if (nl->networks[i].numIps > 0) {
  328. for(unsigned int j=0;j<nl->networks[i].numIps;++j) {
  329. if (j > 0)
  330. printf(",");
  331. printf("%s/%d",nl->networks[i].ips[j].ascii,(int)nl->networks[i].ips[j].port);
  332. }
  333. } else printf("-");
  334. printf(ZT_EOL_S);
  335. }
  336. n->second->node.freeQueryResult(nl);
  337. }
  338. }
  339. }
  340. }
  341. static void doListPeers(const std::vector<std::string> &cmd)
  342. {
  343. if (cmd.size() < 2) {
  344. doHelp(cmd);
  345. return;
  346. }
  347. std::vector<Address> addrs;
  348. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  349. bool includeSuper = (cmd[1] == "**");
  350. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  351. if ((includeSuper)||(!n->second->supernode))
  352. addrs.push_back(n->first);
  353. }
  354. } else addrs.push_back(Address(cmd[1]));
  355. printf("---------- <ztaddr> <paths> <latency> <version> <role>"ZT_EOL_S);
  356. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  357. std::string astr(a->toString());
  358. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  359. if (n != nodes.end()) {
  360. ZT1_Node_PeerList *pl = n->second->node.listPeers();
  361. if (pl) {
  362. for(unsigned int i=0;i<pl->numPeers;++i) {
  363. printf("%s %.10llx ",astr.c_str(),(unsigned long long)pl->peers[i].rawAddress);
  364. if (pl->peers[i].numPaths == 0)
  365. printf("-");
  366. else {
  367. for(unsigned int j=0;j<pl->peers[i].numPaths;++j) {
  368. if (j > 0)
  369. printf(",");
  370. switch(pl->peers[i].paths[j].type) {
  371. default:
  372. printf("unknown;");
  373. break;
  374. case ZT1_Node_PhysicalPath_TYPE_UDP:
  375. printf("udp;");
  376. break;
  377. case ZT1_Node_PhysicalPath_TYPE_TCP_OUT:
  378. printf("tcp_out;");
  379. break;
  380. case ZT1_Node_PhysicalPath_TYPE_TCP_IN:
  381. printf("tcp_in;");
  382. break;
  383. case ZT1_Node_PhysicalPath_TYPE_ETHERNET:
  384. printf("eth;");
  385. break;
  386. }
  387. printf("%s/%d;%ld;%ld;%ld;%s",
  388. pl->peers[i].paths[j].address.ascii,
  389. (int)pl->peers[i].paths[j].address.port,
  390. pl->peers[i].paths[j].lastSend,
  391. pl->peers[i].paths[j].lastReceive,
  392. pl->peers[i].paths[j].lastPing,
  393. (pl->peers[i].paths[j].fixed ? "fixed" : (pl->peers[i].paths[j].active ? "active" : "inactive")));
  394. }
  395. }
  396. const char *rolestr;
  397. switch(pl->peers[i].role) {
  398. case ZT1_Node_Peer_SUPERNODE: rolestr = "SUPERNODE"; break;
  399. case ZT1_Node_Peer_HUB: rolestr = "HUB"; break;
  400. case ZT1_Node_Peer_NODE: rolestr = "NODE"; break;
  401. default: rolestr = "?"; break;
  402. }
  403. printf(" %u %s %s"ZT_EOL_S,
  404. pl->peers[i].latency,
  405. ((pl->peers[i].remoteVersion[0]) ? pl->peers[i].remoteVersion : "-"),
  406. rolestr);
  407. }
  408. n->second->node.freeQueryResult(pl);
  409. }
  410. }
  411. }
  412. }
  413. static void doUnicast(const std::vector<std::string> &cmd)
  414. {
  415. volatile union {
  416. uint64_t ts;
  417. unsigned char data[2800];
  418. } pkt,inpkt;
  419. if (cmd.size() < 5) {
  420. doHelp(cmd);
  421. return;
  422. }
  423. uint64_t nwid = Utils::hexStrToU64(cmd[3].c_str());
  424. unsigned int frameLen = Utils::strToUInt(cmd[4].c_str());
  425. uint64_t tout = 2000;
  426. if (cmd.size() >= 6)
  427. tout = Utils::strToU64(cmd[5].c_str()) * 1000ULL;
  428. if (frameLen < 8) {
  429. doHelp(cmd);
  430. return;
  431. }
  432. if (frameLen > 2800)
  433. frameLen = 2800;
  434. std::vector<Address> senders;
  435. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  436. bool includeSuper = (cmd[1] == "**");
  437. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  438. if ((includeSuper)||(!n->second->supernode))
  439. senders.push_back(n->first);
  440. }
  441. } else senders.push_back(Address(cmd[1]));
  442. std::vector<Address> receivers;
  443. if ((cmd[2] == "*")||(cmd[2] == "**")) {
  444. bool includeSuper = (cmd[2] == "**");
  445. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  446. if ((includeSuper)||(!n->second->supernode))
  447. receivers.push_back(n->first);
  448. }
  449. } else receivers.push_back(Address(cmd[2]));
  450. for(unsigned int i=0;i<frameLen;++i)
  451. pkt.data[i] = (unsigned char)prng.next32();
  452. for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) {
  453. for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) {
  454. if (*s == *r)
  455. continue;
  456. SimNode *sender = nodes[*s];
  457. SimNode *receiver = nodes[*r];
  458. SharedPtr<TestEthernetTap> stap(sender->tapFactory.getByNwid(nwid));
  459. SharedPtr<TestEthernetTap> rtap(receiver->tapFactory.getByNwid(nwid));
  460. if ((stap)&&(rtap)) {
  461. pkt.ts = Utils::now();
  462. tap->injectPacketFromHost(stap->mac(),rtap->mac(),0xdead,pkt.data,frameLen);
  463. printf("%s -> %s etherType 0xdead network %.16llx length %u"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid,frameLen);
  464. } else if (stap)
  465. printf("%s -> !%s (receiver not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  466. else if (rtap)
  467. printf("%s -> !%s (sender not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  468. else printf("%s -> !%s (neither party is a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  469. }
  470. }
  471. printf("---------- waiting up to %llu seconds...",tout / 1000ULL);
  472. std::set<Address> receivedFrom;
  473. uint64_t toutend = Utils::now() + tout;
  474. do {
  475. std::vector<TestEthernetTap::TestFrame> frames;
  476. for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) {
  477. SimNode *receiver = nodes[*r];
  478. SharedPtr<TestEthernetTap> rtap(receiver->tapFactory.getByNwid(nwid));
  479. if (rtap) {
  480. rtap->get(frames,true);
  481. for(std::vector<TestEthernetTap::TestFrame>::iterator f(frames.begin());f!=frames.end();++f) {
  482. if ((f->len == frameLen)&&(!memcmp(f->data + 8,pkt.data + 8,frameLen - 8))) {
  483. receivedFrom.insert(*r);
  484. }
  485. }
  486. }
  487. }
  488. } while ((receivedFrom.size() < receivers.size())&&(Utils::now() < toutend));
  489. }
  490. int main(int argc,char **argv)
  491. {
  492. char linebuf[1024];
  493. if (argc <= 1) {
  494. fprintf(stderr,"Usage: %s <base path for temporary node home directories>"ZT_EOL_S,argv[0]);
  495. return 1;
  496. }
  497. basePath = argv[1];
  498. #ifdef __WINDOWS__
  499. CreateDirectoryA(basePath.c_str(),NULL);
  500. #else
  501. mkdir(basePath.c_str(),0700);
  502. #endif
  503. printf("*** ZeroTier One Version %s -- Headless Network Simulator ***"ZT_EOL_S,Node::versionString());
  504. printf(ZT_EOL_S);
  505. {
  506. printf("---------- scanning '%s' for existing network..."ZT_EOL_S,basePath.c_str());
  507. std::vector<Address> snodes(initSupernodes());
  508. if (snodes.empty()) {
  509. printf("---------- no existing network found; use 'mksn' to create one."ZT_EOL_S);
  510. } else {
  511. for(std::vector<Address>::iterator a(snodes.begin());a!=snodes.end();++a)
  512. printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
  513. printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
  514. std::vector<Address> nodes(scanForNewNodes());
  515. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  516. printf("%s started (normal peer)"ZT_EOL_S,a->toString().c_str());
  517. printf("---------- %u peers and %u supernodes loaded!"ZT_EOL_S,(unsigned int)nodes.size(),(unsigned int)snodes.size());
  518. }
  519. }
  520. printf(ZT_EOL_S);
  521. printf("Type 'help' for help."ZT_EOL_S);
  522. printf(ZT_EOL_S);
  523. for(;;) {
  524. printf(">> ");
  525. fflush(stdout);
  526. if (!fgets(linebuf,sizeof(linebuf),stdin))
  527. break;
  528. std::vector<std::string> cmd(Utils::split(linebuf," \r\n\t","\\","\""));
  529. if (cmd.size() == 0)
  530. continue;
  531. if (cmd[0] == "quit")
  532. break;
  533. else if (cmd[0] == "help")
  534. doHelp(cmd);
  535. else if (cmd[0] == "mksn")
  536. doMKSN(cmd);
  537. else if (cmd[0] == "mkn")
  538. doMKN(cmd);
  539. else if (cmd[0] == "list")
  540. doList(cmd);
  541. else if (cmd[0] == "join")
  542. doJoin(cmd);
  543. else if (cmd[0] == "leave")
  544. doLeave(cmd);
  545. else if (cmd[0] == "listnetworks")
  546. doListNetworks(cmd);
  547. else if (cmd[0] == "listpeers")
  548. doListPeers(cmd);
  549. else if (cmd[0] == "unicast")
  550. doUnicast(cmd);
  551. else doHelp(cmd);
  552. }
  553. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  554. printf("%s shutting down..."ZT_EOL_S,n->first.toString().c_str());
  555. delete n->second;
  556. }
  557. return 0;
  558. }