account.h 15.4 KB
Newer Older
yanmorin's avatar
 
yanmorin committed
1
/*
Sébastien Blin's avatar
Sébastien Blin committed
2
 *  Copyright (C) 2004-2019 Savoir-faire Linux Inc.
Guillaume Roguez's avatar
Guillaume Roguez committed
3
 *
4
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
yanmorin's avatar
 
yanmorin committed
5
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
Guillaume Roguez's avatar
Guillaume Roguez committed
6
 *  Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Julien Bonjean's avatar
Julien Bonjean committed
7
 *
yanmorin's avatar
 
yanmorin committed
8 9
 *  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
10
 *  the Free Software Foundation; either version 3 of the License, or
yanmorin's avatar
 
yanmorin committed
11
 *  (at your option) any later version.
Julien Bonjean's avatar
Julien Bonjean committed
12
 *
yanmorin's avatar
 
yanmorin committed
13 14 15 16
 *  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.
Julien Bonjean's avatar
Julien Bonjean committed
17
 *
yanmorin's avatar
 
yanmorin committed
18 19
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
yanmorin's avatar
 
yanmorin committed
21
 */
22

yanmorin's avatar
 
yanmorin committed
23 24 25
#ifndef ACCOUNT_H
#define ACCOUNT_H

Stepan Salenikovich's avatar
Stepan Salenikovich committed
26 27 28 29
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

30
#include "configurationmanager_interface.h"
31
#include "noncopyable.h"
32
#include "config/serializable.h"
33
#include "registration_states.h"
Adrien Béraud's avatar
Adrien Béraud committed
34
#include "im/message_engine.h"
Stepan Salenikovich's avatar
Stepan Salenikovich committed
35
#include "ip_utils.h"
Éloi Bail's avatar
Éloi Bail committed
36
#include "media_codec.h"
Guillaume Roguez's avatar
Guillaume Roguez committed
37
#include "logger.h"
38
#include "compiler_intrinsics.h" // include the "UNUSED" macro
yanmorin's avatar
 
yanmorin committed
39

40 41 42
#include <functional>
#include <string>
#include <vector>
43
#include <memory>
44
#include <map>
Guillaume Roguez's avatar
Guillaume Roguez committed
45
#include <set>
46
#include <random>
47
#include <stdexcept>
Stepan Salenikovich's avatar
Stepan Salenikovich committed
48 49
#include <atomic>
#include <mutex>
50
#include <chrono>
Stepan Salenikovich's avatar
Stepan Salenikovich committed
51

Adrien Béraud's avatar
Adrien Béraud committed
52
namespace jami { namespace upnp {
Stepan Salenikovich's avatar
Stepan Salenikovich committed
53
class Controller;
Adrien Béraud's avatar
Adrien Béraud committed
54
}} // namespace jami::upnp
55

Guillaume Roguez's avatar
Guillaume Roguez committed
56 57 58
namespace YAML {
class Emitter;
class Node;
Éloi Bail's avatar
Éloi Bail committed
59
} // namespace YAML
Guillaume Roguez's avatar
Guillaume Roguez committed
60

Adrien Béraud's avatar
Adrien Béraud committed
61
namespace jami {
Guillaume Roguez's avatar
Guillaume Roguez committed
62

63
class Call;
Éloi Bail's avatar
Éloi Bail committed
64
class SystemCodecContainer;
Adrien Béraud's avatar
Adrien Béraud committed
65
struct IceTransportOptions;
yanmorin's avatar
 
yanmorin committed
66

Éloi Bail's avatar
Éloi Bail committed
67 68
class VoipLinkException : public std::runtime_error
{
69 70
    public:
        VoipLinkException(const std::string &str = "") :
aviau's avatar
aviau committed
71
            std::runtime_error("VoipLinkException occurred: " + str) {}
72 73
};

74 75
/**
 * @file account.h
76
 * @brief Interface to protocol account (ex: SIPAccount)
77 78 79 80
 * It can be enable on loading or activate after.
 * It contains account, configuration, VoIP Link and Calls (inside the VoIPLink)
 */

Éloi Bail's avatar
Éloi Bail committed
81 82
class Account : public Serializable, public std::enable_shared_from_this<Account>
{
83
    public:
84
        Account(const std::string& accountID);
85 86 87 88 89 90

