jamiaccount.h 26.3 KB
Newer Older
Adrien Béraud's avatar
Adrien Béraud committed
1
/*
Sébastien Blin's avatar
Sébastien Blin committed
2
 *  Copyright (C) 2014-2019 Savoir-faire Linux Inc.
Adrien Béraud's avatar
Adrien Béraud committed
3 4
 *
 *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
5
 *  Author: Simon Désaulniers <simon.desaulniers@gmail.com>
6
 *  Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Adrien Béraud's avatar
Adrien Béraud committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 *  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, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

23
#pragma once
Adrien Béraud's avatar
Adrien Béraud committed
24 25 26 27 28

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

29
#include "security/tls_session.h"
30
#include "security/diffie-hellman.h"
Adrien Béraud's avatar
Adrien Béraud committed
31
#include "sip/sipaccountbase.h"
32
#include "dring/datatransfer_interface.h"
33

Adrien Béraud's avatar
Adrien Béraud committed
34 35
#include "noncopyable.h"
#include "ip_utils.h"
36
#include "ring_types.h" // enable_if_base_of
Guillaume Roguez's avatar
Guillaume Roguez committed
37
#include "security/certstore.h"
38
#include "scheduled_executor.h"
39 40

#include <opendht/dhtrunner.h>
41
#include <opendht/default_types.h>
Adrien Béraud's avatar
Adrien Béraud committed
42 43 44 45 46

#include <pjsip/sip_types.h>

#include <vector>
#include <map>
47
#include <chrono>
48
#include <list>
Adrien Béraud's avatar
Adrien Béraud committed
49
#include <future>
Adrien Béraud's avatar
Adrien Béraud committed
50

51 52 53 54
#if HAVE_RINGNS
#include "namedirectory.h"
#endif

Guillaume Roguez's avatar
Guillaume Roguez committed
55 56 57 58 59
namespace YAML {
class Node;
class Emitter;
}

60 61 62 63 64 65 66
namespace dev
{
    template <unsigned N> class FixedHash;
    using h160 = FixedHash<20>;
    using Address = h160;
}

Adrien Béraud's avatar
Adrien Béraud committed
67
namespace jami {
Guillaume Roguez's avatar
Guillaume Roguez committed
68

69
class IceTransport;
70
struct Contact;
71
struct AccountArchive;
72 73
class DhtPeerConnector;
class PeerConnection;
74

75 76 77 78
/**
 * @brief Ring Account is build on top of SIPAccountBase and uses DHT to handle call connectivity.
 */
class JamiAccount : public SIPAccountBase {
79 80 81
    private:
        struct PeerConnectionMsg;

Adrien Béraud's avatar
Adrien Béraud committed
82
    public:
83
        constexpr static const char* const ACCOUNT_TYPE = "RING";
Adrien Béraud's avatar
Adrien Béraud committed
84
        constexpr static const in_port_t DHT_DEFAULT_PORT = 4222;
85
        constexpr static const char* const DHT_DEFAULT_BOOTSTRAP = "bootstrap.jami.net";
86
        constexpr static const char* const DHT_DEFAULT_PROXY = "dhtproxy.jami.net:[80-100]";
87 88
        constexpr static const char* const DHT_TYPE_NS = "cx.ring";

89
        /* constexpr */ static const std::pair<uint16_t, uint16_t> DHT_PORT_RANGE;
Adrien Béraud's avatar
Adrien Béraud committed
90

Alexandre Lision's avatar
Alexandre Lision committed
91
        const char* getAccountType() const override {
Adrien Béraud's avatar
Adrien Béraud committed
92 93 94
            return ACCOUNT_TYPE;
        }

95 96
        std::shared_ptr<JamiAccount> shared() {
            return std::static_pointer_cast<JamiAccount>(shared_from_this());
97
        }
98 99
        std::shared_ptr<JamiAccount const> shared() const {
            return std::static_pointer_cast<JamiAccount const>(shared_from_this());
100
        }
101 102
        std::weak_ptr<JamiAccount> weak() {
            return std::static_pointer_cast<JamiAccount>(shared_from_this());
Adrien Béraud's avatar
Adrien Béraud committed
103
        }
104 105
        std::weak_ptr<JamiAccount const> weak() const {
            return std::static_pointer_cast<JamiAccount const>(shared_from_this());
Adrien Béraud's avatar
Adrien Béraud committed
106
        }
107

108 109 110 111
        const std::string& getPath() const {
            return idPath_;
        }

Adrien Béraud's avatar
Adrien Béraud committed
112 113 114 115
        /**
         * Constructor
         * @param accountID The account identifier
         */
116
        JamiAccount(const std::string& accountID, bool presenceEnabled);
Adrien Béraud's avatar
Adrien Béraud committed
117

118
        ~JamiAccount();
Adrien Béraud's avatar
Adrien Béraud committed
119 120 121 122 123

