|
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 // RTPFlow Implementation |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #include <comms-infras/ss_log.h> |
|
24 |
|
25 #include "rtpflow.h" |
|
26 #include "rtppint.h" |
|
27 #include "rtp_cfmessages.h" |
|
28 |
|
29 |
|
30 #if defined(ESOCK_LOGGING_ACTIVE) |
|
31 _LIT8(KRtpFlowSubTag, "RtpFlow"); |
|
32 #endif |
|
33 |
|
34 |
|
35 CRtpFlow::CRtpFlow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf) |
|
36 :CRtpBaseFlow(aFactory, aSubConnId, aProtocolIntf) |
|
37 { |
|
38 LOG_NODE_CREATE(KESockFlowTag, CRtpFlow); |
|
39 } |
|
40 |
|
41 CRtpFlow* CRtpFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConn, CProtocolIntfBase* aProtocolIntf) |
|
42 { |
|
43 CRtpFlow *pRtpFlow = new (ELeave) CRtpFlow(aFactory, aSubConn, aProtocolIntf); |
|
44 |
|
45 CleanupStack::PushL(pRtpFlow); |
|
46 pRtpFlow->ConstructL(); |
|
47 /* Register the flow with Rtp Pint */ |
|
48 ((CRtpProtocolIntf*)aProtocolIntf)->RegisterSubConnProvIDL(pRtpFlow,aSubConn); |
|
49 CleanupStack::Pop(); |
|
50 |
|
51 return pRtpFlow; |
|
52 } |
|
53 |
|
54 void CRtpFlow::ConstructL() |
|
55 { |
|
56 TSockAddr addr; |
|
57 /* Create the RTP Handler */ |
|
58 iRtpHandler = CCFRtpHandler::NewL(this,EPriorityNormal); |
|
59 iRtpSession = CRtpController::NewL(*iRtpHandler,EPriorityNormal,addr, _L8("")); |
|
60 iRtpBuffer.ReAllocL(KRtpDefBufSz); |
|
61 } |
|
62 |
|
63 |
|
64 CRtpFlow::~CRtpFlow() |
|
65 { |
|
66 delete iRtpSession; |
|
67 iRtpBuffer.Close(); |
|
68 LOG_NODE_DESTROY(KESockFlowTag, CRtpFlow); |
|
69 } |
|
70 |
|
71 void CRtpFlow::CanSend() |
|
72 { |
|
73 __ASSERT_DEBUG(iSessionDataNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider)); |
|
74 CRtpBaseFlow::CanSend(); |
|
75 } |
|
76 |
|
77 TInt CRtpFlow::Write(RMBufChain& aData, TUint aOptions, TSockAddr* anAddr ) |
|
78 { |
|
79 |
|
80 TInt nwr = -1; |
|
81 TInt ret = KErrNone; |
|
82 /* Findout the amount of Data contained in the RMbuf Chain */ |
|
83 TInt rmbuflen = aData.Length(); |
|
84 TPtr8 rtpBufPtr(NULL, 0); |
|
85 |
|
86 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tWrite() Len=%d"), this, rmbuflen)); |
|
87 |
|
88 if(!(aData.First()->Next())) |
|
89 { |
|
90 RMBuf *buffer = aData.First(); |
|
91 __ASSERT_DEBUG(rmbuflen == buffer->Length() ,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicIncompleteBuffer)); |
|
92 rtpBufPtr.Set(buffer->Ptr(), rmbuflen, rmbuflen); |
|
93 } |
|
94 else |
|
95 { |
|
96 if(iRtpBuffer.MaxLength() < rmbuflen) |
|
97 { |
|
98 iRtpBuffer.SetLength(0); |
|
99 ret = iRtpBuffer.ReAlloc(rmbuflen); |
|
100 |
|
101 if(KErrNone != ret) |
|
102 { |
|
103 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tWrite() -ALLOC Failed!"), this)); |
|
104 /* In case of error a protocol is supposed to Error and then return 0 */ |
|
105 iSessionControlNotify->Error(ret,MSessionControlNotify::EErrorSend); |
|
106 return 0; |
|
107 } |
|
108 } |
|
109 |
|
110 /* Copy the Data from RMbuf to Descriptor. Then Pass it to the RtpStack*/ |
|
111 iRtpBuffer.SetLength(rmbuflen); |
|
112 aData.CopyOut(iRtpBuffer); |
|
113 rtpBufPtr.Set(&iRtpBuffer[0], rmbuflen, iRtpBuffer.MaxLength()); |
|
114 } |
|
115 |
|
116 if(!NonRtpSendData()) |
|
117 { |
|
118 iRtpSession->PacketBeingSent(rtpBufPtr, ERtp); |
|
119 } |
|
120 //It is assumed that a Properly Created packet is passed down here. |
|
121 //Maybe we should handle a return code for PacketbeingSent function. |
|
122 if(aData.First()->Next()) |
|
123 { |
|
124 aData.CopyIn(iRtpBuffer); |
|
125 } |
|
126 |
|
127 __ASSERT_DEBUG(iSSPData,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoServiceProvider)); |
|
128 nwr = iSSPData->Write(aData, aOptions, anAddr); |
|
129 |
|
130 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tWrite() Done nwr=%d"), this,nwr)); |
|
131 |
|
132 return nwr; |
|
133 |
|
134 } |
|
135 |
|
136 |
|
137 void CRtpFlow::ReceivedL(const Messages::TRuntimeCtxId& aSender, const Messages::TNodeId& aRecipient, Messages::TSignatureBase& aMessage) |
|
138 { |
|
139 CRtpBaseFlow::ReceivedL(aSender,aRecipient,aMessage); |
|
140 |
|
141 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tReceivedL() Msg %d"), this, aMessage.MessageId().MessageId())); |
|
142 |
|
143 if ( aMessage.IsMessage<Messages::TEBase::TError>() ) |
|
144 { |
|
145 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tGot TError from Sunconn"), this)); |
|
146 HandleError(static_cast<Messages::TEBase::TError&>(aMessage).iValue); |
|
147 } |
|
148 else if (Messages::TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
149 { |
|
150 switch (aMessage.MessageId().MessageId()) |
|
151 { |
|
152 case Messages::TEChild::TDestroy::EId : |
|
153 { |
|
154 Destroy(); |
|
155 break; |
|
156 } |
|
157 } |
|
158 } |
|
159 else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
160 { |
|
161 switch (aMessage.MessageId().MessageId()) |
|
162 { |
|
163 case TCFDataClient::TProvisionConfig::EId: |
|
164 { |
|
165 TCFDataClient::TProvisionConfig& aMess = Messages::message_cast<TCFDataClient::TProvisionConfig>(aMessage); |
|
166 |
|
167 iAccessPointConfig.Close(); |
|
168 iAccessPointConfig.Open(aMess.iConfig); |
|
169 |
|
170 const CRtpProvisionConfig& rtpProv = static_cast<const CRtpProvisionConfig&>(AccessPointConfig().FindExtensionL(STypeId::CreateSTypeId(KRtpProvisionUid, KRtpProvisionConfigType))); |
|
171 DoProvisionL(&rtpProv); |
|
172 |
|
173 /* Deafult Processing */ |
|
174 HandleProvisionMessage(aMessage); |
|
175 break; |
|
176 } |
|
177 |
|
178 case TCFDataClient::TStart::EId : |
|
179 { |
|
180 /* Check if we Have a Bearer. If we donot Have |
|
181 complete when we Have one */ |
|
182 User::LeaveIfError(iStartRequest.Open(iSubConnectionProvider,aSender)); |
|
183 if(iSSPData) |
|
184 { |
|
185 CompleteStart(KErrNone); |
|
186 } |
|
187 else |
|
188 { |
|
189 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tGot TDataClientStart no SP iIsStarting=>ETrue"), this)); |
|
190 iIsStarting = ETrue; |
|
191 } |
|
192 } |
|
193 break; |
|
194 |
|
195 case TCFDataClient::TStop::EId : |
|
196 { |
|
197 StopFlow(static_cast<TCFDataClient::TStop&>(aMessage)); |
|
198 break; |
|
199 } |
|
200 |
|
201 case TCFDataClient::TBindTo::EId : |
|
202 { |
|
203 TCFDataClient::TBindTo& bindToMsg(static_cast<TCFDataClient::TBindTo&>(aMessage)); |
|
204 TRAPD(err,BindToL(bindToMsg)); |
|
205 |
|
206 if(err) |
|
207 { |
|
208 Messages::RClientInterface::OpenPostMessageClose(Id(), aSender, Messages::TEBase::TError(TCFDataClient::TBindTo::Id(), err).CRef()); |
|
209 } |
|
210 else |
|
211 { |
|
212 Messages::RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); |
|
213 } |
|
214 |
|
215 //If we have received TDataClientStart before (when we did not yet have a bearer), |
|
216 //we complete the start here as well |
|
217 if (iIsStarting) |
|
218 { |
|
219 CompleteStart(err); |
|
220 } |
|
221 |
|
222 HandleBindToMessage(aMessage,err); |
|
223 break; |
|
224 } |
|
225 |
|
226 } |
|
227 } |
|
228 else if (TCFControlProvider::ERealmId == aMessage.MessageId().Realm()) |
|
229 { |
|
230 /* VRAMY : LOG Here!!! */ |
|
231 } |
|
232 } |
|
233 |
|
234 |
|
235 void CRtpFlow::DoProvisionL(const CRtpProvisionConfig *apRtpProv) |
|
236 { |
|
237 iRtpSession->SetSessionBandwidth(apRtpProv->BandWidth()); |
|
238 iRtpSession->SetRTPTimeConversion(apRtpProv->RtpTimeNow(),apRtpProv->RtptimeConversion()); |
|
239 iRtpSession->SetRtpStreamParameters(apRtpProv->MaxDropOut(), |
|
240 apRtpProv->MaxMisorder(), |
|
241 apRtpProv->MinSequential()); |
|
242 } |
|
243 |
|
244 TInt CRtpFlow::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* anAddr) |
|
245 { |
|
246 ASSERT(iSSPData); |
|
247 TInt ret; |
|
248 |
|
249 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tGetData "), this )); |
|
250 |
|
251 ret = iSSPData->GetData(aData, aLength, aOptions, anAddr); |
|
252 if(ret < 0) |
|
253 { |
|
254 /* The Read failed. Just pass the error up */ |
|
255 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tGetData failed (ret =%d)"), this)); |
|
256 return ret; |
|
257 } |
|
258 |
|
259 /* Findout the amount of Data contained in the RMbuf Chain */ |
|
260 TInt rmbuflen = aData.Length(); |
|
261 TPtr8 rtpBufPtr(NULL, 0); |
|
262 |
|
263 if(!(aData.First()->Next())) |
|
264 { |
|
265 RMBuf *buffer = aData.First(); |
|
266 __ASSERT_DEBUG(rmbuflen == buffer->Length() ,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicIncompleteBuffer)); |
|
267 rtpBufPtr.Set(buffer->Ptr(), rmbuflen, rmbuflen); |
|
268 } |
|
269 else |
|
270 { |
|
271 if(iRtpBuffer.MaxLength() < rmbuflen) |
|
272 { |
|
273 iRtpBuffer.SetLength(0); |
|
274 ret = iRtpBuffer.ReAlloc(rmbuflen); |
|
275 if(KErrNone != ret) |
|
276 { |
|
277 return ret; |
|
278 } |
|
279 } |
|
280 |
|
281 iRtpBuffer.SetLength(rmbuflen); |
|
282 aData.CopyOut(iRtpBuffer); |
|
283 rtpBufPtr.Set(&iRtpBuffer[0], rmbuflen, iRtpBuffer.MaxLength()); |
|
284 } |
|
285 |
|
286 if(anAddr) |
|
287 { |
|
288 iRtpHandler->SetRecvAddress(*anAddr); |
|
289 } |
|
290 else |
|
291 { |
|
292 /* Connected Socket */ |
|
293 __ASSERT_DEBUG(iConnected,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicIncorrectState)); |
|
294 iRtpHandler->SetRecvAddress(iDestAddr); |
|
295 } |
|
296 |
|
297 TRAP(ret,iRtpSession->DoReceiveL(rtpBufPtr,ERtp)); |
|
298 |
|
299 if((KErrNone == ret) && (aData.First()->Next())) |
|
300 { |
|
301 aData.CopyIn(iRtpBuffer); |
|
302 } |
|
303 |
|
304 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tGetData()) done ret=%d"), this,ret)); |
|
305 |
|
306 return ret; |
|
307 } |
|
308 |
|
309 |
|
310 void CRtpFlow::SendData(TDes8& , TSockAddr &, TInt , TRequestStatus &aStatus) |
|
311 { |
|
312 |
|
313 TRequestStatus *stat = &aStatus; |
|
314 User::RequestComplete(stat,KErrNone); |
|
315 } |
|
316 |
|
317 |
|
318 void CRtpFlow::NewData(TUint aCount) |
|
319 { |
|
320 __ASSERT_DEBUG(iSessionDataNotify,User::Panic(KRtpFlowPanic, RtpFlowPanics::KPanicNoControlProvider)); |
|
321 |
|
322 LOG( ESockLogExternal::Printf(KESockFlowTag,KRtpFlowSubTag,_L8("CRtpFlow %08x:\tNewData()"), this)); |
|
323 |
|
324 CRtpBaseFlow::NewData(aCount); |
|
325 } |
|
326 |
|
327 |
|
328 /* When an RTCP flow is created call this function to enable RTCP in |
|
329 RtpSession. The function will return a Pointer to RTPSession which |
|
330 can be passed on to RTCP Flow */ |
|
331 CRtpController* CRtpFlow::GetRtpSession() const |
|
332 { |
|
333 return iRtpSession; |
|
334 } |
|
335 |
|
336 void CRtpFlow::DoCanClose(MSessionControlNotify::TDelete ) |
|
337 /** |
|
338 Called from protocol to indicate that a graceful close has completed |
|
339 */ |
|
340 { |
|
341 /* RTP Session is no longer Valid and Can be Closed now */ |
|
342 /* OOPS no API to close the RtpSession :(*/ |
|
343 } |
|
344 |
|
345 |
|
346 void CRtpFlow::DoUpdateLocalAddress(const TSockAddr& anAddr) |
|
347 /* Called by BaseFlow to notify that Local address has been |
|
348 Updated. Ideally called only once */ |
|
349 { |
|
350 iRtpSession->SetLocalAddress(anAddr); |
|
351 } |
|
352 |
|
353 TInt CRtpFlow::DoGetOption(TUint level, TUint name, TDes8 &aOption) const |
|
354 { |
|
355 /* Socket option for RTP */ |
|
356 if(KSolRtp == level) |
|
357 { |
|
358 switch(name) |
|
359 { |
|
360 case KSoLocalSSRC: |
|
361 { |
|
362 TUint locSSRC = iRtpSession->GetLocalSSRC(); |
|
363 CopyOptionToDesc(aOption,locSSRC); |
|
364 break; |
|
365 } |
|
366 default: |
|
367 { |
|
368 return KErrNotSupported; |
|
369 } |
|
370 } |
|
371 return KErrNone; |
|
372 } |
|
373 |
|
374 if(iSSP) |
|
375 return iSSP->GetOption(level,name,aOption); |
|
376 return KErrNone; |
|
377 } |
|
378 |
|
379 TInt CRtpFlow::DoSetOption(TUint level, TUint name, const TDesC8 &aOption) |
|
380 { |
|
381 |
|
382 /* Socket option for RTP */ |
|
383 if(KSolRtp == level) |
|
384 { |
|
385 TInt ret = KErrNone; |
|
386 switch(name) |
|
387 { |
|
388 case KSoRtpBandwidth: |
|
389 { |
|
390 TInt optInt=0; |
|
391 GETOPTION_OR_RETURN(aOption,optInt); |
|
392 iRtpSession->SetSessionBandwidth(optInt); |
|
393 break; |
|
394 } |
|
395 case KSoStreamParams: |
|
396 { |
|
397 TRtpStreamParams strmParams; |
|
398 GETOPTION_OR_RETURN(aOption,strmParams); |
|
399 iRtpSession->SetRtpStreamParameters(strmParams.iMaxDropout, |
|
400 strmParams.iMaxMisorder, |
|
401 strmParams.iMinSequential); |
|
402 break; |
|
403 } |
|
404 |
|
405 case KSoRtpTimeConvertion: |
|
406 { |
|
407 TRtpTimeConversion rtpTimeConv; |
|
408 GETOPTION_OR_RETURN(aOption,rtpTimeConv); |
|
409 iRtpSession->SetRTPTimeConversion(rtpTimeConv.iRtpTimeNow, |
|
410 rtpTimeConv.iConversion); |
|
411 break; |
|
412 } |
|
413 |
|
414 case KSoSendNonRtpData: |
|
415 { |
|
416 TInt nonRtpData = 0; |
|
417 GETOPTION_OR_RETURN(aOption,nonRtpData); |
|
418 SetNonRtpSendData(nonRtpData); |
|
419 break; |
|
420 } |
|
421 |
|
422 case KSoReceiveNonRtpData: |
|
423 { |
|
424 TInt nonRtpData = 0; |
|
425 GETOPTION_OR_RETURN(aOption,nonRtpData); |
|
426 iRtpSession->SetNonRtpData(nonRtpData); |
|
427 break; |
|
428 } |
|
429 case KSoSamplingRate: |
|
430 { |
|
431 TSamplingRateInfo sampRateInfo; |
|
432 GETOPTION_OR_RETURN(aOption,sampRateInfo); |
|
433 ret = iRtpSession->SetSamplingRate(sampRateInfo.iPayloadType, |
|
434 sampRateInfo.iSamplingRate); |
|
435 break; |
|
436 } |
|
437 |
|
438 default: |
|
439 { |
|
440 return KErrNotSupported; |
|
441 } |
|
442 } |
|
443 return ret; |
|
444 } |
|
445 if(iSSP) |
|
446 return iSSP->SetOption(level,name,aOption); |
|
447 return KErrNone; |
|
448 } |
|
449 |
|
450 void CRtpFlow::SetNonRtpSendData(TInt aNonRtpData) |
|
451 { |
|
452 iNonRtpSendData = aNonRtpData; |
|
453 } |
|
454 |
|
455 TInt CRtpFlow::NonRtpSendData() |
|
456 { |
|
457 return iNonRtpSendData; |
|
458 } |
|
459 |
|
460 |