瀏覽代碼

Bunch more debugging and loop closing on new netconf.

Adam Ierymenko 12 年之前
父節點
當前提交
28a73b620e
共有 7 個文件被更改,包括 100 次插入44 次删除
  1. 22 18
      node/Network.cpp
  2. 16 0
      node/Network.hpp
  3. 11 10
      node/Node.cpp
  4. 42 8
      node/NodeConfig.cpp
  5. 5 4
      node/PacketDecoder.cpp
  6. 3 3
      node/RuntimeEnvironment.hpp
  7. 1 1
      node/Utils.cpp

+ 22 - 18
node/Network.cpp

@@ -113,8 +113,24 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
 	_destroyOnDelete(false)
 {
 	if (controller() == _r->identity.address())
-		throw std::runtime_error("configuration error: cannot add a network for which I am the netconf master");
+		throw std::runtime_error("cannot add a network for which I am the netconf master");
+}
 
+Network::~Network()
+{
+	if (_destroyOnDelete) {
+		std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
+		std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
+		unlink(confPath.c_str());
+		unlink(mcdbPath.c_str());
+	} else {
+		// Causes flush of membership certs to disk
+		clean();
+	}
+}
+
+void Network::restoreState()
+{
 	std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
 	std::string confs;
 	if (Utils::readFile(confPath.c_str(),confs)) {
@@ -122,7 +138,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
 			if (confs.length()) {
 				Config conf(confs);
 				if (conf.containsAllFields())
-					setConfiguration(Config(conf));
+					setConfiguration(conf);
 			}
 		} catch ( ... ) {} // ignore invalid config on disk, we will re-request
 	} else {
@@ -132,32 +148,20 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
 		if (tmp)
 			fclose(tmp);
 	}
