reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
MediaStream.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <rutil/Log.hxx>
6#include <rutil/Logger.hxx>
7#include <rutil/Timer.hxx>
8
9#include "MediaStream.hxx"
11#include "FlowManager.hxx"
12
13
14using namespace flowmanager;
15#ifdef USE_SSL
16using namespace dtls;
17#endif
18using namespace resip;
19using namespace std;
20
21#define RESIPROCATE_SUBSYSTEM FlowManagerSubsystem::FLOWMANAGER
22
23MediaStream::MediaStream(asio::io_context& ioService,
24#ifdef USE_SSL
25 asio::ssl::context& sslContext,
26#endif
27 MediaStreamHandler& mediaStreamHandler,
28 const StunTuple& localRtpBinding,
29 const StunTuple& localRtcpBinding,
30#ifdef USE_SSL
31 DtlsFactory* dtlsFactory,
32#endif
33 NatTraversalMode natTraversalMode,
34 const char* natTraversalServerHostname,
35 unsigned short natTraversalServerPort,
36 const char* stunUsername,
37 const char* stunPassword,
38 bool forceCOMedia,
39 std::shared_ptr<RTCPEventLoggingHandler> rtcpEventLoggingHandler,
40 std::shared_ptr<FlowContext> context,
41 bool validateTlsServerHostname) :
42#ifdef USE_SSL
43 mDtlsFactory(dtlsFactory),
44#endif
45 mSRTPSessionInCreated(false),
46 mSRTPSessionOutCreated(false),
47 mNatTraversalMode(natTraversalMode),
48 mNatTraversalServerHostname(natTraversalServerHostname),
49 mNatTraversalServerPort(natTraversalServerPort),
50 mStunUsername(stunUsername),
51 mStunPassword(stunPassword),
52 mForceCOMedia(forceCOMedia),
53 mValidateTlsServerHostname(validateTlsServerHostname),
54 mMediaStreamHandler(mediaStreamHandler)
55{
56 // Rtcp is enabled if localRtcpBinding transport type != None
57 mRtcpEnabled = localRtcpBinding.getTransportType() != StunTuple::None;
58
59 if(mRtcpEnabled)
60 {
61 mRtpFlow = new Flow(ioService,
62#ifdef USE_SSL
63 sslContext,
64#endif
66 localRtpBinding,
67 *this,
69 nullptr,
70 context);
71
72 mRtcpFlow = new Flow(ioService,
73#ifdef USE_SSL
74 sslContext,
75#endif
77 localRtcpBinding,
78 *this,
80 rtcpEventLoggingHandler,
81 context);
82
84
85 // If doing an allocation then wait until RTP flow is allocated, then activate RTCP flow
86 if(natTraversalMode != TurnAllocation)
87 {
88 mRtcpFlow->activateFlow();
89 }
90 }
91 else
92 {
93 mRtpFlow = new Flow(ioService,
94#ifdef USE_SSL
95 sslContext,
96#endif
98 localRtpBinding,
99 *this,
101 nullptr,
102 context);
104 mRtcpFlow = 0;
105 }
106}
107
109{
110 {
111 Lock lock(mMutex);
112
114 {
116 srtp_dealloc(mSRTPSessionOut);
117 }
119 {
120 mSRTPSessionInCreated = false;
121 srtp_dealloc(mSRTPSessionIn);
122 }
123 }
124 delete mRtpFlow;
125 if(mRtcpEnabled)
126 {
127 delete mRtcpFlow;
128 }
129}
130
131bool
133{
134 if(keyLen != SRTP_MASTER_KEY_LEN)
135 {
136 ErrLog(<< "Unable to create outbound SRTP session, invalid keyLen=" << keyLen);
137 return false;
138 }
139
140 srtp_err_status_t status;
141 Lock lock(mMutex);
143 {
144 // Check if settings are the same - if so just return true
145 if(cryptoSuite == mCryptoSuiteOut && memcmp(mSRTPMasterKeyOut, key, keyLen) == 0)
146 {
147 InfoLog(<< "Outbound SRTP session settings unchanged.");
148 return true;
149 }
150 else
151 {
152 InfoLog(<< "Re-creating outbound SRTP session with new settings.");
154 srtp_dealloc(mSRTPSessionOut);
155 }
156 }
157 memset(&mSRTPPolicyOut, 0, sizeof(mSRTPPolicyOut));
158
159 // Copy key locally
160 memcpy(mSRTPMasterKeyOut, key, SRTP_MASTER_KEY_LEN);
161
162 // load default srtp/srtcp policy settings
163 mCryptoSuiteOut = cryptoSuite;
164 switch(cryptoSuite)
165 {
169 break;
173 break;
174 default:
175 ErrLog(<< "Unable to create outbound SRTP session, invalid crypto suite=" << cryptoSuite);
176 return false;
177 }
178
179 // set remaining policy settings
180 mSRTPPolicyOut.ssrc.type = ssrc_any_outbound;
182 mSRTPPolicyOut.window_size = 64;
183
184 // Allocate and initailize the SRTP sessions
185 status = srtp_create(&mSRTPSessionOut, &mSRTPPolicyOut);
186 if(status)
187 {
188 ErrLog(<< "Unable to create srtp out session, error code=" << status);
189 return false;
190 }
192
193 return true;
194}
195
196bool
198{
199 if(keyLen != SRTP_MASTER_KEY_LEN)
200 {
201 ErrLog(<< "Unable to create inbound SRTP session, invalid keyLen=" << keyLen);
202 return false;
203 }
204
205 srtp_err_status_t status;
206 Lock lock(mMutex);
208 {
209 // Check if settings are the same - if so just return true
210 if(cryptoSuite == mCryptoSuiteIn && memcmp(mSRTPMasterKeyIn, key, keyLen) == 0)
211 {
212 InfoLog(<< "Inbound SRTP session settings unchanged.");
213 return true;
214 }
215 else
216 {
217 InfoLog(<< "Re-creating inbound SRTP session with new settings.");
218 mSRTPSessionInCreated = false;
219 srtp_dealloc(mSRTPSessionIn);
220 }
221 }
222 memset(&mSRTPPolicyIn, 0, sizeof(mSRTPPolicyIn));
223
224 // Copy key locally
225 memcpy(mSRTPMasterKeyIn, key, SRTP_MASTER_KEY_LEN);
226
227 // load default srtp/srtcp policy settings
228 mCryptoSuiteIn = cryptoSuite;
229 switch(cryptoSuite)
230 {
234 break;
238 break;
239 default:
240 ErrLog(<< "Unable to create inbound SRTP session, invalid crypto suite=" << cryptoSuite);
241 return false;
242 }
243
244 // set remaining policy settings
245 mSRTPPolicyIn.ssrc.type = ssrc_any_inbound;
247 mSRTPPolicyIn.window_size = 64;
248
249 // Allocate and initailize the SRTP sessions
250 status = srtp_create(&mSRTPSessionIn, &mSRTPPolicyIn);
251 if(status)
252 {
253 ErrLog(<< "Unable to create srtp in session, error code=" << status);
254 return false;
255 }
257
258 return true;
259}
260
261srtp_err_status_t
262MediaStream::srtpProtect(void* data, int* size, bool rtcp)
263{
264 Lock lock(mMutex);
265 srtp_err_status_t status = srtp_err_status_no_ctx;
267 {
268 if(rtcp)
269 {
270 status = srtp_protect_rtcp(mSRTPSessionOut, data, size);
271 }
272 else
273 {
274 status = srtp_protect(mSRTPSessionOut, data, size);
275 }
276 }
277 return status;
278}
279
280srtp_err_status_t
281MediaStream::srtpUnprotect(void* data, int* size, bool rtcp)
282{
283 Lock lock(mMutex);
284 srtp_err_status_t status = srtp_err_status_no_ctx;
286 {
287 if(rtcp)
288 {
289 status = srtp_unprotect_rtcp(mSRTPSessionIn, data, size);
290 }
291 else
292 {
293 status = srtp_unprotect(mSRTPSessionIn, data, size);
294 }
295 }
296 return status;
297}
298
299void
300MediaStream::onFlowReady(unsigned int componentId)
301{
302 if(componentId == RTP_COMPONENT_ID && mNatTraversalMode == TurnAllocation && mRtcpFlow)
303 {
304 // RTP Flow is ready - we can now activate RTCP flow using the reservation token
305 mRtcpFlow->activateFlow(mRtpFlow->getReservationToken());
306 }
307 else
308 {
309 if(mRtpFlow && mRtcpFlow)
310 {
311 if(mRtpFlow->isReady() && mRtcpFlow->isReady())
312 {
313 mMediaStreamHandler.onMediaStreamReady(mRtpFlow->getSessionTuple(), mRtcpFlow->getSessionTuple());
314 }
315 }
316 else if(mRtpFlow && mRtpFlow->isReady())
317 {
318 mMediaStreamHandler.onMediaStreamReady(mRtpFlow->getSessionTuple(), StunTuple());
319 }
320 }
321}
322
323void
324MediaStream::onFlowError(unsigned int componentId, unsigned int errorCode)
325{
326 mMediaStreamHandler.onMediaStreamError(errorCode); // TODO assign real error code
327}
328
329
330/* ====================================================================
331
332 Copyright (c) 2008-2026 SIP Spectrum, Inc. https://www.sipspectrum.com
333 Copyright (c) 2007-2008, Plantronics, Inc.
334 All rights reserved.
335
336 Redistribution and use in source and binary forms, with or without
337 modification, are permitted provided that the following conditions are
338 met:
339
340 1. Redistributions of source code must retain the above copyright
341 notice, this list of conditions and the following disclaimer.
342
343 2. Redistributions in binary form must reproduce the above copyright
344 notice, this list of conditions and the following disclaimer in the
345 documentation and/or other materials provided with the distribution.
346
347 3. Neither the name of Plantronics nor the names of its contributors
348 may be used to endorse or promote products derived from this
349 software without specific prior written permission.
350
351 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
352 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
353 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
354 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
355 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
356 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
358 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
359 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
360 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
361 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362
363 ==================================================================== */
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define RTCP_COMPONENT_ID
#define RTP_COMPONENT_ID
#define crypto_policy_set_aes_cm_128_hmac_sha1_32
#define crypto_policy_set_aes_cm_128_hmac_sha1_80
uint64_t getReservationToken()
Definition Flow.cxx:637
bool isReady()
Definition Flow.hxx:80
StunTuple getSessionTuple()
Definition Flow.cxx:604
void activateFlow(uint8_t allocationProps=StunMessage::PropsNone)
Definition Flow.cxx:227
virtual void onMediaStreamError(unsigned int errorCode)=0
virtual void onMediaStreamReady(const StunTuple &rtpTuple, const StunTuple &rtcpTuple)=0
bool createInboundSRTPSession(resip::MediaConstants::SrtpCryptoSuite cryptoSuite, const char *key, size_t keyLen)
bool createOutboundSRTPSession(resip::MediaConstants::SrtpCryptoSuite cryptoSuite, const char *key, size_t keyLen)
NatTraversalMode mNatTraversalMode
uint8_t mSRTPMasterKeyIn[SRTP_MASTER_KEY_LEN]
srtp_err_status_t srtpProtect(void *data, int *size, bool rtcp)
volatile bool mSRTPSessionInCreated
resip::MediaConstants::SrtpCryptoSuite mCryptoSuiteOut
srtp_err_status_t srtpUnprotect(void *data, int *size, bool rtcp)
MediaStream(asio::io_context &ioService, asio::ssl::context &sslContext, MediaStreamHandler &mediaStreamHandler, const StunTuple &localRtpBinding, const StunTuple &localRtcpBinding, dtls::DtlsFactory *dtlsFactory=0, NatTraversalMode natTraversalMode=NoNatTraversal, const char *natTraversalServerHostname=0, unsigned short natTraversalServerPort=0, const char *stunUsername=0, const char *stunPassword=0, bool forceCOMedia=false, std::shared_ptr< RTCPEventLoggingHandler > rtcpEventLoggingHandler=nullptr, std::shared_ptr< FlowContext > context=nullptr, bool validateTlsServerHostname=true)
uint8_t mSRTPMasterKeyOut[SRTP_MASTER_KEY_LEN]
volatile bool mSRTPSessionOutCreated
resip::MediaConstants::SrtpCryptoSuite mCryptoSuiteIn
static const uint8_t PropsPortEven
static const uint8_t PropsPortPair
TransportType getTransportType() const
Definition StunTuple.hxx:41
This class is used during media sessions that use Dtls-Srtp for a media transport.
Definition ErrorCode.hxx:4
dcm! – add UnusedChecking(_enum) below;
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
Definition Lock.hxx:28