        /**
         * Serialize internal state of this account for configuration
         * @param YamlEmitter the configuration engine which generate the configuration file
         */
124
        virtual void serialize(YAML::Emitter &out) const override;
Adrien Béraud's avatar
Adrien Béraud committed
125 126 127 128 129

        /**
         * Populate the internal state for this account based on info stored in the configuration file
         * @param The configuration node for this account
         */
Alexandre Lision's avatar
Alexandre Lision committed
130
        virtual void unserialize(const YAML::Node &node) override;
Adrien Béraud's avatar
Adrien Béraud committed
131 132 133 134 135 136

        /**
         * Return an map containing the internal state of this account. Client application can use this method to manage
         * account info.
         * @return A map containing the account information.
         */
Alexandre Lision's avatar
Alexandre Lision committed
137
        virtual std::map<std::string, std::string> getAccountDetails() const override;
Adrien Béraud's avatar
Adrien Béraud committed
138

139 140 141 142 143 144
        /**
         * Retrieve volatile details such as recent registration errors
         * @return std::map< std::string, std::string > The account volatile details
         */
        virtual std::map<std::string, std::string> getVolatileAccountDetails() const override;

Adrien Béraud's avatar
Adrien Béraud committed
145 146 147
        /**
         * Actually useless, since config loading is done in init()
         */
Alexandre Lision's avatar
Alexandre Lision committed
148
        void loadConfig() override {}
Adrien Béraud's avatar
Adrien Béraud committed
149

150 151 152 153 154 155
        /**
         * Adds an account id to the list of accounts to track on the DHT for
         * buddy presence.
         *
         * @param buddy_id  The buddy id.
         */
156
        void trackBuddyPresence(const std::string& buddy_id, bool track);
157 158 159 160 161 162 163

        /**
         * Tells for each tracked account id if it has been seen online so far
         * in the last DeviceAnnouncement::TYPE.expiration minutes.
         *
         * @return map of buddy_uri to bool (online or not)
         */
164
        std::map<std::string, bool> getTrackedBuddyPresence() const;
165

Adrien Béraud's avatar
Adrien Béraud committed
166 167 168
        /**
         * Connect to the DHT.
         */
Alexandre Lision's avatar
Alexandre Lision committed
169
        void doRegister() override;
Adrien Béraud's avatar
Adrien Béraud committed
170 171 172 173

        /**
         * Disconnect from the DHT.
         */
174
        void doUnregister(std::function<void(bool)> cb = {}) override;
Adrien Béraud's avatar
Adrien Béraud committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

        /**
         * @return pj_str_t "From" uri based on account information.
         * From RFC3261: "The To header field first and foremost specifies the desired
         * logical" recipient of the request, or the address-of-record of the
         * user or resource that is the target of this request. [...]  As such, it is
         * very important that the From URI not contain IP addresses or the FQDN
         * of the host on which the UA is running, since these are not logical
         * names."
         */
        std::string getFromUri() const;

