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

24
#pragma once
jpbl's avatar
jpbl committed
25

26 27 28 29
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

30 31
#include "logger.h"

32
#include "recordable.h"
33
#include "ip_utils.h"
34
#include "ice_transport.h"
35 36 37 38

#include <mutex>
#include <map>
#include <sstream>
39 40
#include <memory>
#include <vector>
41
#include <condition_variable>
42
#include <set>
43
#include <list>
yanmorin's avatar
yanmorin committed
44

45 46
namespace ring {

47
class VoIPLink;
48
class Account;
49
class AccountVideoCodecInfo;
50

51 52
template <class T> using CallMap = std::map<std::string, std::shared_ptr<T> >;

Julien Bonjean's avatar
Julien Bonjean committed
53 54
/*
 * @file call.h
55 56 57
 * @brief A call is the base class for protocol-based calls
 */

58
class Call : public Recordable, public std::enable_shared_from_this<Call> {
59
    public:
60
        static const char * const DEFAULT_ID;
61 62

        /**
63 64
         * This determines if the call originated from the local user (OUTGOING)
         * or from some remote peer (INCOMING, MISSED).
65
         */
66
        enum class CallType : unsigned {INCOMING, OUTGOING, MISSED};
67 68 69 70

        /**
         * Tell where we're at with the call. The call gets Connected when we know
         * from the other end what happened with out call. A call can be 'Connected'
71
         * even if the call state is Busy, or Error.
72 73 74
         *
         * Audio should be transmitted when ConnectionState = Connected AND
         * CallState = Active.
75 76
         *
         * \note modify validStateTransition/getStateStr if this enum changes
77
         */
78 79 80
        enum class ConnectionState : unsigned {
            DISCONNECTED, TRYING, PROGRESSING, RINGING, CONNECTED, COUNT__
        };
81 82 83

        /**
         * The Call State.
84 85
         *
         * \note modify validStateTransition/getStateStr if this enum changes
86
         */
87
        enum class CallState : unsigned {
88
            INACTIVE, ACTIVE, HOLD, BUSY, MERROR, OVER, COUNT__
89
        };
90 91 92

        virtual ~Call();

93
        /**
94
         * Return a reference on the call id
95 96
         * @return call id
         */
97
        const std::string& getCallId() const {
98
            return id_;
Julien Bonjean's avatar
Julien Bonjean committed
99
        }
100

Julien Bonjean's avatar
Julien Bonjean committed
101
        /**
102 103 104
         * Return a reference on the conference id
         * @return call id
         */
105
        const std::string& getConfId() const {
106
            return confID_;
Julien Bonjean's avatar
Julien Bonjean committed
107
        }
108

109
        void setConfId(const std::string &id) {
110
            confID_ = id;
Julien Bonjean's avatar
Julien Bonjean committed
111
        }
112

113
        Account& getAccount() const { return account_; }
114
        const std::string& getAccountId() const;
115

116 117
        CallType getCallType() const {
            return type_;
118 119
        }

120 121
        virtual const char* getLinkType() const = 0;

Julien Bonjean's avatar
Julien Bonjean committed
122
        /**
123 124 125 126
         * Set the peer number (destination on outgoing)
         * not protected by mutex (when created)
         * @param number peer number
         */
127
        void setPeerNumber(const std::string& number) {
128
            peerNumber_ = number;
Julien Bonjean's avatar
Julien Bonjean committed
129
        }
130

Julien Bonjean's avatar
Julien Bonjean committed
131
        /**
132 133 134 135
         * Get the peer number (destination on outgoing)
         * not protected by mutex (when created)
         * @return std::string The peer number
         */
136 137
        std::string getPeerNumber() const {
            return peerNumber_;
Julien Bonjean's avatar
Julien Bonjean committed
138
        }
139

Julien Bonjean's avatar
Julien Bonjean committed
140
        /**
141 142 143 144
         * Set the display name (caller in ingoing)
         * not protected by mutex (when created)
         * @return std::string The peer display name
         */
145 146
        void setPeerDisplayName(const std::string& name) {
            peerDisplayName_ = name;
Julien Bonjean's avatar
Julien Bonjean committed
147
        }
148

Julien Bonjean's avatar
Julien Bonjean committed
149
        /**
150 151 152 153
         * Get the peer display name (caller in ingoing)
         * not protected by mutex (when created)
         * @return std::string The peer name
         */
154 155
        const std::string& getPeerDisplayName() const {
            return peerDisplayName_;
Julien Bonjean's avatar
Julien Bonjean committed
156
        }
157

158 159
        /**
         * Tell if the call is incoming
160
         * @return true if yes false otherwise
161
         */
162
        bool isIncoming() const {
163
            return type_ == CallType::INCOMING;
Julien Bonjean's avatar
Julien Bonjean committed
164
        }
165 166 167

