/* * This file is part of the Flowee project * Copyright (C) 2019-2021 Tom Zander * * 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 . */ #ifndef CONTEXTDATA_H #define CONTEXTDATA_H #include "Flowee.h" #include "Engine.h" #include /** * @brief The ContextData class is the main class in the flowee-JS engine. * * Every session is build around this class. It can connect to the hub and indexer * and it has the logic to do searchers on both with ease. * */ class ContextData { public: ContextData(Napi::Env env); void setupBindings(Napi::Env env, Napi::Object exports); Napi::Value connect(napi_env env, const std::string &hostname, Engine::Net net); Napi::Value connectHub(napi_env env, const std::string &hostname, int port); Napi::Value connectIndexer(napi_env env, const std::string &hostname, int port); void messageFromHub(const Message &message); bool hubConnected(const std::string &hubVersion); bool indexerConnected(const std::set &services); /* * startSearch takes an object literal argument with lots of details * about the search and return the resulting [something]. */ Napi::Value startSearch(const Napi::CallbackInfo &info); /* * sendTransaction takes an argument that should be possible to convert to * a transaction which it will then send to a connected Hub. * * We return a promise to report on the status. */ Napi::Value sendTransaction(const Napi::CallbackInfo &info); enum UpdateType { Subscribe, Unsubscribe }; /* * (un)subscribes an address from the monitor service. */ Napi::Value updateAddressMonitor(const Napi::CallbackInfo &info, UpdateType type); /* * send a random message (constructed in JS) to hub. */ Napi::Value sendJsMessage(const Napi::CallbackInfo &info); // we have callbacks in the shape of a property: std::unique_ptr m_onIndexerConnect, m_onHubConnect, m_onAllConnected; std::unique_ptr m_addressMonitorCallback; std::unique_ptr m_newBlockCallback; // then we also create promises on the 3 connect methods. Flowee::PromiseCallback m_hubConnectPromise; Flowee::PromiseCallback m_indexerConnectPromise; Flowee::PromiseCallback m_fullConnectPromise; /* a simple connect() creates a promise for both the hub and indexer getting connected * Since promises can only be fulfilled in the JS main thread we need a callback for this, * but only if no other callbacks are set by the user yet. */ std::unique_ptr m_promiseCallback; void startAllConnectedCallbacks(); /// handle the message for a certain network-job. void handleMessageForNetPromise(Napi::Env env, const Message &message); void shutdown(Napi::Env env); Engine *engine() const { return m_engine.get(); } private: // This can only be called in the JS thread, and is useful to future callbacks. void createPromiseCallback(Napi::Env env); // this supports things like the sendTransaction() std::map m_networkJobs; int m_nextNetworkJobId = 1; template bool promiseCallback(DataType* data, Callback callback) { // We need to do a call to resolve the promise as Resolve() is not thread-safe. // An empty ThreadSafeFunction has been added only in node 12.6 (2019-07), // so lets try to not use it if we don't have to. Maybe one of the other two // callbacks are present. if (m_onIndexerConnect && m_onIndexerConnect->acquire()) { m_onIndexerConnect->f.NonBlockingCall(data, callback); return true; } if (m_onHubConnect && m_onHubConnect->acquire()) { m_onHubConnect->f.NonBlockingCall(data, callback); return true; } if (m_promiseCallback && m_promiseCallback->acquire()) { m_promiseCallback->f.NonBlockingCall(data, callback); return true; } logCritical() << "promise fulfullment can't happen due to too old NodeJS"; return false; } std::unique_ptr m_engine; }; #endif