Ring Daemon
Loading...
Searching...
No Matches
sipcall.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2026 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
18#pragma once
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include "call.h"
25#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} // namespace dhtnet
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(const std::vector<libjami::MediaMap>& mediaList) override;
116 bool checkMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
117 void handleMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
118 void answerMediaChangeRequest(const std::vector<libjami::MediaMap>& mediaList, bool isRemote = false) override;
119 void hangup(int code) override;
120 void refuse() override;
121 void transfer(const std::string& to) override;
122 bool attendedTransfer(const std::string& to) override;
123 bool hold(OnReadyCb&& cb) override;
124 bool resume(OnReadyCb&& cb) override;
125 void switchInput(const std::string& resource = {}) override;
126 void peerHungup() override;
127 void carryingDTMFdigits(char code) override;
128 bool requestMediaChange(const std::vector<libjami::MediaMap>& mediaList) override;
129 std::vector<libjami::MediaMap> currentMediaList() const override;
130 void sendTextMessage(const std::map<std::string, std::string>& messages, const std::string& from) override;
131 void removeCall(int code = 0) override;
132 void muteMedia(const std::string& mediaType, bool isMuted) override;
133 std::vector<MediaAttribute> getMediaAttributeList() const override;
134 std::map<std::string, bool> getAudioStreams() const override;
135 std::map<std::string, bool> getRemoteAudioStreams() const override;
136 void restartMediaSender() override;
137 std::shared_ptr<SystemCodecInfo> getAudioCodec() const override;
138 std::shared_ptr<SystemCodecInfo> getVideoCodec() const override;
139 void sendKeyframe(int streamIdx = -1) override;
140 bool isIceEnabled() const override;
141 std::map<std::string, std::string> getDetails() const override;
142 void enterConference(std::shared_ptr<Conference> conference) override;
143 void exitConference() override;
144#ifdef ENABLE_VIDEO
145 std::mutex sinksMtx_;
146 void createSinks(ConfInfo& infos) override;
147 std::map<std::string, std::shared_ptr<video::SinkClient>> callSinksMap_ {};
148 std::map<std::string, std::string> local2RemoteSinks_ {};
149#endif
150 bool hasVideo() const override;
151
152 // TODO: cleanup this (used by conference + Call::getDetails() (and clients can use this))
153 bool isCaptureDeviceMuted(const MediaType& mediaType) const override;
154 bool isSrtpEnabled() const { return srtpEnabled_; }
155 // End of override of Call class
156
157 // Override of Recordable class
158 bool toggleRecording() override;
159 // End of override of Recordable class
160
161 // Override PeerRecorder
162 void peerRecording(bool state) override;
163 void peerMuted(bool state, int streamIdx) override;
164 void peerVoice(bool state) override;
165 // end override PeerRecorder
166
167 void monitor() const override;
168
172 void setPeerUaVersion(std::string_view ua);
173
177 void setPeerAllowMethods(std::vector<std::string> methods);
178
182 bool isSipMethodAllowedByPeer(const std::string_view method) const;
183
187 Sdp& getSDP() { return *sdp_; }
188
189 // Implementation of events reported by SipVoipLink.
193 void onPeerRinging();
197 void onAnswered();
202 void onFailure(int code = 0);
206 void onBusyHere();
210 void onClosed();
211
214
220 // End fo SiPVoipLink events
221
222 const std::string& getContactHeader() const;
223
224 void setSipTransport(const std::shared_ptr<SipTransport>& transport, const std::string& contactHdr = {});
225
226 SipTransport* getTransport() { return sipTransport_.get(); }
227
228 void sendSIPInfo(std::string_view body, std::string_view subtype);
229
230 void requestKeyframe(int streamIdx = -1);
231
232 void updateRecState(bool state) override;
233
234 std::shared_ptr<SIPAccountBase> getSIPAccount() const;
235
236 bool remoteHasValidIceAttributes() const;
238
239 std::shared_ptr<dhtnet::IceTransport> getIceMedia() const
240 {
241 std::lock_guard lk(transportMtx_);
242 return reinvIceMedia_ ? reinvIceMedia_ : iceMedia_;
243 };
244
245 // Set ICE instance. Must be called only for sub-calls
246 void setIceMedia(std::shared_ptr<dhtnet::IceTransport> ice, bool isReinvite = false);
247
248 // Switch to re-invite ICE media if needed
250
255 void setupIceResponse(bool isReinvite = false);
256
257 void terminateSipSession(int status);
258
263 {
264 void operator()(pjsip_inv_session*) const noexcept;
265 };
266
267#ifdef ENABLE_VIDEO
268 void setRotation(int streamIdx, int rotation);
269#endif
270 // Get the list of current RTP sessions
271 std::vector<std::shared_ptr<RtpSession>> getRtpSessionList(MediaType type = MediaType::MEDIA_ALL) const;
272 static size_t getActiveMediaStreamCount(const std::vector<MediaAttribute>& mediaAttrList);
273 void setActiveMediaStream(const std::string& accountUri,
274 const std::string& deviceId,
275 const std::string& streamId,
276 const bool& state);
277
278 void setPeerRegisteredName(const std::string& name) { peerRegisteredName_ = name; }
279
280 void setPeerUri(const std::string& peerUri) { peerUri_ = peerUri; }
281
282 std::string_view peerUri() const { return peerUri_; }
283
284 // Create a new ICE media session. If we already have an instance,
285 // it will be destroyed first.
287
288 // Initialize the ICE session.
289 // The initialization is performed asynchronously, i.e, the instance
290 // may not be ready to use when this method returns.
291 bool initIceMediaTransport(bool master, std::optional<dhtnet::IceTransportOptions> options = std::nullopt);
292
293 std::vector<std::string> getLocalIceCandidates(unsigned compId) const;
294
296
297 std::unique_ptr<pjsip_inv_session, InvSessionDeleter> inviteSession_;
298
299 inline std::weak_ptr<const SIPCall> weak() const { return std::weak_ptr<const SIPCall>(shared()); }
300 inline std::weak_ptr<SIPCall> weak() { return std::weak_ptr<SIPCall>(shared()); }
305
306 const std::vector<RtpStream>& getRtpStreams() const { return rtpStreams_; }
307
308private:
309 void generateMediaPorts();
310
311 void openPortsUPnP();
312
313 bool isIceRunning() const;
314
315 std::unique_ptr<dhtnet::IceSocket> newIceSocket(unsigned compId);
316
317 void deinitRecorder();
318
319 void rtpSetupSuccess();
320
321 void setupVoiceCallback(const std::shared_ptr<RtpSession>& rtpSession);
322
323 void sendMuteState(bool state);
324 void sendVoiceActivity(std::string_view streamId, bool state);
325
326 void resetTransport(std::shared_ptr<dhtnet::IceTransport>&& transport);
327
333 void setVideoOrientation(int streamIdx, int rotation);
334
335 mutable std::mutex transportMtx_ {};
336
337#ifdef ENABLE_PLUGIN
343
353 const std::shared_ptr<MediaStreamSubject>& mediaStreamSubject);
358 void createCallAVStreams();
359
363 void clearCallAVStreams();
364
365 std::mutex avStreamsMtx_ {};
366 std::map<std::string, std::shared_ptr<MediaStreamSubject>> callAVStreams;
367#endif // ENABLE_PLUGIN
368
369 void setCallMediaLocal();
370 void startIceMedia();
371 void onIceNegoSucceed();
372 void setupNegotiatedMedia();
373 void startAllMedia();
374 void stopAllMedia();
375
379 bool transferCommon(const pj_str_t* dst);
380
381 bool internalResume(const std::function<void()>& SDPUpdateFunc);
382
383 bool hold();
384
385 bool resume();
386
387 // Update the attributes of a media stream
388 void updateMediaStream(const MediaAttribute& newMediaAttr, size_t streamIdx);
389 bool updateAllMediaStreams(const std::vector<MediaAttribute>& mediaAttrList, bool isRemote);
390 // Check if a SIP re-invite must be sent to negotiate the new media
391 bool isReinviteRequired(const std::vector<MediaAttribute>& mediaAttrList);
392 // Check if a new ICE media session is needed when performing a re-invite
393 bool isNewIceMediaRequired(const std::vector<MediaAttribute>& mediaAttrList);
394 void requestReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
395 int SIPSessionReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
396 int SIPSessionReinvite();
397 // Add a media stream to the call.
398 void addMediaStream(const MediaAttribute& mediaAttr);
399 // Init media streams
400 size_t initMediaStreams(const std::vector<MediaAttribute>& mediaAttrList);
401 // Create a new stream from SDP description.
402 void createRtpSession(RtpStream& rtpStream);
403 // Configure the RTP session from SDP description.
404 void configureRtpSession(const std::shared_ptr<RtpSession>& rtpSession,
405 const std::shared_ptr<MediaAttribute>& mediaAttr,
406 const MediaDescription& localMedia,
407 const MediaDescription& remoteMedia);
408 // Find the stream index with the matching label
409 int findRtpStreamIndex(const std::string& label) const;
410
411 std::vector<IceCandidate> getAllRemoteCandidates(dhtnet::IceTransport& transport) const;
412
413 inline std::shared_ptr<const SIPCall> shared() const
414 {
415 return std::static_pointer_cast<const SIPCall>(shared_from_this());
416 }
417 inline std::shared_ptr<SIPCall> shared() { return std::static_pointer_cast<SIPCall>(shared_from_this()); }
418
419 // Peer's User-Agent.
420 std::string peerUserAgent_ {};
421 // Flag to indicate if the peer's Daemon version supports multi-stream.
422 bool peerSupportMultiStream_ {false};
423 // Flag to indicate if the peer's Daemon version supports multi-stream.
424 bool peerSupportMultiAudioStream_ {false};
425 // Flag to indicate if the peer's Daemon version can negotiate more than 2 ICE medias
426 bool peerSupportMultiIce_ {false};
427
428 // Flag to indicate if the peer's Daemon version supports re-invite
429 // without ICE renegotiation.
430 bool peerSupportReuseIceInReinv_ {false};
431
432 // Peer's allowed methods.
433 std::vector<std::string> peerAllowedMethods_;
434
435 // Vector holding the current RTP sessions.
436 std::vector<RtpStream> rtpStreams_;
437
443 std::shared_ptr<SipTransport> sipTransport_ {};
444
448 std::unique_ptr<Sdp> sdp_ {};
449 bool peerHold_ {false};
450
451 bool isWaitingForIceAndMedia_ {false};
452 enum class Request : uint8_t { Hold, Resume, SwitchInput, NoRequest };
453 Request remainingRequest_ {Request::NoRequest};
454
455 std::string peerRegisteredName_ {};
456
457 std::string contactHeader_ {};
458
459 std::shared_ptr<dhtnet::upnp::Controller> upnp_;
460
462 unsigned int localAudioPort_ {0};
464 unsigned int localVideoPort_ {0};
465
466 bool mediaRestartRequired_ {true};
467 bool enableIce_ {true};
468 bool srtpEnabled_ {false};
469 bool rtcpMuxEnabled_ {false};
470
471 // ICE media transport
472 std::shared_ptr<dhtnet::IceTransport> iceMedia_;
473 // Re-invite (temporary) ICE media transport.
474 std::shared_ptr<dhtnet::IceTransport> reinvIceMedia_;
475
476 std::string peerUri_ {};
477
478 bool readyToRecord_ {false};
479 bool pendingRecord_ {false};
480
481 time_point lastKeyFrameReq_ {time_point::min()};
482
483 OnReadyCb holdCb_ {};
484 OnReadyCb resumeCb_ {};
485
486 std::atomic_bool waitForIceInit_ {false};
487
488 void detachAudioFromConference();
489
490 std::mutex mediaStateMutex_;
491#ifdef ENABLE_VIDEO
492 int rotation_ {0};
493#endif
494
495 std::string mediaPlayerId_ {};
496};
497
498// Helpers
499
503inline std::shared_ptr<SIPCall>
505{
506 return std::static_pointer_cast<SIPCall>(call.shared_from_this());
507}
508
509} // namespace jami
std::function< void(bool)> OnReadyCb
Definition call.h:94
CallType
This determines if the call originated from the local user (OUTGOING) or from some remote peer (INCOM...
Definition call.h:101
std::vector< MediaAttribute > getMediaAttributeList() const override
Definition sipcall.cpp:2548
bool hasVideo() const override
Definition sipcall.cpp:1886
void terminateSipSession(int status)
Definition sipcall.cpp:718
void answerMediaChangeRequest(const std::vector< libjami::MediaMap > &mediaList, bool isRemote=false) override
Answer to a media update request.
Definition sipcall.cpp:886
std::map< std::string, std::string > getDetails() const override
Definition sipcall.cpp:2973
void setIceMedia(std::shared_ptr< dhtnet::IceTransport > ice, bool isReinvite=false)
Definition sipcall.cpp:3464
void refuse() override
Refuse incoming call.
Definition sipcall.cpp:1034
void onBusyHere()
Peer answered busy.
Definition sipcall.cpp:1498
void switchInput(const std::string &resource={}) override
Definition sipcall.cpp:1338
bool isIceEnabled() const override
Check wether ICE is enabled for media.
Definition sipcall.cpp:1564
std::string_view peerUri() const
Definition sipcall.h:282
void onMediaNegotiationComplete()
Called when the media negotiation (SDP offer/answer) has completed.
Definition sipcall.cpp:2589
std::map< std::string, bool > getRemoteAudioStreams() const override
Return a map of audio stream IDs to their remote (peer-side) muted state.
Definition sipcall.cpp:2573
bool isSrtpEnabled() const
Definition sipcall.h:154
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:1570
void muteMedia(const std::string &mediaType, bool isMuted) override
mute/unmute a media of a call
Definition sipcall.cpp:2179
void reportMediaNegotiationStatus()
Announce to the client that medias are successfully negotiated.
Definition sipcall.cpp:2632
void handleMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList) override
Process incoming media change request.
Definition sipcall.cpp:2767
std::vector< std::shared_ptr< RtpSession > > getRtpSessionList(MediaType type=MediaType::MEDIA_ALL) const
Definition sipcall.cpp:3218
pj_status_t onReceiveReinvite(const pjmedia_sdp_session *offer, pjsip_rx_data *rdata)
Definition sipcall.cpp:2813
void setActiveMediaStream(const std::string &accountUri, const std::string &deviceId, const std::string &streamId, const bool &state)
Definition sipcall.cpp:3109
bool toggleRecording() override
This method must be implemented for this interface as calls and conferences have different behavior.
Definition sipcall.cpp:3254
void onFailure(int code=0)
Called to report server/internal errors.
Definition sipcall.cpp:1484
void setSipTransport(const std::shared_ptr< SipTransport > &transport, const std::string &contactHdr={})
Definition sipcall.cpp:429
void onReceiveOfferIn200OK(const pjmedia_sdp_session *offer)
Definition sipcall.cpp:2877
bool createIceMediaTransport(bool isReinvite)
Definition sipcall.cpp:3301
void monitor() const override
Definition sipcall.cpp:3230
Sdp & getSDP()
Return the SDP's manager of this call.
Definition sipcall.h:187
std::vector< libjami::MediaMap > currentMediaList() const override
Retrieve current medias list.
Definition sipcall.cpp:2542
void restartMediaSender() override
Definition sipcall.cpp:2117
std::weak_ptr< SIPCall > weak()
Definition sipcall.h:300
void removeCall(int code=0) override
Definition sipcall.cpp:1460
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:1418
void sendKeyframe(int streamIdx=-1) override
Definition sipcall.cpp:1543
std::shared_ptr< SystemCodecInfo > getAudioCodec() const override
Definition sipcall.cpp:1828
void hangup(int code) override
Hang up the call.
Definition sipcall.cpp:981
const std::vector< RtpStream > & getRtpStreams() const
Definition sipcall.h:306
static size_t getActiveMediaStreamCount(const std::vector< MediaAttribute > &mediaAttrList)
std::shared_ptr< dhtnet::IceTransport > getIceMedia() const
Definition sipcall.h:239
~SIPCall()
Destructor.
Definition sipcall.cpp:142
void peerMuted(bool state, int streamIdx) override
Definition sipcall.cpp:3591
bool resume(OnReadyCb &&cb) override
Resume call from hold state.
Definition sipcall.cpp:1263
bool initIceMediaTransport(bool master, std::optional< dhtnet::IceTransportOptions > options=std::nullopt)
Definition sipcall.cpp:3319
bool remoteHasValidIceAttributes() const
Definition sipcall.cpp:3443
void exitConference() override
Definition sipcall.cpp:3082
void onClosed()
Peer closed the connection.
Definition sipcall.cpp:1515
void setupIceResponse(bool isReinvite=false)
Setup ICE locally to answer to an ICE offer.
Definition sipcall.cpp:3493
std::shared_ptr< SystemCodecInfo > getVideoCodec() const override
Definition sipcall.cpp:1815
void addLocalIceAttributes()
Definition sipcall.cpp:1688
void answer(const std::vector< libjami::MediaMap > &mediaList) override
Answer a call with a list of media attributes.
Definition sipcall.cpp:754
bool checkMediaChangeRequest(const std::vector< libjami::MediaMap > &remoteMediaList) override
Check the media of an incoming media change request.
Definition sipcall.cpp:2741
bool isCaptureDeviceMuted(const MediaType &mediaType) const override
Definition sipcall.cpp:1904
void onPeerRinging()
Call is in ringing state on peer's side.
Definition sipcall.cpp:1681
void updateRecState(bool state) override
Update recording state.
Definition sipcall.cpp:600
std::vector< std::string > getLocalIceCandidates(unsigned compId) const
Definition sipcall.cpp:3391
SipTransport * getTransport()
Definition sipcall.h:226
bool attendedTransfer(const std::string &to) override
Attended transfer.
Definition sipcall.cpp:1181
void carryingDTMFdigits(char code) override
Send DTMF.
Definition sipcall.cpp:1380
const std::string & getContactHeader() const
Definition sipcall.cpp:423
std::shared_ptr< SIPAccountBase > getSIPAccount() const
Definition sipcall.cpp:301
void transfer(const std::string &to) override
Transfer a call to specified URI.
Definition sipcall.cpp:1159
bool isSipMethodAllowedByPeer(const std::string_view method) const
Check if a SIP method is allowed by peer.
Definition sipcall.cpp:1673
std::map< std::string, bool > getAudioStreams() const override
Definition sipcall.cpp:2559
void setPeerUri(const std::string &peerUri)
Definition sipcall.h:280
void sendSIPInfo(std::string_view body, std::string_view subtype)
Definition sipcall.cpp:570
std::unique_ptr< pjsip_inv_session, InvSessionDeleter > inviteSession_
Definition sipcall.h:297
void peerVoice(bool state) override
Definition sipcall.cpp:3614
void onAnswered()
Peer answered the call.
Definition sipcall.cpp:1527
void setPeerRegisteredName(const std::string &name)
Definition sipcall.h:278
void setPeerAllowMethods(std::vector< std::string > methods)
Set peer's allowed methods.
Definition sipcall.cpp:1666
void switchToIceReinviteIfNeeded()
Definition sipcall.cpp:3480
void enterConference(std::shared_ptr< Conference > conference) override
Definition sipcall.cpp:3055
bool hold(OnReadyCb &&cb) override
Hold call.
Definition sipcall.cpp:1214
void peerHungup() override
Peer has hung up a call.
Definition sipcall.cpp:1367
LinkType getLinkType() const override
Definition sipcall.h:108
void peerRecording(bool state) override
Definition sipcall.cpp:3574
std::weak_ptr< const SIPCall > weak() const
Definition sipcall.h:299
void requestKeyframe(int streamIdx=-1)
Definition sipcall.cpp:620
bool requestMediaChange(const std::vector< libjami::MediaMap > &mediaList) override
Make a change request of the current media with the provided media.
Definition sipcall.cpp:2405
void setInviteSession(pjsip_inv_session *inviteSession=nullptr)
Definition sipcall.cpp:689
SIP transport wraps pjsip_transport.
void emitSignal(Args... args)
Definition jami_signal.h:64
std::shared_ptr< Call > getPtr(Call &call)
Obtain a shared smart pointer of instance.
Definition call.h:531
pj_ice_sess_cand IceCandidate
Definition sipcall.h:65
@ MEDIA_ALL
Definition media_codec.h:48
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:30
The invite session to be reused in case of transfer.
Definition sipcall.h:263
void operator()(pjsip_inv_session *) const noexcept
Definition sipcall.cpp:3289
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