        /**
         * This method adds the correct scheme, hostname and append
         * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
         * It is expected that "port" is present in the internal hostname_.
         *
         * @return pj_str_t "To" uri based on @param username
         * @param username A string formatted as : "username"
         */
Alexandre Lision's avatar
Alexandre Lision committed
195
        std::string getToUri(const std::string& username) const override;
Adrien Béraud's avatar
Adrien Béraud committed
196 197

        /**
Philippe Gorley's avatar
Philippe Gorley committed
198
         * In the current version, "srv" uri is obtained in the preformated
Adrien Béraud's avatar
Adrien Béraud committed
199 200 201 202 203 204 205 206 207 208 209 210
         * way: hostname:port. This method adds the correct scheme and append
         * the ;transport= parameter at the end of the uri, in accordance with RFC3261.
         *
         * @return pj_str_t "server" uri based on @param hostPort
         * @param hostPort A string formatted as : "hostname:port"
         */
        std::string getServerUri() const { return ""; };

        /**
         * Get the contact header for
         * @return pj_str_t The contact header based on account information
         */
Alexandre Lision's avatar
Alexandre Lision committed
211
        pj_str_t getContactHeader(pjsip_transport* = nullptr) override;
Adrien Béraud's avatar
Adrien Béraud committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

        void setReceivedParameter(const std::string &received) {
            receivedParameter_ = received;
            via_addr_.host.ptr = (char *) receivedParameter_.c_str();
            via_addr_.host.slen = receivedParameter_.size();
        }

        std::string getReceivedParameter() const {
            return receivedParameter_;
        }

        pjsip_host_port *
        getViaAddr() {
            return &via_addr_;
        }

        /* Returns true if the username and/or hostname match this account */
229
        MatchRank matches(const std::string &username, const std::string &hostname) const override;
Adrien Béraud's avatar
Adrien Béraud committed
230 231 232 233 234

        /**
         * Implementation of Account::newOutgoingCall()
         * Note: keep declaration before newOutgoingCall template.
         */
235 236
        std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl,
                                              const std::map<std::string, std::string>& volatileCallDetails = {}) override;
Adrien Béraud's avatar
Adrien Béraud committed
237 238 239 240 241 242 243 244

        /**
         * Create outgoing SIPCall.
         * @param[in] toUrl The address to call
         * @return std::shared_ptr<T> A shared pointer on the created call.
         *      The type of this instance is given in template argument.
         *      This type can be any base class of SIPCall class (included).
         */
245
#ifndef _MSC_VER
246 247
        template <class T=SIPCall>
        std::shared_ptr<enable_if_base_of<T, SIPCall> >
248
        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
249 250 251
#else
        template <class T>
        std::shared_ptr<T>
252
        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
253
#endif
Adrien Béraud's avatar
Adrien Béraud committed
254 255 256

        /**
         * Create incoming SIPCall.
257
         * @param[in] from The origin of the call
258
         * @param details use to set some specific details
Adrien Béraud's avatar
Adrien Béraud committed
259 260 261 262 263
         * @return std::shared_ptr<T> A shared pointer on the created call.
         *      The type of this instance is given in template argument.
         *      This type can be any base class of SIPCall class (included).
         */
        virtual std::shared_ptr<SIPCall>
264
        newIncomingCall(const std::string& from, const std::map<std::string, std::string>& details = {}) override;
Adrien Béraud's avatar
Adrien Béraud committed
265

Alexandre Lision's avatar
Alexandre Lision committed
266
        virtual bool isTlsEnabled() const override {
267
            return true;
Adrien Béraud's avatar
Adrien Béraud committed
268 269
        }

270 271 272 273
        virtual bool isSrtpEnabled() const {
            return true;
        }

Alexandre Lision's avatar
Alexandre Lision committed
274
        virtual sip_utils::KeyExchangeProtocol getSrtpKeyExchange() const override {
Guillaume Roguez's avatar
Guillaume Roguez committed
275
            return sip_utils::KeyExchangeProtocol::SDES;
Adrien Béraud's avatar
Adrien Béraud committed
276 277
        }