        /**
         * Virtual destructor
         */
        virtual ~Account();

91 92
        /**
         * Free all ressources related to this account.
Guillaume Roguez's avatar
Guillaume Roguez committed
93
         *   ***Current calls using this account are HANG-UP***
94 95 96
         */
        void freeAccount();

97
        virtual void setAccountDetails(const std::map<std::string, std::string> &details);
Julien Bonjean's avatar
Julien Bonjean committed
98

99
        virtual std::map<std::string, std::string> getAccountDetails() const;
100

101 102
        virtual std::map<std::string, std::string> getVolatileAccountDetails() const;

103 104 105
        /**
         * Load the settings for this account.
         */
106
        virtual void loadConfig() = 0;
107

108
        virtual void serialize(YAML::Emitter &out) const;
109 110
        virtual void unserialize(const YAML::Node &node);

111 112 113 114
        /**
         * Get the account ID
         * @return constant account id
         */
115
        const std::string& getAccountID() const {
Tristan Matthews's avatar
Tristan Matthews committed
116
            return accountID_;
Julien Bonjean's avatar
Julien Bonjean committed
117
        }
118

119 120 121 122 123 124 125
        virtual const char* getAccountType() const = 0;

        /**
         * Returns true if this is the IP2IP account
         */
        virtual bool isIP2IP() const { return false; }

126
        /**
127
         * Register the account.
128 129
         * This should update the getRegistrationState() return value.
         */
130
        virtual void doRegister() = 0;
131 132

        /**
133
         * Unregister the account.
134 135
         * This should update the getRegistrationState() return value.
         */
136
        virtual void doUnregister(std::function<void(bool)> cb = std::function<void(bool)>()) = 0;
137

138 139
        RegistrationState getRegistrationState() const { return registrationState_; }

140
        /**
Guillaume Roguez's avatar
Guillaume Roguez committed
141 142
         * Create a new outgoing call.
         *
143
         * @param toUrl The address to call
Guillaume Roguez's avatar
Guillaume Roguez committed
144
         * @return std::shared_ptr<Call> A pointer on the created call
145
         */
146
        virtual std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {}) = 0;
147

Guillaume Roguez's avatar
Guillaume Roguez committed
148 149 150 151
        /* Note: we forbid incoming call creation from an instance of Account.
         * This is why no newIncomingCall() method exist here.
         */

152 153
        /**
         * If supported, send a text message from this account.
Adrien Béraud's avatar
Adrien Béraud committed
154
         * @return a token to query the message status
155
         */
Adrien Béraud's avatar
Adrien Béraud committed
156 157 158
        virtual uint64_t sendTextMessage(const std::string& to UNUSED,
                                     const std::map<std::string, std::string>& payloads UNUSED) { return 0; }

159
        virtual std::vector<DRing::Message> getLastMessages(const uint64_t& /*base_timestamp*/) {
160 161 162
            return {};
        }

Adrien Béraud's avatar
Adrien Béraud committed
163
        virtual std::map<std::string, std::string> getNearbyPeers() const {
164 165 166
            return {};
        }

Adrien Béraud's avatar
Adrien Béraud committed
167 168 169
        /**
         * Return the status corresponding to the token.
         */
Adrien Béraud's avatar
Adrien Béraud committed
170
        virtual im::MessageStatus getMessageStatus(uint64_t /*id*/) const {
Adrien Béraud's avatar
Adrien Béraud committed
171 172
            return im::MessageStatus::UNKNOWN;
        }
173

Adrien Béraud's avatar
Adrien Béraud committed
174 175 176 177
        virtual bool cancelMessage(uint64_t /*id*/) {
            return false;
        }

Éloi Bail's avatar
Éloi Bail committed
178
        std::vector<std::shared_ptr<Call>> getCalls();
Guillaume Roguez's avatar
Guillaume Roguez committed
179

180
        /**
Julien Bonjean's avatar
Julien Bonjean committed
181
         * Tell if the account is enable or not.
182
         * @return true if enabled, false otherwise
183
         */
184
        bool isEnabled() const noexcept {
Tristan Matthews's avatar
Tristan Matthews committed
185
            return enabled_;
Julien Bonjean's avatar
Julien Bonjean committed
186
        }
187

188 189
        void setEnabled(bool enable) noexcept {
            enabled_ = enable;
190 191
        }

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        /**
         * Tell if the account is activated
         * (can currently be used).
         */
        bool isActive() const noexcept {
            return active_;
        }

