add initial project structure
Change-Id: I6a3fb080ff623b312e42d71754480a7ce00b81a0
diff --git a/include/connectionmanager.h b/include/connectionmanager.h
new file mode 100644
index 0000000..5d2db50
--- /dev/null
+++ b/include/connectionmanager.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "ice_options.h"
+#include "multiplexed_socket.h"
+
+#include <opendht/dhtrunner.h>
+#include <opendht/infohash.h>
+#include <opendht/value.h>
+#include <opendht/default_types.h>
+#include <opendht/sockaddr.h>
+#include <opendht/logger.h>
+
+#include <memory>
+#include <vector>
+#include <string>
+
+namespace jami {
+
+class ChannelSocket;
+class ConnectionManager;
+namespace upnp {
+class Controller;
+}
+namespace tls {
+class CertificateStore;
+}
+
+/**
+ * A PeerConnectionRequest is a request which ask for an initial connection
+ * It contains the ICE request an ID and if it's an answer
+ * Transmitted via the UDP DHT
+ */
+struct PeerConnectionRequest : public dht::EncryptedValue<PeerConnectionRequest>
+{
+ static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA;
+ static constexpr const char* key_prefix = "peer:"; ///< base to compute the DHT listen key
+ dht::Value::Id id = dht::Value::INVALID_ID;
+ std::string ice_msg {};
+ bool isAnswer {false};
+ std::string connType {}; // Used for push notifications to know why we open a new connection
+ MSGPACK_DEFINE_MAP(id, ice_msg, isAnswer, connType)
+};
+
+/**
+ * Used to accept or not an incoming ICE connection (default accept)
+ */
+using onICERequestCallback = std::function<bool(const DeviceId&)>;
+/**
+ * Used to accept or decline an incoming channel request
+ */
+using ChannelRequestCallback = std::function<bool(const std::shared_ptr<dht::crypto::Certificate>&,
+ const std::string& /* name */)>;
+/**
+ * Used by connectDevice, when the socket is ready
+ */
+using ConnectCallback = std::function<void(const std::shared_ptr<ChannelSocket>&, const DeviceId&)>;
+/**
+ * Used when an incoming connection is ready
+ */
+using ConnectionReadyCallback = std::function<
+ void(const DeviceId&, const std::string& /* channel_name */, std::shared_ptr<ChannelSocket>)>;
+
+using iOSConnectedCallback
+ = std::function<bool(const std::string& /* connType */, dht::InfoHash /* peer_h */)>;
+
+/**
+ * Manages connections to other devices
+ * @note the account MUST be valid if ConnectionManager lives
+ */
+class ConnectionManager
+{
+public:
+ class Config;
+
+ ConnectionManager(std::shared_ptr<Config> config_);
+ ~ConnectionManager();
+
+ /**
+ * Open a new channel between the account's device and another device
+ * This method will send a message on the account's DHT, wait a reply
+ * and then, create a Tls socket with remote peer.
+ * @param deviceId Remote device
+ * @param name Name of the channel
+ * @param cb Callback called when socket is ready ready
+ * @param noNewSocket Do not negotiate a new socket if there is none
+ * @param forceNewSocket Negotiate a new socket even if there is one // todo group with previous
+ * (enum)
+ * @param connType Type of the connection
+ */
+ void connectDevice(const DeviceId& deviceId,
+ const std::string& name,
+ ConnectCallback cb,
+ bool noNewSocket = false,
+ bool forceNewSocket = false,
+ const std::string& connType = "");
+ void connectDevice(const std::shared_ptr<dht::crypto::Certificate>& cert,
+ const std::string& name,
+ ConnectCallback cb,
+ bool noNewSocket = false,
+ bool forceNewSocket = false,
+ const std::string& connType = "");
+
+ /**
+ * Check if we are already connecting to a device with a specific name
+ * @param deviceId Remote device
+ * @param name Name of the channel
+ * @return if connecting
+ * @note isConnecting is not true just after connectDevice() as connectDevice is full async
+ */
+ bool isConnecting(const DeviceId& deviceId, const std::string& name) const;
+
+ /**
+ * Close all connections with a current device
+ * @param peerUri Peer URI
+ */
+ void closeConnectionsWith(const std::string& peerUri);
+
+ /**
+ * Method to call to listen to incoming requests
+ * @param deviceId Account's device
+ */
+ void onDhtConnected(const dht::crypto::PublicKey& devicePk);
+
+ /**
+ * Add a callback to decline or accept incoming ICE connections
+ * @param cb Callback to trigger
+ */
+ void onICERequest(onICERequestCallback&& cb);
+
+ /**
+ * Trigger cb on incoming peer channel
+ * @param cb Callback to trigger
+ * @note The callback is used to validate
+ * if the incoming request is accepted or not.
+ */
+ void onChannelRequest(ChannelRequestCallback&& cb);
+
+ /**
+ * Trigger cb when connection with peer is ready
+ * @param cb Callback to trigger
+ */
+ void onConnectionReady(ConnectionReadyCallback&& cb);
+
+ /**
+ * Trigger cb when connection with peer is ready for iOS devices
+ * @param cb Callback to trigger
+ */
+ void oniOSConnected(iOSConnectedCallback&& cb);
+
+ /**
+ * @return the number of active sockets
+ */
+ std::size_t activeSockets() const;
+
+ /**
+ * Log informations for all sockets
+ */
+ void monitor() const;
+
+ /**
+ * Send beacon on peers supporting it
+ */
+ void connectivityChanged();
+
+ /**
+ * Create and return ICE options.
+ */
+ void getIceOptions(std::function<void(IceTransportOptions&&)> cb) noexcept;
+ IceTransportOptions getIceOptions() const noexcept;
+
+ /**
+ * Get the published IP address, fallbacks to NAT if family is unspecified
+ * Prefers the usage of IPv4 if possible.
+ */
+ IpAddr getPublishedIpAddress(uint16_t family = PF_UNSPEC) const;
+
+ /**
+ * Set published IP address according to given family
+ */
+ void setPublishedAddress(const IpAddr& ip_addr);
+
+ /**
+ * Store the local/public addresses used to register
+ */
+ void storeActiveIpAddress(std::function<void()>&& cb = {});
+
+ std::shared_ptr<Config> getConfig();
+
+private:
+ ConnectionManager() = delete;
+ class Impl;
+ std::shared_ptr<Impl> pimpl_;
+};
+
+struct ConnectionManager::Config
+{
+ /**
+ * Determine if STUN public address resolution is required to register this account. In this
+ * case a STUN server hostname must be specified.
+ */
+ bool stunEnabled {false};
+
+ /**
+ * The STUN server hostname (optional), used to provide the public IP address in case the
+ * softphone stay behind a NAT.
+ */
+ std::string stunServer {};
+
+ /**
+ * Determine if TURN public address resolution is required to register this account. In this
+ * case a TURN server hostname must be specified.
+ */
+ bool turnEnabled {false};
+
+ /**
+ * The TURN server hostname (optional), used to provide the public IP address in case the
+ * softphone stay behind a NAT.
+ */
+ std::string turnServer;
+ std::string turnServerUserName;
+ std::string turnServerPwd;
+ std::string turnServerRealm;
+
+ mutable std::mutex cachedTurnMutex {};
+ dht::SockAddr cacheTurnV4 {};
+ dht::SockAddr cacheTurnV6 {};
+
+ std::string cachePath {};
+
+ std::shared_ptr<asio::io_context> ioContext;
+ std::shared_ptr<dht::DhtRunner> dht;
+ dht::crypto::Identity id;
+
+ tls::CertificateStore* certStore;
+
+ /**
+ * UPnP IGD controller and the mutex to access it
+ */
+ bool upnpEnabled;
+ std::shared_ptr<jami::upnp::Controller> upnpCtrl;
+
+ std::shared_ptr<dht::log::Logger> logger;
+
+ /**
+ * returns whether or not UPnP is enabled and active
+ * ie: if it is able to make port mappings
+ */
+ bool getUPnPActive() const;
+};
+
+} // namespace jami
\ No newline at end of file