Alexandre Lision's avatar
Alexandre Lision committed
278
        virtual bool getSrtpFallback() const override {
Adrien Béraud's avatar
Adrien Béraud committed
279 280 281
            return false;
        }

282 283 284
        bool setCertificateStatus(const std::string& cert_id, tls::TrustStore::PermissionStatus status);

        std::vector<std::string> getCertificatesByStatus(tls::TrustStore::PermissionStatus status);
285 286

        bool findCertificate(const std::string& id);
287
        bool findCertificate(const dht::InfoHash& h, std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
288 289

        /* contact requests */
290
        std::vector<std::map<std::string, std::string>> getTrustRequests() const;
291 292 293
        bool acceptTrustRequest(const std::string& from);
        bool discardTrustRequest(const std::string& from);

294 295 296 297 298
        /**
         * Add contact to the account contact list.
         * Set confirmed if we know the contact also added us.
         */
        void addContact(const std::string& uri, bool confirmed = false);
299
        void removeContact(const std::string& uri, bool banned = true);
300 301
        std::vector<std::map<std::string, std::string>> getContacts() const;

302 303 304 305 306
        ///
        /// Obtain details about one account contact in serializable form.
        ///
        std::map<std::string, std::string> getContactDetails(const std::string& uri) const;

307
        void sendTrustRequest(const std::string& to, const std::vector<uint8_t>& payload);
308
        void sendTrustRequestConfirm(const dht::InfoHash& to);
Adrien Béraud's avatar
Adrien Béraud committed
309
        virtual void sendTextMessage(const std::string& to, const std::map<std::string, std::string>& payloads, uint64_t id) override;
310
        virtual uint64_t sendTextMessage(const std::string& to, const std::map<std::string, std::string>& payloads) override;
311

312
        /* Devices */
313
        void addDevice(const std::string& password);
314 315 316 317 318 319 320
        /**
         * Export the archive to a file
         * @param destinationPath
         * @param (optional) password, if not provided, will update the contacts only if the archive doesn't have a password
         * @return if the archive was exported
         */
        bool exportArchive(const std::string& destinationPath, const std::string& password = {});
321
        bool revokeDevice(const std::string& password, const std::string& device);
322
        std::map<std::string, std::string> getKnownDevices() const;
323

324 325
        bool changeArchivePassword(const std::string& password_old, const std::string& password_new);

326
        void connectivityChanged() override;
327

328
        // overloaded methods
329 330
        void flush() override;

331 332 333 334 335 336
#if HAVE_RINGNS
        void lookupName(const std::string& name);
        void lookupAddress(const std::string& address);
        void registerName(const std::string& password, const std::string& name);
#endif

337
        ///
338
        /// Send a E2E connection request to a given peer for the given transfer id
339
        ///
340 341
        /// /// \param[in] peer RingID on request's recipient
        /// /// \param[in] tid linked outgoing data transfer
342
        ///
343
        void requestPeerConnection(const std::string& peer, const DRing::DataTransferId& tid,
344
                                   const std::function<void(PeerConnection*)>& connect_cb);
345

346 347 348 349 350 351 352 353
        ///
        /// Close a E2E connection between a given peer and a given transfer id.
        ///
        /// /// \param[in] peer RingID on request's recipient
        /// /// \param[in] tid linked outgoing data transfer
        ///
        void closePeerConnection(const std::string& peer, const DRing::DataTransferId& tid);

354 355 356 357 358 359 360
        std::vector<std::string> publicAddresses();


        /// \return true if the given DHT message identifier has been treated
        /// \note if message has not been treated yet this method store this id and returns true at further calls
        bool isMessageTreated(unsigned int id) ;

361 362
        dht::DhtRunner& dht() { return dht_; }

363 364 365 366
        const dht::crypto::Identity& identity() const { return identity_; }

        const std::shared_future<tls::DhParams> dhParams() const { return dhParams_; }

367
        void forEachDevice(const dht::InfoHash& to,
368 369
                           std::function<void(const dht::InfoHash&)>&& op,
                           std::function<void(bool)>&& end = {});
370 371 372

        /**
         * Inform that a potential peer device have been found.
Philippe Gorley's avatar
Philippe Gorley committed
373
         * Returns true only if the device certificate is a valid device certificate.
374 375 376 377
         * In that case (true is returned) the account_id parameter is set to the peer account ID.
         */
        static bool foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, dht::InfoHash& account_id);

