diff --git a/src/Network/http/MirrorPropertyTreeWebsocket.cxx b/src/Network/http/MirrorPropertyTreeWebsocket.cxx index 8fd68b60a..1991e7c9a 100644 --- a/src/Network/http/MirrorPropertyTreeWebsocket.cxx +++ b/src/Network/http/MirrorPropertyTreeWebsocket.cxx @@ -142,7 +142,7 @@ using std::string; { } - virtual void valueChanged(SGPropertyNode* node) override + void valueChanged(SGPropertyNode* node) override { auto it = idHash.find(node); if (it == idHash.end()) { @@ -158,11 +158,16 @@ using std::string; } } - virtual void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override + void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override { + SG_UNUSED(parent); + recursiveAdd(child); + } - const auto type = child->getType(); - const auto& path = child->getPath(); + void recursiveAdd(SGPropertyNode* node) + { + const auto type = node->getType(); + const auto& path = node->getPath(); auto rrIt = std::find_if(recentlyRemoved.begin(), recentlyRemoved.end(), [type, &path](const RecentlyRemovedNode& rr) { return (type == rr.type) && (path == rr.path); }); @@ -170,16 +175,26 @@ using std::string; // recycle nodes which get thrashed from Nasal (deleted + re-created // each time a Nasal timer fires) removedNodes.erase(rrIt->id); // don't remove it! - idHash.insert(std::make_pair(child, rrIt->id)); - changedNodes.insert(child); + idHash.insert(std::make_pair(node, rrIt->id)); + changedNodes.insert(node); recentlyRemoved.erase(rrIt); + #if defined (MIRROR_DEBUG) + SG_LOG(SG_NETWORK, SG_INFO, "recycling node:" << path); + #endif return; } + #if defined (MIRROR_DEBUG) + SG_LOG(SG_NETWORK, SG_INFO, "new node:" << path); + #endif + newNodes.insert(node); - newNodes.insert(child); + int child = 0; + for (; child < node->nChildren(); ++child) { + recursiveAdd(node->getChild(child)); + } } - virtual void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override + void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override { changedNodes.erase(child); // have to do this here with the pointer valid newNodes.erase(child); @@ -198,6 +213,9 @@ using std::string; void registerSubtree(SGPropertyNode* node) { +#if defined (MIRROR_DEBUG) + SG_LOG(SG_NETWORK, SG_INFO, "register subtree:" << node->getPath()); +#endif valueChanged(node); // and recurse @@ -380,13 +398,11 @@ static void handleExecCommand(cJSON* json) #endif MirrorPropertyTreeWebsocket::MirrorPropertyTreeWebsocket(const std::string& path) : + _rootPath(path), _listener(new MirrorTreeListener), _minSendInterval(100) { - _subtreeRoot = globals->get_props()->getNode(path, true); - _subtreeRoot->addChangeListener(_listener.get()); - _listener->registerSubtree(_subtreeRoot); - _lastSendTime = SGTimeStamp::now(); + checkNodeExists(); } MirrorPropertyTreeWebsocket::~MirrorPropertyTreeWebsocket() @@ -395,16 +411,30 @@ MirrorPropertyTreeWebsocket::~MirrorPropertyTreeWebsocket() void MirrorPropertyTreeWebsocket::close() { - _subtreeRoot->removeChangeListener(_listener.get()); + if (_subtreeRoot) { + _subtreeRoot->removeChangeListener(_listener.get()); + } +} - #if 0 - SG_LOG(SG_NETWORK, SG_INFO, "closing PropertyChangeWebsocket #" << id); - _watchedNodes.clear(); - #endif +void MirrorPropertyTreeWebsocket::checkNodeExists() +{ + _subtreeRoot = globals->get_props()->getNode(_rootPath, false); + if (_subtreeRoot) { + _subtreeRoot->addChangeListener(_listener.get()); + _listener->registerSubtree(_subtreeRoot); + _lastSendTime = SGTimeStamp::now(); + } } void MirrorPropertyTreeWebsocket::handleRequest(const HTTPRequest & request, WebsocketWriter &writer) { + if (!_subtreeRoot) { + checkNodeExists(); + if (!_subtreeRoot) { + return; // still no node exists, we can't process this + } + } + if (request.Content.empty()) return; #if 0 /* @@ -463,6 +493,13 @@ void MirrorPropertyTreeWebsocket::handleRequest(const HTTPRequest & request, Web void MirrorPropertyTreeWebsocket::poll(WebsocketWriter & writer) { + if (!_subtreeRoot) { + checkNodeExists(); + if (!_subtreeRoot) { + return; + } + } + if (!_listener->haveChangesToSend()) { return; } diff --git a/src/Network/http/MirrorPropertyTreeWebsocket.hxx b/src/Network/http/MirrorPropertyTreeWebsocket.hxx index 653280053..8f3e772a6 100644 --- a/src/Network/http/MirrorPropertyTreeWebsocket.hxx +++ b/src/Network/http/MirrorPropertyTreeWebsocket.hxx @@ -38,15 +38,18 @@ class MirrorPropertyTreeWebsocket : public Websocket { public: MirrorPropertyTreeWebsocket(const std::string& path); - virtual ~MirrorPropertyTreeWebsocket(); + ~MirrorPropertyTreeWebsocket() override; - virtual void close(); - virtual void handleRequest(const HTTPRequest & request, WebsocketWriter & writer); - virtual void poll(WebsocketWriter & writer); + void close() override; + void handleRequest(const HTTPRequest & request, WebsocketWriter & writer) override; + void poll(WebsocketWriter & writer) override; private: + void checkNodeExists(); + friend class MirrorTreeListener; + std::string _rootPath; SGPropertyNode_ptr _subtreeRoot; std::unique_ptr<MirrorTreeListener> _listener; int _minSendInterval; diff --git a/src/Network/http/httpd.cxx b/src/Network/http/httpd.cxx index 00c59bd44..237170928 100644 --- a/src/Network/http/httpd.cxx +++ b/src/Network/http/httpd.cxx @@ -610,8 +610,9 @@ Websocket * MongooseHttpd::newWebsocket(const string & uri) SG_LOG(SG_NETWORK, SG_INFO, "new PropertyChangeWebsocket for: " << uri); return new PropertyChangeWebsocket(&_propertyChangeObserver); } else if (uri.find("/PropertyTreeMirror/") == 0) { - SG_LOG(SG_NETWORK, SG_INFO, "new MirrorPropertyTreeWebsocket for: " << uri); - return new MirrorPropertyTreeWebsocket(uri.substr(20)); + const auto path = uri.substr(20); + SG_LOG(SG_NETWORK, SG_INFO, "new MirrorPropertyTreeWebsocket for: " << path); + return new MirrorPropertyTreeWebsocket(path); } return NULL; }