|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // RTCPFlow Implementation |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include <comms-infras/ss_log.h> |
|
24 |
|
25 #include "rtcpflow.h" |
|
26 #include "rtppint.h" |
|
27 |
|
28 #include "rtp_cfmessages.h" |
|
29 |
|
30 #if defined(ESOCK_LOGGING_ACTIVE) |
|
31 _LIT8(KRtcpFlowSubTag, "RtcpFlow"); |
|
32 #endif |
|
33 |
|
34 CRtcpFlow::CRtcpFlow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf) |
|
35 :CRtpBaseFlow(aFactory, aSubConnId, aProtocolIntf) |
|
36 { |
|
37 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8(" CRtcpFlow %08x:\t "), this)); |
|
38 LOG_NODE_CREATE(KESockFlowTag, CRtcpFlow); |
|
39 } |
|
40 |
|
41 |
|
42 CRtcpFlow* CRtcpFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
43 { |
|
44 CRtcpFlow *pRtcpFlow = new (ELeave) CRtcpFlow(aFactory, aSubConn, aProtocolIntf); |
|
45 |
|
46 CleanupStack::PushL(pRtcpFlow); |
|
47 pRtcpFlow->ConstructL(); |
|
48 /* Register the flow with Rtp Pint */ |
|
49 ((CRtpProtocolIntf*)aProtocolIntf)->RegisterSubConnProvIDL(pRtcpFlow,aSubConn); |
|
50 CleanupStack::Pop(); |
|
51 |
|
52 return pRtcpFlow; |
|
53 } |
|
54 |
|
55 void CRtcpFlow::ConstructL() |
|
56 { |
|
57 iRtcpHandler = CCFRtpHandler::NewL(this,EPriorityNormal); |
|
58 iRtcpHandler->SetType(ERtcp); |
|
59 iRtcpBuffer.CreateL(KRtcpDefBufSz); |
|
60 iRtcpTempBuffer.CreateL(KRtcpDefBufSz); |
|
61 } |
|
62 |
|
63 |
|
64 CRtcpFlow::~CRtcpFlow() |
|
65 { |
|
66 iRtcpBuffer.Close(); |
|
67 iRtcpTempBuffer.Close(); |
|
68 LOG_NODE_DESTROY(KESockFlowTag, CRtcpFlow); |
|
69 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8(" ~CRtcpFlow %08x:\t "), this)); |
|
70 } |
|
71 |
|
72 void CRtcpFlow::CanSend() |
|
73 { |
|
74 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t CanSend() "), this)); |
|
75 if(!iBlockedWrite) |
|
76 { |
|
77 /* This can happen if after doing a write any buffer allocations |
|
78 failed or an internal error happened. Just return and in the |
|
79 next timeout will try writing again */ |
|
80 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t CanSend() iBlockedWrite is false"), this)); |
|
81 return; |
|
82 } |
|
83 |
|
84 TInt nwr = -1; |
|
85 /* Alloc the RMBuff Chain. The allocation might fail |
|
86 because there are not enough MBufs. This needs to be |
|
87 handled */ |
|
88 TInt ret = iRtcpDataChain.Alloc(iRtcpTempBuffer.Size()); |
|
89 if(ret == KErrNone) |
|
90 { |
|
91 iRtcpDataChain.CopyIn(iRtcpTempBuffer); |
|
92 if(iSSPData) |
|
93 { |
|
94 nwr = iSSPData->Write(iRtcpDataChain, 0 , &iDestAddr); |
|
95 } |
|
96 if(nwr == 0) |
|
97 { |
|
98 /* This will be a Strange Behaviour because we are in cansend() */ |
|
99 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t CanSend() nwr is 0"), this)); |
|
100 /* Free the MBuf */ |
|
101 iRtcpDataChain.Free(); |
|
102 return; /* IsBlocked is still ture */ |
|
103 } |
|
104 iRtcpDataChain.Free(); |
|
105 } |
|
106 iBlockedWrite = EFalse; |
|
107 return; |
|
108 } |
|
109 |
|
110 TInt CRtcpFlow::Write(RMBufChain& aData, TUint, TSockAddr* anAddr) |
|
111 { |
|
112 TInt nwr = -1; |
|
113 |
|
114 /* Findout the amount of Data contained in the RMbuf Chain */ |
|
115 TInt rmbuflen = aData.Length(); |
|
116 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t Write() Len %d"), this, rmbuflen)); |
|
117 if(iRtcpBuffer.MaxLength() < rmbuflen) |
|
118 { |
|
119 |
|
120 TInt ret; |
|
121 iRtcpBuffer.SetLength(0); |
|
122 ret = iRtcpBuffer.ReAlloc(rmbuflen); |
|
123 |
|
124 if(KErrNone != ret) |
|
125 { |
|
126 /* In case of error a protocol is supposed to Error and then return 0 */ |
|
127 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t Write() Alloc failed!"), this)); |
|
128 iSessionControlNotify->Error(ret,MSessionControlNotify::EErrorSend); |
|
129 return 0; |
|
130 } |
|
131 } |
|
132 |
|
133 /* Copy the Data from RMbuf to Descriptor. Then Pass it to the RtpStack */ |
|
134 iRtcpBuffer.SetLength(rmbuflen); |
|
135 aData.CopyOut(iRtcpBuffer); |
|
136 |
|
137 /* The responsibility of the Upper Layer ends here. */ |
|
138 if(!NonRtcpSendData()) |
|
139 { |
|
140 TRAPD(errPack,iRtpSession->ProcessRTCPRequestL(iRtcpBuffer)); |
|
141 if(KErrNone != errPack) |
|
142 { |
|
143 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\tSendRTCPPacketL Leave with code %d"), this, errPack)); |
|
144 iSessionControlNotify->Error(errPack,MSessionControlNotify::EErrorSend); |
|
145 return errPack; |
|
146 } |
|
147 } |
|
148 else |
|
149 { |
|
150 TRequestStatus stat; |
|
151 stat = KRequestPending; |
|
152 if(anAddr) |
|
153 { |
|
154 SendData(iRtcpBuffer, *anAddr, 0, stat); |
|
155 } |
|
156 else |
|
157 { |
|
158 SendData(iRtcpBuffer, iRtcpHandler->DefaultRemoteAddress(), 0, stat); |
|
159 } |
|
160 User::WaitForRequest(stat); |
|
161 //Errors are ingnored |
|
162 } |
|
163 |
|
164 /* Uncomment this to bypass RTP Stack */ |
|
165 //SendData(*anAddr, iRtcpBuffer); |
|
166 |
|
167 |
|
168 nwr = 1; //Always Success. |
|
169 |
|
170 /* Correct Protocol behaviour is to free this data even though CSocket frees |
|
171 * it. */ |
|
172 aData.Free(); |
|
173 return nwr; |
|
174 } |
|
175 |
|
176 |
|
177 void CRtcpFlow::ReceivedL(const Messages::TRuntimeCtxId& aSender, const Messages::TNodeId& aRecipient, Messages::TSignatureBase& aMessage) |
|
178 { |
|
179 CRtpBaseFlow::ReceivedL(aSender,aRecipient,aMessage); |
|
180 |
|
181 if ( aMessage.IsMessage<Messages::TEBase::TError>() ) |
|
182 { |
|
183 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\tGot TError from Sunconn"), this)); |
|
184 HandleError(static_cast<Messages::TEBase::TError&>(aMessage).iValue); |
|
185 } |
|
186 else if (Messages::TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
187 { |
|
188 switch (aMessage.MessageId().MessageId()) |
|
189 { |
|
190 case Messages::TEChild::TDestroy::EId: |
|
191 Destroy(); |
|
192 break; |
|
193 } |
|
194 |
|
195 } |
|
196 else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
197 { |
|
198 switch (aMessage.MessageId().MessageId()) |
|
199 { |
|
200 case TCFDataClient::TStart::EId : |
|
201 { |
|
202 /* Check if we Have a Bearer. If we donot Have |
|
203 complete when we Have one */ |
|
204 User::LeaveIfError(iStartRequest.Open(iSubConnectionProvider,aSender)); |
|
205 if(iSSPData) |
|
206 { |
|
207 CompleteStart(KErrNone); |
|
208 } |
|
209 else |
|
210 { |
|
211 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\tGot TDataClientStart no SP iIsStarting=>ETrue"), this)); |
|
212 iIsStarting = ETrue; |
|
213 } |
|
214 } |
|
215 break; |
|
216 |
|
217 case TCFDataClient::TStop::EId : |
|
218 { |
|
219 StopFlow(static_cast<TCFDataClient::TStop&>(aMessage)); |
|
220 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t DataClientStopped"), this)); |
|
221 break; |
|
222 } |
|
223 |
|
224 case TCFDataClient::TProvisionConfig::EId: |
|
225 { |
|
226 TCFDataClient::TProvisionConfig& aMess = Messages::message_cast<TCFDataClient::TProvisionConfig>(aMessage); |
|
227 |
|
228 iAccessPointConfig.Close(); |
|
229 iAccessPointConfig.Open(aMess.iConfig); |
|
230 |
|
231 const CRtpProvisionConfig& rtpProv = static_cast<const CRtpProvisionConfig&>(AccessPointConfig().FindExtensionL(STypeId::CreateSTypeId(KRtpProvisionUid, KRtpProvisionConfigType))); |
|
232 DoProvisionL(&rtpProv); |
|
233 |
|
234 /* Deafult Processing */ |
|
235 HandleProvisionMessage(aMessage); |
|
236 break; |
|
237 } |
|
238 |
|
239 case TCFDataClient::TBindTo::EId : |
|
240 { |
|
241 TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage)); |
|
242 TRAPD(err,BindToL(bindToMsg)); |
|
243 |
|
244 if(err) |
|
245 { |
|
246 Messages::RClientInterface::OpenPostMessageClose(Id(), aSender, Messages::TEBase::TError(TCFDataClient::TBindTo::Id(), err).CRef()); |
|
247 } |
|
248 else |
|
249 { |
|
250 Messages::RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); |
|
251 } |
|
252 |
|
253 //If we have received TDataClientStart before (when we did not yet have a bearer), |
|
254 //we complete the start here as well |
|
255 if (iIsStarting) |
|
256 { |
|
257 CompleteStart(err); |
|
258 } |
|
259 |
|
260 HandleBindToMessage(aMessage,err); |
|
261 break; |
|
262 } |
|
263 |
|
264 } |
|
265 |
|
266 } |
|
267 else if (TCFControlProvider::ERealmId == aMessage.MessageId().Realm()) |
|
268 { |
|
269 switch (aMessage.MessageId().MessageId()) |
|
270 { |
|
271 } |
|
272 } |
|
273 } |
|
274 |
|
275 |
|
276 void CRtcpFlow::DoProvisionL(const CRtpProvisionConfig *apRtpProv) |
|
277 { |
|
278 |
|
279 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\tDoProvisionL()"), this)); |
|
280 |
|
281 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow: \t RtpTimeNow=%d RtpTimeConv=%d "),apRtpProv->RtpTimeNow(),apRtpProv->RtptimeConversion())); |
|
282 |
|
283 /* Now that the Provision is available. Bring the RTCP Stack up. */ |
|
284 // RTCP given more priority .. Verify :=@ |
|
285 iRtpSession->CreateRtcpL(iRtcpHandler,apRtpProv->GetCNAME()); |
|
286 |
|
287 iRtpSession->SetSessionBandwidth(apRtpProv->BandWidth()); |
|
288 iRtpSession->SetRTPTimeConversion(apRtpProv->RtpTimeNow(),apRtpProv->RtptimeConversion()); |
|
289 |
|
290 /* Auto Send Option */ |
|
291 iRtpSession->SetAutoSendOption(apRtpProv->RtpAutoSend()); |
|
292 |
|
293 TInetAddr destAddr = apRtpProv->GetDefDestinationAddr(); |
|
294 destAddr.SetPort(destAddr.Port()+1); |
|
295 iRtcpHandler->SetDefaultRemoteAddress(destAddr); |
|
296 |
|
297 /* Report Interval */ |
|
298 iRtpSession->SetRtcpInterval(apRtpProv->GetRtcpReportInterval()); |
|
299 |
|
300 } |
|
301 |
|
302 TInt CRtcpFlow::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr) |
|
303 { |
|
304 ASSERT(iSSPData); |
|
305 TInt ret; |
|
306 |
|
307 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\tGetData()"), this)); |
|
308 |
|
309 ret = iSSPData->GetData(aData, aLength, aOptions, anAddr); |
|
310 if(ret < 0) |
|
311 { |
|
312 /* The Read failed. Just pass the error up */ |
|
313 return ret; |
|
314 } |
|
315 |
|
316 /* Findout the amount of Data contained in the RMbuf Chain */ |
|
317 TInt rbuflen = aData.Length(); |
|
318 |
|
319 if(iRtcpBuffer.MaxLength() < rbuflen) |
|
320 { |
|
321 TInt ret; |
|
322 iRtcpBuffer.SetLength(0); |
|
323 ret = iRtcpBuffer.ReAlloc(rbuflen); |
|
324 |
|
325 if(KErrNone != ret) |
|
326 { |
|
327 return ret; |
|
328 } |
|
329 } |
|
330 |
|
331 /* Copy the Data from RMbuf to Descriptor. Then Pass it to the RtpStack*/ |
|
332 iRtcpBuffer.SetLength(rbuflen); |
|
333 aData.CopyOut(iRtcpBuffer); |
|
334 if(anAddr) |
|
335 { |
|
336 iRtcpHandler->SetRecvAddress(*anAddr); |
|
337 } |
|
338 else |
|
339 { |
|
340 /* Connected Socket */ |
|
341 if(!iConnected) |
|
342 { |
|
343 return KErrArgument; |
|
344 } |
|
345 iRtcpHandler->SetRecvAddress(iDestAddr); |
|
346 } |
|
347 |
|
348 TRAP(ret,iRtpSession->DoReceiveL(iRtcpBuffer,ERtcp)) |
|
349 if(KErrNone == ret) |
|
350 { |
|
351 aData.CopyIn(iRtcpBuffer); |
|
352 } |
|
353 |
|
354 return ret; |
|
355 } |
|
356 |
|
357 /* RTP Stack calls this function when ever it needs to send |
|
358 an RTCP report */ |
|
359 void CRtcpFlow::SendData(TDes8& aBuffer, TSockAddr &aAddr, TInt , TRequestStatus &aStatus) |
|
360 { |
|
361 |
|
362 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t RtcpSend()"), this)); |
|
363 /* See if a Write is already pending. If it is then just update the buffered data with the new report |
|
364 and return */ |
|
365 if(iBlockedWrite) |
|
366 { |
|
367 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t RtcpSend() Write Blocked already-OVERWRITE"), this)); |
|
368 HandleWriteBlocked(aAddr, aBuffer); |
|
369 TRequestStatus *pStat = &aStatus; |
|
370 User::RequestComplete(pStat,KErrNone); |
|
371 return; |
|
372 } |
|
373 |
|
374 |
|
375 TInt nwr = -1; |
|
376 /* Alloc the RMBuf Chain. The allocation might fail |
|
377 because there are not enough MBufs. |
|
378 [TO BE DONE] This needs to be handled */ |
|
379 TInt ret = iRtcpDataChain.Alloc(aBuffer.Size()); |
|
380 if(ret == KErrNone) |
|
381 { |
|
382 iRtcpDataChain.CopyIn(aBuffer); |
|
383 if(iSSPData) |
|
384 { |
|
385 nwr = iSSPData->Write(iRtcpDataChain, 0 /* Shud be ok */, &aAddr); |
|
386 } |
|
387 else |
|
388 { |
|
389 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t RtcpSend(): iSSPData is NULL (Flow was Stopped??"), this)); |
|
390 } |
|
391 |
|
392 if(nwr == 0) |
|
393 { |
|
394 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t RtcpSend(): WriteBlocked"), this)); |
|
395 /* Flow not able to accept our data. Set the blocked flag and |
|
396 make a temporary copy */ |
|
397 HandleWriteBlocked(aAddr, aBuffer); |
|
398 } |
|
399 /* Free the Descriptor */ |
|
400 iRtcpDataChain.Free(); |
|
401 } |
|
402 else |
|
403 { |
|
404 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t RtcpSend(): RmbufChain Alloc Failed"), this)); |
|
405 } |
|
406 TRequestStatus *pStat = &aStatus; |
|
407 User::RequestComplete(pStat,KErrNone); |
|
408 return; |
|
409 } |
|
410 |
|
411 void CRtcpFlow::SetRtpSession(CRtpController *apRtpSession) |
|
412 { |
|
413 iRtpSession = apRtpSession; |
|
414 //iRtpSession->CreateRtcpL(); |
|
415 } |
|
416 |
|
417 void CRtcpFlow::NewData(TUint aCount) |
|
418 { |
|
419 __ASSERT_DEBUG(iSessionDataNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider)); |
|
420 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t NewData(): Count %d"), this, aCount)); |
|
421 iSessionDataNotify->NewData(aCount); |
|
422 } |
|
423 |
|
424 /* Buffer the data and Set the Blocked flag to True when a write failure |
|
425 happens */ |
|
426 void CRtcpFlow::HandleWriteBlocked(TSockAddr& aAddr,TDes8& aBuffer) |
|
427 { |
|
428 TInt ret; |
|
429 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtcpFlowSubTag,_L8("CRtcpFlow %08x:\t HandleWriteBlocked()"), this)); |
|
430 if(iRtcpTempBuffer.MaxLength() < aBuffer.Length()) |
|
431 { |
|
432 iRtcpTempBuffer.SetLength(0); |
|
433 ret = iRtcpTempBuffer.ReAlloc(aBuffer.Length()); |
|
434 if(KErrNone != ret) |
|
435 { |
|
436 /* donot do anything and just return. Write is already blocked |
|
437 in CanSend() isBlockedWrite flag will not be True and normal |
|
438 flow will be resumed */ |
|
439 return; |
|
440 } |
|
441 } |
|
442 iBlockedWrite = ETrue; |
|
443 iRtcpTempBuffer = aBuffer; |
|
444 iDestAddr = aAddr; |
|
445 } |
|
446 |
|
447 void CRtcpFlow::DoCanClose(MSessionControlNotify::TDelete ) |
|
448 /** |
|
449 Called from protocol to indicate that a graceful close has completed |
|
450 */ |
|
451 { |
|
452 /* There is nothing much to Do here for RTCP. The Cleaning up will be done |
|
453 by the base class. The RTPSession is owned by the RTPFlow and the Cleaning will |
|
454 be handled from there */ |
|
455 return; |
|
456 } |
|
457 |
|
458 void CRtcpFlow::DoUpdateLocalAddress(const TSockAddr& ) |
|
459 /* Called by BaseFlow to notify that Local address has been |
|
460 Updated. Ideally called only once */ |
|
461 { |
|
462 /* Not handled Now */ |
|
463 } |
|
464 |
|
465 |
|
466 TInt CRtcpFlow::DoGetOption(TUint level, TUint name, TDes8 &aOption) const |
|
467 { |
|
468 TInt err = KErrNone; |
|
469 /* Socket option for RTP */ |
|
470 if(KSolRtcp == level) |
|
471 { |
|
472 switch(name) |
|
473 { |
|
474 case KSoRtcpAutoSend: |
|
475 { |
|
476 TInt rtcpAutoSend = iRtpSession->AutoSendOption(); |
|
477 CopyOptionToDesc(aOption,rtcpAutoSend); |
|
478 break; |
|
479 } |
|
480 case KSoRtcpStatistics: |
|
481 { |
|
482 /* The SSRC is specified in the Params structue.*/ |
|
483 TRtcpStatisticsParams rtcpStatistics; |
|
484 GETOPTION_OR_RETURN(aOption,rtcpStatistics); |
|
485 err = iRtpSession->RtcpStatistics(rtcpStatistics.iSsrc,rtcpStatistics); |
|
486 if(KErrNone == err) |
|
487 { |
|
488 CopyOptionToDesc(aOption,rtcpStatistics); |
|
489 } |
|
490 break; |
|
491 } |
|
492 |
|
493 default: |
|
494 { |
|
495 return KErrNotSupported; |
|
496 } |
|
497 } |
|
498 return KErrNone; |
|
499 } |
|
500 if(iSSP) |
|
501 return iSSP->GetOption(level,name,aOption); |
|
502 return KErrNone; |
|
503 } |
|
504 |
|
505 TInt CRtcpFlow::DoSetOption(TUint level, TUint name, const TDesC8 &aOption) |
|
506 { |
|
507 TInt err = KErrNone; |
|
508 /* Socket option for RTP */ |
|
509 if(KSolRtcp == level) |
|
510 { |
|
511 switch(name) |
|
512 { |
|
513 case KSoRtcpAutoSend: |
|
514 { |
|
515 TInt optInt=0; |
|
516 GETOPTION_OR_RETURN(aOption,optInt); |
|
517 iRtpSession->SetAutoSendOption(optInt); |
|
518 break; |
|
519 } |
|
520 case KSoRtcpTimeInterval: |
|
521 { |
|
522 TTimeIntervalMicroSeconds32 timeInterval; |
|
523 GETOPTION_OR_RETURN(aOption,timeInterval); |
|
524 iRtpSession->SetRtcpInterval(timeInterval); |
|
525 break; |
|
526 } |
|
527 case KSoRtcpCNAME: |
|
528 { |
|
529 TRAPD(err,iRtpSession->CreateRtcpL(iRtcpHandler,aOption)); |
|
530 return err; |
|
531 } |
|
532 case KSoDefaultDestAddr: |
|
533 { |
|
534 TSockAddr destAddr; |
|
535 GETOPTION_OR_RETURN(aOption,destAddr); |
|
536 iRtcpHandler->SetDefaultRemoteAddress(destAddr); |
|
537 break; |
|
538 } |
|
539 |
|
540 case KSoSendNonRtcpData: |
|
541 { |
|
542 TBool nonRtcpData = EFalse; |
|
543 GETOPTION_OR_RETURN(aOption,nonRtcpData); |
|
544 SetNonRtcpSendData(nonRtcpData); |
|
545 break; |
|
546 } |
|
547 |
|
548 case KSoReceiveNonRtcpData: |
|
549 { |
|
550 TInt nonRtcpData = 0; |
|
551 GETOPTION_OR_RETURN(aOption,nonRtcpData); |
|
552 iRtpSession->SetNonRtcpData(nonRtcpData); |
|
553 break; |
|
554 } |
|
555 default: |
|
556 { |
|
557 return KErrNotSupported; |
|
558 } |
|
559 } |
|
560 return err; |
|
561 } |
|
562 |
|
563 if(iSSP) |
|
564 return iSSP->SetOption(level,name,aOption); |
|
565 return err; |
|
566 } |
|
567 |
|
568 void CRtcpFlow::SetNonRtcpSendData(TBool aNonRtcpData) |
|
569 { |
|
570 iNonRtcpSendData = aNonRtcpData; |
|
571 } |
|
572 |
|
573 TBool CRtcpFlow::NonRtcpSendData() |
|
574 { |
|
575 return iNonRtcpSendData; |
|
576 } |