378 379 380 381 382 383 384 385 386 387
        /**
         * Start or stop to use the proxy client
         * @param address of the proxy
         * @param deviceKey the device key for push notifications (empty to not use it)
         */
        void enableProxyClient(bool enable);

        void setPushNotificationToken(const std::string& pushDeviceToken = "");

        /**
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
388
         * To be called by clients with relevant data when a push notification is received.
389 390 391
         */
        void pushNotificationReceived(const std::string& from, const std::map<std::string, std::string>& data);

Philippe Gorley's avatar
Philippe Gorley committed
392 393
        std::string getUserUri() const override;

394 395 396 397
        /**
         * Get last messages (should be used to retrieve messages when launching the client)
         * @param base_timestamp
         */
Philippe Gorley's avatar
Philippe Gorley committed
398
        std::vector<DRing::Message> getLastMessages(const uint64_t& base_timestamp) override;
399

400 401
        void saveConfig() const;

402 403 404
        /**
         * Get current discovered peers account id and display name
         */
Adrien Béraud's avatar
Adrien Béraud committed
405
        std::map<std::string, std::string> getNearbyPeers() const override;
406

Adrien Béraud's avatar
Adrien Béraud committed
407
    private:
408
        NON_COPYABLE(JamiAccount);
409

410 411 412
        using clock = std::chrono::system_clock;
        using time_point = clock::time_point;

413
        /**
414
         * Private structures
415
         */
416 417 418 419 420 421
        struct PendingCall;
        struct PendingMessage;
        struct TrustRequest;
        struct KnownDevice;
        struct DeviceAnnouncement;
        struct DeviceSync;
422
        struct BuddyInfo;
423
        struct DiscoveredPeer;
Adrien Béraud's avatar
Adrien Béraud committed
424 425 426 427

        void syncDevices();
        void onReceiveDeviceSync(DeviceSync&& sync);

428 429
#if HAVE_RINGNS
        std::reference_wrapper<NameDirectory> nameDir_;
430
        std::string nameServer_;
431 432 433
        std::string registeredName_;
#endif

434 435 436 437 438
        /**
         * Compute archive encryption key and DHT storage location from password and PIN.
         */
        static std::pair<std::vector<uint8_t>, dht::InfoHash> computeKeys(const std::string& password, const std::string& pin, bool previous=false);

439 440
        void trackPresence(const dht::InfoHash& h, BuddyInfo& buddy);

441 442 443
        /**
         * Update tracking info when buddy appears offline.
         */
444
        void onTrackedBuddyOffline(const dht::InfoHash&);
445 446 447 448

        /**
         * Update tracking info when buddy appears offline.
         */
449
        void onTrackedBuddyOnline(const dht::InfoHash&);
450

Stepan Salenikovich's avatar
Stepan Salenikovich committed
451
        void doRegister_();
452
        void incomingCall(dht::IceCandidates&& msg, const std::shared_ptr<dht::crypto::Certificate>& from_cert, const dht::InfoHash& from);
Stepan Salenikovich's avatar
Stepan Salenikovich committed
453

454
        const dht::ValueType USER_PROFILE_TYPE = {9, "User profile", std::chrono::hours(24 * 7)};
455

456
        void startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::string& toUri);
457 458

        void onConnectedOutgoingCall(SIPCall& call, const std::string& to_id, IpAddr target);
Adrien Béraud's avatar
Adrien Béraud committed
459 460 461 462 463

        /**
         * Set the internal state for this account, mainly used to manage account details from the client application.
         * @param The map containing the account information.
         */