        void setActive(bool active) noexcept {
            active_ = active;
        }

        bool isUsable() const noexcept {
            return enabled_ and active_;
        }

        bool isVideoEnabled() const noexcept {
            return videoEnabled_;
Julien Bonjean's avatar
Julien Bonjean committed
210
        }
211

212 213
        /**
         * Set the registration state of the specified link
214
         * @param state The registration state of underlying VoIPLink
215
         */
216
        virtual void setRegistrationState(RegistrationState state, unsigned detail_code=0, const std::string& detail_str={});
Julien Bonjean's avatar
Julien Bonjean committed
217

218
        /* They should be treated like macro definitions by the C++ compiler */
219
        std::string getUsername() const {
Tristan Matthews's avatar
Tristan Matthews committed
220
            return username_;
Julien Bonjean's avatar
Julien Bonjean committed
221
        }
222

223
        std::string getHostname() const {
Tristan Matthews's avatar
Tristan Matthews committed
224
            return hostname_;
Julien Bonjean's avatar
Julien Bonjean committed
225
        }
226
        void setHostname(const std::string &hostname) {
Tristan Matthews's avatar
Tristan Matthews committed
227
            hostname_ = hostname;
Julien Bonjean's avatar
Julien Bonjean committed
228 229
        }

230
        std::string getAlias() const {
Tristan Matthews's avatar
Tristan Matthews committed
231
            return alias_;
Julien Bonjean's avatar
Julien Bonjean committed
232
        }
233

234
        void setAlias(const std::string &alias) {
Tristan Matthews's avatar
Tristan Matthews committed
235
            alias_ = alias;
Julien Bonjean's avatar
Julien Bonjean committed
236 237
        }

238 239
        static std::vector<unsigned> getDefaultCodecsId();
        static std::map<std::string, std::string> getDefaultCodecDetails(const unsigned& codecId);
240

Tristan Matthews's avatar
Tristan Matthews committed
241
         /* Accessor to data structures
242
         * @return The list that reflects the user's choice
Julien Bonjean's avatar
Julien Bonjean committed
243
         */
244 245
        std::vector<unsigned> getActiveCodecs(MediaType mediaType = MEDIA_ALL) const;
        bool hasActiveCodec(MediaType mediaType) const;
246 247 248 249 250