        /**
         * Set the state of the call (protected by mutex)
168 169 170
         * @param call_state The call state
         * @param cnx_state The call connection state
         * @param code Optionnal state dependent error code (used to report more information)
171
         * @return true if the requested state change was valid, false otherwise
172
         */
173 174 175
        bool setState(CallState call_state, signed code=0);
        bool setState(CallState call_state, ConnectionState cnx_state, signed code=0);
        bool setState(ConnectionState cnx_state, signed code=0);
176

Julien Bonjean's avatar
Julien Bonjean committed
177
        /**
178 179 180
         * Get the call state of the call (protected by mutex)
         * @return CallState  The call state
         */
181
        CallState getState() const;
Julien Bonjean's avatar
Julien Bonjean committed
182

183 184 185 186 187 188
        /**
         * Get the connection state of the call (protected by mutex)
         * @return ConnectionState The connection state
         */
        ConnectionState getConnectionState() const;

189
        std::string getStateStr() const;
190

191 192
        void setIPToIP(bool IPToIP) {
            isIPToIP_ = IPToIP;
Julien Bonjean's avatar
Julien Bonjean committed
193 194 195 196
        }

        /**
         * Set my IP [not protected]
197 198
         * @param ip  The local IP address
         */
Adrien Béraud's avatar
Adrien Béraud committed
199 200
        void setLocalIp(const IpAddr& ip) {
            localAddr_ = ip;
Julien Bonjean's avatar
Julien Bonjean committed
201
        }
202

Julien Bonjean's avatar
Julien Bonjean committed
203
        /**
204 205 206
         * Set local audio port, as seen by me [not protected]
         * @param port  The local audio port
         */
207
        void setLocalAudioPort(unsigned int port) {
208
            localAudioPort_ = port;
Julien Bonjean's avatar
Julien Bonjean committed
209
        }
210

211 212 213 214
        /**
         * Set local video port, as seen by me [not protected]
         * @param port  The local video port
         */
Tristan Matthews's avatar
Tristan Matthews committed
215
        void setLocalVideoPort(unsigned int port)  {
216
            localVideoPort_ = port;
217 218
        }

Julien Bonjean's avatar
Julien Bonjean committed
219 220
        /**
         * Return my IP [mutex protected]
221 222
         * @return std::string The local IP
         */
Adrien Béraud's avatar
Adrien Béraud committed
223
        IpAddr getLocalIp() const;
224

Julien Bonjean's avatar
Julien Bonjean committed
225 226
        /**
         * Return port used locally (for my machine) [mutex protected]
227 228
         * @return unsigned int  The local audio port
         */
229
        unsigned int getLocalAudioPort() const;
230

231 232 233 234
        /**
         * Return port used locally (for my machine) [mutex protected]
         * @return unsigned int  The local video port
         */
235
        unsigned int getLocalVideoPort() const;
236

237
        virtual std::map<std::string, std::string> getDetails() const;
238
        static std::map<std::string, std::string> getNullDetails();
239

240
        virtual bool toggleRecording();
241

242 243 244 245 246
        /**
         * Answer the call
         */
        virtual void answer() = 0;

247 248 249 250 251 252
        /**
         * Hang up the call
         * @param reason
         */
        virtual void hangup(int reason) = 0;

253 254
        virtual void switchInput(const std::string&) {};

255 256 257 258 259
        /**
         * Refuse incoming call
         */
        virtual void refuse() = 0;

260 261 262 263 264 265 266 267 268 269 270 271 272
        /**
         * Transfer a call to specified URI
         * @param to The recipient of the call
         */
        virtual void transfer(const std::string &to) = 0;

        /**
         * Attended transfer
         * @param The target call id
         * @return True on success
         */
        virtual bool attendedTransfer(const std::string& to) = 0;

273 274 275 276
        /**
         * Put a call on hold
         * @return bool True on success
         */
277
        virtual bool onhold() = 0;
278 279 280 281 282