-
-	requestConfiguration();
-}
-
-Network::~Network()
-{
-	if (_destroyOnDelete) {
-		std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
-		std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
-		unlink(confPath.c_str());
-		unlink(mcdbPath.c_str());
-	} else {
-		// Causes flush of membership certs to disk
-		clean();
-	}
+	// TODO: restore membership certs
 }
 
 void Network::setConfiguration(const Network::Config &conf)
 {
 	Mutex::Lock _l(_lock);
 	if ((conf.networkId() == _id)&&(conf.peerAddress() == _r->identity.address())) { // sanity check
-		TRACE("network %.16llx got netconf:\n%s",(unsigned long long)_id,conf.toString().c_str());
+		//TRACE("network %.16llx got netconf:\n%s",(unsigned long long)_id,conf.toString().c_str());
 		_configuration = conf;
 		_myCertificate = conf.certificateOfMembership();
 		_lastConfigUpdate = Utils::now();
 
+		_tap.setIps(conf.staticAddresses());
+
 		std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
 		if (!Utils::writeFile(confPath.c_str(),conf.toString())) {
 			LOG("error: unable to write network configuration file at: %s",confPath.c_str());

+ 16 - 0
node/Network.hpp

@@ -272,6 +272,22 @@ private:
 
 	~Network();
 
+	/**
+	 * Called by NodeConfig after create
+	 *
+	 * This is called separately to avoid a rather evil race condition.
+	 * If config is restored in the constructor, then it's possible that
+	 * the tap will be assigned an IP and will start getting packets
+	 * before SharedPtr<Network> has gotten the pointer from the initial
+	 * object construct. That causes SharedPtr<Network> in the static
+	 * method that handles tap traffic to delete the object, resulting
+	 * in all sorts of utter madness. C++ is crazy like that.
+	 *
+	 * Actually the way we're using SharedPtr<Network> is hacky and
+	 * ugly, so it's our fault sorta.
+	 */
+	void restoreState();
+
 	/**
 	 * Causes all persistent disk presence to be erased on delete
 	 */

+ 11 - 10
node/Node.cpp

@@ -202,13 +202,14 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
 	const RuntimeEnvironment *_r = (const RuntimeEnvironment *)renv;
 
 	try {
+		//TRACE("from netconf:\n%s",msg.toString().c_str());
 		const std::string &type = msg.get("type");
 		if (type == "netconf-response") {
 			uint64_t inRePacketId = strtoull(msg.get("requestId").c_str(),(char **)0,16);
-			SharedPtr<Network> network = _r->nc->network(strtoull(msg.get("nwid").c_str(),(char **)0,16));
+			uint64_t nwid = strtoull(msg.get("nwid").c_str(),(char **)0,16);
 			Address peerAddress(msg.get("peer").c_str());
 
-			if ((network)&&(peerAddress)) {
+			if (peerAddress) {
 				if (msg.contains("error")) {
 					Packet::ErrorCode errCode = Packet::ERROR_INVALID_REQUEST;
 					const std::string &err = msg.get("error");
@@ -219,7 +220,7 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
 					outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
 					outp.append(inRePacketId);
 					outp.append((unsigned char)errCode);
-					outp.append(network->id());
+					outp.append(nwid);
 					_r->sw->send(outp,true);
 				} else if (msg.contains("netconf")) {
 					const std::string &netconf = msg.get("netconf");
@@ -227,7 +228,7 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
 						Packet outp(peerAddress,_r->identity.address(),Packet::VERB_OK);
 						outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
 						outp.append(inRePacketId);
-						outp.append(network->id());
+						outp.append(nwid);
 						outp.append((uint16_t)netconf.length());
 						outp.append(netconf.data(),netconf.length());
 						outp.compress();
@@ -266,12 +267,12 @@ Node::~Node()
 	delete impl->renv.netconfService;
 #endif
 
+	delete impl->renv.nc;
 	delete impl->renv.sysEnv;
 	delete impl->renv.topology;
 	delete impl->renv.sw;
 	delete impl->renv.multicaster;
 	delete impl->renv.demarc;
-	delete impl->renv.nc;
 	delete impl->renv.prng;
 	delete impl->renv.log;
 
@@ -362,6 +363,11 @@ Node::ReasonForTermination Node::run()
 		// Create the core objects in RuntimeEnvironment: node config, demarcation
 		// point, switch, network topology database, and system environment
 		// watcher.
+		_r->demarc = new Demarc(_r);
+		_r->multicaster = new Multicaster();
+		_r->sw = new Switch(_r);
+		_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
+		_r->sysEnv = new SysEnv(_r);
 		try {
 			_r->nc = new NodeConfig(_r,configAuthToken.c_str());
 		} catch ( ... ) {
@@ -369,11 +375,6 @@ Node::ReasonForTermination Node::run()
 			// One is running.
 			return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound");
 		}
-		_r->demarc = new Demarc(_r);
-		_r->multicaster = new Multicaster();
-		_r->sw = new Switch(_r);
-		_r->topology = new Topology(_r,(_r->homePath + ZT_PATH_SEPARATOR_S + "peer.db").c_str());
-		_r->sysEnv = new SysEnv(_r);
 
 		// TODO: make configurable
 		bool boundPort = false;

+ 42 - 8
node/NodeConfig.cpp

@@ -32,6 +32,8 @@
 
 #include <memory>
 #include <string>
+#include <map>
+#include <set>
 
 #include <openssl/sha.h>
 
@@ -58,6 +60,32 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken)
 	SHA256_Init(&sha);
 	SHA256_Update(&sha,authToken,strlen(authToken));
 	SHA256_Final(_controlSocketKey,&sha);
+
+	std::map<std::string,bool> networksDotD(Utils::listDirectory((_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str()));
+	std::set<uint64_t> nwids;
+	for(std::map<std::string,bool>::iterator d(networksDotD.begin());d!=networksDotD.end();++d) {
+		if (!d->second) {
+			std::string::size_type dot = d->first.rfind(".conf");
+			if (dot != std::string::npos) {
+				uint64_t nwid = strtoull(d->first.substr(0,dot).c_str(),(char **)0,16);
+				if (nwid > 0)
+					nwids.insert(nwid);
+			}
+		}
+	}
+
+	for(std::set<uint64_t>::iterator nwid(nwids.begin());nwid!=nwids.end();++nwid) {
+		try {
+			SharedPtr<Network> nw(new Network(_r,*nwid));
+			_networks[*nwid] = nw;
+			nw->restoreState();
+			nw->requestConfiguration();
+		} catch (std::exception &exc) {
+			LOG("unable to create network %.16llx: %s",(unsigned long long)*nwid,exc.what());
+		} catch ( ... ) {
+			LOG("unable to create network %.16llx: (unknown exception)",(unsigned long long)*nwid);
+		}
+	}
 }
 
 NodeConfig::~NodeConfig()
@@ -149,14 +177,20 @@ std::vector<std::string> NodeConfig::execute(const char *command)
 			uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16);
 			if (nwid > 0) {
 				Mutex::Lock _l(_networks_m);
-				try {
-					SharedPtr<Network> nw(new Network(_r,nwid));
-					_networks[nwid] = nw;
-					_P("200 join %.16llx OK",(unsigned long long)nwid);
-				} catch (std::exception &exc) {
-					_P("500 join %.16llx ERROR: %s",(unsigned long long)nwid,exc.what());
-				} catch ( ... ) {
-					_P("500 join %.16llx ERROR: (unknown exception)",(unsigned long long)nwid);
+				if (_networks.count(nwid)) {
+					_P("400 already a member of %.16llx",(unsigned long long)nwid);
+				} else {
+					try {
+						SharedPtr<Network> nw(new Network(_r,nwid));
+						_networks[nwid] = nw;
+						nw->restoreState();
+						nw->requestConfiguration();
+						_P("200 join %.16llx OK",(unsigned long long)nwid);
+					} catch (std::exception &exc) {
+						_P("500 join %.16llx ERROR: %s",(unsigned long long)nwid,exc.what());
+					} catch ( ... ) {
+						_P("500 join %.16llx ERROR: (unknown exception)",(unsigned long long)nwid);
+					}
 				}
 			} else {
 				_P("400 join requires a network ID (>0) in hexadecimal format");

+ 5 - 4
node/PacketDecoder.cpp

@@ -463,10 +463,12 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP
 					_r->multicaster->likesMulticastGroup(nwid,MulticastGroup(mac,adi),source(),now);
 					++numAccepted;
 				} else {
-					TRACE("ignored MULTICAST_LIKE from %s(%s): not a member of closed network %llu",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid);
+					ptr += 10;
+					TRACE("ignored MULTICAST_LIKE from %s(%s): not a member of closed network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)nwid);
 				}
 			} else {
-				TRACE("ignored MULTICAST_LIKE from %s(%s): network %llu unknown or we are not a member",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid);
+				ptr += 10;
+				TRACE("ignored MULTICAST_LIKE from %s(%s): network %.16llx unknown or we are not a member",source().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned long long)nwid);
 			}
 		}
 
@@ -610,7 +612,6 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
 	char tmp[128];
 	try {
 		uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
-		TRACE("NETWORK_CONFIG_REQUEST for %.16llx from %s",(unsigned long long)nwid,source().toString().c_str());
 #ifndef __WINDOWS__
 		if (_r->netconfService) {
 			unsigned int dictLen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
@@ -624,6 +625,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
 			request["nwid"] = tmp;
 			sprintf(tmp,"%llx",(unsigned long long)packetId());
 			request["requestId"] = tmp;
+			//TRACE("to netconf:\n%s",request.toString().c_str());
 			_r->netconfService->send(request);
 		} else {
 #endif // !__WINDOWS__
@@ -635,7 +637,6 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
 			outp.encrypt(peer->cryptKey());
 			outp.hmacSet(peer->macKey());
 			_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
-			TRACE("sent ERROR(NETWORK_CONFIG_REQUEST,UNSUPPORTED_OPERATION) to %s(%s)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
 #ifndef __WINDOWS__
 		}
 #endif // !__WINDOWS__

+ 3 - 3
node/RuntimeEnvironment.hpp

@@ -63,12 +63,12 @@ public:
 	RuntimeEnvironment() :
 		log((Logger *)0),
 		prng((CMWC4096 *)0),
-		nc((NodeConfig *)0),
 		demarc((Demarc *)0),
 		multicaster((Multicaster *)0),
 		sw((Switch *)0),
 		topology((Topology *)0),
-		sysEnv((SysEnv *)0)
+		sysEnv((SysEnv *)0),
+		nc((NodeConfig *)0)
 #ifndef __WINDOWS__
 		,netconfService((Service *)0)
 #endif
@@ -87,12 +87,12 @@ public:
 
 	Logger *log; // may be null
 	CMWC4096 *prng;
-	NodeConfig *nc;
 	Demarc *demarc;
 	Multicaster *multicaster;
 	Switch *sw;
 	Topology *topology;
 	SysEnv *sysEnv;
+	NodeConfig *nc;
 
 #ifndef __WINDOWS__
 	Service *netconfService; // may be null

+ 1 - 1
node/Utils.cpp

@@ -231,7 +231,7 @@ std::map<std::string,bool> Utils::listDirectory(const char *path)
 		if (readdir_r(d,&de,&dptr))
 			break;
 		if (dptr) {
-			if ((!strcmp(dptr->d_name,"."))&&(!strcmp(dptr->d_name,"..")))
+			if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,"..")))
 				r[std::string(dptr->d_name)] = (dptr->d_type == DT_DIR);
 		} else break;
 	}