        /**
         * Update both the codec order structure and the codec string used for
         * SDP offer and configuration respectively
         */
Éloi Bail's avatar
Éloi Bail committed
251 252
        void setActiveCodecs(const std::vector<unsigned>& list);
        std::shared_ptr<AccountCodecInfo> searchCodecById(unsigned codecId, MediaType mediaType);
253 254
        std::vector<std::shared_ptr<AccountCodecInfo>> getActiveAccountCodecInfoList(MediaType mediaType) const;
        std::shared_ptr<AccountCodecInfo> searchCodecByPayload(unsigned payload, MediaType mediaType);
Éloi Bail's avatar
Éloi Bail committed
255

256
        std::string getRingtonePath() const {
Tristan Matthews's avatar
Tristan Matthews committed
257
            return ringtonePath_;
Julien Bonjean's avatar
Julien Bonjean committed
258
        }
Éloi Bail's avatar
Éloi Bail committed
259

260
        void setRingtonePath(const std::string &path) {
Tristan Matthews's avatar
Tristan Matthews committed
261
            ringtonePath_ = path;
Julien Bonjean's avatar
Julien Bonjean committed
262 263
        }

264
        bool getRingtoneEnabled() const {
Tristan Matthews's avatar
Tristan Matthews committed
265
            return ringtoneEnabled_;
Julien Bonjean's avatar
Julien Bonjean committed
266
        }
267
        void setRingtoneEnabled(bool enable) {
Tristan Matthews's avatar
Tristan Matthews committed
268
            ringtoneEnabled_ = enable;
Julien Bonjean's avatar
Julien Bonjean committed
269 270
        }

271
        std::string getDisplayName() const {
Tristan Matthews's avatar
Tristan Matthews committed
272
            return displayName_;
Julien Bonjean's avatar
Julien Bonjean committed
273
        }
274
        void setDisplayName(const std::string &name) {
Tristan Matthews's avatar
Tristan Matthews committed
275
            displayName_ = name;
Julien Bonjean's avatar
Julien Bonjean committed
276 277
        }

278
        std::string getMailBox() const {
Tristan Matthews's avatar
Tristan Matthews committed
279
            return mailBox_;
280 281
        }

282
        void setMailBox(const std::string &mb) {
Tristan Matthews's avatar
Tristan Matthews committed
283
            mailBox_ = mb;
284 285
        }

Guillaume Roguez's avatar
Guillaume Roguez committed
286 287 288
        void attachCall(const std::string& id);
        void detachCall(const std::string& id);

289
        static const char * const VIDEO_CODEC_ENABLED;
290
        static const char * const VIDEO_CODEC_NAME;
291
        static const char * const VIDEO_CODEC_PARAMETERS;
292
        static const char * const VIDEO_CODEC_BITRATE;
Guillaume Roguez's avatar
Guillaume Roguez committed
293

Stepan Salenikovich's avatar
Stepan Salenikovich committed
294
        /**
Stepan Salenikovich's avatar
Stepan Salenikovich committed
295 296
         * returns whether or not UPnP is enabled and active
         * ie: if it is able to make port mappings
Stepan Salenikovich's avatar
Stepan Salenikovich committed
297
         */
298
        bool getUPnPActive(std::chrono::seconds timeout = {}) const;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
299 300 301 302 303