Alexandre Lision's avatar
Alexandre Lision committed
464
        virtual void setAccountDetails(const std::map<std::string, std::string> &details) override;
Adrien Béraud's avatar
Adrien Béraud committed
465 466 467 468 469 470

        /**
         * Start a SIP Call
         * @param call  The current call
         * @return true if all is correct
         */
471
        bool SIPStartCall(SIPCall& call, IpAddr target);
Adrien Béraud's avatar
Adrien Béraud committed
472

473 474 475 476
        /**
         * Inform that a potential account device have been found.
         * Returns true if the device have been validated to be part of this account
         */
477
        bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, const std::string& name = {}, const time_point& last_sync = time_point::min());
478

479 480 481 482 483 484 485 486 487
        /**
         * For a call with (from_device, from_account), check the peer certificate chain (cert_list, cert_num)
         * with session check status.
         * Put deserialized certificate to cert_out;
         */
        static pj_status_t checkPeerTlsCertificate(dht::InfoHash from_device, dht::InfoHash from_account,
                                unsigned status,
                                const gnutls_datum_t* cert_list, unsigned cert_num,
                                std::shared_ptr<dht::crypto::Certificate>& cert_out);
488 489 490 491 492 493 494

        /**
         * Check that a peer is authorised to talk to us.
         * If everything is in order, calls the callback with the
         * peer certificate chain (down to the peer device certificate),
         * and the peer account id.
         */
495
        void onPeerMessage(const dht::InfoHash& peer_device, std::function<void(const std::shared_ptr<dht::crypto::Certificate>& crt, const dht::InfoHash& account_id)>&&);
496 497

        void onTrustRequest(const dht::InfoHash& peer_account, const dht::InfoHash& peer_device, time_t received , bool confirm, std::vector<uint8_t>&& payload);
498

499 500 501 502 503 504 505 506 507 508
        /**
         * Start Publish the Jami Account onto the Network
         */
        void startAccountPublish();

        /**
         * Start Discovery the Jami Account from the Network
         */
        void startAccountDiscovery();

Stepan Salenikovich's avatar
Stepan Salenikovich committed
509 510 511 512 513
        /**
         * Maps require port via UPnP
         */
        bool mapPortUPnP();

514 515
        void igdChanged();

Adrien Béraud's avatar
Adrien Béraud committed
516
        dht::DhtRunner dht_ {};
517
        dht::crypto::Identity identity_ {};
Adrien Béraud's avatar
Adrien Béraud committed
518

519 520
        dht::InfoHash callKey_;

521
        bool handlePendingCallList();
522 523
        bool handlePendingCall(PendingCall& pc, bool incoming);

524 525
        mutable std::mutex callsMutex_ {};

526
        /**
527
         * DHT calls waiting for ICE negotiation
528
         */
529
        std::list<PendingCall> pendingCalls_;
530

531
        /**
532
         * Incoming DHT calls that are not yet actual SIP calls.
533
         */
534
        std::list<PendingCall> pendingSipCalls_;
535 536
        std::set<dht::Value::Id> treatedCalls_ {};

537
        mutable std::mutex messageMutex_ {};
538
        std::map<dht::Value::Id, PendingMessage> sentMessages_;
Adrien Béraud's avatar
Adrien Béraud committed
539 540
        std::set<dht::Value::Id> treatedMessages_ {};

541 542
        std::string ringAccountId_ {};
        std::string ringDeviceId_ {};
543
        std::string ringDeviceName_ {};
544
        std::string idPath_ {};
545
        std::string cachePath_ {};
Adrien Béraud's avatar
Adrien Béraud committed
546
        std::string dataPath_ {};
547 548
        std::string ethPath_ {};
        std::string ethAccount_ {};
Adrien Béraud's avatar
Adrien Béraud committed
549

550
        std::string archivePath_ {};
551
        bool archiveHasPassword_ {true};
552 553 554 555

        std::string receipt_ {};
        std::vector<uint8_t> receiptSignature_ {};
        dht::Value announceVal_;
