Ring Daemon 16.0.0
Loading...
Searching...
No Matches
sipcall.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 "call.h"
24#include <dhtnet/ice_transport.h>
26#include "media/media_codec.h" // for MediaType enum
27#include "sip/sdp.h"
28
29#include "media/rtp_session.h"
30#ifdef ENABLE_VIDEO
33#endif
34#ifdef ENABLE_PLUGIN
35#include "plugin/streamdata.h"
36#endif
37#include "noncopyable.h"
38
39#include <memory>
40#include <optional>
41
42extern "C" {
43#include <pjsip/sip_config.h>
44struct pjsip_evsub;
45struct pjsip_inv_session;
46struct pjmedia_sdp_session;
47struct pj_ice_sess_cand;
48struct pjsip_rx_data;
49}
50
51namespace dhtnet {
52class IceSocket;
53namespace upnp {
54class Controller;
55}
56}
57
58namespace jami {
59
60class Sdp;
61class SIPAccountBase;
62class SipTransport;
63class AudioRtpSession;
64
66
71class SIPCall : public Call
72{
73private:
74 using clock = std::chrono::steady_clock;
75 using time_point = clock::time_point;
76
78
79public:
80 static constexpr LinkType LINK_TYPE = LinkType::SIP;
81
82 struct RtpStream
83 {
84 std::shared_ptr<RtpSession> rtpSession_ {};
85 std::shared_ptr<MediaAttribute> mediaAttribute_ {};
86 std::shared_ptr<MediaAttribute> remoteMediaAttribute_;
87 std::unique_ptr<dhtnet::IceSocket> rtpSocket_;
88 std::unique_ptr<dhtnet::IceSocket> rtcpSocket_;
89 };
90
94 ~SIPCall();
95
102 SIPCall(const std::shared_ptr<SIPAccountBase>& account,
103 const std::string& id,
104 Call::CallType type,
105 const std::vector<libjami::MediaMap>& mediaList);
106
107 // Inherited from Call class
108 LinkType getLinkType() const override { return LINK_TYPE; }
109
110 // Override of Call class
111private:
112 void merge(Call& call) override; // not public - only called by Call
113
114public:
115 void answer() override;
116 void answer(const std::vector<libjami::MediaMap>& mediaList) override;
117 bool checkMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
118 void handleMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
119 void answerMediaChangeRequest(const std::vector<libjami::MediaMap>& mediaList,
120 bool isRemote = false) override;
121 void hangup(int reason) override;
122 void refuse() override;
123 void transfer(const std::string& to) override;
124 bool attendedTransfer(const std::string& to) override;
125 bool onhold(OnReadyCb&& cb) override;
126 bool offhold(OnReadyCb&& cb) override;
127 void switchInput(const std::string& resource = {}) override;
128 void peerHungup() override;
129 void carryingDTMFdigits(char code) override;
130 bool requestMediaChange(const std::vector<libjami::MediaMap>& mediaList) override;
131 std::vector<libjami::MediaMap> currentMediaList() const override;
132 void sendTextMessage(const std::map<std::string, std::string>& messages,
133 const std::string& from) override;
134 void removeCall() override;
135 void muteMedia(const std::string& mediaType, bool isMuted) override;
136 std::vector<MediaAttribute> getMediaAttributeList() const override;
137 std::map<std::string, bool> getAudioStreams() const override;
138 void restartMediaSender() override;
139 std::shared_ptr<SystemCodecInfo> getAudioCodec() const override;
140 std::shared_ptr<SystemCodecInfo> getVideoCodec() const override;
141 void sendKeyframe(int streamIdx = -1) override;
142 bool isIceEnabled() const override;
143 std::map<std::string, std::string> getDetails() const override;
144 void enterConference(std::shared_ptr<Conference> conference) override;
145 void exitConference() override;
146#ifdef ENABLE_VIDEO
147 std::mutex sinksMtx_;
148 void createSinks(ConfInfo& infos) override;
149 std::map<std::string, std::shared_ptr<video::SinkClient>> callSinksMap_ {};
150 std::map<std::string, std::string> local2RemoteSinks_ {};
151#endif
152 bool hasVideo() const override;
153
154 // TODO: cleanup this (used by conference + Call::getDetails() (and clients can use this))
155 bool isCaptureDeviceMuted(const MediaType& mediaType) const override;
156 bool isSrtpEnabled() const
157 {
158 return srtpEnabled_;
159 }
160 // End of override of Call class
161
162 // Override of Recordable class
163 bool toggleRecording() override;
164 // End of override of Recordable class
165
166 // Override PeerRecorder
167 void peerRecording(bool state) override;
168 void peerMuted(bool state, int streamIdx) override;
169 void peerVoice(bool state) override;
170 // end override PeerRecorder
171
172 void monitor() const override;
173
177 void setPeerUaVersion(std::string_view ua);
178
182 void setPeerAllowMethods(std::vector<std::string> methods);
183
187 bool isSipMethodAllowedByPeer(const std::string_view method) const;
188
193 {
194 return *sdp_;
195 }
196
197 // Implementation of events reported by SipVoipLink.
201 void onPeerRinging();
205 void onAnswered();
210 void onFailure(signed cause = 0);
214 void onBusyHere();
218 void onClosed();
219
222
228 // End fo SiPVoipLink events
229
230 const std::string& getContactHeader() const;
231
232 void setSipTransport(const std::shared_ptr<SipTransport>& transport,
233 const std::string& contactHdr = {});
234
236 {
237 return sipTransport_.get();
238 }
239
240 void sendSIPInfo(std::string_view body, std::string_view subtype);
241
242 void requestKeyframe(int streamIdx = -1);
243
244 void updateRecState(bool state) override;
245
246 std::shared_ptr<SIPAccountBase> getSIPAccount() const;
247
248 bool remoteHasValidIceAttributes() const;
250
251 std::shared_ptr<dhtnet::IceTransport> getIceMedia() const
252 {
253 std::lock_guard lk(transportMtx_);
254 return reinvIceMedia_ ? reinvIceMedia_ : iceMedia_;
255 };
256
257 // Set ICE instance. Must be called only for sub-calls
258 void setIceMedia(std::shared_ptr<dhtnet::IceTransport> ice, bool isReinvite = false);
259
260 // Switch to re-invite ICE media if needed
262
267 void setupIceResponse(bool isReinvite = false);
268
269 void terminateSipSession(int status);
270
275 {
276 void operator()(pjsip_inv_session*) const noexcept;
277 };
278
279#ifdef ENABLE_VIDEO
280 void setRotation(int streamIdx, int rotation);
281#endif
282 // Get the list of current RTP sessions
283 std::vector<std::shared_ptr<RtpSession>> getRtpSessionList(
284 MediaType type = MediaType::MEDIA_ALL) const;
285 static size_t getActiveMediaStreamCount(const std::vector<MediaAttribute>& mediaAttrList);
286 void setActiveMediaStream(const std::string& accountUri,
287 const std::string& deviceId,
288 const std::string& streamId,
289 const bool& state);
290
291 void setPeerRegisteredName(const std::string& name)
292 {
293 peerRegisteredName_ = name;
294 }
295
296 void setPeerUri(const std::string& peerUri)
297 {
298 peerUri_ = peerUri;
299 }
300
301 std::string_view peerUri() const {
302 return peerUri_;
303 }
304
305 // Create a new ICE media session. If we already have an instance,
306 // it will be destroyed first.
308
309 // Initialize the ICE session.
310 // The initialization is performed asynchronously, i.e, the instance
311 // may not be ready to use when this method returns.
313 std::optional<dhtnet::IceTransportOptions> options = std::nullopt);
314
315 std::vector<std::string> getLocalIceCandidates(unsigned compId) const;
316
318
319 std::unique_ptr<pjsip_inv_session, InvSessionDeleter> inviteSession_;
320
321 inline std::weak_ptr<const SIPCall> weak() const
322 {
323 return std::weak_ptr<const SIPCall>(shared());
324 }
325 inline std::weak_ptr<SIPCall> weak()
326 {
327 return std::weak_ptr<SIPCall>(shared());
328 }
333
334 const std::vector<RtpStream>& getRtpStreams() const { return rtpStreams_; }
335
336private:
337 void generateMediaPorts();
338
339 void openPortsUPnP();
340
341 bool isIceRunning() const;
342
343 std::unique_ptr<dhtnet::IceSocket> newIceSocket(unsigned compId);
344
345 void deinitRecorder();
346
347 void rtpSetupSuccess();
348
349 void setupVoiceCallback(const std::shared_ptr<RtpSession>& rtpSession);
350
351 void sendMuteState(bool state);
352 void sendVoiceActivity(std::string_view streamId, bool state);
353
354 void resetTransport(std::shared_ptr<dhtnet::IceTransport>&& transport);
355
361 void setVideoOrientation(int streamIdx, int rotation);
362
363 mutable std::mutex transportMtx_ {};
364
365#ifdef ENABLE_PLUGIN
371
381 const std::shared_ptr<MediaStreamSubject>& mediaStreamSubject);
386 void createCallAVStreams();
387
391 void clearCallAVStreams();
392
393 std::mutex avStreamsMtx_ {};
394 std::map<std::string, std::shared_ptr<MediaStreamSubject>> callAVStreams;
395#endif // ENABLE_PLUGIN
396
397 void setCallMediaLocal();
398 void startIceMedia();
399 void onIceNegoSucceed();
400 void setupNegotiatedMedia();
401 void startAllMedia();
402 void stopAllMedia();
403 void updateRemoteMedia();
404
408 bool transferCommon(const pj_str_t* dst);
409
410 bool internalOffHold(const std::function<void()>& SDPUpdateFunc);
411
412 bool hold();
413
414 bool unhold();
415
416 // Update the attributes of a media stream
417 void updateMediaStream(const MediaAttribute& newMediaAttr, size_t streamIdx);
418 bool updateAllMediaStreams(const std::vector<MediaAttribute>& mediaAttrList, bool isRemote);
419 // Check if a SIP re-invite must be sent to negotiate the new media
420 bool isReinviteRequired(const std::vector<MediaAttribute>& mediaAttrList);
421 // Check if a new ICE media session is needed when performing a re-invite
422 bool isNewIceMediaRequired(const std::vector<MediaAttribute>& mediaAttrList);
423 void requestReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
424 int SIPSessionReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
425 int SIPSessionReinvite();
426 // Add a media stream to the call.
427 void addMediaStream(const MediaAttribute& mediaAttr);
428 // Init media streams
429 size_t initMediaStreams(const std::vector<MediaAttribute>& mediaAttrList);
430 // Create a new stream from SDP description.
431 void createRtpSession(RtpStream& rtpStream);
432 // Configure the RTP session from SDP description.
433 void configureRtpSession(const std::shared_ptr<RtpSession>& rtpSession,
434 const std::shared_ptr<MediaAttribute>& mediaAttr,
435 const MediaDescription& localMedia,
436 const MediaDescription& remoteMedia);
437 // Find the stream index with the matching label
438 int findRtpStreamIndex(const std::string& label) const;
439
440 std::vector<IceCandidate> getAllRemoteCandidates(dhtnet::IceTransport& transport) const;
441
442 inline std::shared_ptr<const SIPCall> shared() const
443 {
444 return std::static_pointer_cast<const SIPCall>(shared_from_this());
445 }
446 inline std::shared_ptr<SIPCall> shared()
447 {
448 return std::static_pointer_cast<SIPCall>(shared_from_this());
449 }
450
451 // Peer's User-Agent.
452 std::string peerUserAgent_ {};
453 // Flag to indicate if the peer's Daemon version supports multi-stream.
454 bool peerSupportMultiStream_ {false};
455 // Flag to indicate if the peer's Daemon version supports multi-stream.
456 bool peerSupportMultiAudioStream_ {false};
457 // Flag to indicate if the peer's Daemon version can negotiate more than 2 ICE medias
458 bool peerSupportMultiIce_ {false};
459
460 // Flag to indicate if the peer's Daemon version supports re-invite
461 // without ICE renegotiation.
462 bool peerSupportReuseIceInReinv_ {false};
463
464 // Peer's allowed methods.
465 std::vector<std::string> peerAllowedMethods_;
466
467 // Vector holding the current RTP sessions.
468 std::vector<RtpStream> rtpStreams_;
469
475 std::shared_ptr<SipTransport> sipTransport_ {};
476
480 std::unique_ptr<Sdp> sdp_ {};
481 bool peerHolding_ {false};
482
483 bool isWaitingForIceAndMedia_ {false};
484 enum class Request { HoldingOn, HoldingOff, SwitchInput, NoRequest };
485 Request remainingRequest_ {Request::NoRequest};
486
487 std::string peerRegisteredName_ {};
488
489 std::string contactHeader_ {};
490
491 std::shared_ptr<dhtnet::upnp::Controller> upnp_;
492
494 unsigned int localAudioPort_ {0};
496 unsigned int localVideoPort_ {0};
497
498 bool mediaRestartRequired_ {true};
499 bool enableIce_ {true};
500 bool srtpEnabled_ {false};
501 bool rtcpMuxEnabled_ {false};
502
503 // ICE media transport
504 std::shared_ptr<dhtnet::IceTransport> iceMedia_;
505 // Re-invite (temporary) ICE media transport.
506 std::shared_ptr<dhtnet::IceTransport> reinvIceMedia_;
507
508 std::string peerUri_ {};
509
510 bool readyToRecord_ {false};
511 bool pendingRecord_ {false};
512
513 time_point lastKeyFrameReq_ {time_point::min()};
514
515 OnReadyCb holdCb_ {};
516 OnReadyCb offHoldCb_ {};
517
518 std::atomic_bool waitForIceInit_ {false};
519
520 void detachAudioFromConference();
521
522 std::mutex setupSuccessMutex_;
523#ifdef ENABLE_VIDEO
524 int rotation_ {0};
525#endif
526
527 std::string mediaPlayerId_ {};
528};
529
530// Helpers
531
535inline std::shared_ptr<SIPCall>
537{
538 return std::static_pointer_cast<SIPCall>(call.shared_from_this());
539}
540
541} // namespace jami
std::function< void(bool)> OnReadyCb
Definition call.h:113
CallType
This determines if the call originated from the local user (OUTGOING) or from some remote peer (INCOM...
Definition call.h:120
std::vector< MediaAttribute > getMediaAttributeList() const override
Definition sipcall.cpp:2660
bool hasVideo() const override
Definition sipcall.cpp:2034
void terminateSipSession(int status)
Definition sipcall.cpp:766
void answerMediaChangeRequest(const std::vector< libjami::MediaMap > &mediaList, bool isRemote=false) override
Answer to a media update request.
Definition sipcall.cpp:999
std::map< std::string, std::string > getDetails() const override
Definition sipcall.cpp:3072
void setIceMedia(std::shared_ptr< dhtnet::IceTransport > ice, bool isReinvite=false)
Definition sipcall.cpp:3583
void refuse() override
Refuse incoming call.
Definition sipcall.cpp:1157
void onBusyHere()
Peer answered busy.
Definition sipcall.cpp:1634
void switchInput(const std::string &resource={}) override
Definition sipcall.cpp:1466
bool isIceEnabled() const override
Check wether ICE is enabled for media.
Definition sipcall.cpp:1702
std::string_view peerUri() const
Definition sipcall.h:301
void onMediaNegotiationComplete()
Called when the media negotiation (SDP offer/answer) has completed.
Definition sipcall.cpp:2685
bool isSrtpEnabled() const
Definition sipcall.h:156
static constexpr LinkType LINK_TYPE
Definition sipcall.h:80
void setPeerUaVersion(std::string_view ua)
Set peer's User-Agent found in the message header.
Definition sipcall.cpp:1708
void answer() override
Answer the call.
Definition sipcall.cpp:804
void muteMedia(const std::string &mediaType, bool isMuted) override
mute/unmute a media of a call
Definition sipcall.cpp:2304
void reportMediaNegotiationStatus()
Announce to the client that medias are successfully negotiated.
Definition sipcall.cpp:2730
void handleMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList) override
Process incoming media change request.
Definition sipcall.cpp:2861
std::vector< std::shared_ptr< RtpSession > > getRtpSessionList(MediaType type=MediaType::MEDIA_ALL) const
Definition sipcall.cpp:3333
void onFailure(signed cause=0)
Called to report server/internal errors.
Definition sipcall.cpp:1620
pj_status_t onReceiveReinvite(const pjmedia_sdp_session *offer, pjsip_rx_data *rdata)
Definition sipcall.cpp:2910
void setActiveMediaStream(const std::string &accountUri, const std::string &deviceId, const std::string &streamId, const bool &state)
Definition sipcall.cpp:3219
bool toggleRecording() override
This method must be implemented for this interface as calls and conferences have different behavior.
Definition sipcall.cpp:3369
void setSipTransport(const std::shared_ptr< SipTransport > &transport, const std::string &contactHdr={})
Definition sipcall.cpp:464
void onReceiveOfferIn200OK(const pjmedia_sdp_session *offer)
Definition sipcall.cpp:2975
bool createIceMediaTransport(bool isReinvite)
Definition sipcall.cpp:3418
void monitor() const override
Definition sipcall.cpp:3345
Sdp & getSDP()
Return the SDP's manager of this call.
Definition sipcall.h:192
std::vector< libjami::MediaMap > currentMediaList() const override
Retrieve current medias list.
Definition sipcall.cpp:2654
void restartMediaSender() override
Definition sipcall.cpp:2232
std::weak_ptr< SIPCall > weak()
Definition sipcall.h:325
bool offhold(OnReadyCb &&cb) override
Resume a call from hold state.
Definition sipcall.cpp:1391
bool onhold(OnReadyCb &&cb) override
Put a call on hold.
Definition sipcall.cpp:1342
void sendTextMessage(const std::map< std::string, std::string > &messages, const std::string &from) override
Send a message to a call identified by its callid.
Definition sipcall.cpp:1550
void sendKeyframe(int streamIdx=-1) override
Definition sipcall.cpp:1679
std::shared_ptr< SystemCodecInfo > getAudioCodec() const override
Definition sipcall.cpp:1979
const std::vector< RtpStream > & getRtpStreams() const
Definition sipcall.h:334
static size_t getActiveMediaStreamCount(const std::vector< MediaAttribute > &mediaAttrList)
void hangup(int reason) override
Hang up the call.
Definition sipcall.cpp:1103
std::shared_ptr< dhtnet::IceTransport > getIceMedia() const
Definition sipcall.h:251
~SIPCall()
Destructor.
Definition sipcall.cpp:155
void peerMuted(bool state, int streamIdx) override
Definition sipcall.cpp:3712
bool initIceMediaTransport(bool master, std::optional< dhtnet::IceTransportOptions > options=std::nullopt)
Definition sipcall.cpp:3436
bool remoteHasValidIceAttributes() const
Definition sipcall.cpp:3562
void exitConference() override
Definition sipcall.cpp:3192
void onClosed()
Peer closed the connection.
Definition sipcall.cpp:1651
void setupIceResponse(bool isReinvite=false)
Setup ICE locally to answer to an ICE offer.
Definition sipcall.cpp:3614
std::shared_ptr< SystemCodecInfo > getVideoCodec() const override
Definition sipcall.cpp:1966
void addLocalIceAttributes()
Definition sipcall.cpp:1832
bool checkMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList) override
Check the media of an incoming media change request.
Definition sipcall.cpp:2834
bool isCaptureDeviceMuted(const MediaType &mediaType) const override
Definition sipcall.cpp:2054
void onPeerRinging()
Call is in ringing state on peer's side.
Definition sipcall.cpp:1825
void updateRecState(bool state) override
Update recording state.
Definition sipcall.cpp:647
std::vector< std::string > getLocalIceCandidates(unsigned compId) const
Definition sipcall.cpp:3509
SipTransport * getTransport()
Definition sipcall.h:235
bool attendedTransfer(const std::string &to) override
Attended transfer.
Definition sipcall.cpp:1306
void carryingDTMFdigits(char code) override
Send DTMF.
Definition sipcall.cpp:1508
const std::string & getContactHeader() const
Definition sipcall.cpp:458
std::shared_ptr< SIPAccountBase > getSIPAccount() const
Definition sipcall.cpp:325
void transfer(const std::string &to) override
Transfer a call to specified URI.
Definition sipcall.cpp:1284
bool isSipMethodAllowedByPeer(const std::string_view method) const
Check if a SIP method is allowed by peer.
Definition sipcall.cpp:1816
std::map< std::string, bool > getAudioStreams() const override
Definition sipcall.cpp:2671
void setPeerUri(const std::string &peerUri)
Definition sipcall.h:296
void sendSIPInfo(std::string_view body, std::string_view subtype)
Definition sipcall.cpp:614
std::unique_ptr< pjsip_inv_session, InvSessionDeleter > inviteSession_
Definition sipcall.h:319
void peerVoice(bool state) override
Definition sipcall.cpp:3735
void onAnswered()
Peer answered the call.
Definition sipcall.cpp:1663
void setPeerRegisteredName(const std::string &name)
Definition sipcall.h:291
void removeCall() override
Definition sipcall.cpp:1595
void setPeerAllowMethods(std::vector< std::string > methods)
Set peer's allowed methods.
Definition sipcall.cpp:1809
void switchToIceReinviteIfNeeded()
Definition sipcall.cpp:3599
void enterConference(std::shared_ptr< Conference > conference) override
Definition sipcall.cpp:3163
void peerHungup() override
Peer has hung up a call.
Definition sipcall.cpp:1495
LinkType getLinkType() const override
Definition sipcall.h:108
void peerRecording(bool state) override
Definition sipcall.cpp:3695
std::weak_ptr< const SIPCall > weak() const
Definition sipcall.h:321
void requestKeyframe(int streamIdx=-1)
Definition sipcall.cpp:667
bool requestMediaChange(const std::vector< libjami::MediaMap > &mediaList) override
Make a change request of the current media with the provided media.
Definition sipcall.cpp:2511
void setInviteSession(pjsip_inv_session *inviteSession=nullptr)
Definition sipcall.cpp:737
SIP transport wraps pjsip_transport.
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
pj_ice_sess_cand IceCandidate
Definition sipcall.h:65
@ MEDIA_ALL
Definition media_codec.h:49
Simple macro to hide class' copy constructor and assignment operator.
#define NON_COPYABLE(ClassName)
Definition noncopyable.h:30
Contains information about an AV subject.
Definition streamdata.h:29
The invite session to be reused in case of transfer.
Definition sipcall.h:275
void operator()(pjsip_inv_session *) const noexcept
Definition sipcall.cpp:3406
std::shared_ptr< MediaAttribute > remoteMediaAttribute_
Definition sipcall.h:86
std::unique_ptr< dhtnet::IceSocket > rtpSocket_
Definition sipcall.h:87
std::unique_ptr< dhtnet::IceSocket > rtcpSocket_
Definition sipcall.h:88
std::shared_ptr< RtpSession > rtpSession_
Definition sipcall.h:84
std::shared_ptr< MediaAttribute > mediaAttribute_
Definition sipcall.h:85