        /**
         * Get the UPnP IP (external router) address.
         * If use UPnP is set to false, the address will be empty.
         */
Stepan Salenikovich's avatar
Stepan Salenikovich committed
304
        IpAddr getUPnPIpAddress() const;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
305

306 307
        virtual const IceTransportOptions getIceOptions() const noexcept;

Adrien Béraud's avatar
Adrien Béraud committed
308 309 310 311
        /**
         * Random generator engine
         * Logical account state shall never rely on the state of the random generator.
         */
312
        mutable std::mt19937_64 rand;
Adrien Béraud's avatar
Adrien Béraud committed
313

314 315 316 317 318
        /**
         * Inform the account that the network status has changed.
         */
        virtual void connectivityChanged() {};

319 320 321 322 323 324 325
    public: // virtual methods that has to be implemented by concrete classes
        /**
         * This method is called to request removal of possible account traces on the system,
         * like internal account setup files.
         */
        virtual void flush() { /* nothing to do here - overload */ };

326
    private:
327
        NON_COPYABLE(Account);
328

329 330 331
        /**
         * Helper function used to load the default codec order from the codec factory
         */
332
        void loadDefaultCodecs();
333

Guillaume Roguez's avatar
Guillaume Roguez committed
334 335 336
        /**
         * Set of call's ID attached to the account.
         */
Éloi Bail's avatar
Éloi Bail committed
337
        std::set<std::string> callIDSet_;
338

339 340
        void enableUpnp(bool state);

Guillaume Roguez's avatar
Guillaume Roguez committed
341
    protected:
342 343
        static void parseString(const std::map<std::string, std::string> &details, const char *key, std::string &s);
        static void parseBool(const std::map<std::string, std::string> &details, const char *key, bool &b);
344
        static void parsePath(const std::map<std::string, std::string> &details, const char *key, std::string &s, const std::string& base);
345

Guillaume Roguez's avatar
Guillaume Roguez committed
346 347
        template<class T>
        static inline void
348
        parseInt(const std::map<std::string, std::string>& details, const char* key, T& i) {
Guillaume Roguez's avatar
Guillaume Roguez committed
349 350
            const auto& iter = details.find(key);
            if (iter == details.end()) {
Adrien Béraud's avatar
Adrien Béraud committed
351
                JAMI_ERR("Couldn't find key \"%s\"", key);
Guillaume Roguez's avatar
Guillaume Roguez committed
352 353 354 355 356
                return;
            }
            i = atoi(iter->second.c_str());
        }

357
        friend class ConfigurationTest;
Éloi Bail's avatar
Éloi Bail committed
358

359
        // General configuration keys for accounts
Éloi Bail's avatar
Éloi Bail committed
360
        static const char * const ALL_CODECS_KEY;
361 362
        static const char * const RINGTONE_PATH_KEY;
        static const char * const RINGTONE_ENABLED_KEY;
363
        static const char * const VIDEO_ENABLED_KEY;
364 365 366 367 368 369 370 371 372
        static const char * const DISPLAY_NAME_KEY;
        static const char * const ALIAS_KEY;
        static const char * const TYPE_KEY;
        static const char * const ID_KEY;
        static const char * const USERNAME_KEY;
        static const char * const AUTHENTICATION_USERNAME_KEY;
        static const char * const PASSWORD_KEY;
        static const char * const HOSTNAME_KEY;
        static const char * const ACCOUNT_ENABLE_KEY;
373
        static const char * const ACCOUNT_AUTOANSWER_KEY;
374
        static const char * const ACCOUNT_ACTIVE_CALL_LIMIT_KEY;
375
        static const char * const MAILBOX_KEY;
376
        static const char * const USER_AGENT_KEY;
377
        static const char * const HAS_CUSTOM_USER_AGENT_KEY;
378
        static const char * const DEFAULT_USER_AGENT;
379
        static const char * const PRESENCE_MODULE_ENABLED_KEY;
380
        static const char * const UPNP_ENABLED_KEY;
381 382 383
        static const char * const PROXY_ENABLED_KEY;
        static const char * const PROXY_SERVER_KEY;
        static const char * const PROXY_PUSH_TOKEN_KEY;
384

385
        static std::string mapStateNumberToString(RegistrationState state);
386

387 388 389
        /**
         * Account ID are assign in constructor and shall not changed
         */
Tristan Matthews's avatar
Tristan Matthews committed
390
        const std::string accountID_;
391

392 393
        mutable std::mutex configurationMutex_ {};

394 395 396
        /**
         * Account login information: username
         */
Tristan Matthews's avatar
Tristan Matthews committed
397
        std::string username_;
398 399 400 401

        /**
         * Account login information: hostname
         */
Tristan Matthews's avatar
Tristan Matthews committed
402
        std::string hostname_;
403 404 405 406