556

557 558
        std::map<dht::InfoHash, TrustRequest> trustRequests_;
        void loadTrustRequests();
559 560 561 562 563 564
        void saveTrustRequests() const;

        std::map<dht::InfoHash, Contact> contacts_;
        void loadContacts();
        void saveContacts() const;
        void updateContact(const dht::InfoHash&, const Contact&);
565
        void addContact(const dht::InfoHash&, bool confirmed = false);
566

Philippe Gorley's avatar
Philippe Gorley committed
567
        // Trust store with account main certificate as the only CA
568
        dht::crypto::TrustList accountTrust_;
569
        // Trust store for to match peer certificates
570 571
        tls::TrustStore trust_;

572
        std::shared_ptr<dht::Value> announce_;
573

574
        /* this ring account associated devices */
575
        mutable std::mutex deviceListMutex_ {};
576
        std::map<dht::InfoHash, KnownDevice> knownDevices_;
577

578
        /* tracked buddies presence */
579
        mutable std::mutex buddyInfoMtx;
580 581
        std::map<dht::InfoHash, BuddyInfo> trackedBuddies_;

582 583
        void loadAccount(const std::string& archive_password = {}, const std::string& archive_pin = {}, const std::string& archive_path = {});
        void loadAccountFromFile(const std::string& archive_path, const std::string& archive_password);
584
        void loadAccountFromDHT(const std::string& archive_password, const std::string& archive_pin);
585
        void loadAccountFromArchive(AccountArchive&& archive, const std::string& archive_password);
586 587 588

        bool hasCertificate() const;
        bool hasPrivateKey() const;
589 590
        bool useIdentity(const dht::crypto::Identity& id);
        static bool needsMigration(const dht::crypto::Identity& id);
591 592 593

        std::string makeReceipt(const dht::crypto::Identity& id);
        void createRingDevice(const dht::crypto::Identity& id);
594
        void initRingDevice(const AccountArchive& a);
595
        void migrateAccount(const std::string& pwd, dht::crypto::Identity& device);
596
        static bool updateCertificates(AccountArchive& archive, dht::crypto::Identity& device);
597

598
        void createAccount(const std::string& archive_password, dht::crypto::Identity&& migrate);
599 600 601
        void updateArchive(AccountArchive& content) const;
        void saveArchive(AccountArchive& content, const std::string& pwd);
        AccountArchive readArchive(const std::string& pwd) const;
602
        std::vector<dht::SockAddr> loadBootstrap() const;
603

604
        static std::pair<std::string, std::string> saveIdentity(const dht::crypto::Identity id, const std::string& path, const std::string& name);
Adrien Béraud's avatar
Adrien Béraud committed
605 606
        void saveNodes(const std::vector<dht::NodeExport>&) const;
        void saveValues(const std::vector<dht::ValuesExport>&) const;
Adrien Béraud's avatar
Adrien Béraud committed
607

608 609 610
        void loadTreatedCalls();
        void saveTreatedCalls() const;

611 612 613
        void loadTreatedMessages();
        void saveTreatedMessages() const;

614 615 616
        void loadKnownDevices();
        void saveKnownDevices() const;

617 618
        void replyToIncomingIceMsg(const std::shared_ptr<SIPCall>&,
                                   const std::shared_ptr<IceTransport>&,
619
                                   const dht::IceCandidates&,
620 621
                                   const std::shared_ptr<dht::crypto::Certificate>& from_cert,
                                   const dht::InfoHash& from);
622

Adrien Béraud's avatar
Adrien Béraud committed
623
        static tls::DhParams loadDhParams(std::string path);
Adrien Béraud's avatar
Adrien Béraud committed
624

625 626 627 628 629
        /**
         * If privkeyPath_ is a valid private key file (PEM or DER),
         * and certPath_ a valid certificate file, load and returns them.
         * Otherwise, generate a new identity and returns it.
         */
