Skip to content
Snippets Groups Projects
self.hpp 3.99 KiB
Newer Older
/**
 * @file self.hpp
 * @copyright Copyright (c) 2022 University of Turku, MIT License
 * @author Nicolas Pope
 */

#pragma once

#include <memory>
#include <string>
#include <vector>
#include <list>
#include <ftl/uuid.hpp>
#include <ftl/uri.hpp>
#include <ftl/handle.hpp>
#include <ftl/protocol/error.hpp>

namespace ftl {
namespace net {
class Universe;
}

namespace protocol {

Nicolas Pope's avatar
Nicolas Pope committed
class Node;
class Stream;

/**
 * @brief A wrapper providing RPC API and local node management. Internally the
 * Self instance is responsible for handling all network operations. Typically
 * there is just a single instance of this class, but more can be created for
 * testing purposes.
 * 
 */
class Self {
 public:
    /** Peer for outgoing connection: resolve address and connect */
    explicit Self(const std::shared_ptr<ftl::net::Universe> &impl);
    virtual ~Self();

    /**
     * @brief Connect to another host from this Self instance. Usually the
     * namespace method can be used instead.
     * 
     * @param uri A TCP URI.
     * @return std::shared_ptr<ftl::protocol::Node> 
     */
    std::shared_ptr<ftl::protocol::Node> connectNode(const std::string &uri);

    /**
     * @brief Create a new stream. Use the namespace method if possible.
     * 
     * @param uri A file:// or ftl:// URI.
     * @return std::shared_ptr<ftl::protocol::Stream> 
     */
    std::shared_ptr<ftl::protocol::Stream> createStream(const std::string &uri);

    /**
     * @brief Open an existing stream. Use the namespace method if possible.
     * 
     * @param uri A file:// or ftl:// URI
     * @return std::shared_ptr<ftl::protocol::Stream> 
     */
    std::shared_ptr<ftl::protocol::Stream> getStream(const std::string &uri);

    void start();

    /**
     * Open a new listening port on a given interfaces.
     *   eg. "tcp://localhost:9000"
     * @param addr URI giving protocol, interface and port
     */
    bool listen(const ftl::URI &addr);

    /**
     * @brief Get the list of all listening addresses and ports.
     * 
     * @return std::vector<ftl::URI> 
     */
    std::vector<ftl::URI> getListeningURIs();

    /**
     * Essential to call this before destroying anything that registered
     * callbacks or binds for RPC. It will terminate all connections and
     * stop any network activity but without deleting the net object.
     */
    void shutdown();

    bool isConnected(const ftl::URI &uri);
    bool isConnected(const std::string &s);

    size_t numberOfNodes() const;

    /**
     * Will block until all currently registered connnections have completed.
     * You should not use this, but rather use onConnect.
     */
    int waitConnections(int seconds = 1);

    /** get peer pointer by peer UUID, returns nullptr if not found */
    std::shared_ptr<ftl::protocol::Node> getNode(const ftl::UUID &pid) const;
    /** get webservice peer pointer, returns nullptr if not connected to webservice */
    std::shared_ptr<ftl::protocol::Node>  getWebService() const;
    std::list<std::shared_ptr<ftl::protocol::Node>> getNodes() const;

    /**
     * @brief Register a callback for new node connections.
     * 
     * @return ftl::Handle 
     */
    ftl::Handle onConnect(const std::function<bool(const std::shared_ptr<ftl::protocol::Node>&)>&);

    /**
     * @brief Register a callback for node disconnects.
     * 
     * @return ftl::Handle 
     */
    ftl::Handle onDisconnect(const std::function<bool(const std::shared_ptr<ftl::protocol::Node>&)>&);

    /**
     * @brief Register a callback for any node or network errors. Note that the node pointer can
     * be null if the error was not associated with a specific node.
     * 
     * @return ftl::Handle 
     */
    ftl::Handle onError(
        const std::function<bool(const std::shared_ptr<ftl::protocol::Node>&,
        ftl::protocol::Error,
        const std::string &)>&);

    // Used for testing
    ftl::net::Universe *getUniverse() const { return universe_.get(); }

 protected:
    std::shared_ptr<ftl::net::Universe> universe_;
}  // namespace protocol
}  // namespace ftl