diff --git a/ZeroTierUI/Info.plist b/attic/ZeroTierUI/Info.plist similarity index 100% rename from ZeroTierUI/Info.plist rename to attic/ZeroTierUI/Info.plist diff --git a/ZeroTierUI/README.md b/attic/ZeroTierUI/README.md similarity index 100% rename from ZeroTierUI/README.md rename to attic/ZeroTierUI/README.md diff --git a/ZeroTierUI/WindowsBuildOfficial.bat b/attic/ZeroTierUI/WindowsBuildOfficial.bat similarity index 100% rename from ZeroTierUI/WindowsBuildOfficial.bat rename to attic/ZeroTierUI/WindowsBuildOfficial.bat diff --git a/ZeroTierUI/ZT1GUI.png b/attic/ZeroTierUI/ZT1GUI.png similarity index 100% rename from ZeroTierUI/ZT1GUI.png rename to attic/ZeroTierUI/ZT1GUI.png diff --git a/ZeroTierUI/ZT1GUI.xcf b/attic/ZeroTierUI/ZT1GUI.xcf similarity index 100% rename from ZeroTierUI/ZT1GUI.xcf rename to attic/ZeroTierUI/ZT1GUI.xcf diff --git a/ZeroTierUI/ZeroTierUI.pro b/attic/ZeroTierUI/ZeroTierUI.pro similarity index 100% rename from ZeroTierUI/ZeroTierUI.pro rename to attic/ZeroTierUI/ZeroTierUI.pro diff --git a/ZeroTierUI/ZeroTierUI.rc b/attic/ZeroTierUI/ZeroTierUI.rc similarity index 100% rename from ZeroTierUI/ZeroTierUI.rc rename to attic/ZeroTierUI/ZeroTierUI.rc diff --git a/ZeroTierUI/aboutwindow.cpp b/attic/ZeroTierUI/aboutwindow.cpp similarity index 100% rename from ZeroTierUI/aboutwindow.cpp rename to attic/ZeroTierUI/aboutwindow.cpp diff --git a/ZeroTierUI/aboutwindow.h b/attic/ZeroTierUI/aboutwindow.h similarity index 100% rename from ZeroTierUI/aboutwindow.h rename to attic/ZeroTierUI/aboutwindow.h diff --git a/ZeroTierUI/aboutwindow.ui b/attic/ZeroTierUI/aboutwindow.ui similarity index 100% rename from ZeroTierUI/aboutwindow.ui rename to attic/ZeroTierUI/aboutwindow.ui diff --git a/ZeroTierUI/installdialog.cpp b/attic/ZeroTierUI/installdialog.cpp similarity index 100% rename from ZeroTierUI/installdialog.cpp rename to attic/ZeroTierUI/installdialog.cpp diff --git a/ZeroTierUI/installdialog.h b/attic/ZeroTierUI/installdialog.h similarity index 100% rename from ZeroTierUI/installdialog.h rename to attic/ZeroTierUI/installdialog.h diff --git a/ZeroTierUI/installdialog.ui b/attic/ZeroTierUI/installdialog.ui similarity index 100% rename from ZeroTierUI/installdialog.ui rename to attic/ZeroTierUI/installdialog.ui diff --git a/ZeroTierUI/licensedialog.cpp b/attic/ZeroTierUI/licensedialog.cpp similarity index 100% rename from ZeroTierUI/licensedialog.cpp rename to attic/ZeroTierUI/licensedialog.cpp diff --git a/ZeroTierUI/licensedialog.h b/attic/ZeroTierUI/licensedialog.h similarity index 100% rename from ZeroTierUI/licensedialog.h rename to attic/ZeroTierUI/licensedialog.h diff --git a/ZeroTierUI/licensedialog.ui b/attic/ZeroTierUI/licensedialog.ui similarity index 100% rename from ZeroTierUI/licensedialog.ui rename to attic/ZeroTierUI/licensedialog.ui diff --git a/ZeroTierUI/mac_doprivileged.h b/attic/ZeroTierUI/mac_doprivileged.h similarity index 100% rename from ZeroTierUI/mac_doprivileged.h rename to attic/ZeroTierUI/mac_doprivileged.h diff --git a/ZeroTierUI/mac_doprivileged.mm b/attic/ZeroTierUI/mac_doprivileged.mm similarity index 100% rename from ZeroTierUI/mac_doprivileged.mm rename to attic/ZeroTierUI/mac_doprivileged.mm diff --git a/ZeroTierUI/main.cpp b/attic/ZeroTierUI/main.cpp similarity index 100% rename from ZeroTierUI/main.cpp rename to attic/ZeroTierUI/main.cpp diff --git a/ZeroTierUI/main.h b/attic/ZeroTierUI/main.h similarity index 100% rename from ZeroTierUI/main.h rename to attic/ZeroTierUI/main.h diff --git a/ZeroTierUI/mainwindow.cpp b/attic/ZeroTierUI/mainwindow.cpp similarity index 100% rename from ZeroTierUI/mainwindow.cpp rename to attic/ZeroTierUI/mainwindow.cpp diff --git a/ZeroTierUI/mainwindow.h b/attic/ZeroTierUI/mainwindow.h similarity index 100% rename from ZeroTierUI/mainwindow.h rename to attic/ZeroTierUI/mainwindow.h diff --git a/ZeroTierUI/mainwindow.ui b/attic/ZeroTierUI/mainwindow.ui similarity index 100% rename from ZeroTierUI/mainwindow.ui rename to attic/ZeroTierUI/mainwindow.ui diff --git a/ZeroTierUI/networkwidget.cpp b/attic/ZeroTierUI/networkwidget.cpp similarity index 100% rename from ZeroTierUI/networkwidget.cpp rename to attic/ZeroTierUI/networkwidget.cpp diff --git a/ZeroTierUI/networkwidget.h b/attic/ZeroTierUI/networkwidget.h similarity index 100% rename from ZeroTierUI/networkwidget.h rename to attic/ZeroTierUI/networkwidget.h diff --git a/ZeroTierUI/networkwidget.ui b/attic/ZeroTierUI/networkwidget.ui similarity index 100% rename from ZeroTierUI/networkwidget.ui rename to attic/ZeroTierUI/networkwidget.ui diff --git a/ZeroTierUI/onetimedialog.cpp b/attic/ZeroTierUI/onetimedialog.cpp similarity index 100% rename from ZeroTierUI/onetimedialog.cpp rename to attic/ZeroTierUI/onetimedialog.cpp diff --git a/ZeroTierUI/onetimedialog.h b/attic/ZeroTierUI/onetimedialog.h similarity index 100% rename from ZeroTierUI/onetimedialog.h rename to attic/ZeroTierUI/onetimedialog.h diff --git a/ZeroTierUI/onetimedialog.ui b/attic/ZeroTierUI/onetimedialog.ui similarity index 100% rename from ZeroTierUI/onetimedialog.ui rename to attic/ZeroTierUI/onetimedialog.ui diff --git a/ZeroTierUI/quickstartdialog.ui b/attic/ZeroTierUI/quickstartdialog.ui similarity index 100% rename from ZeroTierUI/quickstartdialog.ui rename to attic/ZeroTierUI/quickstartdialog.ui diff --git a/ZeroTierUI/resources.qrc b/attic/ZeroTierUI/resources.qrc similarity index 100% rename from ZeroTierUI/resources.qrc rename to attic/ZeroTierUI/resources.qrc diff --git a/ZeroTierUI/stylesheet.css b/attic/ZeroTierUI/stylesheet.css similarity index 100% rename from ZeroTierUI/stylesheet.css rename to attic/ZeroTierUI/stylesheet.css diff --git a/ZeroTierUI/zt1icon.icns b/attic/ZeroTierUI/zt1icon.icns similarity index 100% rename from ZeroTierUI/zt1icon.icns rename to attic/ZeroTierUI/zt1icon.icns diff --git a/ZeroTierUI/zt1icon.ico b/attic/ZeroTierUI/zt1icon.ico similarity index 100% rename from ZeroTierUI/zt1icon.ico rename to attic/ZeroTierUI/zt1icon.ico diff --git a/ZeroTierUI/zt1icon.png b/attic/ZeroTierUI/zt1icon.png similarity index 100% rename from ZeroTierUI/zt1icon.png rename to attic/ZeroTierUI/zt1icon.png diff --git a/testnet.cpp b/attic/testnet.cpp similarity index 100% rename from testnet.cpp rename to attic/testnet.cpp diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 870255f15..fa4c48d67 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -524,6 +524,16 @@ typedef struct * Is path fixed? (i.e. not learned, static) */ int fixed; + + /** + * Is path active? + */ + int active; + + /** + * Is path preferred? + */ + int preferred; } ZT1_PeerPhysicalPath; /** @@ -796,6 +806,9 @@ enum ZT1_ResultCode ZT1_Node_processBackgroundTasks(ZT1_Node *node,uint64_t now, * This may generate calls to the port config callback before it returns, * or these may be deffered if a netconf is not available yet. * + * If we are already a member of the network, nothing is done and OK is + * returned. + * * @param node Node instance * @param nwid 64-bit ZeroTier network ID * @return OK (0) or error code if a fatal error condition has occurred diff --git a/make-mac.mk b/make-mac.mk index 840a47b33..1492a6b1e 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -63,18 +63,18 @@ selftest: $(OBJS) selftest.o $(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS) $(STRIP) zerotier-selftest -testnet: $(TESTNET_OBJS) $(OBJS) testnet.o - $(CXX) $(CXXFLAGS) -o zerotier-testnet testnet.o $(OBJS) $(TESTNET_OBJS) $(LIBS) - $(STRIP) zerotier-testnet +#testnet: $(TESTNET_OBJS) $(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 - cd build-ZeroTierUI-release ; ../../Qt/bin/qmake ../ZeroTierUI/ZeroTierUI.pro ; make -j 4 - strip "build-ZeroTierUI-release/ZeroTier One.app/Contents/MacOS/ZeroTier One" - find "build-ZeroTierUI-release/ZeroTier One.app" -type f -name '.DS_Store' -print0 | xargs -0 rm -f - $(CODESIGN) -f -s $(CODESIGN_CERT) "build-ZeroTierUI-release/ZeroTier One.app" - $(CODESIGN) -vvv "build-ZeroTierUI-release/ZeroTier One.app" +#mac-ui: FORCE +# mkdir -p build-ZeroTierUI-release +# cd build-ZeroTierUI-release ; ../../Qt/bin/qmake ../ZeroTierUI/ZeroTierUI.pro ; make -j 4 +# strip "build-ZeroTierUI-release/ZeroTier One.app/Contents/MacOS/ZeroTier One" +# find "build-ZeroTierUI-release/ZeroTier One.app" -type f -name '.DS_Store' -print0 | xargs -0 rm -f +# $(CODESIGN) -f -s $(CODESIGN_CERT) "build-ZeroTierUI-release/ZeroTier One.app" +# $(CODESIGN) -vvv "build-ZeroTierUI-release/ZeroTier One.app" clean: rm -rf *.dSYM build-* *.o netconf/*.o service/*.o node/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o zerotier-* ZeroTierOneInstaller-* "ZeroTier One.zip" "ZeroTier One.dmg" @@ -82,7 +82,6 @@ clean: # For our use -- builds official signed binary, packages in installer and download DMG official: FORCE make -j 4 ZT_OFFICIAL_RELEASE=1 - make mac-ui ZT_OFFICIAL_RELEASE=1 ./buildinstaller.sh make mac-dmg ZT_OFFICIAL_RELEASE=1 diff --git a/node/Node.cpp b/node/Node.cpp index be9eadfa7..beb064303 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -357,12 +357,15 @@ ZT1_PeerList *Node::peers() const p->role = RR->topology->isSupernode(pi->second->address()) ? ZT1_PEER_ROLE_SUPERNODE : ZT1_PEER_ROLE_LEAF; std::vector paths(pi->second->paths()); + Path *bestPath = pi->second->getBestPath(_now); p->pathCount = 0; for(std::vector::iterator path(paths.begin());path!=paths.end();++path) { memcpy(&(p->paths[p->pathCount].address),&(path->address()),sizeof(struct sockaddr_storage)); p->paths[p->pathCount].lastSend = path->lastSend(); p->paths[p->pathCount].lastReceive = path->lastReceived(); p->paths[p->pathCount].fixed = path->fixed() ? 1 : 0; + p->paths[p->pathCount].active = path->active(_now) ? 1 : 0; + p->paths[p->pathCount].preferred = ((bestPath)&&(*path == *bestPath)) ? 1 : 0; ++p->pathCount; } } diff --git a/node/Peer.cpp b/node/Peer.cpp index 541fe5dd4..4d9429571 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -111,7 +111,7 @@ void Peer::received( * paths without confirming that a bidirectional link is in * fact present, but any packet that decodes and authenticates * correctly is considered valid. */ - TRACE("got non-confirmation packet from unknown path %s(%s), pinging...",_id.address().toString().c_str(),remoteAddr.toString().c_str()); + TRACE("got non-confirmation %s from unknown path %s(%s), pinging...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str()); attemptToContactAt(RR,remoteAddr,linkDesperation,now); } } diff --git a/service/ControlPlane.cpp b/service/ControlPlane.cpp index dceba8d6a..5077dce94 100644 --- a/service/ControlPlane.cpp +++ b/service/ControlPlane.cpp @@ -36,6 +36,8 @@ #include "../node/Node.hpp" #include "../node/Utils.hpp" +#define ZT_BUILD_IN_WEB_UI + namespace ZeroTier { static std::string _jsonEscape(const char *s) @@ -102,7 +104,12 @@ static std::string _jsonEnumerate(const ZT1_PeerPhysicalPath *pp,unsigned int co buf.push_back(','); buf.append("{\"address\":\""); buf.append(_jsonEscape(reinterpret_cast(&(pp[i].address))->toString())); - Utils::snprintf(tmp,sizeof(tmp),"\",\"lastSend\":%llu,\"lastReceive\":%llu,\"fixed\":%s}",pp[i].lastSend,pp[i].lastReceive,(pp[i].fixed == 0) ? "falase" : "true"); + Utils::snprintf(tmp,sizeof(tmp),"\",\"lastSend\":%llu,\"lastReceive\":%llu,\"fixed\":%s,\"active\":%s,\"preferred\":%s}", + pp[i].lastSend, + pp[i].lastReceive, + (pp[i].fixed == 0) ? "false" : "true", + (pp[i].active == 0) ? "false" : "true", + (pp[i].preferred == 0) ? "false" : "true"); buf.append(tmp); } buf.push_back(']'); @@ -186,9 +193,8 @@ static void _jsonAppend(std::string &buf,const ZT1_Peer *peer) buf.append(json); } -ControlPlane::ControlPlane(Node *n,const std::set atoks) : - _node(n), - _authTokens(atoks) +ControlPlane::ControlPlane(Node *n) : + _node(n) { } @@ -197,6 +203,7 @@ ControlPlane::~ControlPlane() } unsigned int ControlPlane::handleRequest( + const InetAddress &fromAddress, unsigned int httpMethod, const std::string &path, const std::map &headers, @@ -209,11 +216,13 @@ unsigned int ControlPlane::handleRequest( std::vector ps(Utils::split(path.c_str(),"/","","")); std::map urlArgs; + if (!((fromAddress.ipsEqual(InetAddress::LO4))||(fromAddress.ipsEqual(InetAddress::LO6)))) + return 403; // Forbidden: we only allow access from localhost right now + /* Note: this is kind of restricted in what it'll take. It does not support * URL encoding, and /'s in URL args will screw it up. But the only URL args * it really uses in ?jsonp=funcionName, and otherwise it just takes simple * paths to simply-named resources. */ - if (ps.size() > 0) { std::size_t qpos = ps[ps.size() - 1].find('?'); if (qpos != std::string::npos) { @@ -228,112 +237,202 @@ unsigned int ControlPlane::handleRequest( } } } else { - ps.push_back(std::string("index")); + ps.push_back(std::string("index.html")); } + bool isAuth = true; // TODO: auth tokens + if (httpMethod == HTTP_GET) { - if (ps[0] == "index") { - responseContentType = "text/html"; + + std::string ext; + std::size_t dotIdx = ps[0].find_last_of('.'); + if (dotIdx != std::string::npos) + ext = ps[0].substr(dotIdx); + + if ((ps.size() == 1)&&(ext.length() >= 2)&&(ext[0] == '.')) { +#ifdef ZT_BUILD_IN_WEB_UI + // .anything == static page -- also the only thing you can get without isAuth == true + if (ext == ".html") + responseContentType = "text/html"; + else if (ext == ".js") + responseContentType = "application/javascript"; + else if (ext == ".json") + responseContentType = "application/json"; + else if (ext == ".css") + responseContentType = "text/css"; + else if (ext == ".png") + responseContentType = "image/png"; + else if (ext == ".jpg") + responseContentType = "image/jpeg"; + else if (ext == ".gif") + responseContentType = "image/gif"; + else if (ext == ".txt") + responseContentType = "text/plain"; + else if (ext == ".xml") + responseContentType = "text/xml"; + else if (ext == ".svg") + responseContentType = "image/svg+xml"; + else responseContentType = "application/octet-stream"; responseBody = "Hello World!"; scode = 200; - } else if (ps[0] == "status") { - responseContentType = "application/json"; - ZT1_NodeStatus status; - _node->status(&status); - Utils::snprintf(json,sizeof(json), - "{" - "\"address\":\"%.10llx\"," - "\"publicIdentity\":\"%s\"," - "\"online\":%s," - "\"versionMajor\":%d," - "\"versionMinor\":%d," - "\"versionRev\":%d," - "\"version\":\"%d.%d.%d\"" - "}", - status.address, - status.publicIdentity, - (status.online) ? "true" : "false", - ZEROTIER_ONE_VERSION_MAJOR, - ZEROTIER_ONE_VERSION_MINOR, - ZEROTIER_ONE_VERSION_REVISION, - ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); - responseBody = json; - scode = 200; - } else if (ps[0] == "config") { - responseContentType = "application/json"; - responseBody = "{}"; // TODO - scode = 200; - } else if (ps[0] == "network") { - ZT1_VirtualNetworkList *nws = _node->networks(); - if (nws) { - if (ps.size() == 1) { - // Return [array] of all networks - responseContentType = "application/json"; - responseBody = "["; - for(unsigned long i=0;inetworkCount;++i) { - if (i > 0) - responseBody.push_back(','); - _jsonAppend(responseBody,&(nws->networks[i])); - } - responseBody.push_back(']'); - scode = 200; - } else if (ps.size() == 2) { - // Return a single network by ID or 404 if not found - uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); - for(unsigned long i=0;inetworkCount;++i) { - if (nws->networks[i].nwid == wantnw) { +#endif // ZT_BUILD_IN_WEB_UI + } else if (isAuth) { + if (ps[0] == "status") { + responseContentType = "application/json"; + ZT1_NodeStatus status; + _node->status(&status); + Utils::snprintf(json,sizeof(json), + "{" + "\"address\":\"%.10llx\"," + "\"publicIdentity\":\"%s\"," + "\"online\":%s," + "\"versionMajor\":%d," + "\"versionMinor\":%d," + "\"versionRev\":%d," + "\"version\":\"%d.%d.%d\"" + "}", + status.address, + status.publicIdentity, + (status.online) ? "true" : "false", + ZEROTIER_ONE_VERSION_MAJOR, + ZEROTIER_ONE_VERSION_MINOR, + ZEROTIER_ONE_VERSION_REVISION, + ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION); + responseBody = json; + scode = 200; + } else if (ps[0] == "config") { + responseContentType = "application/json"; + responseBody = "{}"; // TODO + scode = 200; + } else if (ps[0] == "network") { + if ((ps.size() > 1)&&(ps[1] == "controller")) { + // TODO + } else { + ZT1_VirtualNetworkList *nws = _node->networks(); + if (nws) { + if (ps.size() == 1) { + // Return [array] of all networks responseContentType = "application/json"; - _jsonAppend(responseBody,&(nws->networks[i])); + responseBody = "["; + for(unsigned long i=0;inetworkCount;++i) { + if (i > 0) + responseBody.push_back(','); + _jsonAppend(responseBody,&(nws->networks[i])); + } + responseBody.push_back(']'); scode = 200; - break; - } - } - } // else 404 - _node->freeQueryResult((void *)nws); - } else { - scode = 500; - } - } else if (ps[0] == "peer") { - ZT1_PeerList *pl = _node->peers(); - if (pl) { - if (ps.size() == 1) { - // Return [array] of all peers - responseContentType = "application/json"; - responseBody = "["; - for(unsigned long i=0;ipeerCount;++i) { - if (i > 0) - responseBody.push_back(','); - _jsonAppend(responseBody,&(pl->peers[i])); - } - responseBody.push_back(']'); - scode = 200; - } else if (ps.size() == 2) { - // Return a single peer by ID or 404 if not found - uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); - for(unsigned long i=0;ipeerCount;++i) { - if (pl->peers[i].address == wantp) { - responseContentType = "application/json"; + } else if (ps.size() == 2) { + // Return a single network by ID or 404 if not found + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + responseContentType = "application/json"; + _jsonAppend(responseBody,&(nws->networks[i])); + scode = 200; + break; + } + } + } // else 404 + _node->freeQueryResult((void *)nws); + } else scode = 500; + } + } else if (ps[0] == "peer") { + ZT1_PeerList *pl = _node->peers(); + if (pl) { + if (ps.size() == 1) { + // Return [array] of all peers + responseContentType = "application/json"; + responseBody = "["; + for(unsigned long i=0;ipeerCount;++i) { + if (i > 0) + responseBody.push_back(','); _jsonAppend(responseBody,&(pl->peers[i])); - scode = 200; - break; } - } - } // else 404 - _node->freeQueryResult((void *)pl); - } else { - scode = 500; - } - } - } else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { // PUT is weird in REST but we'll take it anyway + responseBody.push_back(']'); + scode = 200; + } else if (ps.size() == 2) { + // Return a single peer by ID or 404 if not found + uint64_t wantp = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;ipeerCount;++i) { + if (pl->peers[i].address == wantp) { + responseContentType = "application/json"; + _jsonAppend(responseBody,&(pl->peers[i])); + scode = 200; + break; + } + } + } // else 404 + _node->freeQueryResult((void *)pl); + } else scode = 500; + } // else 404 + } else scode = 401; // isAuth == false + + } else if ((httpMethod == HTTP_POST)||(httpMethod == HTTP_PUT)) { + + if (isAuth) { + if (ps[0] == "config") { + // TODO + } else if (ps[0] == "network") { + if ((ps.size() > 1)&&(ps[1] == "controller")) { + // TODO + } else { + if (ps.size() == 2) { + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + _node->join(wantnw); // does nothing if we are a member + ZT1_VirtualNetworkList *nws = _node->networks(); + if (nws) { + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + responseContentType = "application/json"; + _jsonAppend(responseBody,&(nws->networks[i])); + scode = 200; + break; + } + } + _node->freeQueryResult((void *)nws); + } else scode = 500; + } // else 404 + } + } // else 404 + } else scode = 401; // isAuth == false + } else if (httpMethod == HTTP_DELETE) { + + if (isAuth) { + if (ps[0] == "config") { + // TODO + } else if (ps[0] == "network") { + if ((ps.size() > 1)&&(ps[1] == "controller")) { + // TODO + } else { + ZT1_VirtualNetworkList *nws = _node->networks(); + if (nws) { + if (ps.size() == 2) { + uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str()); + for(unsigned long i=0;inetworkCount;++i) { + if (nws->networks[i].nwid == wantnw) { + _node->leave(wantnw); + responseBody = "true"; + responseContentType = "application/json"; + scode = 200; + break; + } + } + } // else 404 + _node->freeQueryResult((void *)nws); + } else scode = 500; + } + } // else 404 + } else scode = 401; // isAuth = false + } else { scode = 400; - responseBody = "Method not supported for resource "; - responseBody.append(path); + responseBody = "Method not supported."; } + // Wrap result in jsonp function call if the user included a jsonp= url argument std::map::const_iterator jsonp(urlArgs.find("jsonp")); - if (jsonp != urlArgs.end()) { + if ((jsonp != urlArgs.end())&&(responseContentType == "application/json")) { if (responseBody.length() > 0) responseBody = jsonp->second + "(" + responseBody + ");"; else responseBody = jsonp->second + "(null);"; diff --git a/service/ControlPlane.hpp b/service/ControlPlane.hpp index 29b84faa1..87a65eadd 100644 --- a/service/ControlPlane.hpp +++ b/service/ControlPlane.hpp @@ -37,6 +37,7 @@ namespace ZeroTier { class Node; +struct InetAddress; /** * HTTP control plane and static web server @@ -44,12 +45,13 @@ class Node; class ControlPlane { public: - ControlPlane(Node *n,const std::set atoks); + ControlPlane(Node *n); ~ControlPlane(); /** * Handle HTTP request * + * @param fromAddress Originating IP address of request * @param httpMethod HTTP method (as defined in ext/http-parser/http_parser.h) * @param path Request path * @param headers Request headers @@ -59,6 +61,7 @@ public: * @return HTTP response code */ unsigned int handleRequest( + const InetAddress &fromAddress, unsigned int httpMethod, const std::string &path, const std::map &headers, diff --git a/service/One.cpp b/service/One.cpp index 08210da12..5e81bc61a 100644 --- a/service/One.cpp +++ b/service/One.cpp @@ -189,7 +189,7 @@ public: if (_master) _node->setNetconfMaster((void *)_master); - _controlPlane = new ControlPlane(_node,std::set()); + _controlPlane = new ControlPlane(_node); _nextBackgroundTaskDeadline = 0; for(;;) { @@ -454,16 +454,12 @@ public: std::string contentType("text/plain"); // default if not changed in handleRequest() unsigned int scode = 404; - if ((htc->from.ipsEqual(InetAddress::LO4))||(htc->from.ipsEqual(InetAddress::LO6))) { - try { - if (_controlPlane) - scode = _controlPlane->handleRequest(htc->parser.method,htc->url,htc->headers,htc->body,data,contentType); - } catch ( ... ) { - scode = 500; - } - } else { - scode = 403; - htc->shouldKeepAlive = false; + try { + if (_controlPlane) + scode = _controlPlane->handleRequest(htc->from,htc->parser.method,htc->url,htc->headers,htc->body,data,contentType); + else scode = 500; + } catch ( ... ) { + scode = 500; } const char *scodestr;