630
        dht::crypto::Identity loadIdentity(const std::string& crt_path, const std::string& key_path, const std::string& key_pwd) const;
Adrien Béraud's avatar
Adrien Béraud committed
631 632
        std::vector<dht::NodeExport> loadNodes() const;
        std::vector<dht::ValuesExport> loadValues() const;
633
        mutable std::mutex dhtValuesMtx_;
Adrien Béraud's avatar
Adrien Béraud committed
634

635 636
        bool dhtPublicInCalls_ {true};

Adrien Béraud's avatar
Adrien Béraud committed
637
        /**
Adrien Béraud's avatar
Adrien Béraud committed
638
         * DHT port preference
Adrien Béraud's avatar
Adrien Béraud committed
639
         */
640
        in_port_t dhtPort_ {};
Adrien Béraud's avatar
Adrien Béraud committed
641

642 643
        bool dhtPeerDiscovery_ {false};

Stepan Salenikovich's avatar
Stepan Salenikovich committed
644 645 646 647 648 649
        /**
         * DHT port actually used,
         * this holds the actual port used for DHT, which may not be the port
         * selected in the configuration in the case that UPnP is used and the
         * configured port is already used by another client
         */
650
        UsedPort dhtPortUsed_ {};
Stepan Salenikovich's avatar
Stepan Salenikovich committed
651

652 653 654 655 656
        /**
         * Proxy
         */
        bool proxyEnabled_;
        std::string proxyServer_;
657
        std::string proxyServerCached_;
658
        std::string deviceKey_;
659
        std::string getDhtProxyServer();
660

Adrien Béraud's avatar
Adrien Béraud committed
661 662 663
        /**
         * The TLS settings, used only if tls is chosen as a sip transport.
         */
664
        void generateDhParams();
665

Adrien Béraud's avatar
Adrien Béraud committed
666
        std::shared_future<tls::DhParams> dhParams_;
667 668
        std::mutex dhParamsMtx_;
        std::condition_variable dhParamsCv_;
669 670 671 672

        bool allowPeersFromHistory_ {true};
        bool allowPeersFromContact_ {true};
        bool allowPeersFromTrusted_ {true};
Adrien Béraud's avatar
Adrien Béraud committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686

        /**
         * Optional: "received" parameter from VIA header
         */
        std::string receivedParameter_ {};

        /**
         * Optional: "rport" parameter from VIA header
         */
        int rPort_ {-1};

        /**
         * Optional: via_addr construct from received parameters
         */
Guillaume Roguez's avatar
Guillaume Roguez committed
687
        pjsip_host_port via_addr_ {};
Adrien Béraud's avatar
Adrien Béraud committed
688 689 690

        char contactBuffer_[PJSIP_MAX_URL_SIZE] {};
        pj_str_t contact_ {contactBuffer_, 0};
691
        pjsip_transport* via_tp_ {nullptr};
692 693

        template <class... Args>
694
        std::shared_ptr<IceTransport> createIceTransport(const Args&... args);
695 696

        void registerDhtAddress(IceTransport&);
697 698

        std::unique_ptr<DhtPeerConnector> dhtPeerConnector_;
699

700 701 702
        std::mutex discoveryMapMtx_;
        std::shared_ptr<dht::PeerDiscovery> peerDiscovery_;
        std::map<dht::InfoHash, DiscoveredPeer> discoveredPeers_;
703
        std::map<std::string, std::string> discoveredPeerMap_;
704
        bool accountPeerDiscovery_ {false};
705
        bool accountPublish_ {false};
706

707
        std::shared_ptr<RepeatedTask> eventHandler {};
708
        void checkPendingCallsTask();
Adrien Béraud's avatar
Adrien Béraud committed
709 710
};

711
static inline std::ostream& operator<< (std::ostream& os, const JamiAccount& acc)
712 713 714 715 716
{
    os << "[Account " << acc.getAccountID() << "] ";
    return os;
}

Adrien Béraud's avatar
Adrien Béraud committed
717
} // namespace jami