        /**
         * Resume a call from hold state
         * @return bool True on success
         */
283
        virtual bool offhold() = 0;
284

285 286 287 288 289 290 291
        /**
         * mute/unmute a media of a call
         * @param mediaType type of media
         * @param isMuted true for muting, false for unmuting
         */
        virtual void muteMedia(const std::string& mediaType, bool isMuted)  = 0;

292
        /**
293
         * Peer has hung up a call
294
         */
295
        virtual void peerHungup();
296

297 298 299 300 301 302
        /**
         * Send DTMF
         * @param code  The char code
         */
        virtual void carryingDTMFdigits(char code) = 0;

303 304 305
        /**
         * Send a message to a call identified by its callid
         *
306
         * @param A list of mimetype/payload pairs
307 308
         * @param The sender of this message (could be another participant of a conference)
         */
309
        virtual void sendTextMessage(const std::map<std::string, std::string>& messages,
310 311
                                     const std::string &from) = 0;

312

313
        void onTextMessage(std::map<std::string, std::string>&& messages);
314

315
        virtual void removeCall();
316

317
        virtual bool initIceTransport(bool master, unsigned channel_num=4);
318 319 320 321 322 323 324

        int waitForIceInitialization(unsigned timeout);

        int waitForIceNegotiation(unsigned timeout);

        bool isIceUsed() const;
        bool isIceRunning() const;
325 326 327

        std::unique_ptr<IceSocket> newIceSocket(unsigned compId);

328
        std::shared_ptr<IceTransport> getIceTransport() const {
329 330 331
            return iceTransport_;
        }

332 333 334 335
        virtual bool useVideoCodec(const AccountVideoCodecInfo* /*codec*/) const {
            return false;
        }

336
        virtual void restartMediaSender() = 0;
337 338
        virtual void restartMediaReceiver() = 0;

339 340 341 342 343 344 345 346 347 348
        using StateListener = std::function<void(CallState, int)>;

        template<class T>
        void addStateListener(T&& list) {
            stateChangedListeners_.emplace_back(std::forward<T>(list));
        }
        void addSubCall(const std::shared_ptr<Call>& call);

        virtual void merge(std::shared_ptr<Call> scall);

349 350 351 352 353 354 355 356
    protected:
        /**
         * Constructor of a call
         * @param id Unique identifier of the call
         * @param type set definitely this call as incoming/outgoing
         */
        Call(Account& account, const std::string& id, Call::CallType type);

357
        std::shared_ptr<IceTransport> iceTransport_ {};
358

359 360
        bool isAudioMuted_{false};
        bool isVideoMuted_{false};
361 362
        bool quiet {false};
        std::set<std::shared_ptr<Call>> subcalls {};
363 364
        std::list<std::pair<std::map<std::string, std::string>, std::string>> pendingInMessages_ {};
        std::list<std::pair<std::map<std::string, std::string>, std::string>> pendingOutMessages_ {};
365

366
    private:
367

368
        bool validStateTransition(CallState newState);
369

370
        /** Protect every attribute that can be changed by two threads */
371
        mutable std::recursive_mutex callMutex_ {};
372

373 374
        std::vector<std::function<void(CallState, ConnectionState, int)>> stateChangedListeners_ {};

375 376 377
        // Informations about call socket / audio

        /** My IP address */
378
        IpAddr localAddr_ {};
379 380

        /** Local audio port, as seen by me. */
381
        unsigned int localAudioPort_ {0};
382

383
        /** Local video port, as seen by me. */
384
        unsigned int localVideoPort_ {0};
385 386

        /** Unique ID of the call */
387
        std::string id_;
388

Julien Bonjean's avatar
Julien Bonjean committed
389
        /** Unique conference ID, used exclusively in case of a conferece */
390
        std::string confID_ {};
391

392
        /** Type of the call */
393
        CallType type_;
394

395
        /** Associate account ID */
396
        Account& account_;
397

398
        /** Disconnected/Progressing/Trying/Ringing/Connected */
399
        ConnectionState connectionState_ {ConnectionState::DISCONNECTED};
400

401
        /** Inactive/Active/Hold/Busy/Error */
402
        CallState callState_ {CallState::INACTIVE};
403 404

        /** Direct IP-to-IP or classic call */
405
        bool isIPToIP_ {false};
406 407

        /** Number of the peer */
408
        std::string peerNumber_ {};
409

410 411
        /** Peer Display Name */
        std::string peerDisplayName_ {};
412

413
        time_t timestamp_start_ {0};
jpbl's avatar
jpbl committed
414 415
};

416
} // namespace ring