        /**
         * Account login information: Alias
         */
Tristan Matthews's avatar
Tristan Matthews committed
407
        std::string alias_;
408

409
        /**
410
         * Tells if the account is enabled.
411 412 413
         * This implies the link will be initialized on startup.
         * Modified by the configuration (key: ENABLED)
         */
Tristan Matthews's avatar
Tristan Matthews committed
414
        bool enabled_;
415

416 417 418 419 420 421 422
        /**
         * Tells if the account is active now.
         * This allows doRegister to be called.
         * When an account is unactivated, doUnregister must be called.
         */
        bool active_ {true};

423 424 425
        /* If true, automatically answer calls to this account */
        bool autoAnswerEnabled_;

426 427 428 429 430 431 432 433 434
        /**
         * The number of concurrent calls for the account
         * -1: Unlimited
         *  0: Do not disturb
         *  1: Single call
         *  +: Multi line
         */
        int activeCallLimit_ {-1} ;

435
        /*
Julien Bonjean's avatar
Julien Bonjean committed
436
         * The general, protocol neutral registration
437
         * state of the account
438
         */
Tristan Matthews's avatar
Tristan Matthews committed
439
        RegistrationState registrationState_;
440

441
        /**
Éloi Bail's avatar
Éloi Bail committed
442
         * Vector containing all system codecs (with default parameters)
443
         */
Éloi Bail's avatar
Éloi Bail committed
444
        std::shared_ptr<SystemCodecContainer> systemCodecContainer_;
Julien Bonjean's avatar
Julien Bonjean committed
445
        /**
Éloi Bail's avatar
Éloi Bail committed
446
         * Vector containing all account codecs (set of system codecs with custom parameters)
Julien Bonjean's avatar
Julien Bonjean committed
447
         */
Éloi Bail's avatar
Éloi Bail committed
448
        std::vector<std::shared_ptr<AccountCodecInfo>> accountCodecInfoList_;
Julien Bonjean's avatar
Julien Bonjean committed
449 450 451 452

        /**
         * Ringtone .au file used for this account
         */
Tristan Matthews's avatar
Tristan Matthews committed
453
        std::string ringtonePath_;
Julien Bonjean's avatar
Julien Bonjean committed
454

455 456 457 458 459 460
        /**
         * Allows user to temporarily disable video calling
         */

        bool videoEnabled_ = true;

Julien Bonjean's avatar
Julien Bonjean committed
461 462 463
        /**
         * Play ringtone when receiving a call
         */
Tristan Matthews's avatar
Tristan Matthews committed
464
        bool ringtoneEnabled_;
Julien Bonjean's avatar
Julien Bonjean committed
465 466 467 468

        /**
         * Display name when calling
         */
Tristan Matthews's avatar
Tristan Matthews committed
469
        std::string displayName_;
470

Julien Bonjean's avatar
Julien Bonjean committed
471 472 473
        /**
         * Useragent used for registration
         */
Tristan Matthews's avatar
Tristan Matthews committed
474
        std::string userAgent_;
475

476 477 478
        //  true if user has overridden default
        bool hasCustomUserAgent_;

479
        /**
480
         * Account mail box
481
         */
Tristan Matthews's avatar
Tristan Matthews committed
482
        std::string mailBox_;
483

Stepan Salenikovich's avatar
Stepan Salenikovich committed
484
        /**
Stepan Salenikovich's avatar
Stepan Salenikovich committed
485
         * UPnP IGD controller and the mutex to access it
Stepan Salenikovich's avatar
Stepan Salenikovich committed
486
         */
Adrien Béraud's avatar
Adrien Béraud committed
487
        std::unique_ptr<jami::upnp::Controller> upnp_;
Stepan Salenikovich's avatar
Stepan Salenikovich committed
488
        mutable std::mutex upnp_mtx {};
489

Éloi Bail's avatar
Éloi Bail committed
490 491 492
        /**
         * private account codec searching functions
         */
Adrien Béraud's avatar
Adrien Béraud committed
493
        std::shared_ptr<AccountCodecInfo> searchCodecByName(const std::string& name, MediaType mediaType);
Éloi Bail's avatar
Éloi Bail committed
494
        std::vector<unsigned> getAccountCodecInfoIdList(MediaType mediaType) const;
495
        void setAllCodecsActive(MediaType mediaType, bool active);
yanmorin's avatar
 
yanmorin committed
496 497
};

498 499 500 501 502 503 504
static inline std::ostream&
operator<< (std::ostream& os, const Account& acc)
{
    os << "[Account " << acc.getAccountID() << "] ";
    return os;
}

Adrien Béraud's avatar
Adrien Béraud committed
505
} // namespace jami
Guillaume Roguez's avatar
Guillaume Roguez committed
506

yanmorin's avatar
 
yanmorin committed
507
#endif