Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
5 : * Author: Yan Morin <yan.morin@savoirfairelinux.com>
6 : * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
7 : * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
8 : * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, write to the Free Software
22 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 : */
24 :
25 : #pragma once
26 :
27 : #ifdef HAVE_CONFIG_H
28 : #include "config.h"
29 : #endif
30 :
31 : #include "call.h"
32 : #include <dhtnet/ice_transport.h>
33 : #include "connectivity/sip_utils.h"
34 : #include "media/media_codec.h" // for MediaType enum
35 : #include "sip/sdp.h"
36 :
37 : #include "media/rtp_session.h"
38 : #ifdef ENABLE_VIDEO
39 : #include "media/video/video_receive_thread.h"
40 : #include "media/video/video_rtp_session.h"
41 : #endif
42 : #ifdef ENABLE_PLUGIN
43 : #include "plugin/streamdata.h"
44 : #endif
45 : #include "noncopyable.h"
46 :
47 : #include <memory>
48 : #include <optional>
49 :
50 : extern "C" {
51 : #include <pjsip/sip_config.h>
52 : struct pjsip_evsub;
53 : struct pjsip_inv_session;
54 : struct pjmedia_sdp_session;
55 : struct pj_ice_sess_cand;
56 : struct pjsip_rx_data;
57 : }
58 :
59 : namespace dhtnet {
60 : class IceSocket;
61 : namespace upnp {
62 : class Controller;
63 : }
64 : }
65 :
66 : namespace jami {
67 :
68 : class Sdp;
69 : class SIPAccountBase;
70 : class SipTransport;
71 : class AudioRtpSession;
72 :
73 : using IceCandidate = pj_ice_sess_cand;
74 :
75 : /**
76 : * @file sipcall.h
77 : * @brief SIPCall are SIP implementation of a normal Call
78 : */
79 : class SIPCall : public Call
80 : {
81 : private:
82 : using clock = std::chrono::steady_clock;
83 : using time_point = clock::time_point;
84 :
85 : NON_COPYABLE(SIPCall);
86 :
87 : public:
88 : static constexpr LinkType LINK_TYPE = LinkType::SIP;
89 :
90 : struct RtpStream
91 : {
92 : std::shared_ptr<RtpSession> rtpSession_ {};
93 : std::shared_ptr<MediaAttribute> mediaAttribute_ {};
94 : std::shared_ptr<MediaAttribute> remoteMediaAttribute_;
95 : std::unique_ptr<dhtnet::IceSocket> rtpSocket_;
96 : std::unique_ptr<dhtnet::IceSocket> rtcpSocket_;
97 : };
98 :
99 : /**
100 : * Destructor
101 : */
102 : ~SIPCall();
103 :
104 : /**
105 : * Constructor
106 : * @param id The call identifier
107 : * @param type The type of the call (incoming/outgoing)
108 : * @param mediaList A list of medias to include in the call
109 : */
110 : SIPCall(const std::shared_ptr<SIPAccountBase>& account,
111 : const std::string& id,
112 : Call::CallType type,
113 : const std::vector<libjami::MediaMap>& mediaList);
114 :
115 : // Inherited from Call class
116 823 : LinkType getLinkType() const override { return LINK_TYPE; }
117 :
118 : // Override of Call class
119 : private:
120 : void merge(Call& call) override; // not public - only called by Call
121 :
122 : public:
123 : void answer() override;
124 : void answer(const std::vector<libjami::MediaMap>& mediaList) override;
125 : bool checkMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
126 : void handleMediaChangeRequest(const std::vector<libjami::MediaMap>& remoteMediaList) override;
127 : void answerMediaChangeRequest(const std::vector<libjami::MediaMap>& mediaList,
128 : bool isRemote = false) override;
129 : void hangup(int reason) override;
130 : void refuse() override;
131 : void transfer(const std::string& to) override;
132 : bool attendedTransfer(const std::string& to) override;
133 : bool onhold(OnReadyCb&& cb) override;
134 : bool offhold(OnReadyCb&& cb) override;
135 : void switchInput(const std::string& resource = {}) override;
136 : void peerHungup() override;
137 : void carryingDTMFdigits(char code) override;
138 : bool requestMediaChange(const std::vector<libjami::MediaMap>& mediaList) override;
139 : std::vector<libjami::MediaMap> currentMediaList() const override;
140 : void sendTextMessage(const std::map<std::string, std::string>& messages,
141 : const std::string& from) override;
142 : void removeCall() override;
143 : void muteMedia(const std::string& mediaType, bool isMuted) override;
144 : std::vector<MediaAttribute> getMediaAttributeList() const override;
145 : std::map<std::string, bool> getAudioStreams() const override;
146 : void restartMediaSender() override;
147 : std::shared_ptr<SystemCodecInfo> getAudioCodec() const override;
148 : std::shared_ptr<SystemCodecInfo> getVideoCodec() const override;
149 : void sendKeyframe(int streamIdx = -1) override;
150 : bool isIceEnabled() const override;
151 : std::map<std::string, std::string> getDetails() const override;
152 : void enterConference(std::shared_ptr<Conference> conference) override;
153 : void exitConference() override;
154 : #ifdef ENABLE_VIDEO
155 : std::mutex sinksMtx_;
156 : void createSinks(ConfInfo& infos) override;
157 : std::map<std::string, std::shared_ptr<video::SinkClient>> callSinksMap_ {};
158 : std::map<std::string, std::string> local2RemoteSinks_ {};
159 : #endif
160 : bool hasVideo() const override;
161 :
162 : // TODO: cleanup this (used by conference + Call::getDetails() (and clients can use this))
163 : bool isCaptureDeviceMuted(const MediaType& mediaType) const override;
164 2094 : bool isSrtpEnabled() const
165 : {
166 2094 : return srtpEnabled_;
167 : }
168 : // End of override of Call class
169 :
170 : // Override of Recordable class
171 : bool toggleRecording() override;
172 : // End of override of Recordable class
173 :
174 : // Override PeerRecorder
175 : void peerRecording(bool state) override;
176 : void peerMuted(bool state, int streamIdx) override;
177 : void peerVoice(bool state) override;
178 : // end override PeerRecorder
179 :
180 : void monitor() const override;
181 :
182 : /**
183 : * Set peer's User-Agent found in the message header
184 : */
185 : void setPeerUaVersion(std::string_view ua);
186 :
187 : /**
188 : * Set peer's allowed methods
189 : */
190 : void setPeerAllowMethods(std::vector<std::string> methods);
191 :
192 : /**
193 : * Check if a SIP method is allowed by peer
194 : */
195 : bool isSipMethodAllowedByPeer(const std::string_view method) const;
196 :
197 : /**
198 : * Return the SDP's manager of this call
199 : */
200 714 : Sdp& getSDP()
201 : {
202 714 : return *sdp_;
203 : }
204 :
205 : // Implementation of events reported by SipVoipLink.
206 : /**
207 : * Call is in ringing state on peer's side
208 : */
209 : void onPeerRinging();
210 : /**
211 : * Peer answered the call
212 : */
213 : void onAnswered();
214 : /**
215 : * Called to report server/internal errors
216 : * @param cause Optional error code
217 : */
218 : void onFailure(signed cause = 0);
219 : /**
220 : * Peer answered busy
221 : */
222 : void onBusyHere();
223 : /**
224 : * Peer closed the connection
225 : */
226 : void onClosed();
227 :
228 : pj_status_t onReceiveReinvite(const pjmedia_sdp_session* offer, pjsip_rx_data* rdata);
229 : void onReceiveOfferIn200OK(const pjmedia_sdp_session* offer);
230 :
231 : /**
232 : * Called when the media negotiation (SDP offer/answer) has
233 : * completed.
234 : */
235 : void onMediaNegotiationComplete();
236 : // End fo SiPVoipLink events
237 :
238 : const std::string& getContactHeader() const;
239 :
240 : void setSipTransport(const std::shared_ptr<SipTransport>& transport,
241 : const std::string& contactHdr = {});
242 :
243 620 : SipTransport* getTransport()
244 : {
245 620 : return sipTransport_.get();
246 : }
247 :
248 : void sendSIPInfo(std::string_view body, std::string_view subtype);
249 :
250 : void requestKeyframe(int streamIdx = -1);
251 :
252 : void updateRecState(bool state) override;
253 :
254 : std::shared_ptr<SIPAccountBase> getSIPAccount() const;
255 :
256 : bool remoteHasValidIceAttributes() const;
257 : void addLocalIceAttributes();
258 :
259 2126 : std::shared_ptr<dhtnet::IceTransport> getIceMedia() const
260 : {
261 2126 : std::lock_guard lk(transportMtx_);
262 4252 : return reinvIceMedia_ ? reinvIceMedia_ : iceMedia_;
263 2126 : };
264 :
265 : // Set ICE instance. Must be called only for sub-calls
266 : void setIceMedia(std::shared_ptr<dhtnet::IceTransport> ice, bool isReinvite = false);
267 :
268 : // Switch to re-invite ICE media if needed
269 : void switchToIceReinviteIfNeeded();
270 :
271 : /**
272 : * Setup ICE locally to answer to an ICE offer. The ICE session has
273 : * the controlled role (slave)
274 : */
275 : void setupIceResponse(bool isReinvite = false);
276 :
277 : void terminateSipSession(int status);
278 :
279 : /**
280 : * The invite session to be reused in case of transfer
281 : */
282 : struct InvSessionDeleter
283 : {
284 : void operator()(pjsip_inv_session*) const noexcept;
285 : };
286 :
287 : #ifdef ENABLE_VIDEO
288 : void setRotation(int streamIdx, int rotation);
289 : #endif
290 : // Get the list of current RTP sessions
291 : std::vector<std::shared_ptr<RtpSession>> getRtpSessionList(
292 : MediaType type = MediaType::MEDIA_ALL) const;
293 : static size_t getActiveMediaStreamCount(const std::vector<MediaAttribute>& mediaAttrList);
294 : void setActiveMediaStream(const std::string& accountUri,
295 : const std::string& deviceId,
296 : const std::string& streamId,
297 : const bool& state);
298 :
299 1 : void setPeerRegisteredName(const std::string& name)
300 : {
301 1 : peerRegisteredName_ = name;
302 1 : }
303 :
304 336 : void setPeerUri(const std::string& peerUri)
305 : {
306 336 : peerUri_ = peerUri;
307 336 : }
308 :
309 80 : std::string_view peerUri() const {
310 80 : return peerUri_;
311 : }
312 :
313 : // Create a new ICE media session. If we already have an instance,
314 : // it will be destroyed first.
315 : bool createIceMediaTransport(bool isReinvite);
316 :
317 : // Initialize the ICE session.
318 : // The initialization is performed asynchronously, i.e, the instance
319 : // may not be ready to use when this method returns.
320 : bool initIceMediaTransport(bool master,
321 : std::optional<dhtnet::IceTransportOptions> options = std::nullopt);
322 :
323 : std::vector<std::string> getLocalIceCandidates(unsigned compId) const;
324 :
325 : void setInviteSession(pjsip_inv_session* inviteSession = nullptr);
326 :
327 : std::unique_ptr<pjsip_inv_session, InvSessionDeleter> inviteSession_;
328 :
329 : inline std::weak_ptr<const SIPCall> weak() const
330 : {
331 : return std::weak_ptr<const SIPCall>(shared());
332 : }
333 2609 : inline std::weak_ptr<SIPCall> weak()
334 : {
335 2609 : return std::weak_ptr<SIPCall>(shared());
336 : }
337 : /**
338 : * Announce to the client that medias are successfully negotiated
339 : */
340 : void reportMediaNegotiationStatus();
341 :
342 : private:
343 : void generateMediaPorts();
344 :
345 : void openPortsUPnP();
346 :
347 : bool isIceRunning() const;
348 :
349 : std::unique_ptr<dhtnet::IceSocket> newIceSocket(unsigned compId);
350 :
351 : void deinitRecorder();
352 :
353 : void rtpSetupSuccess();
354 :
355 : void setupVoiceCallback(const std::shared_ptr<RtpSession>& rtpSession);
356 :
357 : void sendMuteState(bool state);
358 : void sendVoiceActivity(std::string_view streamId, bool state);
359 :
360 : void resetTransport(std::shared_ptr<dhtnet::IceTransport>&& transport);
361 :
362 : /**
363 : * Send device orientation through SIP INFO
364 : * @param streamIdx The stream to rotate
365 : * @param rotation Device orientation (0/90/180/270) (counterclockwise)
366 : */
367 : void setVideoOrientation(int streamIdx, int rotation);
368 :
369 : mutable std::mutex transportMtx_ {};
370 :
371 : #ifdef ENABLE_PLUGIN
372 : /**
373 : * Call Streams and some typedefs
374 : */
375 : using AVMediaStream = Observable<std::shared_ptr<MediaFrame>>;
376 : using MediaStreamSubject = PublishMapSubject<std::shared_ptr<MediaFrame>, AVFrame*>;
377 :
378 : /**
379 : * @brief createCallAVStream
380 : * Creates a call AV stream like video input, video receive, audio input or audio receive
381 : * @param StreamData The type of the stream (audio/video, input/output,
382 : * @param streamSource
383 : * @param mediaStreamSubject
384 : */
385 : void createCallAVStream(const StreamData& StreamData,
386 : AVMediaStream& streamSource,
387 : const std::shared_ptr<MediaStreamSubject>& mediaStreamSubject);
388 : /**
389 : * @brief createCallAVStreams
390 : * Creates all Call AV Streams (2 if audio, 4 if audio video)
391 : */
392 : void createCallAVStreams();
393 :
394 : /**
395 : * @brief Detach all plugins from call streams;
396 : */
397 : void clearCallAVStreams();
398 :
399 : std::mutex avStreamsMtx_ {};
400 : std::map<std::string, std::shared_ptr<MediaStreamSubject>> callAVStreams;
401 : #endif // ENABLE_PLUGIN
402 :
403 : void setCallMediaLocal();
404 : void startIceMedia();
405 : void onIceNegoSucceed();
406 : void setupNegotiatedMedia();
407 : void startAllMedia();
408 : void stopAllMedia();
409 : void updateRemoteMedia();
410 :
411 : /**
412 : * Transfer method used for both type of transfer
413 : */
414 : bool transferCommon(const pj_str_t* dst);
415 :
416 : bool internalOffHold(const std::function<void()>& SDPUpdateFunc);
417 :
418 : bool hold();
419 :
420 : bool unhold();
421 :
422 : // Update the attributes of a media stream
423 : void updateMediaStream(const MediaAttribute& newMediaAttr, size_t streamIdx);
424 : bool updateAllMediaStreams(const std::vector<MediaAttribute>& mediaAttrList, bool isRemote);
425 : // Check if a SIP re-invite must be sent to negotiate the new media
426 : bool isReinviteRequired(const std::vector<MediaAttribute>& mediaAttrList);
427 : // Check if a new ICE media session is needed when performing a re-invite
428 : bool isNewIceMediaRequired(const std::vector<MediaAttribute>& mediaAttrList);
429 : void requestReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
430 : int SIPSessionReinvite(const std::vector<MediaAttribute>& mediaAttrList, bool needNewIce);
431 : int SIPSessionReinvite();
432 : // Add a media stream to the call.
433 : void addMediaStream(const MediaAttribute& mediaAttr);
434 : // Init media streams
435 : size_t initMediaStreams(const std::vector<MediaAttribute>& mediaAttrList);
436 : // Create a new stream from SDP description.
437 : void createRtpSession(RtpStream& rtpStream);
438 : // Configure the RTP session from SDP description.
439 : void configureRtpSession(const std::shared_ptr<RtpSession>& rtpSession,
440 : const std::shared_ptr<MediaAttribute>& mediaAttr,
441 : const MediaDescription& localMedia,
442 : const MediaDescription& remoteMedia);
443 : // Find the stream index with the matching label
444 : int findRtpStreamIndex(const std::string& label) const;
445 :
446 : std::vector<IceCandidate> getAllRemoteCandidates(dhtnet::IceTransport& transport) const;
447 :
448 : inline std::shared_ptr<const SIPCall> shared() const
449 : {
450 : return std::static_pointer_cast<const SIPCall>(shared_from_this());
451 : }
452 2609 : inline std::shared_ptr<SIPCall> shared()
453 : {
454 2609 : return std::static_pointer_cast<SIPCall>(shared_from_this());
455 : }
456 :
457 : // Peer's User-Agent.
458 : std::string peerUserAgent_ {};
459 : // Flag to indicate if the peer's Daemon version supports multi-stream.
460 : bool peerSupportMultiStream_ {false};
461 : // Flag to indicate if the peer's Daemon version supports multi-stream.
462 : bool peerSupportMultiAudioStream_ {false};
463 : // Flag to indicate if the peer's Daemon version can negotiate more than 2 ICE medias
464 : bool peerSupportMultiIce_ {false};
465 :
466 : // Flag to indicate if the peer's Daemon version supports re-invite
467 : // without ICE renegotiation.
468 : bool peerSupportReuseIceInReinv_ {false};
469 :
470 : // Peer's allowed methods.
471 : std::vector<std::string> peerAllowedMethods_;
472 :
473 : // Vector holding the current RTP sessions.
474 : std::vector<RtpStream> rtpStreams_;
475 :
476 : /**
477 : * Hold the transport used for SIP communication.
478 : * Will be different from the account registration transport for
479 : * non-IP2IP calls.
480 : */
481 : std::shared_ptr<SipTransport> sipTransport_ {};
482 :
483 : /**
484 : * The SDP session
485 : */
486 : std::unique_ptr<Sdp> sdp_ {};
487 : bool peerHolding_ {false};
488 :
489 : bool isWaitingForIceAndMedia_ {false};
490 : enum class Request { HoldingOn, HoldingOff, SwitchInput, NoRequest };
491 : Request remainingRequest_ {Request::NoRequest};
492 :
493 : std::string peerRegisteredName_ {};
494 :
495 : std::string contactHeader_ {};
496 :
497 : std::shared_ptr<dhtnet::upnp::Controller> upnp_;
498 :
499 : /** Local audio port, as seen by me. */
500 : unsigned int localAudioPort_ {0};
501 : /** Local video port, as seen by me. */
502 : unsigned int localVideoPort_ {0};
503 :
504 : bool mediaRestartRequired_ {true};
505 : bool enableIce_ {true};
506 : bool srtpEnabled_ {false};
507 : bool rtcpMuxEnabled_ {false};
508 :
509 : // ICE media transport
510 : std::shared_ptr<dhtnet::IceTransport> iceMedia_;
511 : // Re-invite (temporary) ICE media transport.
512 : std::shared_ptr<dhtnet::IceTransport> reinvIceMedia_;
513 :
514 : std::string peerUri_ {};
515 :
516 : bool readyToRecord_ {false};
517 : bool pendingRecord_ {false};
518 :
519 : time_point lastKeyFrameReq_ {time_point::min()};
520 :
521 : OnReadyCb holdCb_ {};
522 : OnReadyCb offHoldCb_ {};
523 :
524 : std::atomic_bool waitForIceInit_ {false};
525 :
526 : void detachAudioFromConference();
527 :
528 : std::mutex setupSuccessMutex_;
529 : #ifdef ENABLE_VIDEO
530 : int rotation_ {0};
531 : #endif
532 :
533 : std::string mediaPlayerId_ {};
534 : };
535 :
536 : // Helpers
537 :
538 : /**
539 : * Obtain a shared smart pointer of instance
540 : */
541 : inline std::shared_ptr<SIPCall>
542 : getPtr(SIPCall& call)
543 : {
544 : return std::static_pointer_cast<SIPCall>(call.shared_from_this());
545 : }
546 :
547 : } // namespace jami
|