Ring Daemon 16.0.0
Loading...
Searching...
No Matches
call.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "logger.h"
24
25#include "conference.h"
26#include "media/recordable.h"
27#include "media/peerrecorder.h"
28#include "media/media_codec.h"
30
31#include <dhtnet/ip_utils.h>
32
33#include <atomic>
34#include <mutex>
35#include <map>
36#include <sstream>
37#include <memory>
38#include <vector>
39#include <condition_variable>
40#include <set>
41#include <list>
42#include <functional>
43
44template<typename T>
45bool
46is_uninitialized(std::weak_ptr<T> const& weak)
47{
48 using wt = std::weak_ptr<T>;
49 return !weak.owner_before(wt {}) && !wt {}.owner_before(weak);
50}
51
52namespace jami {
53
54class VoIPLink;
55class Account;
56class AudioDeviceGuard;
57
58class Call;
59class Conference;
60
61using CallMap = std::map<std::string, std::shared_ptr<Call>>;
62
63namespace video {
64class VideoGenerator;
65}
66
67/*
68 * @file call.h
69 * @brief A call is the base class for protocol-based calls
70 */
71
72class Call : public Recordable, public PeerRecorder, public std::enable_shared_from_this<Call>
73{
74public:
85 enum class ConnectionState : unsigned {
87 TRYING,
89 RINGING,
92 };
93
99 enum class CallState : unsigned {
100 INACTIVE,
101 ACTIVE,
102 HOLD,
103 BUSY,
104 PEER_BUSY,
105 MERROR,
106 OVER,
107 COUNT__
108 };
109
110 enum class LinkType { GENERIC, SIP };
111
112 using SubcallSet = std::set<std::shared_ptr<Call>, std::owner_less<std::shared_ptr<Call>>>;
113 using OnReadyCb = std::function<void(bool)>;
114 using StateListenerCb = std::function<bool(CallState, ConnectionState, int)>;
115
120 enum class CallType : unsigned { INCOMING, OUTGOING, MISSED };
121
122 virtual ~Call();
123
124 std::weak_ptr<Call> weak() { return std::static_pointer_cast<Call>(shared_from_this()); }
125
126 virtual LinkType getLinkType() const { return LinkType::GENERIC; }
127
132 const std::string& getCallId() const { return id_; }
133
138 std::shared_ptr<Conference> getConference() const { return conf_.lock(); }
140
141 std::weak_ptr<Account> getAccount() const { return account_; }
142 std::string getAccountId() const;
143
144 CallType getCallType() const { return type_; }
145
151 void setPeerNumber(const std::string& number) { peerNumber_ = number; }
152
158 const std::string& getPeerNumber() const { return peerNumber_; }
164 void setPeerDisplayName(const std::string& name) { peerDisplayName_ = name; }
165
171 const std::string& toUsername() const { return toUsername_; }
176 void toUsername(const std::string& username) { toUsername_ = username; }
177
183 const std::string& getPeerDisplayName() const { return peerDisplayName_; }
188 bool isIncoming() const { return type_ == CallType::INCOMING; }
189
197 bool setState(CallState call_state, signed code = 0);
198 bool setState(CallState call_state, ConnectionState cnx_state, signed code = 0);
199 bool setState(ConnectionState cnx_state, signed code = 0);
200
205 CallState getState() const;
206
212
213 std::string getStateStr() const;
214
216
217 virtual std::map<std::string, std::string> getDetails() const;
218
222 virtual void answer() = 0;
223
233 virtual void answer(const std::vector<libjami::MediaMap>& mediaList) = 0;
234
249 virtual bool checkMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) = 0;
250
256 virtual void handleMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) = 0;
257
269 virtual void answerMediaChangeRequest(const std::vector<libjami::MediaMap>& mediaList,
270 bool isRemote = false)
271 = 0;
276 virtual void hangup(int reason) = 0;
277
281 virtual void refuse() = 0;
282
287 virtual void transfer(const std::string& to) = 0;
288
294 virtual bool attendedTransfer(const std::string& to) = 0;
295
301 virtual bool onhold(OnReadyCb&& cb) = 0;
302
308 virtual bool offhold(OnReadyCb&& cb) = 0;
309
310 virtual void sendKeyframe(int streamIdx = -1) = 0;
311
315 virtual bool isIceEnabled() const = 0;
316
320 virtual void peerHungup();
321
322 virtual void removeCall();
323
328 virtual void updateRecState(bool state) = 0;
329
331 {
332 std::lock_guard lk {callMutex_};
333 stateChangedListeners_.emplace_back(std::move(listener));
334 }
335
340 void addSubCall(Call& call);
341
345 bool isSubcall() const
346 {
347 std::lock_guard lk {callMutex_};
348 return parent_ != nullptr;
349 }
350
354 std::chrono::milliseconds getCallDuration() const
355 {
356 return duration_start_ == time_point::min()
357 ? std::chrono::milliseconds::zero()
358 : std::chrono::duration_cast<std::chrono::milliseconds>(clock::now()
360 }
361
362 // media management
363 virtual bool toggleRecording();
364
365 virtual std::vector<MediaAttribute> getMediaAttributeList() const = 0;
366
367 virtual std::map<std::string, bool> getAudioStreams() const = 0;
368
369#ifdef ENABLE_VIDEO
370 virtual void createSinks(ConfInfo& infos) = 0;
371#endif
372
373 virtual void switchInput(const std::string& = {}) {};
374
380 virtual void muteMedia(const std::string& mediaType, bool isMuted) = 0;
381
386 virtual void carryingDTMFdigits(char code) = 0;
387
393 virtual bool requestMediaChange(const std::vector<libjami::MediaMap>& mediaList) = 0;
394
399 virtual std::vector<libjami::MediaMap> currentMediaList() const = 0;
400
407 virtual void sendTextMessage(const std::map<std::string, std::string>& messages,
408 const std::string& from)
409 = 0;
410
411 void onTextMessage(std::map<std::string, std::string>&& messages);
412
413 virtual std::shared_ptr<SystemCodecInfo> getAudioCodec() const
414 {
415 return {};
416 }
417 virtual std::shared_ptr<SystemCodecInfo> getVideoCodec() const
418 {
419 return {};
420 }
421
422 virtual void restartMediaSender() = 0;
423
424 // Media status methods
425 virtual bool hasVideo() const = 0;
426 virtual bool isCaptureDeviceMuted(const MediaType& mediaType) const = 0;
427
433 void setConferenceInfo(const std::string& msg);
434
435 virtual void enterConference(std::shared_ptr<Conference> conference) = 0;
436 virtual void exitConference() = 0;
437
438 std::vector<std::map<std::string, std::string>> getConferenceInfos() const
439 {
441 }
442
443 std::unique_ptr<AudioDeviceGuard> audioGuard;
444 void sendConfOrder(const Json::Value& root);
445 void sendConfInfo(const std::string& json);
446 void resetConfInfo();
447
448 virtual void monitor() const = 0;
449
451 {
452 return peerConfProtocol_;
453 }
454
455protected:
456 using clock = std::chrono::steady_clock;
457 using time_point = clock::time_point;
458 virtual void merge(Call& scall);
459
466 Call(const std::shared_ptr<Account>& account,
467 const std::string& id,
468 Call::CallType type,
469 const std::map<std::string, std::string>& details = {});
470
471 // TODO all these members are not protected against multi-thread access
472
473 const std::string id_ {};
474
476 mutable std::shared_ptr<Call> parent_;
477
480
481 using MsgList = std::list<std::pair<std::map<std::string, std::string>, std::string>>;
482
485
487 mutable std::recursive_mutex callMutex_ {};
488
489 mutable std::mutex confInfoMutex_ {};
490 mutable ConfInfo confInfo_ {};
491 time_point duration_start_ {time_point::min()};
492
493private:
494 bool validStateTransition(CallState newState);
495
496 void checkPendingIM();
497
498 void checkAudio();
499
500 void subcallStateChanged(Call&, Call::CallState, Call::ConnectionState);
501
502 SubcallSet safePopSubcalls();
503
504 std::vector<StateListenerCb> stateChangedListeners_ {};
505
506protected:
508 std::weak_ptr<Conference> conf_ {};
509
512
514 std::weak_ptr<Account> account_;
515
518
521
522 std::string reason_ {};
523
525 bool isIPToIP_ {false};
526
528 std::string peerNumber_ {};
529
531 std::string peerDisplayName_ {};
532
534
537
540 std::string toUsername_ {};
541};
542
543// Helpers
544
548inline std::shared_ptr<Call>
550{
551 return call.shared_from_this();
552}
553
554} // namespace jami
bool is_uninitialized(std::weak_ptr< T > const &weak)
Definition call.h:46
std::string reason_
Definition call.h:522
virtual bool onhold(OnReadyCb &&cb)=0
Put a call on hold.
virtual LinkType getLinkType() const
Definition call.h:126
int peerConfProtocol_
Supported conference protocol version.
Definition call.h:539
virtual bool offhold(OnReadyCb &&cb)=0
Resume a call from hold state.
std::chrono::steady_clock clock
Definition call.h:456
virtual bool isIceEnabled() const =0
Check wether ICE is enabled for media.
void setPeerDisplayName(const std::string &name)
Set the display name (caller in ingoing) not protected by mutex (when created)
Definition call.h:164
void onTextMessage(std::map< std::string, std::string > &&messages)
Definition call.cpp:389
virtual void restartMediaSender()=0
MsgList pendingInMessages_
Definition call.h:536
virtual void switchInput(const std::string &={})
Definition call.h:373
virtual void exitConference()=0
const std::string & toUsername() const
Get "To" from the invite.
Definition call.h:171
virtual bool checkMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList)=0
Check the media of an incoming media change request.
std::string peerNumber_
Number of the peer.
Definition call.h:528
const std::string & getCallId() const
Return a reference on the call id.
Definition call.h:132
virtual void carryingDTMFdigits(char code)=0
Send DTMF.
virtual void transfer(const std::string &to)=0
Transfer a call to specified URI.
virtual bool isCaptureDeviceMuted(const MediaType &mediaType) const =0
virtual bool requestMediaChange(const std::vector< libjami::MediaMap > &mediaList)=0
Make a change request of the current media with the provided media.
std::set< std::shared_ptr< Call >, std::owner_less< std::shared_ptr< Call > > > SubcallSet
Definition call.h:112
CallState getState() const
Get the call state of the call (protected by mutex)
Definition call.cpp:174
virtual void sendTextMessage(const std::map< std::string, std::string > &messages, const std::string &from)=0
Send a message to a call identified by its callid.
virtual void muteMedia(const std::string &mediaType, bool isMuted)=0
mute/unmute a media of a call
virtual void sendKeyframe(int streamIdx=-1)=0
std::function< void(bool)> OnReadyCb
Definition call.h:113
std::mutex confInfoMutex_
Definition call.h:489
void toUsername(const std::string &username)
Updated by sipvoiplink, corresponds to the "To" in the invite.
Definition call.h:176
virtual std::vector< libjami::MediaMap > currentMediaList() const =0
Retrieve current medias list.
virtual std::shared_ptr< SystemCodecInfo > getAudioCodec() const
Definition call.h:413
void addSubCall(Call &call)
Attach subcall to this instance.
Definition call.cpp:430
std::weak_ptr< Account > account_
Associate account ID.
Definition call.h:514
CallType
This determines if the call originated from the local user (OUTGOING) or from some remote peer (INCOM...
Definition call.h:120
virtual void answer()=0
Answer the call.
std::string getStateStr() const
Definition call.cpp:304
virtual void hangup(int reason)=0
Hang up the call.
virtual void monitor() const =0
clock::time_point time_point
Definition call.h:457
std::chrono::milliseconds getCallDuration() const
Definition call.h:354
bool isConferenceParticipant() const
Definition call.h:139
ConnectionState getConnectionState() const
Get the connection state of the call (protected by mutex)
Definition call.cpp:167
CallType type_
Type of the call.
Definition call.h:511
std::shared_ptr< Conference > getConference() const
Return a reference on the conference id.
Definition call.h:138
void resetConfInfo()
Definition call.cpp:716
std::shared_ptr< Call > parent_
MultiDevice: list of attached subcall.
Definition call.h:476
bool isSubcall() const
Return true if this call instance is a subcall (internal call for multi-device handling)
Definition call.h:345
void sendConfOrder(const Json::Value &root)
Definition call.cpp:692
virtual void refuse()=0
Refuse incoming call.
virtual std::map< std::string, std::string > getDetails() const
Definition call.cpp:368
virtual void updateRecState(bool state)=0
Update recording state.
bool isIncoming() const
Tell if the call is incoming.
Definition call.h:188
std::list< std::pair< std::map< std::string, std::string >, std::string > > MsgList
MultiDevice: message waiting to be sent (need a valid subcall)
Definition call.h:483
virtual void peerHungup()
Peer has hung up a call.
Definition call.cpp:422
std::weak_ptr< Call > weak()
Definition call.h:124
CallState
The Call State.
Definition call.h:99
void setPeerNumber(const std::string &number)
Set the peer number (destination on outgoing) not protected by mutex (when created)
Definition call.h:151
ConnectionState
Tell where we're at with the call.
Definition call.h:85
virtual bool hasVideo() const =0
virtual void merge(Call &scall)
Replace current call data with ones from the given subcall.
Definition call.cpp:562
virtual void answer(const std::vector< libjami::MediaMap > &mediaList)=0
Answer a call with a list of media attributes.
std::string peerDisplayName_
Peer Display Name.
Definition call.h:531
ConfInfo confInfo_
Definition call.h:490
CallType getCallType() const
Definition call.h:144
std::weak_ptr< Conference > conf_
Unique conference ID, used exclusively in case of a conference.
Definition call.h:508
const std::string & getPeerNumber() const
Get the peer number (destination on outgoing) not protected by mutex (when created)
Definition call.h:158
void setIPToIP(bool IPToIP)
Definition call.h:215
SubcallSet subcalls_
Definition call.h:479
std::string getAccountId() const
Definition call.cpp:158
virtual std::shared_ptr< SystemCodecInfo > getVideoCodec() const
Definition call.h:417
virtual bool toggleRecording()
This method must be implemented for this interface as calls and conferences have different behavior.
Definition call.cpp:361
MsgList pendingOutMessages_
Definition call.h:484
std::unique_ptr< AudioDeviceGuard > audioGuard
Definition call.h:443
void setConferenceInfo(const std::string &msg)
A Call can be in a conference.
Definition call.cpp:636
virtual void handleMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList)=0
Process incoming media change request.
virtual std::vector< MediaAttribute > getMediaAttributeList() const =0
std::string toUsername_
Definition call.h:540
bool setState(CallState call_state, signed code=0)
Set the state of the call (protected by mutex)
Definition call.cpp:290
const std::string id_
MultiDevice: parent call, nullptr otherwise. Access protected by callMutex_.
Definition call.h:473
CallState callState_
Inactive/Active/Hold/Busy/Error.
Definition call.h:520
ConnectionState connectionState_
Disconnected/Progressing/Trying/Ringing/Connected.
Definition call.h:517
const std::string & getPeerDisplayName() const
Get the peer display name (caller in ingoing) not protected by mutex (when created)
Definition call.h:183
virtual bool attendedTransfer(const std::string &to)=0
Attended transfer.
time_t timestamp_start_
MultiDevice: message received by subcall to merged yet.
Definition call.h:533
virtual void enterConference(std::shared_ptr< Conference > conference)=0
virtual void removeCall()
Definition call.cpp:144
void sendConfInfo(const std::string &json)
Definition call.cpp:704
int conferenceProtocolVersion() const
Definition call.h:450
std::vector< std::map< std::string, std::string > > getConferenceInfos() const
Definition call.h:438
bool isIPToIP_
Direct IP-to-IP or classic call.
Definition call.h:525
std::weak_ptr< Account > getAccount() const
Definition call.h:141
virtual ~Call()
Definition call.cpp:141
virtual std::map< std::string, bool > getAudioStreams() const =0
virtual void answerMediaChangeRequest(const std::vector< libjami::MediaMap > &mediaList, bool isRemote=false)=0
Answer to a media update request.
time_point duration_start_
Definition call.h:491
void addStateListener(StateListenerCb &&listener)
Definition call.h:330
std::function< bool(CallState, ConnectionState, int)> StateListenerCb
Definition call.h:114
std::recursive_mutex callMutex_
Protect every attribute that can be changed by two threads.
Definition call.h:487
std::map< std::string, std::shared_ptr< Call > > CallMap
Definition call.h:61
void emitSignal(Args... args)
Definition ring_signal.h:64
std::shared_ptr< Call > getPtr(Call &call)
Obtain a shared smart pointer of instance.
Definition call.h:549
bool is_uninitialized(std::weak_ptr< T > const &weak)
std::vector< std::map< std::string, std::string > > toVectorMapStringString() const